[
  {
    "path": ".changeset/config.json",
    "content": "{\n  \"$schema\": \"https://unpkg.com/@changesets/config@3.1.2/schema.json\",\n  \"changelog\": [\n    \"@svitejs/changesets-changelog-github-compact\",\n    { \"repo\": \"TanStack/query\" }\n  ],\n  \"commit\": false,\n  \"access\": \"public\",\n  \"baseBranch\": \"main\",\n  \"updateInternalDependencies\": \"patch\",\n  \"fixed\": [],\n  \"linked\": [],\n  \"ignore\": [],\n  \"___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH\": {\n    \"onlyUpdatePeerDependentsWhenOutOfRange\": true\n  }\n}\n"
  },
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n"
  },
  {
    "path": ".gitattributes",
    "content": "# Auto detect text files and perform LF normalization\n* text=auto eol=lf\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "github: [tannerlinsley, tkdodo]\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "content": "name: '🐛 Bug report'\ndescription: Report a reproducible bug or regression\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thank you for reporting an issue :pray:.\n\n        This issue tracker is for reporting reproducible bugs or regression's found in [TanStack Query](https://github.com/TanStack/query)\n        If you have a question about how to achieve something and are struggling, please post a question\n        inside of TanStack Query's [Discussions tab](https://github.com/TanStack/query/discussions)\n\n        Before submitting a new bug/issue, please check the links below to see if there is a solution or question posted there already:\n         - TanStack Query's [Discussions tab](https://github.com/TanStack/query/discussions)\n         - TanStack Query's [Open Issues](https://github.com/TanStack/query/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc)\n         - TanStack Query's [Closed Issues](https://github.com/TanStack/query/issues?q=is%3Aissue+sort%3Aupdated-desc+is%3Aclosed)\n\n        The more information you fill in, the better the community can help you.\n  - type: textarea\n    id: description\n    attributes:\n      label: Describe the bug\n      description: Provide a clear and concise description of the challenge you are running into.\n    validations:\n      required: true\n  - type: input\n    id: link\n    attributes:\n      label: Your minimal, reproducible example\n      description: |\n        Please add a link to a minimal reproduction.\n        Note:\n        - Your bug may get fixed much faster if we can run your code and it doesn't have dependencies other than React/Solid/Vue/Svelte.\n        - To create a shareable code example for web, you can use CodeSandbox (https://codesandbox.io/s/new) or Stackblitz (https://stackblitz.com/).\n        - Please make sure the example is complete and runnable - e.g. avoid localhost URLs.\n        - To stub out real api requests - Promise.resolve and Promise.reject are good options for easy reproduction\n        - Feel free to fork any of the official examples to reproduce your issue: https://tanstack.com/query/latest/docs/framework/react/examples/simple\n        - For React Native, you can use: https://snack.expo.dev/\n        - For TypeScript related issues only, a TypeScript Playground link might be sufficient: https://www.typescriptlang.org/play\n        - Please read these tips for providing a minimal example: https://stackoverflow.com/help/mcve.\n      placeholder: |\n        e.g. Code Sandbox, Stackblitz, Expo Snack or TypeScript playground\n    validations:\n      required: true\n  - type: textarea\n    id: steps\n    attributes:\n      label: Steps to reproduce\n      description: Describe the steps we have to take to reproduce the behavior.\n      placeholder: |\n        1. Go to '...'\n        2. Click on '....'\n        3. Scroll down to '....'\n        4. See error\n    validations:\n      required: true\n  - type: textarea\n    id: expected\n    attributes:\n      label: Expected behavior\n      description: Provide a clear and concise description of what you expected to happen.\n      placeholder: |\n        As a user, I expected ___ behavior but i am seeing ___\n    validations:\n      required: true\n  - type: dropdown\n    attributes:\n      label: How often does this bug happen?\n      description: |\n        Following the repro steps above, how easily are you able to reproduce this bug?\n      options:\n        - Every time\n        - Often\n        - Sometimes\n        - Only once\n  - type: textarea\n    id: screenshots_or_videos\n    attributes:\n      label: Screenshots or Videos\n      description: |\n        If applicable, add screenshots or a video to help explain your problem.\n        For more information on the supported file image/file types and the file size limits, please refer\n        to the following link: https://docs.github.com/en/github/writing-on-github/working-with-advanced-formatting/attaching-files\n      placeholder: |\n        You can drag your video or image files inside of this editor ↓\n  - type: textarea\n    id: platform\n    attributes:\n      label: Platform\n      description: |\n        Please let us know which Operting System, Browser and Browser version you were using when the issue occurred.\n      placeholder: |\n        - OS: [e.g. macOS, Windows, Linux, iOS, Android]\n        - Browser: [e.g. Chrome, Safari, Firefox, React Native]\n        - Version: [e.g. 91.1]\n    validations:\n      required: true\n  - type: dropdown\n    id: adapter\n    attributes:\n      label: Tanstack Query adapter\n      description: |\n        Please let us know which adapter of TanStack Query you were using when the issue occurred.\n      options:\n        - react-query\n        - solid-query\n        - svelte-query\n        - vue-query\n        - angular-query\n        - vanilla\n  - type: input\n    id: rq-version\n    attributes:\n      label: TanStack Query version\n      description: |\n        Please let us know the exact version of TanStack Query you were using when the issue occurred. Please don't just put in \"latest\", as this is subject to change.\n      placeholder: |\n        e.g. v5.51.9\n    validations:\n      required: true\n  - type: input\n    id: ts-version\n    attributes:\n      label: TypeScript version\n      description: |\n        If you are using TypeScript, please let us know the exact version of TypeScript you were using when the issue occurred.\n      placeholder: |\n        e.g. v5.5.4\n  - type: textarea\n    id: additional\n    attributes:\n      label: Additional context\n      description: Add any other context about the problem here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: 🤔 Feature Requests & Questions\n    url: https://github.com/TanStack/query/discussions\n    about: Please ask and answer questions here.\n  - name: 💬 Community Chat\n    url: https://discord.gg/mQd7egN\n    about: A dedicated discord server hosted by TanStack\n  - name: 🦋 TanStack Bluesky\n    url: https://bsky.app/profile/tanstack.com\n    about: Stay up to date with new releases of our libraries\n"
  },
  {
    "path": ".github/pull_request_template.md",
    "content": "## 🎯 Changes\n\n<!-- What changes are made in this PR? Describe the change and its motivation. -->\n\n## ✅ Checklist\n\n- [ ] I have followed the steps in the [Contributing guide](https://github.com/TanStack/query/blob/main/CONTRIBUTING.md).\n- [ ] I have tested this code locally with `pnpm run test:pr`.\n\n## 🚀 Release Impact\n\n- [ ] This change affects published code, and I have generated a [changeset](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).\n- [ ] This change is docs/CI/dev-only (no release).\n"
  },
  {
    "path": ".github/renovate.json",
    "content": "{\n  \"$schema\": \"https://docs.renovatebot.com/renovate-schema.json\",\n  \"configMigration\": true,\n  \"extends\": [\n    \"config:recommended\",\n    \"group:allNonMajor\",\n    \"schedule:weekly\",\n    \":approveMajorUpdates\",\n    \":automergeMinor\",\n    \":disablePeerDependencies\",\n    \":maintainLockFilesMonthly\",\n    \":semanticCommits\",\n    \":semanticCommitTypeAll(chore)\"\n  ],\n  \"ignorePresets\": [\":ignoreModulesAndTests\"],\n  \"labels\": [\"dependencies\"],\n  \"rangeStrategy\": \"bump\",\n  \"postUpdateOptions\": [\"pnpmDedupe\"],\n  \"ignoreDeps\": [\n    \"@types/node\",\n    \"@types/react\",\n    \"@types/react-dom\",\n    \"node\",\n    \"react\",\n    \"react-dom\",\n    \"tsup\",\n    \"typescript\",\n    \"typescript54\",\n    \"typescript55\",\n    \"typescript56\",\n    \"typescript57\",\n    \"typescript58\",\n    \"typescript59\",\n    \"typescript60\",\n    \"vue\",\n    \"vue-tsc\",\n    \"vue2\",\n    \"vue2.7\",\n    \"webpack\"\n  ]\n}\n"
  },
  {
    "path": ".github/workflows/autofix.yml",
    "content": "name: autofix.ci # needed to securely identify the workflow\n\non:\n  pull_request:\n  push:\n    branches: [main, 'v[0-9]', '*-pre', '*-maint']\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.event.number || github.ref }}\n  cancel-in-progress: true\n\npermissions:\n  contents: read\n\njobs:\n  autofix:\n    name: autofix\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6.0.2\n      - name: Setup Tools\n        uses: TanStack/config/.github/setup@main\n      - name: Fix formatting\n        run: pnpm run format\n      - name: Apply fixes\n        uses: autofix-ci/action@635ffb0c9798bd160680f18fd73371e355b85f27\n        with:\n          commit-message: 'ci: apply automated fixes'\n"
  },
  {
    "path": ".github/workflows/detect-agent.yml",
    "content": "name: Detect Agent\n\non:\n  pull_request_target:\n    types: [opened]\n  workflow_dispatch: {}\n\npermissions:\n  issues: write\n  pull-requests: write\n\njobs:\n  detect:\n    if: github.event_name != 'workflow_dispatch'\n    uses: bombshell-dev/automation/.github/workflows/detect-agent.yml@a1553cebd9318d416f6a8e9f38f363b6aaa19c72\n\n  backfill:\n    if: github.event_name == 'workflow_dispatch'\n    uses: bombshell-dev/automation/.github/workflows/detect-agent-backfill.yml@a1553cebd9318d416f6a8e9f38f363b6aaa19c72\n"
  },
  {
    "path": ".github/workflows/labeler.yml",
    "content": "name: Labeler\n\non:\n  pull_request_target:\n\npermissions:\n  contents: read\n  pull-requests: write\n\njobs:\n  labeler:\n    name: Labeler\n    runs-on: ubuntu-latest\n    steps:\n      - name: Labeler\n        uses: actions/labeler@v6.0.1\n        with:\n          repo-token: ${{ secrets.GITHUB_TOKEN }}\n          configuration-path: labeler-config.yml\n"
  },
  {
    "path": ".github/workflows/pr.yml",
    "content": "name: PR\n\non:\n  pull_request:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.event.number || github.ref }}\n  cancel-in-progress: true\n\nenv:\n  NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}\n\npermissions:\n  contents: read\n  pull-requests: write\n  issues: write\n\njobs:\n  test:\n    name: Test\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6.0.2\n        with:\n          fetch-depth: 0\n      - name: Start Nx Agents\n        run: npx nx-cloud start-ci-run --distribute-on=\".nx/workflows/dynamic-changesets.yaml\"\n      - name: Setup Tools\n        uses: TanStack/config/.github/setup@main\n      - name: Get base and head commits for `nx affected`\n        uses: nrwl/nx-set-shas@v4.4.0\n        with:\n          main-branch-name: main\n      - name: Run Checks\n        run: pnpm run test:pr\n      - name: Stop Nx Agents\n        if: ${{ always() }}\n        run: npx nx-cloud stop-all-agents\n  preview:\n    name: Preview\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6.0.2\n      - name: Setup Tools\n        uses: TanStack/config/.github/setup@main\n      - name: Build Packages\n        run: pnpm run build:all\n      - name: Publish Previews\n        run: pnpx pkg-pr-new publish --pnpm --compact './packages/*' --template './examples/*/*'\n      - name: Determine commit SHA\n        id: determine-sha\n        run: |\n          echo \"COMMIT_SHA=${{ github.event.pull_request.head.sha || github.sha }}\" >> $GITHUB_ENV\n      - name: Size Limit\n        uses: andresz1/size-limit-action@94bc357df29c36c8f8d50ea497c3e225c3c95d1d\n        with:\n          github_token: ${{ secrets.GITHUB_TOKEN }}\n          skip_step: install\n          build_script: build:all\n  provenance:\n    name: Provenance\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6.0.2\n      - name: Check Provenance\n        uses: danielroe/provenance-action@v0.1.1\n        with:\n          fail-on-downgrade: true\n  version-preview:\n    name: Version Preview\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6.0.2\n      - name: Setup Tools\n        uses: TanStack/config/.github/setup@main\n      - name: Changeset Preview\n        uses: TanStack/config/.github/changeset-preview@main\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Release\n\non:\n  push:\n    branches: [main, 'v[0-9]', '*-pre', '*-maint']\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: false\n\nenv:\n  NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}\n\npermissions:\n  contents: write\n  id-token: write\n  pull-requests: write\n\njobs:\n  release:\n    name: Release\n    if: \"!contains(github.event.head_commit.message, 'ci: changeset release')\"\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6.0.2\n        with:\n          fetch-depth: 0\n      - name: Check for changesets\n        id: changesets\n        run: |\n          CHANGESET_FILES=$(ls .changeset/*.md 2>/dev/null | grep -v README.md || true)\n          if [ -z \"$CHANGESET_FILES\" ]; then\n            echo \"has_changesets=false\" >> \"$GITHUB_OUTPUT\"\n          else\n            echo \"has_changesets=true\" >> \"$GITHUB_OUTPUT\"\n          fi\n      - name: Start Nx Agents\n        if: steps.changesets.outputs.has_changesets == 'true'\n        run: npx nx-cloud start-ci-run --distribute-on=\".nx/workflows/dynamic-changesets.yaml\"\n      - name: Setup Tools\n        uses: TanStack/config/.github/setup@main\n      - name: Run Tests\n        if: steps.changesets.outputs.has_changesets == 'true'\n        run: pnpm run test:ci\n      - name: Stop Nx Agents\n        if: ${{ always() && steps.changesets.outputs.has_changesets == 'true' }}\n        run: npx nx-cloud stop-all-agents\n      - name: Enter Pre-Release Mode\n        if: \"contains(github.ref_name, '-pre') && !hashFiles('.changeset/pre.json')\"\n        run: pnpm changeset pre enter pre\n      - name: Version Packages\n        run: pnpm run changeset:version\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n      - name: Commit and Push Version Changes\n        id: commit\n        run: |\n          git config user.name \"github-actions[bot]\"\n          git config user.email \"github-actions[bot]@users.noreply.github.com\"\n          git add .\n          if git commit -m \"ci: changeset release\"; then\n            git push\n            echo \"committed=true\" >> \"$GITHUB_OUTPUT\"\n          fi\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n      - name: Determine dist-tag\n        if: steps.commit.outputs.committed == 'true'\n        id: dist-tag\n        run: |\n          BRANCH=\"${GITHUB_REF_NAME}\"\n          if [[ \"$BRANCH\" == *-pre ]]; then\n            echo \"prerelease=true\" >> \"$GITHUB_OUTPUT\"\n          elif [[ \"$BRANCH\" == *-maint ]]; then\n            echo \"tag=maint\" >> \"$GITHUB_OUTPUT\"\n          elif [[ \"$BRANCH\" =~ ^v[0-9]+$ ]]; then\n            echo \"tag=$BRANCH\" >> \"$GITHUB_OUTPUT\"\n          else\n            echo \"latest=true\" >> \"$GITHUB_OUTPUT\"\n          fi\n      - name: Publish Packages\n        if: steps.commit.outputs.committed == 'true'\n        run: pnpm run changeset:publish ${{ steps.dist-tag.outputs.tag && format('--tag {0}', steps.dist-tag.outputs.tag) }}\n      - name: Create GitHub Release\n        if: steps.commit.outputs.committed == 'true'\n        run: node scripts/create-github-release.mjs ${{ steps.dist-tag.outputs.prerelease == 'true' && '--prerelease' }} ${{ steps.dist-tag.outputs.latest == 'true' && '--latest' }}\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".gitignore",
    "content": "\n# See https://help.github.com/ignore-files/ for more about ignoring files.\n\n# dependencies\nnode_modules\npackage-lock.json\nyarn.lock\n\n# builds\nbuild\ncoverage\ndist\ndist-ts\n\n# misc\n.DS_Store\n.env\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n.next\nnext-env.d.ts\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n.history\nsize-plugin.json\nstats-hydration.json\nstats.json\nstats.html\n.vscode/settings.json\n.vscode/mcp.json\n.cursor/rules\n.github/instructions/nx.instructions.md\n\n*.log\n*.tsbuildinfo\n.angular\n.cache\n.idea\n.nx/cache\n.nx/workspace-data\n.pnpm-store\n.svelte-kit\n.tsup\n.vinxi\ntemp\n\nvite.config.js.timestamp-*\nvite.config.ts.timestamp-*\n"
  },
  {
    "path": ".npmrc",
    "content": "provenance=true\n"
  },
  {
    "path": ".nvmrc",
    "content": "24.8.0\n"
  },
  {
    "path": ".nx/workflows/dynamic-changesets.yaml",
    "content": "distribute-on:\n  small-changeset: 3 linux-medium-js\n  medium-changeset: 4 linux-medium-js\n  large-changeset: 5 linux-medium-js\n"
  },
  {
    "path": ".prettierignore",
    "content": "**/.next\n**/.nx/cache\n**/.svelte-kit\n**/build\n**/coverage\n**/dist\n**/query-codemods/**/__testfixtures__\n.changeset/*.md\npnpm-lock.yaml\npackages/**/tsup.config.bundled*.mjs\n**/tsconfig.vitest-temp.json\ndocs/framework/*/reference\n"
  },
  {
    "path": ".size-limit.json",
    "content": "[\n  {\n    \"name\": \"react full\",\n    \"path\": \"packages/react-query/build/modern/index.js\",\n    \"limit\": \"13.00 kB\",\n    \"ignore\": [\"react\", \"react-dom\"]\n  },\n  {\n    \"name\": \"react minimal\",\n    \"path\": \"packages/react-query/build/modern/index.js\",\n    \"limit\": \"9.99 kB\",\n    \"import\": \"{ useQuery, QueryClient, QueryClientProvider }\",\n    \"ignore\": [\"react\", \"react-dom\"]\n  }\n]\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\n## Questions\n\nIf you have questions about implementation details, help or support, then please use our dedicated community forum at [GitHub Discussions](https://github.com/TanStack/query/discussions) **PLEASE NOTE:** If you choose to instead open an issue for your question, your issue will be immediately closed and redirected to the forum.\n\n## Reporting Issues\n\nIf you have found what you think is a bug, please [file an issue](https://github.com/TanStack/query/issues/new/choose). **PLEASE NOTE:** Issues that are identified as implementation questions or non-issues will be immediately closed and redirected to [GitHub Discussions](https://github.com/TanStack/query/discussions)\n\n## Suggesting new features\n\nIf you are here to suggest a feature, first create an issue if it does not already exist. From there, we will discuss use-cases for the feature and then finally discuss how it could be implemented.\n\n## Development\n\n_TanStack/query uses **symlink-based** configuration files. For smooth development in a local environment, we recommend developing in an environment that supports symlinks(ex: Linux, macOS, Windows Subsystem for Linux / WSL)._\n\nIf you have been assigned to fix an issue or develop a new feature, please follow these steps to get started:\n\n- Fork this repository.\n- Install dependencies\n\n  ```bash\n  pnpm install\n  ```\n\n  - We use [pnpm](https://pnpm.io/) v10 for package management (run in case of pnpm-related issues).\n\n    ```bash\n    corepack enable && corepack prepare\n    ```\n\n  - We use [nvm](https://github.com/nvm-sh/nvm) to manage node versions - please make sure to use the version mentioned in `.nvmrc`\n\n    ```bash\n    nvm use\n    ```\n\n- Build all packages.\n\n  ```bash\n  pnpm build:all\n  ```\n\n- Run development server.\n\n  ```bash\n  pnpm run watch\n  ```\n\n- Implement your changes and tests to files in the `src/` directory and corresponding test files.\n- Document your changes in the appropriate doc page.\n- Git stage your required changes and commit (see below commit guidelines).\n- Submit PR for review.\n\n### Editing the docs locally and previewing the changes\n\nThe documentations for all the TanStack projects are hosted on [tanstack.com](https://tanstack.com), which is a TanStack Start application (https://github.com/TanStack/tanstack.com). You need to run this app locally to preview your changes in the `TanStack/query` docs.\n\n> [!NOTE]\n> The website fetches the doc pages from GitHub in production, and searches for them at `../query/docs` in development. Your local clone of `TanStack/query` needs to be in the same directory as the local clone of `TanStack/tanstack.com`.\n\nYou can follow these steps to set up the docs for local development:\n\n1. Make a new directory called `tanstack`.\n\n```sh\nmkdir tanstack\n```\n\n2. Enter that directory and clone the [`TanStack/query`](https://github.com/TanStack/query) and [`TanStack/tanstack.com`](https://github.com/TanStack/tanstack.com) repos.\n\n```sh\ncd tanstack\ngit clone git@github.com:TanStack/query.git\n# We probably don't need all the branches and commit history\n# from the `tanstack.com` repo, so let's just create a shallow\n# clone of the latest version of the `main` branch.\n# Read more about shallow clones here:\n# https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/#user-content-shallow-clones\ngit clone git@github.com:TanStack/tanstack.com.git --depth=1 --single-branch --branch=main\n```\n\n> [!NOTE]\n> Your `tanstack` directory should look like this:\n>\n> ```\n> tanstack/\n>    |\n>    +-- query/ (<-- this directory cannot be called anything else!)\n>    |\n>    +-- tanstack.com/\n> ```\n\n3. Enter the `tanstack/tanstack.com` directory, install the dependencies and run the app in dev mode:\n\n```sh\ncd tanstack.com\npnpm i\n# The app will run on https://localhost:3000 by default\npnpm dev\n```\n\n4. Now you can visit http://localhost:3000/query/latest/docs/framework/react/overview in the browser and see the changes you make in `tanstack/query/docs` there.\n\n> [!WARNING]\n> You will need to update the `docs/config.json` file (in `TanStack/query`) if you add a new documentation page!\n\nYou can see the whole process in the screen capture below:\n\nhttps://github.com/fulopkovacs/form/assets/43729152/9d35a3c3-8153-4e74-9cb2-af275f7a269b\n\n### Running examples\n\n- Make sure you've installed the dependencies in the repo's root directory.\n\n  ```bash\n  pnpm install\n  ```\n\n- If you want to run the example against your local changes, run below in the repo's root directory. Otherwise, it will be run against the latest TanStack Query release.\n\n  ```bash\n  pnpm run watch\n  ```\n\n- Run below in the selected examples' directory.\n\n  ```bash\n  pnpm run dev\n  ```\n\n#### Note on standalone execution\n\nIf you want to run an example without installing dependencies for the whole repo, just follow the instructions from the example's README.md file. It will then be run against the latest TanStack Query release.\n\n## Online one-click setup\n\nYou can use Gitpod (An Online open-source VS Code-like IDE that is free for Open Source) for developing online. With a single click it will start a workspace and automatically:\n\n- clone the `TanStack/query` repo.\n- install all the dependencies in `/` and `/docs`.\n- run below in the root(`/`) to Auto-build files.\n\n  ```bash\n  npm start\n  ```\n\n- run below in `/docs`.\n\n  ```bash\n  npm run dev\n  ```\n\n[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/TanStack/query)\n\n## Changesets\n\nThis repo uses [Changesets](https://github.com/changesets/changesets) to automate releases. If your PR should release a new package version (patch, minor, or major), please run `pnpm changeset` and commit the file. If needed, changeset descriptions can be more descriptive, and will be included in the changelog. If your PR affects docs, examples, styles, etc., you probably don't need to generate a changeset.\n\n## Pull requests\n\nMaintainers merge pull requests by squashing all commits and editing the commit message if necessary using the GitHub user interface.\n\nUse an appropriate commit type. Be especially careful with breaking changes.\n\n## Releases\n\nFor each new commit added to `main`, a GitHub Workflow is triggered which runs the [Changesets Action](https://github.com/changesets/action). This generates a preview PR showing the impact of all changesets. When this PR is merged, the package will be published to NPM.\n\n## 🧪 Test\n\nTanStack Query uses [Nx](https://nx.dev/) as its monorepo tool.\nTo run tests in a local environment, you should use `nx` commands from the root directory.\n\n### ✅ Run all tests\n\nTo run tests for **all packages**, run:\n\n```bash\nnpm run test\n```\n\n### ✅ Run tests for a specific package\n\nTo run tests for a specific package, use the following command:\n\n```bash\nnpx nx run @tanstack/{package-name}:test:lib\n```\n\nFor example:\n\n```bash\nnpx nx run @tanstack/react-query:test:lib\n```\n\n### ⚠️ Caution\n\nDo not run `pnpm run test:lib` inside individual package folders.\nThis can cause test failures due to dependencies between packages.\nAlways run tests from the **root folder** using `nx` commands.\n"
  },
  {
    "path": "FUNDING.json",
    "content": "{\n  \"drips\": {\n    \"ethereum\": {\n      \"ownedBy\": \"0xD5371B61b35E13F2ae354BE95081aD63FB383452\"\n    }\n  }\n}\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2021-present Tanner Linsley\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "<img referrerpolicy=\"no-referrer-when-downgrade\" src=\"https://static.scarf.sh/a.png?x-pxid=be2d8a11-9712-4c1d-9963-580b2d4fb133\" />\n\n<div align=\"center\">\n  <img src=\"./media/header_query.png\" alt=\"TanStack Query\" />\n</div>\n\n<br />\n\n<div align=\"center\">\n<a href=\"https://www.npmjs.com/package/@tanstack/query-core\" target=\"_parent\">\n  <img alt=\"\" src=\"https://img.shields.io/npm/dm/@tanstack/query-core.svg\" alt=\"npm downloads\" />\n</a>\n <a href=\"https://github.com/TanStack/query/stargazers\" target=\"_parent\">\n  <img alt=\"\" src=\"https://img.shields.io/github/stars/TanStack/query.svg?style=social&label=Star\" alt=\"GitHub stars\" />\n</a>\n<a href=\"https://bundlejs.com/?q=%40tanstack%2Freact-query&config=%7B%22esbuild%22%3A%7B%22external%22%3A%5B%22react%22%2C%22react-dom%22%5D%7D%7D&badge=\" target=\"_parent\">\n  <img alt=\"\" src=\"https://deno.bundlejs.com/?q=@tanstack/react-query&config={%22esbuild%22:{%22external%22:[%22react%22,%22react-dom%22]}}&badge=detailed\" alt=\"Bundle size\" />\n</a>\n</div>\n\n<div align=\"center\">\n<a href=\"#badge\">\n    <img src=\"https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg\" alt=\"semantic-release\">\n  </a>\n<a href=\"https://bestofjs.org/projects/tanstack-query\"><img src=\"https://img.shields.io/endpoint?url=https://bestofjs-serverless.now.sh/api/project-badge?fullName=TanStack%2Fquery%26since=daily\" alt=\"Best of JS\" /></a>\n  <a href=\"https://twitter.com/tan_stack\"><img src=\"https://img.shields.io/twitter/follow/tan_stack.svg?style=social\" alt=\"Follow @TanStack\"/></a>\n</div>\n\n<div align=\"center\">\n\n### [Become a Sponsor!](https://github.com/sponsors/tannerlinsley/)\n\n</div>\n\n# TanStack Query\n\nAn async state management library built to simplify fetching, caching, synchronizing, and updating server state.\n\n- Protocol‑agnostic fetching (REST, GraphQL, promises, etc.)\n- Caching, refetching, pagination & infinite scroll\n- Mutations, dependent queries & background updates\n- Prefetching, cancellation & React Suspense support\n\n### <a href=\"https://tanstack.com/query\">Read the docs →</b></a>\n\n## Get Involved\n\n- We welcome issues and pull requests!\n- Participate in [GitHub discussions](https://github.com/TanStack/query/discussions)\n- Chat with the community on [Discord](https://discord.com/invite/WrRKjPJ)\n- See [CONTRIBUTING.md](./CONTRIBUTING.md) for setup instructions\n\n## Partners\n\n<table align=\"center\">\n  <tr>\n    <td>\n      <a href=\"https://www.coderabbit.ai/?via=tanstack&dub_id=aCcEEdAOqqutX6OS\" >\n        <picture>\n          <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://tanstack.com/assets/coderabbit-dark-D643Zkrv.svg\" />\n          <source media=\"(prefers-color-scheme: light)\" srcset=\"https://tanstack.com/assets/coderabbit-light-CIzGLYU_.svg\" />\n          <img src=\"https://tanstack.com/assets/coderabbit-light-CIzGLYU_.svg\" height=\"40\" alt=\"CodeRabbit\" />\n        </picture>\n      </a>\n    </td>\n    <td>\n      <a href=\"https://www.cloudflare.com?utm_source=tanstack\">\n        <picture>\n          <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://tanstack.com/assets/cloudflare-white-Co-Tyjbl.svg\" />\n          <source media=\"(prefers-color-scheme: light)\" srcset=\"https://tanstack.com/assets/cloudflare-black-6Ojsn8yh.svg\" />\n          <img src=\"https://tanstack.com/assets/cloudflare-white-Co-Tyjbl.svg\" height=\"60\" alt=\"Cloudflare\" />\n        </picture>\n      </a>\n    </td>\n  </tr>\n</table>\n\n<div align=\"center\">\n<img src=\"./media/partner_logo.svg\" alt=\"Query & you?\" height=\"65\">\n<p>\nWe're looking for TanStack Query Partners to join our mission! Partner with us to push the boundaries of TanStack Query and build amazing things together.\n</p>\n<a href=\"mailto:partners@tanstack.com?subject=TanStack Query Partnership\"><b>LET'S CHAT</b></a>\n</div>\n\n</div>\n\n## Explore the TanStack Ecosystem\n\n- <a href=\"https://github.com/tanstack/config\"><b>TanStack Config</b></a> – Tooling for JS/TS packages\n- <a href=\"https://github.com/tanstack/db\"><b>TanStack DB</b></a> – Reactive sync client store\n- <a href=\"https://github.com/tanstack/devtools\"><b>TanStack DevTools</b></a> – Unified devtools panel\n- <a href=\"https://github.com/tanstack/form\"><b>TanStack Form</b></a> – Type‑safe form state\n- <a href=\"https://github.com/tanstack/pacer\"><b>TanStack Pacer</b></a> – Debouncing, throttling, batching <br/>\n- <a href=\"https://github.com/tanstack/query\"><b>TanStack Query</b></a> – Async state & caching\n- <a href=\"https://github.com/tanstack/ranger\"><b>TanStack Ranger</b></a> – Range & slider primitives\n- <a href=\"https://github.com/tanstack/router\"><b>TanStack Router</b></a> – Type‑safe routing, caching & URL state\n- <a href=\"https://github.com/tanstack/router\"><b>TanStack Start</b></a> – Full‑stack SSR & streaming\n- <a href=\"https://github.com/tanstack/store\"><b>TanStack Store</b></a> – Reactive data store\n- <a href=\"https://github.com/tanstack/table\"><b>TanStack Table</b></a> – Headless datagrids\n- <a href=\"https://github.com/tanstack/virtual\"><b>TanStack Virtual</b></a> – Virtualized rendering\n\n… and more at <a href=\"https://tanstack.com\"><b>TanStack.com »</b></a>\n\n<!-- Use the force, Luke -->\n"
  },
  {
    "path": "docs/community-resources.md",
    "content": "---\ntitle: Community Resources\narticles:\n  [\n    {\n      title: \"TkDodo's Blog Posts\",\n      url: 'https://tkdodo.eu/blog/practical-react-query',\n      description: 'TkDodo, a maintainer of TanStack Query, writes a series of blog posts about the library. These articles offer general best practices and often present opinionated perspectives on using TanStack Query.',\n    },\n  ]\nmedia:\n  [\n    {\n      title: 'React Query: It’s Time to Break up with your Global State! – Tanner Linsley',\n      url: 'https://www.youtube.com/watch?v=seU46c6Jz7E',\n      description: 'Get the lowdown on “global state” and how React Query can help you fetch, cache and manage your asynchronous data with a fraction of the effort and code that you’re used to',\n    },\n    {\n      title: 'All About React Query (with Tanner Linsley) — Learn With Jason',\n      url: 'https://www.youtube.com/watch?v=DocXo3gqGdI',\n      description: 'Learn all about React Query with its creator Tanner Linsley.',\n    },\n    {\n      title: 'Hooks for Fetching with ReactQuery Creator Tanner Linsley aka @tannerlinsley',\n      url: 'https://www.youtube.com/watch?v=PPvWXbSCtBU',\n      description: 'Learn how React Query simplifies asynchronous data fetching in React applications.',\n    },\n    {\n      title: 'React Query - Open Source Friday stream with Tanner Linsley from',\n      url: 'https://www.youtube.com/watch?v=B3cJDT3j19I',\n      description: 'An Open Source Friday stream featuring Tanner Linsley.',\n    },\n    {\n      title: 'React Query Presentation - Tanner Linsley',\n      url: 'https://www.youtube.com/watch?v=_ehibado6rU',\n      description: 'Tanner Linsley gives a talk to Lambda School students about the React Query.',\n    },\n    {\n      title: 'TanStack Query v4 (with Dominik Dorfmeister) — Learn With Jason',\n      url: 'https://www.youtube.com/watch?v=SPPQm0dvEes',\n      description: 'Dominik Dorfmeister covering TanStack Query v4.',\n    },\n    {\n      title: 'React Query Exposed by Its Maintainer',\n      url: 'https://www.youtube.com/watch?v=8-RTNnn9GR8',\n      description: 'Dominik Dorfmeister explores the less favorable aspects of React Query and situations where it may not be the best fit.',\n    },\n    {\n      title: 'React Query API Design: Lessons Learned - Dominik Dorfmeister',\n      url: 'https://www.youtube.com/watch?v=l3PxErcKeAI',\n      description: 'Dominik Dorfmeister walks through some of the API design choices that were made in React Query to get to the DX.',\n    },\n  ]\nutilities:\n  [\n    {\n      title: 'batshit',\n      url: 'https://github.com/yornaath/batshit',\n      description: 'A batch manager that will deduplicate and batch requests for a certain data type made within a window',\n    },\n    {\n      title: 'GraphQL Code Generator',\n      url: 'https://the-guild.dev/graphql/codegen',\n      description: 'Generate React Query hooks from your GraphQL schema',\n    },\n\n    {\n      title: 'Http-wizard',\n      url: 'https://http-wizard.com',\n      description: 'End-to-end type-safe Fastify API with typeScript magic ✨',\n    },\n\n    {\n      title: 'Normy',\n      url: 'https://github.com/klis87/normy',\n      description: 'Automatic normalization and data updates for data fetching libraries',\n    },\n\n    {\n      title: 'Orval',\n      url: 'https://orval.dev/',\n      description: 'Generate TypeScript client from OpenAPI specifications.',\n    },\n    {\n      title: 'Query Key Factory',\n      url: 'https://github.com/lukemorales/query-key-factory',\n      description: 'A library for creating typesafe standardized query keys, useful for cache management in @tanstack/query',\n    },\n\n    {\n      title: 'React Query Kit',\n      url: 'https://github.com/liaoliao666/react-query-kit',\n      description: '🕊️ A toolkit for ReactQuery that makes ReactQuery hooks reusable and typesafe',\n    },\n    {\n      title: 'React Query Rewind',\n      url: 'https://reactqueryrewind.com/',\n      description: 'Time travel and visualize state during development',\n    },\n    {\n      title: 'React Query Swagger',\n      url: 'https://github.com/Shaddix/react-query-swagger',\n      description: 'Generate React Query hooks based on Swagger API definitions',\n    },\n    {\n      title: 'Suspensive React Query',\n      url: 'https://suspensive.org/docs/react-query/motivation',\n      description: 'Enhances React Query with Suspense support, allowing for simpler and more declarative data fetching',\n    },\n    {\n      title: 'tRPC',\n      url: 'https://trpc.io/',\n      description: 'End-to-end typesafe APIs made easy',\n    },\n  ]\nothers:\n  [\n    {\n      title: 'Atomic CRM',\n      url: 'https://marmelab.com/atomic-crm/',\n      description: 'A full-featured CRM built with React, react-admin, and Supabase.',\n    },\n    {\n      title: 'Blitz',\n      url: 'https://blitzjs.com/',\n      description: 'The Missing Fullstack Toolkit for Next.js',\n    },\n    {\n      title: 'Connect',\n      url: 'https://connectrpc.com/docs',\n      description: 'A family of libraries for building browser and gRPC-compatible HTTP APIs.',\n    },\n    {\n      title: 'Hey API',\n      url: 'https://heyapi.dev/openapi-ts/plugins/tanstack-query',\n      description: 'OpenAPI to TypeScript codegen. Production-ready SDKs, Zod schemas, TanStack Query hooks, and 20+ plugins. Used by Vercel, OpenCode, and PayPal.',\n    },\n    {\n      title: 'Kubb',\n      url: 'https://www.kubb.dev/',\n      description: 'Generate SDKs for all your APIs',\n    },\n    {\n      title: 'OpenAPI codegen',\n      url: 'https://github.com/fabien0102/openapi-codegen',\n      description: 'A tool for generating code based on an OpenAPI schema.',\n    },\n    {\n      title: 'OpenAPI Qraft React',\n      url: 'https://github.com/OpenAPI-Qraft/openapi-qraft',\n      description: 'Generate type-safe API clients and Hooks for TanStack Query directly from OpenAPI Documents.Zero-runtime overhead, Proxy-based design, seamless SSR support, and full TanStack Query functionality.',\n    },\n    {\n      title: 'OpenAPI React Query codegen',\n      url: 'https://github.com/7nohe/openapi-react-query-codegen',\n      description: 'Generate TanStack Query hooks based on an OpenAPI specification file.',\n    },\n    {\n      title: 'OpenAPI zod client',\n      url: 'https://github.com/astahmer/openapi-zod-client',\n      description: 'Generate a zodios client from an OpenAPI specification',\n    },\n    {\n      title: 'openapi-fetch',\n      url: 'https://openapi-ts.dev/openapi-react-query/',\n      description: 'A 2KB min, typesafe fetch wrapper that uses static TypeScript type inference and no runtime checks.',\n    },\n    {\n      title: 'oRPC',\n      url: 'https://orpc.unnoq.com/docs/integrations/tanstack-query',\n      description: 'Easy to build APIs that are end-to-end type-safe and adhere to OpenAPI standards.',\n    },\n    {\n      title: 'Rapini',\n      url: 'https://github.com/rametta/rapini',\n      description: '🥬 OpenAPI to React Query (or SWR) & Axios',\n    },\n    {\n      title: 'Tanstack Query Visualizer',\n      url: 'https://tanstack-query-visualizer.sofi.coop/',\n      description: 'An interactive sandbox that visualizes the relationship between mutations and query keys.',\n    },\n    {\n      title: 'ts-rest',\n      url: 'https://ts-rest.com/',\n      description: 'Incrementally adoptable type-safety for your new and existing APIs',\n    },\n    {\n      title: 'wagmi',\n      url: 'https://wagmi.sh/',\n      description: 'React Hooks for Ethereum based on @tanstack/react-query',\n    },\n    {\n      title: 'zodios',\n      url: 'https://www.zodios.org/',\n      description: 'End-to-end typesafe REST API toolbox',\n    },\n  ]\n---\n"
  },
  {
    "path": "docs/config.json",
    "content": "{\n  \"$schema\": \"https://raw.githubusercontent.com/TanStack/tanstack.com/main/tanstack-docs-config.schema.json\",\n  \"docSearch\": {\n    \"appId\": \"20TOVD6LOE\",\n    \"apiKey\": \"35bc6c51aa322700d1383e17c4f669f4\",\n    \"indexName\": \"tanstackquery\"\n  },\n  \"sections\": [\n    {\n      \"label\": \"Community Resources\",\n      \"children\": [],\n      \"frameworks\": []\n    },\n    {\n      \"label\": \"Getting Started\",\n      \"children\": [],\n      \"frameworks\": [\n        {\n          \"label\": \"react\",\n          \"children\": [\n            {\n              \"label\": \"Overview\",\n              \"to\": \"framework/react/overview\"\n            },\n            {\n              \"label\": \"Installation\",\n              \"to\": \"framework/react/installation\"\n            },\n            {\n              \"label\": \"Quick Start\",\n              \"to\": \"framework/react/quick-start\"\n            },\n            {\n              \"label\": \"Devtools\",\n              \"to\": \"framework/react/devtools\"\n            },\n            {\n              \"label\": \"Comparison\",\n              \"to\": \"framework/react/comparison\"\n            },\n            {\n              \"label\": \"TypeScript\",\n              \"to\": \"framework/react/typescript\"\n            },\n            {\n              \"label\": \"GraphQL\",\n              \"to\": \"framework/react/graphql\"\n            },\n            {\n              \"label\": \"React Native\",\n              \"to\": \"framework/react/react-native\"\n            }\n          ]\n        },\n        {\n          \"label\": \"solid\",\n          \"children\": [\n            {\n              \"label\": \"Overview\",\n              \"to\": \"framework/solid/overview\"\n            },\n            {\n              \"label\": \"Quick Start\",\n              \"to\": \"framework/solid/quick-start\"\n            },\n            {\n              \"label\": \"Installation\",\n              \"to\": \"framework/solid/installation\"\n            },\n            {\n              \"label\": \"Devtools\",\n              \"to\": \"framework/solid/devtools\"\n            },\n            {\n              \"label\": \"TypeScript\",\n              \"to\": \"framework/solid/typescript\"\n            }\n          ]\n        },\n        {\n          \"label\": \"vue\",\n          \"children\": [\n            {\n              \"label\": \"Overview\",\n              \"to\": \"framework/vue/overview\"\n            },\n            {\n              \"label\": \"Installation\",\n              \"to\": \"framework/vue/installation\"\n            },\n            {\n              \"label\": \"Quick Start\",\n              \"to\": \"framework/vue/quick-start\"\n            },\n            {\n              \"label\": \"Devtools\",\n              \"to\": \"framework/vue/devtools\"\n            },\n            {\n              \"label\": \"TypeScript\",\n              \"to\": \"framework/vue/typescript\"\n            },\n            {\n              \"label\": \"Reactivity\",\n              \"to\": \"framework/vue/reactivity\"\n            },\n            {\n              \"label\": \"GraphQL\",\n              \"to\": \"framework/vue/graphql\"\n            }\n          ]\n        },\n        {\n          \"label\": \"svelte\",\n          \"children\": [\n            {\n              \"label\": \"Overview\",\n              \"to\": \"framework/svelte/overview\"\n            },\n            {\n              \"label\": \"Installation\",\n              \"to\": \"framework/svelte/installation\"\n            },\n            {\n              \"label\": \"Devtools\",\n              \"to\": \"framework/svelte/devtools\"\n            },\n            {\n              \"label\": \"SSR & SvelteKit\",\n              \"to\": \"framework/svelte/ssr\"\n            },\n            {\n              \"label\": \"Migrate from v5 to v6\",\n              \"to\": \"framework/svelte/migrate-from-v5-to-v6\"\n            }\n          ]\n        },\n        {\n          \"label\": \"angular\",\n          \"children\": [\n            {\n              \"label\": \"Overview\",\n              \"to\": \"framework/angular/overview\"\n            },\n            {\n              \"label\": \"Installation\",\n              \"to\": \"framework/angular/installation\"\n            },\n            {\n              \"label\": \"Quick Start\",\n              \"to\": \"framework/angular/quick-start\"\n            },\n            {\n              \"label\": \"Angular HttpClient and other data fetching clients\",\n              \"to\": \"framework/angular/angular-httpclient-and-other-data-fetching-clients\"\n            },\n            {\n              \"label\": \"Devtools\",\n              \"to\": \"framework/angular/devtools\"\n            },\n            {\n              \"label\": \"TypeScript\",\n              \"to\": \"framework/angular/typescript\"\n            },\n            {\n              \"label\": \"Zoneless\",\n              \"to\": \"framework/angular/zoneless\"\n            }\n          ]\n        },\n        {\n          \"label\": \"preact\",\n          \"children\": [\n            {\n              \"label\": \"Overview\",\n              \"to\": \"framework/preact/overview\"\n            },\n            {\n              \"label\": \"Installation\",\n              \"to\": \"framework/preact/installation\"\n            },\n            {\n              \"label\": \"Quick Start\",\n              \"to\": \"framework/preact/quick-start\"\n            },\n            {\n              \"label\": \"Devtools\",\n              \"to\": \"framework/preact/devtools\"\n            },\n            {\n              \"label\": \"TypeScript\",\n              \"to\": \"framework/preact/typescript\"\n            },\n            {\n              \"label\": \"GraphQL\",\n              \"to\": \"framework/preact/graphql\"\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"label\": \"Guides & Concepts\",\n      \"children\": [],\n      \"frameworks\": [\n        {\n          \"label\": \"react\",\n          \"children\": [\n            {\n              \"label\": \"Important Defaults\",\n              \"to\": \"framework/react/guides/important-defaults\"\n            },\n            {\n              \"label\": \"Queries\",\n              \"to\": \"framework/react/guides/queries\"\n            },\n            {\n              \"label\": \"Query Keys\",\n              \"to\": \"framework/react/guides/query-keys\"\n            },\n            {\n              \"label\": \"Query Functions\",\n              \"to\": \"framework/react/guides/query-functions\"\n            },\n            {\n              \"label\": \"Query Options\",\n              \"to\": \"framework/react/guides/query-options\"\n            },\n            {\n              \"label\": \"Network Mode\",\n              \"to\": \"framework/react/guides/network-mode\"\n            },\n            {\n              \"label\": \"Parallel Queries\",\n              \"to\": \"framework/react/guides/parallel-queries\"\n            },\n            {\n              \"label\": \"Dependent Queries\",\n              \"to\": \"framework/react/guides/dependent-queries\"\n            },\n            {\n              \"label\": \"Background Fetching Indicators\",\n              \"to\": \"framework/react/guides/background-fetching-indicators\"\n            },\n            {\n              \"label\": \"Window Focus Refetching\",\n              \"to\": \"framework/react/guides/window-focus-refetching\"\n            },\n            {\n              \"label\": \"Disabling/Pausing Queries\",\n              \"to\": \"framework/react/guides/disabling-queries\"\n            },\n            {\n              \"label\": \"Query Retries\",\n              \"to\": \"framework/react/guides/query-retries\"\n            },\n            {\n              \"label\": \"Paginated Queries\",\n              \"to\": \"framework/react/guides/paginated-queries\"\n            },\n            {\n              \"label\": \"Infinite Queries\",\n              \"to\": \"framework/react/guides/infinite-queries\"\n            },\n            {\n              \"label\": \"Initial Query Data\",\n              \"to\": \"framework/react/guides/initial-query-data\"\n            },\n            {\n              \"label\": \"Placeholder Query Data\",\n              \"to\": \"framework/react/guides/placeholder-query-data\"\n            },\n            {\n              \"label\": \"Mutations\",\n              \"to\": \"framework/react/guides/mutations\"\n            },\n            {\n              \"label\": \"Query Invalidation\",\n              \"to\": \"framework/react/guides/query-invalidation\"\n            },\n            {\n              \"label\": \"Invalidation from Mutations\",\n              \"to\": \"framework/react/guides/invalidations-from-mutations\"\n            },\n            {\n              \"label\": \"Updates from Mutation Responses\",\n              \"to\": \"framework/react/guides/updates-from-mutation-responses\"\n            },\n            {\n              \"label\": \"Optimistic Updates\",\n              \"to\": \"framework/react/guides/optimistic-updates\"\n            },\n            {\n              \"label\": \"Query Cancellation\",\n              \"to\": \"framework/react/guides/query-cancellation\"\n            },\n            {\n              \"label\": \"Scroll Restoration\",\n              \"to\": \"framework/react/guides/scroll-restoration\"\n            },\n            {\n              \"label\": \"Filters\",\n              \"to\": \"framework/react/guides/filters\"\n            },\n            {\n              \"label\": \"Performance & Request Waterfalls\",\n              \"to\": \"framework/react/guides/request-waterfalls\"\n            },\n            {\n              \"label\": \"Prefetching & Router Integration\",\n              \"to\": \"framework/react/guides/prefetching\"\n            },\n            {\n              \"label\": \"Server Rendering & Hydration\",\n              \"to\": \"framework/react/guides/ssr\"\n            },\n            {\n              \"label\": \"Advanced Server Rendering\",\n              \"to\": \"framework/react/guides/advanced-ssr\"\n            },\n            {\n              \"label\": \"Caching\",\n              \"to\": \"framework/react/guides/caching\"\n            },\n            {\n              \"label\": \"Render Optimizations\",\n              \"to\": \"framework/react/guides/render-optimizations\"\n            },\n            {\n              \"label\": \"Default Query Fn\",\n              \"to\": \"framework/react/guides/default-query-function\"\n            },\n            {\n              \"label\": \"Suspense\",\n              \"to\": \"framework/react/guides/suspense\"\n            },\n            {\n              \"label\": \"Testing\",\n              \"to\": \"framework/react/guides/testing\"\n            },\n            {\n              \"label\": \"Does this replace [Redux, MobX, etc]?\",\n              \"to\": \"framework/react/guides/does-this-replace-client-state\"\n            },\n            {\n              \"label\": \"Migrating to v3\",\n              \"to\": \"framework/react/guides/migrating-to-react-query-3\"\n            },\n            {\n              \"label\": \"Migrating to v4\",\n              \"to\": \"framework/react/guides/migrating-to-react-query-4\"\n            },\n            {\n              \"label\": \"Migrating to v5\",\n              \"to\": \"framework/react/guides/migrating-to-v5\"\n            }\n          ]\n        },\n        {\n          \"label\": \"solid\",\n          \"children\": [\n            {\n              \"label\": \"Important Defaults\",\n              \"to\": \"framework/solid/guides/important-defaults\"\n            },\n            {\n              \"label\": \"Queries\",\n              \"to\": \"framework/solid/guides/queries\"\n            },\n            {\n              \"label\": \"Query Keys\",\n              \"to\": \"framework/solid/guides/query-keys\"\n            },\n            {\n              \"label\": \"Query Functions\",\n              \"to\": \"framework/solid/guides/query-functions\"\n            },\n            {\n              \"label\": \"Query Options\",\n              \"to\": \"framework/solid/guides/query-options\"\n            },\n            {\n              \"label\": \"Network Mode\",\n              \"to\": \"framework/solid/guides/network-mode\"\n            },\n            {\n              \"label\": \"Parallel Queries\",\n              \"to\": \"framework/solid/guides/parallel-queries\"\n            },\n            {\n              \"label\": \"Dependent Queries\",\n              \"to\": \"framework/solid/guides/dependent-queries\"\n            },\n            {\n              \"label\": \"Background Fetching Indicators\",\n              \"to\": \"framework/solid/guides/background-fetching-indicators\"\n            },\n            {\n              \"label\": \"Window Focus Refetching\",\n              \"to\": \"framework/solid/guides/window-focus-refetching\"\n            },\n            {\n              \"label\": \"Disabling/Pausing Queries\",\n              \"to\": \"framework/solid/guides/disabling-queries\"\n            },\n            {\n              \"label\": \"Query Retries\",\n              \"to\": \"framework/solid/guides/query-retries\"\n            },\n            {\n              \"label\": \"Paginated Queries\",\n              \"to\": \"framework/solid/guides/paginated-queries\"\n            },\n            {\n              \"label\": \"Infinite Queries\",\n              \"to\": \"framework/solid/guides/infinite-queries\"\n            },\n            {\n              \"label\": \"Initial Query Data\",\n              \"to\": \"framework/solid/guides/initial-query-data\"\n            },\n            {\n              \"label\": \"Placeholder Query Data\",\n              \"to\": \"framework/solid/guides/placeholder-query-data\"\n            },\n            {\n              \"label\": \"Mutations\",\n              \"to\": \"framework/solid/guides/mutations\"\n            },\n            {\n              \"label\": \"Query Invalidation\",\n              \"to\": \"framework/solid/guides/query-invalidation\"\n            },\n            {\n              \"label\": \"Invalidation from Mutations\",\n              \"to\": \"framework/solid/guides/invalidations-from-mutations\"\n            },\n            {\n              \"label\": \"Updates from Mutation Responses\",\n              \"to\": \"framework/solid/guides/updates-from-mutation-responses\"\n            },\n            {\n              \"label\": \"Optimistic Updates\",\n              \"to\": \"framework/solid/guides/optimistic-updates\"\n            },\n            {\n              \"label\": \"Query Cancellation\",\n              \"to\": \"framework/solid/guides/query-cancellation\"\n            },\n            {\n              \"label\": \"Scroll Restoration\",\n              \"to\": \"framework/solid/guides/scroll-restoration\"\n            },\n            {\n              \"label\": \"Filters\",\n              \"to\": \"framework/solid/guides/filters\"\n            },\n            {\n              \"label\": \"Request Waterfalls\",\n              \"to\": \"framework/solid/guides/request-waterfalls\"\n            },\n            {\n              \"label\": \"Prefetching\",\n              \"to\": \"framework/solid/guides/prefetching\"\n            },\n            {\n              \"label\": \"SSR\",\n              \"to\": \"framework/solid/guides/ssr\"\n            },\n            {\n              \"label\": \"Advanced SSR\",\n              \"to\": \"framework/solid/guides/advanced-ssr\"\n            },\n            {\n              \"label\": \"Caching\",\n              \"to\": \"framework/solid/guides/caching\"\n            },\n            {\n              \"label\": \"Default Query Fn\",\n              \"to\": \"framework/solid/guides/default-query-function\"\n            },\n            {\n              \"label\": \"Suspense\",\n              \"to\": \"framework/solid/guides/suspense\"\n            },\n            {\n              \"label\": \"Testing\",\n              \"to\": \"framework/solid/guides/testing\"\n            },\n            {\n              \"label\": \"Does this replace state managers?\",\n              \"to\": \"framework/solid/guides/does-this-replace-client-state\"\n            }\n          ]\n        },\n        {\n          \"label\": \"vue\",\n          \"children\": [\n            {\n              \"label\": \"Important Defaults\",\n              \"to\": \"framework/vue/guides/important-defaults\"\n            },\n            {\n              \"label\": \"Queries\",\n              \"to\": \"framework/vue/guides/queries\"\n            },\n            {\n              \"label\": \"Query Keys\",\n              \"to\": \"framework/vue/guides/query-keys\"\n            },\n            {\n              \"label\": \"Query Functions\",\n              \"to\": \"framework/vue/guides/query-functions\"\n            },\n            {\n              \"label\": \"Query Options\",\n              \"to\": \"framework/vue/guides/query-options\"\n            },\n            {\n              \"label\": \"Network Mode\",\n              \"to\": \"framework/vue/guides/network-mode\"\n            },\n            {\n              \"label\": \"Parallel Queries\",\n              \"to\": \"framework/vue/guides/parallel-queries\"\n            },\n            {\n              \"label\": \"Dependent Queries\",\n              \"to\": \"framework/vue/guides/dependent-queries\"\n            },\n            {\n              \"label\": \"Background Fetching Indicators\",\n              \"to\": \"framework/vue/guides/background-fetching-indicators\"\n            },\n            {\n              \"label\": \"Window Focus Refetching\",\n              \"to\": \"framework/vue/guides/window-focus-refetching\"\n            },\n            {\n              \"label\": \"Disabling/Pausing Queries\",\n              \"to\": \"framework/vue/guides/disabling-queries\"\n            },\n            {\n              \"label\": \"Query Retries\",\n              \"to\": \"framework/vue/guides/query-retries\"\n            },\n            {\n              \"label\": \"Paginated Queries\",\n              \"to\": \"framework/vue/guides/paginated-queries\"\n            },\n            {\n              \"label\": \"Infinite Queries\",\n              \"to\": \"framework/vue/guides/infinite-queries\"\n            },\n            {\n              \"label\": \"Initial Query Data\",\n              \"to\": \"framework/vue/guides/initial-query-data\"\n            },\n            {\n              \"label\": \"Placeholder Query Data\",\n              \"to\": \"framework/vue/guides/placeholder-query-data\"\n            },\n            {\n              \"label\": \"Mutations\",\n              \"to\": \"framework/vue/guides/mutations\"\n            },\n            {\n              \"label\": \"Query Invalidation\",\n              \"to\": \"framework/vue/guides/query-invalidation\"\n            },\n            {\n              \"label\": \"Invalidation from Mutations\",\n              \"to\": \"framework/vue/guides/invalidations-from-mutations\"\n            },\n            {\n              \"label\": \"Updates from Mutation Responses\",\n              \"to\": \"framework/vue/guides/updates-from-mutation-responses\"\n            },\n            {\n              \"label\": \"Optimistic Updates\",\n              \"to\": \"framework/vue/guides/optimistic-updates\"\n            },\n            {\n              \"label\": \"Query Cancellation\",\n              \"to\": \"framework/vue/guides/query-cancellation\"\n            },\n            {\n              \"label\": \"Scroll Restoration\",\n              \"to\": \"framework/vue/guides/scroll-restoration\"\n            },\n            {\n              \"label\": \"Filters\",\n              \"to\": \"framework/vue/guides/filters\"\n            },\n            {\n              \"label\": \"Prefetching\",\n              \"to\": \"framework/vue/guides/prefetching\"\n            },\n            {\n              \"label\": \"SSR & Nuxt\",\n              \"to\": \"framework/vue/guides/ssr\"\n            },\n            {\n              \"label\": \"Caching\",\n              \"to\": \"framework/vue/guides/caching\"\n            },\n            {\n              \"label\": \"Default Query Fn\",\n              \"to\": \"framework/vue/guides/default-query-function\"\n            },\n            {\n              \"label\": \"Suspense\",\n              \"to\": \"framework/vue/guides/suspense\"\n            },\n            {\n              \"label\": \"Testing\",\n              \"to\": \"framework/vue/guides/testing\"\n            },\n            {\n              \"label\": \"Custom Client\",\n              \"to\": \"framework/vue/guides/custom-client\"\n            },\n            {\n              \"label\": \"Does this replace [Vuex, Pinia]?\",\n              \"to\": \"framework/vue/guides/does-this-replace-client-state\"\n            },\n            {\n              \"label\": \"Migrating to v5\",\n              \"to\": \"framework/vue/guides/migrating-to-v5\"\n            }\n          ]\n        },\n        {\n          \"label\": \"angular\",\n          \"children\": [\n            {\n              \"label\": \"Important Defaults\",\n              \"to\": \"framework/angular/guides/important-defaults\"\n            },\n            {\n              \"label\": \"Queries\",\n              \"to\": \"framework/angular/guides/queries\"\n            },\n            {\n              \"label\": \"Query Keys\",\n              \"to\": \"framework/angular/guides/query-keys\"\n            },\n            {\n              \"label\": \"Query Functions\",\n              \"to\": \"framework/angular/guides/query-functions\"\n            },\n            {\n              \"label\": \"Query Options\",\n              \"to\": \"framework/angular/guides/query-options\"\n            },\n            {\n              \"label\": \"Network Mode\",\n              \"to\": \"framework/angular/guides/network-mode\"\n            },\n            {\n              \"label\": \"Parallel Queries\",\n              \"to\": \"framework/angular/guides/parallel-queries\"\n            },\n            {\n              \"label\": \"Dependent Queries\",\n              \"to\": \"framework/angular/guides/dependent-queries\"\n            },\n            {\n              \"label\": \"Background Fetching Indicators\",\n              \"to\": \"framework/angular/guides/background-fetching-indicators\"\n            },\n            {\n              \"label\": \"Window Focus Refetching\",\n              \"to\": \"framework/angular/guides/window-focus-refetching\"\n            },\n            {\n              \"label\": \"Disabling/Pausing Queries\",\n              \"to\": \"framework/angular/guides/disabling-queries\"\n            },\n            {\n              \"label\": \"Query Retries\",\n              \"to\": \"framework/angular/guides/query-retries\"\n            },\n            {\n              \"label\": \"Paginated Queries\",\n              \"to\": \"framework/angular/guides/paginated-queries\"\n            },\n            {\n              \"label\": \"Infinite Queries\",\n              \"to\": \"framework/angular/guides/infinite-queries\"\n            },\n            {\n              \"label\": \"Initial Query Data\",\n              \"to\": \"framework/angular/guides/initial-query-data\"\n            },\n            {\n              \"label\": \"Placeholder Query Data\",\n              \"to\": \"framework/angular/guides/placeholder-query-data\"\n            },\n            {\n              \"label\": \"Mutations\",\n              \"to\": \"framework/angular/guides/mutations\"\n            },\n            {\n              \"label\": \"Mutation Options\",\n              \"to\": \"framework/angular/guides/mutation-options\"\n            },\n            {\n              \"label\": \"Query Invalidation\",\n              \"to\": \"framework/angular/guides/query-invalidation\"\n            },\n            {\n              \"label\": \"Invalidation from Mutations\",\n              \"to\": \"framework/angular/guides/invalidations-from-mutations\"\n            },\n            {\n              \"label\": \"Optimistic Updates\",\n              \"to\": \"framework/angular/guides/optimistic-updates\"\n            },\n            {\n              \"label\": \"Query Cancellation\",\n              \"to\": \"framework/angular/guides/query-cancellation\"\n            },\n            {\n              \"label\": \"Scroll Restoration\",\n              \"to\": \"framework/angular/guides/scroll-restoration\"\n            },\n            {\n              \"label\": \"Filters\",\n              \"to\": \"framework/angular/guides/filters\"\n            },\n            {\n              \"label\": \"Caching\",\n              \"to\": \"framework/angular/guides/caching\"\n            },\n            {\n              \"label\": \"Default Query Fn\",\n              \"to\": \"framework/angular/guides/default-query-function\"\n            },\n            {\n              \"label\": \"Testing\",\n              \"to\": \"framework/angular/guides/testing\"\n            },\n            {\n              \"label\": \"Does this replace state managers?\",\n              \"to\": \"framework/angular/guides/does-this-replace-client-state\"\n            }\n          ]\n        },\n        {\n          \"label\": \"preact\",\n          \"children\": [\n            {\n              \"label\": \"Important Defaults\",\n              \"to\": \"framework/preact/guides/important-defaults\"\n            },\n            {\n              \"label\": \"Queries\",\n              \"to\": \"framework/preact/guides/queries\"\n            },\n            {\n              \"label\": \"Query Keys\",\n              \"to\": \"framework/preact/guides/query-keys\"\n            },\n            {\n              \"label\": \"Query Functions\",\n              \"to\": \"framework/preact/guides/query-functions\"\n            },\n            {\n              \"label\": \"Query Options\",\n              \"to\": \"framework/preact/guides/query-options\"\n            },\n            {\n              \"label\": \"Network Mode\",\n              \"to\": \"framework/preact/guides/network-mode\"\n            },\n            {\n              \"label\": \"Parallel Queries\",\n              \"to\": \"framework/preact/guides/parallel-queries\"\n            },\n            {\n              \"label\": \"Dependent Queries\",\n              \"to\": \"framework/preact/guides/dependent-queries\"\n            },\n            {\n              \"label\": \"Background Fetching Indicators\",\n              \"to\": \"framework/preact/guides/background-fetching-indicators\"\n            },\n            {\n              \"label\": \"Window Focus Refetching\",\n              \"to\": \"framework/preact/guides/window-focus-refetching\"\n            },\n            {\n              \"label\": \"Disabling/Pausing Queries\",\n              \"to\": \"framework/preact/guides/disabling-queries\"\n            },\n            {\n              \"label\": \"Query Retries\",\n              \"to\": \"framework/preact/guides/query-retries\"\n            },\n            {\n              \"label\": \"Paginated Queries\",\n              \"to\": \"framework/preact/guides/paginated-queries\"\n            },\n            {\n              \"label\": \"Infinite Queries\",\n              \"to\": \"framework/preact/guides/infinite-queries\"\n            },\n            {\n              \"label\": \"Initial Query Data\",\n              \"to\": \"framework/preact/guides/initial-query-data\"\n            },\n            {\n              \"label\": \"Placeholder Query Data\",\n              \"to\": \"framework/preact/guides/placeholder-query-data\"\n            },\n            {\n              \"label\": \"Mutations\",\n              \"to\": \"framework/preact/guides/mutations\"\n            },\n            {\n              \"label\": \"Query Invalidation\",\n              \"to\": \"framework/preact/guides/query-invalidation\"\n            },\n            {\n              \"label\": \"Invalidation from Mutations\",\n              \"to\": \"framework/preact/guides/invalidations-from-mutations\"\n            },\n            {\n              \"label\": \"Updates from Mutation Responses\",\n              \"to\": \"framework/preact/guides/updates-from-mutation-responses\"\n            },\n            {\n              \"label\": \"Optimistic Updates\",\n              \"to\": \"framework/preact/guides/optimistic-updates\"\n            },\n            {\n              \"label\": \"Query Cancellation\",\n              \"to\": \"framework/preact/guides/query-cancellation\"\n            },\n            {\n              \"label\": \"Scroll Restoration\",\n              \"to\": \"framework/preact/guides/scroll-restoration\"\n            },\n            {\n              \"label\": \"Filters\",\n              \"to\": \"framework/preact/guides/filters\"\n            },\n            {\n              \"label\": \"Performance & Request Waterfalls\",\n              \"to\": \"framework/preact/guides/request-waterfalls\"\n            },\n            {\n              \"label\": \"Prefetching & Router Integration\",\n              \"to\": \"framework/preact/guides/prefetching\"\n            },\n            {\n              \"label\": \"Caching\",\n              \"to\": \"framework/preact/guides/caching\"\n            },\n            {\n              \"label\": \"Render Optimizations\",\n              \"to\": \"framework/preact/guides/render-optimizations\"\n            },\n            {\n              \"label\": \"Default Query Fn\",\n              \"to\": \"framework/preact/guides/default-query-function\"\n            },\n            {\n              \"label\": \"Does this replace [Redux, MobX, etc]?\",\n              \"to\": \"framework/preact/guides/does-this-replace-client-state\"\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"label\": \"API Reference\",\n      \"children\": [\n        {\n          \"label\": \"QueryClient\",\n          \"to\": \"reference/QueryClient\"\n        },\n        {\n          \"label\": \"QueryCache\",\n          \"to\": \"reference/QueryCache\"\n        },\n        {\n          \"label\": \"MutationCache\",\n          \"to\": \"reference/MutationCache\"\n        },\n        {\n          \"label\": \"QueryObserver\",\n          \"to\": \"reference/QueryObserver\"\n        },\n        {\n          \"label\": \"InfiniteQueryObserver\",\n          \"to\": \"reference/InfiniteQueryObserver\"\n        },\n        {\n          \"label\": \"QueriesObserver\",\n          \"to\": \"reference/QueriesObserver\"\n        },\n        {\n          \"label\": \"streamedQuery\",\n          \"to\": \"reference/streamedQuery\"\n        },\n        {\n          \"label\": \"focusManager\",\n          \"to\": \"reference/focusManager\"\n        },\n        {\n          \"label\": \"onlineManager\",\n          \"to\": \"reference/onlineManager\"\n        },\n        {\n          \"label\": \"environmentManager\",\n          \"to\": \"reference/environmentManager\"\n        },\n        {\n          \"label\": \"notifyManager\",\n          \"to\": \"reference/notifyManager\"\n        },\n        {\n          \"label\": \"timeoutManager\",\n          \"to\": \"reference/timeoutManager\"\n        }\n      ],\n      \"frameworks\": [\n        {\n          \"label\": \"react\",\n          \"children\": [\n            {\n              \"label\": \"useQuery\",\n              \"to\": \"framework/react/reference/useQuery\"\n            },\n            {\n              \"label\": \"useQueries\",\n              \"to\": \"framework/react/reference/useQueries\"\n            },\n            {\n              \"label\": \"useInfiniteQuery\",\n              \"to\": \"framework/react/reference/useInfiniteQuery\"\n            },\n            {\n              \"label\": \"useMutation\",\n              \"to\": \"framework/react/reference/useMutation\"\n            },\n            {\n              \"label\": \"useIsFetching\",\n              \"to\": \"framework/react/reference/useIsFetching\"\n            },\n            {\n              \"label\": \"useIsMutating\",\n              \"to\": \"framework/react/reference/useIsMutating\"\n            },\n            {\n              \"label\": \"useMutationState\",\n              \"to\": \"framework/react/reference/useMutationState\"\n            },\n            {\n              \"label\": \"useSuspenseQuery\",\n              \"to\": \"framework/react/reference/useSuspenseQuery\"\n            },\n            {\n              \"label\": \"useSuspenseInfiniteQuery\",\n              \"to\": \"framework/react/reference/useSuspenseInfiniteQuery\"\n            },\n            {\n              \"label\": \"useSuspenseQueries\",\n              \"to\": \"framework/react/reference/useSuspenseQueries\"\n            },\n            {\n              \"label\": \"QueryClientProvider\",\n              \"to\": \"framework/react/reference/QueryClientProvider\"\n            },\n            {\n              \"label\": \"useQueryClient\",\n              \"to\": \"framework/react/reference/useQueryClient\"\n            },\n            {\n              \"label\": \"queryOptions\",\n              \"to\": \"framework/react/reference/queryOptions\"\n            },\n            {\n              \"label\": \"infiniteQueryOptions\",\n              \"to\": \"framework/react/reference/infiniteQueryOptions\"\n            },\n            {\n              \"label\": \"mutationOptions\",\n              \"to\": \"framework/react/reference/mutationOptions\"\n            },\n            {\n              \"label\": \"usePrefetchQuery\",\n              \"to\": \"framework/react/reference/usePrefetchQuery\"\n            },\n            {\n              \"label\": \"usePrefetchInfiniteQuery\",\n              \"to\": \"framework/react/reference/usePrefetchInfiniteQuery\"\n            },\n            {\n              \"label\": \"QueryErrorResetBoundary\",\n              \"to\": \"framework/react/reference/QueryErrorResetBoundary\"\n            },\n            {\n              \"label\": \"useQueryErrorResetBoundary\",\n              \"to\": \"framework/react/reference/useQueryErrorResetBoundary\"\n            },\n            {\n              \"label\": \"hydration\",\n              \"to\": \"framework/react/reference/hydration\"\n            }\n          ]\n        },\n        {\n          \"label\": \"vue\",\n          \"children\": [\n            {\n              \"label\": \"useQuery\",\n              \"to\": \"framework/vue/reference/useQuery\"\n            },\n            {\n              \"label\": \"useQueries\",\n              \"to\": \"framework/vue/reference/useQueries\"\n            },\n            {\n              \"label\": \"useInfiniteQuery\",\n              \"to\": \"framework/vue/reference/useInfiniteQuery\"\n            },\n            {\n              \"label\": \"useMutation\",\n              \"to\": \"framework/vue/reference/useMutation\"\n            },\n            {\n              \"label\": \"useIsFetching\",\n              \"to\": \"framework/vue/reference/useIsFetching\"\n            },\n            {\n              \"label\": \"useIsMutating\",\n              \"to\": \"framework/vue/reference/useIsMutating\"\n            },\n            {\n              \"label\": \"useMutationState\",\n              \"to\": \"framework/vue/reference/useMutationState\"\n            },\n            {\n              \"label\": \"useQueryClient\",\n              \"to\": \"framework/vue/reference/useQueryClient\"\n            },\n            {\n              \"label\": \"queryOptions\",\n              \"to\": \"framework/vue/reference/queryOptions\"\n            },\n            {\n              \"label\": \"infiniteQueryOptions\",\n              \"to\": \"framework/vue/reference/infiniteQueryOptions\"\n            },\n            {\n              \"label\": \"hydration\",\n              \"to\": \"framework/vue/reference/hydration\"\n            }\n          ]\n        },\n        {\n          \"label\": \"solid\",\n          \"children\": [\n            {\n              \"label\": \"useQuery\",\n              \"to\": \"framework/solid/reference/useQuery\"\n            },\n            {\n              \"label\": \"useQueries\",\n              \"to\": \"framework/solid/reference/useQueries\"\n            },\n            {\n              \"label\": \"useInfiniteQuery\",\n              \"to\": \"framework/solid/reference/useInfiniteQuery\"\n            },\n            {\n              \"label\": \"useMutation\",\n              \"to\": \"framework/solid/reference/useMutation\"\n            },\n            {\n              \"label\": \"useIsFetching\",\n              \"to\": \"framework/solid/reference/useIsFetching\"\n            },\n            {\n              \"label\": \"useIsMutating\",\n              \"to\": \"framework/solid/reference/useIsMutating\"\n            },\n            {\n              \"label\": \"useMutationState\",\n              \"to\": \"framework/solid/reference/useMutationState\"\n            },\n            {\n              \"label\": \"queryOptions\",\n              \"to\": \"framework/solid/reference/queryOptions\"\n            },\n            {\n              \"label\": \"infiniteQueryOptions\",\n              \"to\": \"framework/solid/reference/infiniteQueryOptions\"\n            },\n            {\n              \"label\": \"hydration\",\n              \"to\": \"framework/solid/reference/hydration\"\n            }\n          ]\n        },\n        {\n          \"label\": \"svelte\",\n          \"children\": [\n            {\n              \"label\": \"Svelte Reference\",\n              \"to\": \"framework/svelte/reference/index\"\n            },\n            {\n              \"label\": \"Functions / createQuery\",\n              \"to\": \"framework/svelte/reference/functions/createQuery\"\n            },\n            {\n              \"label\": \"Functions / createQueries\",\n              \"to\": \"framework/svelte/reference/functions/createQueries\"\n            },\n            {\n              \"label\": \"Functions / createInfiniteQuery\",\n              \"to\": \"framework/svelte/reference/functions/createInfiniteQuery\"\n            },\n            {\n              \"label\": \"Functions / createMutation\",\n              \"to\": \"framework/svelte/reference/functions/createMutation\"\n            },\n            {\n              \"label\": \"Functions / useIsFetching\",\n              \"to\": \"framework/svelte/reference/functions/useIsFetching\"\n            },\n            {\n              \"label\": \"Functions / useIsMutating\",\n              \"to\": \"framework/svelte/reference/functions/useIsMutating\"\n            },\n            {\n              \"label\": \"Functions / useMutationState\",\n              \"to\": \"framework/svelte/reference/functions/useMutationState\"\n            },\n            {\n              \"label\": \"Functions / queryOptions\",\n              \"to\": \"framework/svelte/reference/functions/queryOptions\"\n            },\n            {\n              \"label\": \"Functions / infiniteQueryOptions\",\n              \"to\": \"framework/svelte/reference/functions/infiniteQueryOptions\"\n            },\n            {\n              \"label\": \"Functions / mutationOptions\",\n              \"to\": \"framework/svelte/reference/functions/mutationOptions\"\n            }\n          ]\n        },\n        {\n          \"label\": \"angular\",\n          \"children\": [\n            {\n              \"label\": \"Angular Reference\",\n              \"to\": \"framework/angular/reference/index\"\n            },\n            {\n              \"label\": \"Functions / injectQuery\",\n              \"to\": \"framework/angular/reference/functions/injectQuery\"\n            },\n            {\n              \"label\": \"Functions / injectMutation\",\n              \"to\": \"framework/angular/reference/functions/injectMutation\"\n            }\n          ]\n        },\n        {\n          \"label\": \"preact\",\n          \"children\": [\n            {\n              \"label\": \"useQuery\",\n              \"to\": \"framework/preact/reference/functions/useQuery\"\n            },\n            {\n              \"label\": \"useQueries\",\n              \"to\": \"framework/preact/reference/functions/useQueries\"\n            },\n            {\n              \"label\": \"useInfiniteQuery\",\n              \"to\": \"framework/preact/reference/functions/useInfiniteQuery\"\n            },\n            {\n              \"label\": \"useMutation\",\n              \"to\": \"framework/preact/reference/functions/useMutation\"\n            },\n            {\n              \"label\": \"useIsFetching\",\n              \"to\": \"framework/preact/reference/functions/useIsFetching\"\n            },\n            {\n              \"label\": \"useIsMutating\",\n              \"to\": \"framework/preact/reference/functions/useIsMutating\"\n            },\n            {\n              \"label\": \"useMutationState\",\n              \"to\": \"framework/preact/reference/functions/useMutationState\"\n            },\n            {\n              \"label\": \"useSuspenseQuery\",\n              \"to\": \"framework/preact/reference/functions/useSuspenseQuery\"\n            },\n            {\n              \"label\": \"useSuspenseInfiniteQuery\",\n              \"to\": \"framework/preact/reference/functions/useSuspenseInfiniteQuery\"\n            },\n            {\n              \"label\": \"useSuspenseQueries\",\n              \"to\": \"framework/preact/reference/functions/useSuspenseQueries\"\n            },\n            {\n              \"label\": \"QueryClientProvider\",\n              \"to\": \"framework/preact/reference/functions/QueryClientProvider\"\n            },\n            {\n              \"label\": \"useQueryClient\",\n              \"to\": \"framework/preact/reference/functions/useQueryClient\"\n            },\n            {\n              \"label\": \"queryOptions\",\n              \"to\": \"framework/preact/reference/functions/queryOptions\"\n            },\n            {\n              \"label\": \"infiniteQueryOptions\",\n              \"to\": \"framework/preact/reference/functions/infiniteQueryOptions\"\n            },\n            {\n              \"label\": \"mutationOptions\",\n              \"to\": \"framework/preact/reference/functions/mutationOptions\"\n            },\n            {\n              \"label\": \"usePrefetchQuery\",\n              \"to\": \"framework/preact/reference/functions/usePrefetchQuery\"\n            },\n            {\n              \"label\": \"usePrefetchInfiniteQuery\",\n              \"to\": \"framework/preact/reference/functions/usePrefetchInfiniteQuery\"\n            },\n            {\n              \"label\": \"QueryErrorResetBoundary\",\n              \"to\": \"framework/preact/reference/functions/QueryErrorResetBoundary\"\n            },\n            {\n              \"label\": \"useQueryErrorResetBoundary\",\n              \"to\": \"framework/preact/reference/functions/useQueryErrorResetBoundary\"\n            },\n            {\n              \"label\": \"hydration\",\n              \"to\": \"framework/preact/reference/functions/HydrationBoundary\"\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"label\": \"ESLint\",\n      \"children\": [\n        {\n          \"label\": \"ESLint Plugin Query\",\n          \"to\": \"eslint/eslint-plugin-query\"\n        },\n        {\n          \"label\": \"Exhaustive Deps\",\n          \"to\": \"eslint/exhaustive-deps\"\n        },\n        {\n          \"label\": \"Stable Query Client\",\n          \"to\": \"eslint/stable-query-client\"\n        },\n        {\n          \"label\": \"No Rest Destructuring\",\n          \"to\": \"eslint/no-rest-destructuring\"\n        },\n        {\n          \"label\": \"No Unstable Deps\",\n          \"to\": \"eslint/no-unstable-deps\"\n        },\n        {\n          \"label\": \"Infinite Query Property Order\",\n          \"to\": \"eslint/infinite-query-property-order\"\n        },\n        {\n          \"label\": \"No void Query Functions\",\n          \"to\": \"eslint/no-void-query-fn\"\n        },\n        {\n          \"label\": \"Mutation Property Order\",\n          \"to\": \"eslint/mutation-property-order\"\n        }\n      ]\n    },\n    {\n      \"label\": \"Examples\",\n      \"children\": [],\n      \"frameworks\": [\n        {\n          \"label\": \"react\",\n          \"children\": [\n            {\n              \"label\": \"Simple\",\n              \"to\": \"framework/react/examples/simple\"\n            },\n            {\n              \"label\": \"Basic\",\n              \"to\": \"framework/react/examples/basic\"\n            },\n            {\n              \"label\": \"Basic w/ GraphQL-Request\",\n              \"to\": \"framework/react/examples/basic-graphql-request\"\n            },\n            {\n              \"label\": \"Auto Refetching / Polling / Realtime\",\n              \"to\": \"framework/react/examples/auto-refetching\"\n            },\n            {\n              \"label\": \"Optimistic Updates (UI)\",\n              \"to\": \"framework/react/examples/optimistic-updates-ui\"\n            },\n            {\n              \"label\": \"Optimistic Updates (Cache)\",\n              \"to\": \"framework/react/examples/optimistic-updates-cache\"\n            },\n            {\n              \"label\": \"Pagination\",\n              \"to\": \"framework/react/examples/pagination\"\n            },\n            {\n              \"label\": \"Load-More & Infinite Scroll\",\n              \"to\": \"framework/react/examples/load-more-infinite-scroll\"\n            },\n            {\n              \"label\": \"Infinite query with Max pages\",\n              \"to\": \"framework/react/examples/infinite-query-with-max-pages\"\n            },\n            {\n              \"label\": \"Suspense\",\n              \"to\": \"framework/react/examples/suspense\"\n            },\n            {\n              \"label\": \"Default Query Function\",\n              \"to\": \"framework/react/examples/default-query-function\"\n            },\n            {\n              \"label\": \"Playground\",\n              \"to\": \"framework/react/examples/playground\"\n            },\n            {\n              \"label\": \"Prefetching\",\n              \"to\": \"framework/react/examples/prefetching\"\n            },\n            {\n              \"label\": \"Star Wars\",\n              \"to\": \"framework/react/examples/star-wars\"\n            },\n            {\n              \"label\": \"Rick And Morty\",\n              \"to\": \"framework/react/examples/rick-morty\"\n            },\n            {\n              \"label\": \"Next.js Pages\",\n              \"to\": \"framework/react/examples/nextjs\"\n            },\n            {\n              \"label\": \"Next.js app with prefetching\",\n              \"to\": \"framework/react/examples/nextjs-app-prefetching\"\n            },\n            {\n              \"label\": \"Next.js app with streaming\",\n              \"to\": \"framework/react/examples/nextjs-suspense-streaming\"\n            },\n            {\n              \"label\": \"React Native\",\n              \"to\": \"framework/react/examples/react-native\"\n            },\n            {\n              \"label\": \"React Router\",\n              \"to\": \"framework/react/examples/react-router\"\n            },\n            {\n              \"label\": \"Offline Queries and Mutations\",\n              \"to\": \"framework/react/examples/offline\"\n            },\n            {\n              \"label\": \"Algolia\",\n              \"to\": \"framework/react/examples/algolia\"\n            },\n            {\n              \"label\": \"Shadow DOM\",\n              \"to\": \"framework/react/examples/shadow-dom\"\n            },\n            {\n              \"label\": \"Devtools Embedded Panel\",\n              \"to\": \"framework/react/examples/devtools-panel\"\n            },\n            {\n              \"label\": \"Chat example (streaming)\",\n              \"to\": \"framework/react/examples/chat\"\n            }\n          ]\n        },\n        {\n          \"label\": \"solid\",\n          \"children\": [\n            {\n              \"label\": \"Simple\",\n              \"to\": \"framework/solid/examples/simple\"\n            },\n            {\n              \"label\": \"Basic\",\n              \"to\": \"framework/solid/examples/basic\"\n            },\n            {\n              \"label\": \"Basic w/ GraphQL-Request\",\n              \"to\": \"framework/solid/examples/basic-graphql-request\"\n            },\n            {\n              \"label\": \"Default Query Function\",\n              \"to\": \"framework/solid/examples/default-query-function\"\n            },\n            {\n              \"label\": \"Solid Start\",\n              \"to\": \"framework/solid/examples/solid-start-streaming\"\n            },\n            {\n              \"label\": \"Astro\",\n              \"to\": \"framework/solid/examples/astro\"\n            },\n            {\n              \"label\": \"Offline Queries and Mutations\",\n              \"to\": \"framework/solid/examples/offline\"\n            }\n          ]\n        },\n        {\n          \"label\": \"vue\",\n          \"children\": [\n            {\n              \"label\": \"Basic\",\n              \"to\": \"framework/vue/examples/basic\"\n            },\n            {\n              \"label\": \"Vue 2.6\",\n              \"to\": \"framework/vue/examples/2.6-basic\"\n            },\n            {\n              \"label\": \"Vue 2.7\",\n              \"to\": \"framework/vue/examples/2.7-basic\"\n            },\n            {\n              \"label\": \"Nuxt 3\",\n              \"to\": \"framework/vue/examples/nuxt3\"\n            },\n            {\n              \"label\": \"Persister\",\n              \"to\": \"framework/vue/examples/persister\"\n            }\n          ]\n        },\n        {\n          \"label\": \"svelte\",\n          \"children\": [\n            {\n              \"label\": \"Simple\",\n              \"to\": \"framework/svelte/examples/simple\"\n            },\n            {\n              \"label\": \"Basic\",\n              \"to\": \"framework/svelte/examples/basic\"\n            },\n            {\n              \"label\": \"Auto Refetching / Polling / Realtime\",\n              \"to\": \"framework/svelte/examples/auto-refetching\"\n            },\n            {\n              \"label\": \"SSR\",\n              \"to\": \"framework/svelte/examples/ssr\"\n            },\n            {\n              \"label\": \"Optimistic Updates\",\n              \"to\": \"framework/svelte/examples/optimistic-updates\"\n            },\n            {\n              \"label\": \"Playground\",\n              \"to\": \"framework/svelte/examples/playground\"\n            },\n            {\n              \"label\": \"Star Wars\",\n              \"to\": \"framework/svelte/examples/star-wars\"\n            },\n            {\n              \"label\": \"Infinite Queries\",\n              \"to\": \"framework/svelte/examples/load-more-infinite-scroll\"\n            }\n          ]\n        },\n        {\n          \"label\": \"angular\",\n          \"children\": [\n            {\n              \"label\": \"Simple\",\n              \"to\": \"framework/angular/examples/simple\"\n            },\n            {\n              \"label\": \"Basic\",\n              \"to\": \"framework/angular/examples/basic\"\n            },\n            {\n              \"label\": \"Auto Refetching / Polling / Realtime\",\n              \"to\": \"framework/angular/examples/auto-refetching\"\n            },\n            {\n              \"label\": \"Optimistic Updates\",\n              \"to\": \"framework/angular/examples/optimistic-updates\"\n            },\n            {\n              \"label\": \"Pagination\",\n              \"to\": \"framework/angular/examples/pagination\"\n            },\n            {\n              \"label\": \"Infinite query with maxPages\",\n              \"to\": \"framework/angular/examples/infinite-query-with-max-pages\"\n            },\n            {\n              \"label\": \"Angular Router\",\n              \"to\": \"framework/angular/examples/router\"\n            },\n            {\n              \"label\": \"RxJS autocomplete\",\n              \"to\": \"framework/angular/examples/rxjs\"\n            },\n            {\n              \"label\": \"Query options from a service\",\n              \"to\": \"framework/angular/examples/query-options-from-a-service\"\n            },\n            {\n              \"label\": \"Devtools embedded panel\",\n              \"to\": \"framework/angular/examples/devtools-panel\"\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"label\": \"Plugins\",\n      \"children\": [],\n      \"frameworks\": [\n        {\n          \"label\": \"react\",\n          \"children\": [\n            {\n              \"label\": \"persistQueryClient\",\n              \"to\": \"framework/react/plugins/persistQueryClient\"\n            },\n            {\n              \"label\": \"createSyncStoragePersister\",\n              \"to\": \"framework/react/plugins/createSyncStoragePersister\"\n            },\n            {\n              \"label\": \"createAsyncStoragePersister\",\n              \"to\": \"framework/react/plugins/createAsyncStoragePersister\"\n            },\n            {\n              \"label\": \"broadcastQueryClient (Experimental)\",\n              \"to\": \"framework/react/plugins/broadcastQueryClient\"\n            },\n            {\n              \"label\": \"createPersister (Experimental)\",\n              \"to\": \"framework/react/plugins/createPersister\"\n            }\n          ]\n        },\n        {\n          \"label\": \"solid\",\n          \"children\": [\n            {\n              \"label\": \"broadcastQueryClient (Experimental)\",\n              \"to\": \"framework/solid/plugins/broadcastQueryClient\"\n            },\n            {\n              \"label\": \"createPersister (Experimental)\",\n              \"to\": \"framework/solid/plugins/createPersister\"\n            }\n          ]\n        },\n        {\n          \"label\": \"vue\",\n          \"children\": [\n            {\n              \"label\": \"broadcastQueryClient (Experimental)\",\n              \"to\": \"framework/vue/plugins/broadcastQueryClient\"\n            },\n            {\n              \"label\": \"createPersister (Experimental)\",\n              \"to\": \"framework/vue/plugins/createPersister\"\n            }\n          ]\n        },\n        {\n          \"label\": \"preact\",\n          \"children\": [\n            {\n              \"label\": \"persistQueryClient\",\n              \"to\": \"framework/preact/plugins/persistQueryClient\"\n            },\n            {\n              \"label\": \"createSyncStoragePersister\",\n              \"to\": \"framework/preact/plugins/createSyncStoragePersister\"\n            },\n            {\n              \"label\": \"createAsyncStoragePersister\",\n              \"to\": \"framework/preact/plugins/createAsyncStoragePersister\"\n            },\n            {\n              \"label\": \"broadcastQueryClient (Experimental)\",\n              \"to\": \"framework/preact/plugins/broadcastQueryClient\"\n            },\n            {\n              \"label\": \"createPersister (Experimental)\",\n              \"to\": \"framework/preact/plugins/createPersister\"\n            }\n          ]\n        }\n      ]\n    }\n  ],\n  \"users\": [\n    \"Google\",\n    \"Walmart\",\n    \"Facebook\",\n    \"PayPal\",\n    \"Amazon\",\n    \"American Express\",\n    \"Microsoft\",\n    \"Target\",\n    \"Ebay\",\n    \"Autodesk\",\n    \"CarFAX\",\n    \"Docusign\",\n    \"HP\",\n    \"MLB\",\n    \"Volvo\",\n    \"Ocado\",\n    \"UPC.ch\",\n    \"EFI.com\",\n    \"ReactBricks\",\n    \"Nozzle.io\",\n    \"Uber\"\n  ]\n}\n"
  },
  {
    "path": "docs/eslint/eslint-plugin-query.md",
    "content": "---\nid: eslint-plugin-query\ntitle: ESLint Plugin Query\n---\n\nTanStack Query comes with its own ESLint plugin. This plugin is used to enforce best practices and to help you avoid common mistakes.\n\n## Installation\n\nThe plugin is a separate package that you need to install:\n\n```bash\nnpm i -D @tanstack/eslint-plugin-query\n```\n\nor\n\n```bash\npnpm add -D @tanstack/eslint-plugin-query\n```\n\nor\n\n```bash\nyarn add -D @tanstack/eslint-plugin-query\n```\n\nor\n\n```bash\nbun add -D @tanstack/eslint-plugin-query\n```\n\n## Flat Config (`eslint.config.js`)\n\n### Recommended setup\n\nTo enable all of the recommended rules for our plugin, add the following config:\n\n```js\nimport pluginQuery from '@tanstack/eslint-plugin-query'\n\nexport default [\n  ...pluginQuery.configs['flat/recommended'],\n  // Any other config...\n]\n```\n\n### Custom setup\n\nAlternatively, you can load the plugin and configure only the rules you want to use:\n\n```js\nimport pluginQuery from '@tanstack/eslint-plugin-query'\n\nexport default [\n  {\n    plugins: {\n      '@tanstack/query': pluginQuery,\n    },\n    rules: {\n      '@tanstack/query/exhaustive-deps': 'error',\n    },\n  },\n  // Any other config...\n]\n```\n\n## Legacy Config (`.eslintrc`)\n\n### Recommended setup\n\nTo enable all of the recommended rules for our plugin, add `plugin:@tanstack/query/recommended` in extends:\n\n```json\n{\n  \"extends\": [\"plugin:@tanstack/query/recommended\"]\n}\n```\n\n### Custom setup\n\nAlternatively, add `@tanstack/query` to the plugins section, and configure the rules you want to use:\n\n```json\n{\n  \"plugins\": [\"@tanstack/query\"],\n  \"rules\": {\n    \"@tanstack/query/exhaustive-deps\": \"error\"\n  }\n}\n```\n\n## Rules\n\n- [@tanstack/query/exhaustive-deps](./exhaustive-deps.md)\n- [@tanstack/query/no-rest-destructuring](./no-rest-destructuring.md)\n- [@tanstack/query/stable-query-client](./stable-query-client.md)\n- [@tanstack/query/no-unstable-deps](./no-unstable-deps.md)\n- [@tanstack/query/infinite-query-property-order](./infinite-query-property-order.md)\n- [@tanstack/query/no-void-query-fn](./no-void-query-fn.md)\n- [@tanstack/query/mutation-property-order](./mutation-property-order.md)\n"
  },
  {
    "path": "docs/eslint/exhaustive-deps.md",
    "content": "---\nid: exhaustive-deps\ntitle: Exhaustive dependencies for query keys\n---\n\nQuery keys should be seen like a dependency array to your query function: Every variable that is used inside the queryFn should be added to the query key.\nThis makes sure that queries are cached independently and that queries are refetched automatically when the variables changes.\n\n## Rule Details\n\nExamples of **incorrect** code for this rule:\n\n```tsx\n/* eslint \"@tanstack/query/exhaustive-deps\": \"error\" */\n\nuseQuery({\n  queryKey: ['todo'],\n  queryFn: () => api.getTodo(todoId),\n})\n\nconst todoQueries = {\n  detail: (id) => ({ queryKey: ['todo'], queryFn: () => api.getTodo(id) }),\n}\n```\n\nExamples of **correct** code for this rule:\n\n```tsx\nuseQuery({\n  queryKey: ['todo', todoId],\n  queryFn: () => api.getTodo(todoId),\n})\n\nconst todoQueries = {\n  detail: (id) => ({ queryKey: ['todo', id], queryFn: () => api.getTodo(id) }),\n}\n```\n\n## When Not To Use It\n\nIf you don't care about the rules of the query keys, then you will not need this rule.\n\n## Attributes\n\n- [x] ✅ Recommended\n- [x] 🔧 Fixable\n"
  },
  {
    "path": "docs/eslint/infinite-query-property-order.md",
    "content": "---\nid: infinite-query-property-order\ntitle: Ensure correct order of inference sensitive properties for infinite queries\n---\n\nFor the following functions, the property order of the passed in object matters due to type inference:\n\n- `useInfiniteQuery`\n- `useSuspenseInfiniteQuery`\n- `infiniteQueryOptions`\n\nThe correct property order is as follows:\n\n- `queryFn`\n- `getPreviousPageParam`\n- `getNextPageParam`\n\nAll other properties are insensitive to the order as they do not depend on type inference.\n\n## Rule Details\n\nExamples of **incorrect** code for this rule:\n\n```tsx\n/* eslint \"@tanstack/query/infinite-query-property-order\": \"warn\" */\nimport { useInfiniteQuery } from '@tanstack/react-query'\n\nconst query = useInfiniteQuery({\n  queryKey: ['projects'],\n  getNextPageParam: (lastPage) => lastPage.nextId ?? undefined,\n  queryFn: async ({ pageParam }) => {\n    const response = await fetch(`/api/projects?cursor=${pageParam}`)\n    return await response.json()\n  },\n  initialPageParam: 0,\n  getPreviousPageParam: (firstPage) => firstPage.previousId ?? undefined,\n  maxPages: 3,\n})\n```\n\nExamples of **correct** code for this rule:\n\n```tsx\n/* eslint \"@tanstack/query/infinite-query-property-order\": \"warn\" */\nimport { useInfiniteQuery } from '@tanstack/react-query'\n\nconst query = useInfiniteQuery({\n  queryKey: ['projects'],\n  queryFn: async ({ pageParam }) => {\n    const response = await fetch(`/api/projects?cursor=${pageParam}`)\n    return await response.json()\n  },\n  initialPageParam: 0,\n  getPreviousPageParam: (firstPage) => firstPage.previousId ?? undefined,\n  getNextPageParam: (lastPage) => lastPage.nextId ?? undefined,\n  maxPages: 3,\n})\n```\n\n## Attributes\n\n- [x] ✅ Recommended\n- [x] 🔧 Fixable\n"
  },
  {
    "path": "docs/eslint/mutation-property-order.md",
    "content": "---\nid: mutation-property-order\ntitle: Ensure correct order of inference-sensitive properties in useMutation()\n---\n\nFor the following functions, the property order of the passed in object matters due to type inference:\n\n- `useMutation()`\n\nThe correct property order is as follows:\n\n- `onMutate`\n- `onError`\n- `onSettled`\n\nAll other properties are insensitive to the order as they do not depend on type inference.\n\n## Rule Details\n\nExamples of **incorrect** code for this rule:\n\n```tsx\n/* eslint \"@tanstack/query/mutation-property-order\": \"warn\" */\nimport { useMutation } from '@tanstack/react-query'\n\nconst mutation = useMutation({\n  mutationFn: () => Promise.resolve('success'),\n  onSettled: () => {\n    results.push('onSettled-promise')\n    return Promise.resolve('also-ignored') // Promise<string> (should be ignored)\n  },\n  onMutate: async () => {\n    results.push('onMutate-async')\n    await sleep(1)\n    return { backup: 'async-data' }\n  },\n  onError: async () => {\n    results.push('onError-async-start')\n    await sleep(1)\n    results.push('onError-async-end')\n  },\n})\n```\n\nExamples of **correct** code for this rule:\n\n```tsx\n/* eslint \"@tanstack/query/mutation-property-order\": \"warn\" */\nimport { useMutation } from '@tanstack/react-query'\n\nconst mutation = useMutation({\n  mutationFn: () => Promise.resolve('success'),\n  onMutate: async () => {\n    results.push('onMutate-async')\n    await sleep(1)\n    return { backup: 'async-data' }\n  },\n  onError: async () => {\n    results.push('onError-async-start')\n    await sleep(1)\n    results.push('onError-async-end')\n  },\n  onSettled: () => {\n    results.push('onSettled-promise')\n    return Promise.resolve('also-ignored') // Promise<string> (should be ignored)\n  },\n})\n```\n\n## Attributes\n\n- [x] ✅ Recommended\n- [x] 🔧 Fixable\n"
  },
  {
    "path": "docs/eslint/no-rest-destructuring.md",
    "content": "---\nid: no-rest-destructuring\ntitle: Disallow object rest destructuring on query results\n---\n\nUse object rest destructuring on query results automatically subscribes to every field of the query result, which may cause unnecessary re-renders.\nThis makes sure that you only subscribe to the fields that you actually need.\n\n## Rule Details\n\nExamples of **incorrect** code for this rule:\n\n```tsx\n/* eslint \"@tanstack/query/no-rest-destructuring\": \"warn\" */\n\nconst useTodos = () => {\n  const { data: todos, ...rest } = useQuery({\n    queryKey: ['todos'],\n    queryFn: () => api.getTodos(),\n  })\n  return { todos, ...rest }\n}\n```\n\nExamples of **correct** code for this rule:\n\n```tsx\nconst todosQuery = useQuery({\n  queryKey: ['todos'],\n  queryFn: () => api.getTodos(),\n})\n\n// normal object destructuring is fine\nconst { data: todos } = todosQuery\n```\n\n## When Not To Use It\n\nIf you set the `notifyOnChangeProps` options manually, you can disable this rule.\nSince you are not using tracked queries, you are responsible for specifying which props should trigger a re-render.\n\n## Attributes\n\n- [x] ✅ Recommended\n- [ ] 🔧 Fixable\n"
  },
  {
    "path": "docs/eslint/no-unstable-deps.md",
    "content": "---\nid: no-unstable-deps\ntitle: Disallow putting the result of query hooks directly in a React hook dependency array\n---\n\nThe object returned from the following query hooks is **not** referentially stable:\n\n- `useQuery`\n- `useSuspenseQuery`\n- `useQueries`\n- `useSuspenseQueries`\n- `useInfiniteQuery`\n- `useSuspenseInfiniteQuery`\n- `useMutation`\n\nThe object returned from those hooks should **not** be put directly into the dependency array of a React hook (e.g. `useEffect`, `useMemo`, `useCallback`).\nInstead, destructure the return value of the query hook and pass the destructured values into the dependency array of the React hook.\n\n## Rule Details\n\nExamples of **incorrect** code for this rule:\n\n```tsx\n/* eslint \"@tanstack/query/no-unstable-deps\": \"warn\" */\nimport { useCallback } from 'React'\nimport { useMutation } from '@tanstack/react-query'\n\nfunction Component() {\n  const mutation = useMutation({ mutationFn: (value: string) => value })\n  const callback = useCallback(() => {\n    mutation.mutate('hello')\n  }, [mutation])\n  return null\n}\n```\n\nExamples of **correct** code for this rule:\n\n```tsx\n/* eslint \"@tanstack/query/no-unstable-deps\": \"warn\" */\nimport { useCallback } from 'React'\nimport { useMutation } from '@tanstack/react-query'\n\nfunction Component() {\n  const { mutate } = useMutation({ mutationFn: (value: string) => value })\n  const callback = useCallback(() => {\n    mutate('hello')\n  }, [mutate])\n  return null\n}\n```\n\n## Attributes\n\n- [x] ✅ Recommended\n- [ ] 🔧 Fixable\n"
  },
  {
    "path": "docs/eslint/no-void-query-fn.md",
    "content": "---\nid: no-void-query-fn\ntitle: Disallow returning void from query functions\n---\n\nQuery functions must return a value that will be cached by TanStack Query. Functions that don't return a value (void functions) can lead to unexpected behavior and might indicate a mistake in the implementation.\n\n## Rule Details\n\nExample of **incorrect** code for this rule:\n\n```tsx\n/* eslint \"@tanstack/query/no-void-query-fn\": \"error\" */\n\nuseQuery({\n  queryKey: ['todos'],\n  queryFn: async () => {\n    await api.todos.fetch() // Function doesn't return the fetched data\n  },\n})\n```\n\nExample of **correct** code for this rule:\n\n```tsx\n/* eslint \"@tanstack/query/no-void-query-fn\": \"error\" */\nuseQuery({\n  queryKey: ['todos'],\n  queryFn: async () => {\n    const todos = await api.todos.fetch()\n    return todos\n  },\n})\n```\n\n## Attributes\n\n- [x] ✅ Recommended\n- [ ] 🔧 Fixable\n"
  },
  {
    "path": "docs/eslint/stable-query-client.md",
    "content": "---\nid: stable-query-client\ntitle: Stable Query Client\n---\n\nThe QueryClient contains the QueryCache, so you'd only want to create one instance of the QueryClient for the lifecycle of your application - _not_ a new instance on every render.\n\n> Exception: It's allowed to create a new QueryClient inside an async Server Component, because the async function is only called once on the server.\n\n## Rule Details\n\nExamples of **incorrect** code for this rule:\n\n```tsx\n/* eslint \"@tanstack/query/stable-query-client\": \"error\" */\n\nfunction App() {\n  const queryClient = new QueryClient()\n  return (\n    <QueryClientProvider client={queryClient}>\n      <Home />\n    </QueryClientProvider>\n  )\n}\n```\n\nExamples of **correct** code for this rule:\n\n```tsx\nfunction App() {\n  const [queryClient] = useState(() => new QueryClient())\n  return (\n    <QueryClientProvider client={queryClient}>\n      <Home />\n    </QueryClientProvider>\n  )\n}\n```\n\n```tsx\nconst queryClient = new QueryClient()\nfunction App() {\n  return (\n    <QueryClientProvider client={queryClient}>\n      <Home />\n    </QueryClientProvider>\n  )\n}\n```\n\n```tsx\nasync function App() {\n  const queryClient = new QueryClient()\n  await queryClient.prefetchQuery(options)\n}\n```\n\n## Attributes\n\n- [x] ✅ Recommended\n- [x] 🔧 Fixable\n"
  },
  {
    "path": "docs/framework/angular/angular-httpclient-and-other-data-fetching-clients.md",
    "content": "---\nid: Angular-HttpClient-and-other-data-fetching-clients\ntitle: Angular HttpClient and other data fetching clients\n---\n\nBecause TanStack Query's fetching mechanisms are agnostically built on Promises, you can use literally any asynchronous data fetching client, including the browser native `fetch` API, `graphql-request`, and more.\n\n## Using Angular's `HttpClient` for data fetching\n\n`HttpClient` is a powerful and integrated part of Angular, which gives the following benefits:\n\n- Mock responses in unit tests using [provideHttpClientTesting](https://angular.dev/guide/http/testing).\n- [Interceptors](https://angular.dev/guide/http/interceptors) can be used for a wide range of functionality including adding authentication headers, performing logging, etc. While some data fetching libraries have their own interceptor system, `HttpClient` interceptors are integrated with Angular's dependency injection system.\n- `HttpClient` automatically informs [`PendingTasks`](https://angular.dev/api/core/PendingTasks#), which enables Angular to be aware of pending requests. Unit tests and SSR can use the resulting application _stableness_ information to wait for pending requests to finish. This makes unit testing much easier for [Zoneless](https://angular.dev/guide/zoneless) applications.\n- When using SSR, `HttpClient` will [cache requests](https://angular.dev/guide/ssr#caching-data-when-using-HttpClient) performed on the server. This will prevent unneeded requests on the client. `HttpClient` SSR caching works out of the box. TanStack Query has its own hydration functionality which may be more powerful but requires some setup. Which one fits your needs best depends on your use case.\n\n### Using observables in `queryFn`\n\nAs TanStack Query is a promise based library, observables from `HttpClient` need to be converted to promises. This can be done with the `lastValueFrom` or `firstValueFrom` functions from `rxjs`.\n\n```ts\n@Component({\n  // ...\n})\nclass ExampleComponent {\n  private readonly http = inject(HttpClient)\n\n  readonly query = injectQuery(() => ({\n    queryKey: ['repoData'],\n    queryFn: () =>\n      lastValueFrom(\n        this.http.get('https://api.github.com/repos/tanstack/query'),\n      ),\n  }))\n}\n```\n\n> Since Angular is moving towards RxJS as an optional dependency, it's expected that `HttpClient` will also support promises in the future.\n>\n> Support for observables in TanStack Query for Angular is planned.\n\n## Comparison table\n\n| Data fetching client                                | Pros                                                | Cons                                                                       |\n| --------------------------------------------------- | --------------------------------------------------- | -------------------------------------------------------------------------- |\n| **Angular HttpClient**                              | Featureful and very well integrated with Angular.   | Observables need to be converted to Promises.                              |\n| **Fetch**                                           | Browser native API, so adds nothing to bundle size. | Barebones API which lacks many features.                                   |\n| **Specialized libraries such as `graphql-request`** | Specialized features for specific use cases.        | If it's not an Angular library it won't integrate well with the framework. |\n"
  },
  {
    "path": "docs/framework/angular/devtools.md",
    "content": "---\nid: devtools\ntitle: Devtools\n---\n\n> For Chrome, Firefox, and Edge users: Third-party browser extensions are available for debugging TanStack Query directly in browser DevTools. These provide the same functionality as the framework-specific devtools packages:\n>\n> - <img alt=\"Chrome logo\" src=\"https://www.google.com/chrome/static/images/chrome-logo.svg\" width=\"16\" height=\"16\" class=\"inline mr-1 not-prose\" /> [Devtools for Chrome](https://chromewebstore.google.com/detail/tanstack-query-devtools/annajfchloimdhceglpgglpeepfghfai)\n> - <img alt=\"Firefox logo\" src=\"https://upload.wikimedia.org/wikipedia/commons/a/a0/Firefox_logo%2C_2019.svg\" width=\"16\" height=\"16\" class=\"inline mr-1 not-prose\" /> [Devtools for Firefox](https://addons.mozilla.org/en-US/firefox/addon/tanstack-query-devtools/)\n> - <img alt=\"Edge logo\" src=\"https://upload.wikimedia.org/wikipedia/commons/9/98/Microsoft_Edge_logo_%282019%29.svg\" width=\"16\" height=\"16\" class=\"inline mr-1 not-prose\" /> [Devtools for Edge](https://microsoftedge.microsoft.com/addons/detail/tanstack-query-devtools/edmdpkgkacmjopodhfolmphdenmddobj)\n\n## Enable devtools\n\nThe devtools help you debug and inspect your queries and mutations. You can enable the devtools by adding `withDevtools` to `provideTanStackQuery`.\n\nBy 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.\n\n```ts\nimport {\n  QueryClient,\n  provideTanStackQuery,\n} from '@tanstack/angular-query-experimental'\n\nimport { withDevtools } from '@tanstack/angular-query-experimental/devtools'\n\nexport const appConfig: ApplicationConfig = {\n  providers: [provideTanStackQuery(new QueryClient(), withDevtools())],\n}\n```\n\n## Devtools in production\n\nDevtools are automatically excluded from production builds. However, it might be desirable to lazy load the devtools in production.\n\nTo 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.\n\n```ts\nimport { withDevtools } from '@tanstack/angular-query-experimental/devtools/production'\n```\n\nTo control when devtools are loaded, you can use the `loadDevtools` option.\n\nWhen not setting the option or setting it to 'auto', the devtools will be loaded automatically only when Angular runs in development mode.\n\n```ts\nimport { withDevtools } from '@tanstack/angular-query-experimental/devtools'\n\nprovideTanStackQuery(new QueryClient(), withDevtools())\n\n// which is equivalent to\nprovideTanStackQuery(\n  new QueryClient(),\n  withDevtools(() => ({ loadDevtools: 'auto' })),\n)\n```\n\nWhen setting the option to true, the devtools will be loaded in both development and production mode.\n\nThis is useful if you want to load devtools based on [Angular environment configurations](https://angular.dev/tools/cli/environments). E.g. you could set this to true when the application is running on your production build staging environment.\n\n```ts\nimport { environment } from './environments/environment'\n// Make sure to use the production sub-path to load devtools in production builds\nimport { withDevtools } from '@tanstack/angular-query-experimental/devtools/production'\n\nprovideTanStackQuery(\n  new QueryClient(),\n  withDevtools(() => ({ loadDevtools: environment.loadDevtools })),\n)\n```\n\nWhen setting the option to false, the devtools will not be loaded.\n\n```ts\nprovideTanStackQuery(\n  new QueryClient(),\n  withDevtools(() => ({ loadDevtools: false })),\n)\n```\n\n## Derive options through reactivity\n\nOptions are passed to `withDevtools` from a callback function to support reactivity through signals. In the following example\na 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.\n\nThe example below always loads devtools in development mode and loads on-demand in production mode when a keyboard shortcut is pressed.\n\n```ts\nimport { Injectable, isDevMode } from '@angular/core'\nimport { fromEvent, map, scan } from 'rxjs'\nimport { toSignal } from '@angular/core/rxjs-interop'\n\n@Injectable({ providedIn: 'root' })\nexport class DevtoolsOptionsManager {\n  loadDevtools = toSignal(\n    fromEvent<KeyboardEvent>(document, 'keydown').pipe(\n      map(\n        (event): boolean =>\n          event.metaKey && event.ctrlKey && event.shiftKey && event.key === 'D',\n      ),\n      scan((acc, curr) => acc || curr, isDevMode()),\n    ),\n    {\n      initialValue: isDevMode(),\n    },\n  )\n}\n```\n\nIf 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.\n\nThis is similar to `deps` in Angular's [`useFactory`](https://angular.dev/guide/di/dependency-injection-providers#factory-providers-usefactory) provider.\n\n```ts\n// ...\n// 👇 Note we import from the production sub-path to enable devtools lazy loading in production builds\nimport { withDevtools } from '@tanstack/angular-query-experimental/devtools/production'\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideHttpClient(),\n    provideTanStackQuery(\n      new QueryClient(),\n      withDevtools(\n        (devToolsOptionsManager: DevtoolsOptionsManager) => ({\n          loadDevtools: devToolsOptionsManager.loadDevtools(),\n        }),\n        {\n          // `deps` is used to inject and pass `DevtoolsOptionsManager` to the `withDevtools` callback.\n          deps: [DevtoolsOptionsManager],\n        },\n      ),\n    ),\n  ],\n}\n```\n\n### Options returned from the callback\n\nOf these options `loadDevtools`, `client`, `position`, `errorTypes`, `buttonPosition`, and `initialIsOpen` support reactivity through signals.\n\n- `loadDevtools?: 'auto' | boolean`\n  - Defaults to `auto`: lazily loads devtools when in development mode. Skips loading in production mode.\n  - Use this to control if the devtools are loaded.\n- `initialIsOpen?: Boolean`\n  - Set this to `true` if you want the tools to default to being open\n- `buttonPosition?: \"top-left\" | \"top-right\" | \"bottom-left\" | \"bottom-right\" | \"relative\"`\n  - Defaults to `bottom-right`\n  - The position of the TanStack logo to open and close the devtools panel\n  - If `relative`, the button is placed in the location that you render the devtools.\n- `position?: \"top\" | \"bottom\" | \"left\" | \"right\"`\n  - Defaults to `bottom`\n  - The position of the Angular Query devtools panel\n- `client?: QueryClient`,\n  - Use this to use a custom QueryClient. Otherwise, the QueryClient provided through `provideTanStackQuery` will be injected.\n- `errorTypes?: { name: string; initializer: (query: Query) => TError}[]`\n  - Use this to predefine some errors that can be triggered on your queries. Initializer will be called (with the specific query) when that error is toggled on from the UI. It must return an Error.\n- `styleNonce?: string`\n  - 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.\n- `shadowDOMTarget?: ShadowRoot`\n  - Default behavior will apply the devtool's styles to the head tag within the DOM.\n  - Use this to pass a shadow DOM target to the devtools so that the styles will be applied within the shadow DOM instead of within the head tag in the light DOM.\n- `hideDisabledQueries?: boolean`\n  - Set this to true to hide disabled queries from the devtools panel.\n"
  },
  {
    "path": "docs/framework/angular/guides/background-fetching-indicators.md",
    "content": "---\nid: background-fetching-indicators\ntitle: Background Fetching Indicators\nref: docs/framework/react/guides/background-fetching-indicators.md\nreplace:\n  {\n    'useIsFetching': 'injectIsFetching',\n    'hook': 'function',\n    '@tanstack/react-query': '@tanstack/angular-query-experimental',\n  }\n---\n\n[//]: # 'Example'\n\n```angular-ts\n@Component({\n  selector: 'todos',\n  template: `\n    @if (todosQuery.isPending()) {\n      Loading...\n    } @else if (todosQuery.isError()) {\n      An error has occurred: {{ todosQuery.error().message }}\n    } @else if (todosQuery.isSuccess()) {\n      @if (todosQuery.isFetching()) {\n        Refreshing...\n      }\n      @for (todos of todosQuery.data(); track todo.id) {\n        <todo [todo]=\"todo\" />\n      }\n    }\n  `,\n})\nclass TodosComponent {\n  todosQuery = injectQuery(() => ({\n    queryKey: ['todos'],\n    queryFn: fetchTodos,\n  }))\n}\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```angular-ts\nimport { injectIsFetching } from '@tanstack/angular-query-experimental'\n\n@Component({\n  selector: 'global-loading-indicator',\n  template: `\n    @if (isFetching()) {\n      <div>Queries are fetching in the background...</div>\n    }\n  `,\n})\nexport class GlobalLoadingIndicatorComponent {\n  isFetching = injectIsFetching()\n}\n```\n\n[//]: # 'Example2'\n"
  },
  {
    "path": "docs/framework/angular/guides/caching.md",
    "content": "---\nid: caching\ntitle: Caching Examples\n---\n\n> Please thoroughly read the [Important Defaults](./important-defaults.md) before reading this guide\n\n## Basic Example\n\nThis caching example illustrates the story and lifecycle of:\n\n- Query Instances with and without cache data\n- Background Refetching\n- Inactive Queries\n- Garbage Collection\n\nLet's assume we are using the default `gcTime` of **5 minutes** and the default `staleTime` of `0`.\n\n- A new instance of `injectQuery(() => ({ queryKey: ['todos'], queryFn: fetchTodos }))` initializes.\n  - Since no other queries have been made with the `['todos']` query key, this query will show a hard loading state and make a network request to fetch the data.\n  - When the network request has completed, the returned data will be cached under the `['todos']` key.\n  - The data will be marked as stale after the configured `staleTime` (defaults to `0`, or immediately).\n- A second instance of `injectQuery(() => ({ queryKey: ['todos'], queryFn: fetchTodos }))` initializes elsewhere.\n  - Since the cache already has data for the `['todos']` key from the first query, that data is immediately returned from the cache.\n  - The new instance triggers a new network request using its query function.\n    - Note that regardless of whether both `fetchTodos` query functions are identical or not, both queries' [`status`](../reference/functions/injectQuery.md) are updated (including `isFetching`, `isPending`, and other related values) because they have the same query key.\n  - When the request completes successfully, the cache's data under the `['todos']` key is updated with the new data, and both instances are updated with the new data.\n- Both instances of the `injectQuery(() => ({ queryKey: ['todos'], queryFn: fetchTodos }))` query are destroyed and no longer in use.\n  - Since there are no more active instances of this query, a garbage collection timeout is set using `gcTime` to delete and garbage collect the query (defaults to **5 minutes**).\n- Before the cache timeout has completed, another instance of `injectQuery(() => ({ queryKey: ['todos'], queryFn: fetchTodos }))` mounts. The query immediately returns the available cached data while the `fetchTodos` function is being run in the background. When it completes successfully, it will populate the cache with fresh data.\n- The final instance of `injectQuery(() => ({ queryKey: ['todos'], queryFn: fetchTodos }))` gets destroyed.\n- No more instances of `injectQuery(() => ({ queryKey: ['todos'], queryFn: fetchTodos }))` appear within **5 minutes**.\n  - The cached data under the `['todos']` key is deleted and garbage collected.\n\nFor more advanced use-cases, see [injectQuery](../reference/functions/injectQuery.md).\n"
  },
  {
    "path": "docs/framework/angular/guides/default-query-function.md",
    "content": "---\nid: default-query-function\ntitle: Default Query Function\nref: docs/framework/react/guides/default-query-function.md\n---\n\n[//]: # 'Example'\n\n```ts\n// Define a default query function that will receive the query key\nconst defaultQueryFn: QueryFunction = async ({ queryKey }) => {\n  const { data } = await axios.get(\n    `https://jsonplaceholder.typicode.com${queryKey[0]}`,\n  )\n  return data\n}\n\n// provide the default query function to your app with defaultOptions\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      queryFn: defaultQueryFn,\n    },\n  },\n})\n\nbootstrapApplication(MyAppComponent, {\n  providers: [provideTanStackQuery(queryClient)],\n})\n\nexport class PostsComponent {\n  // All you have to do now is pass a key!\n  postsQuery = injectQuery<Array<Post>>(() => ({\n    queryKey: ['/posts'],\n  }))\n  // ...\n}\n\nexport class PostComponent {\n  // You can even leave out the queryFn and just go straight into options\n  postQuery = injectQuery<Post>(() => ({\n    enabled: this.postIdSignal() > 0,\n    queryKey: [`/posts/${this.postIdSignal()}`],\n  }))\n  // ...\n}\n```\n\n[//]: # 'Example'\n"
  },
  {
    "path": "docs/framework/angular/guides/dependent-queries.md",
    "content": "---\nid: dependent-queries\ntitle: Dependent Queries\nref: docs/framework/react/guides/dependent-queries.md\nreplace: { 'useQuery': 'injectQuery', 'useQueries': 'injectQueries' }\n---\n\n[//]: # 'Example'\n\n```ts\n// Get the user\nuserQuery = injectQuery(() => ({\n  queryKey: ['user', email],\n  queryFn: getUserByEmail,\n}))\n\n// Then get the user's projects\nprojectsQuery = injectQuery(() => ({\n  queryKey: ['projects', this.userQuery.data()?.id],\n  queryFn: getProjectsByUser,\n  // The query will not execute until the user id exists\n  enabled: !!this.userQuery.data()?.id,\n}))\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```ts\n// injectQueries is under development for Angular Query\n```\n\n[//]: # 'Example2'\n"
  },
  {
    "path": "docs/framework/angular/guides/disabling-queries.md",
    "content": "---\nid: disabling-queries\ntitle: Disabling/Pausing Queries\nref: docs/framework/react/guides/disabling-queries.md\nreplace: { 'useQuery': 'injectQuery' }\n---\n\n[//]: # 'Example'\n\n```angular-ts\n@Component({\n  selector: 'todos',\n  template: `<div>\n    <button (click)=\"query.refetch()\">Fetch Todos</button>\n\n    @if (query.data()) {\n      <ul>\n        @for (todo of query.data(); track todo.id) {\n          <li>{{ todo.title }}</li>\n        }\n      </ul>\n    } @else {\n      @if (query.isError()) {\n        <span>Error: {{ query.error().message }}</span>\n      } @else if (query.isLoading()) {\n        <span>Loading...</span>\n      } @else if (!query.isLoading() && !query.isError()) {\n        <span>Not ready ...</span>\n      }\n    }\n\n    <div>{{ query.isLoading() ? 'Fetching...' : '' }}</div>\n  </div>`,\n})\nexport class TodosComponent {\n  query = injectQuery(() => ({\n    queryKey: ['todos'],\n    queryFn: fetchTodoList,\n    enabled: false,\n  }))\n}\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```angular-ts\n@Component({\n  selector: 'todos',\n  template: `\n    <div>\n      // 🚀 applying the filter will enable and execute the query\n      <filters-form onApply=\"filter.set\" />\n      <todos-table data=\"query.data()\" />\n    </div>\n  `,\n})\nexport class TodosComponent {\n  filter = signal('')\n\n  todosQuery = injectQuery(() => ({\n    queryKey: ['todos', this.filter()],\n    queryFn: () => fetchTodos(this.filter()),\n    enabled: !!this.filter(),\n  }))\n}\n```\n\n[//]: # 'Example2'\n[//]: # 'Example3'\n\n```angular-ts\nimport { skipToken, injectQuery } from '@tanstack/query-angular'\n\n@Component({\n  selector: 'todos',\n  template: `\n    <div>\n      // 🚀 applying the filter will enable and execute the query\n      <filters-form onApply=\"filter.set\" />\n      <todos-table data=\"query.data()\" />\n    </div>\n  `,\n})\nexport class TodosComponent {\n  filter = signal('')\n\n  todosQuery = injectQuery(() => ({\n    queryKey: ['todos', this.filter()],\n    queryFn: this.filter() ? () => fetchTodos(this.filter()) : skipToken,\n  }))\n}\n```\n\n[//]: # 'Example3'\n"
  },
  {
    "path": "docs/framework/angular/guides/does-this-replace-client-state.md",
    "content": "---\nid: does-this-replace-client-state\ntitle: Does TanStack Query replace global state managers?\nref: docs/framework/react/guides/does-this-replace-client-state.md\nreplace:\n  {\n    'useQuery': 'injectQuery',\n    'useMutation': 'injectMutation',\n    'hook': 'function',\n  }\n---\n"
  },
  {
    "path": "docs/framework/angular/guides/filters.md",
    "content": "---\nid: filters\ntitle: Filters\nref: docs/framework/react/guides/filters.md\n---\n"
  },
  {
    "path": "docs/framework/angular/guides/important-defaults.md",
    "content": "---\nid: important-defaults\ntitle: Important Defaults\nref: docs/framework/react/guides/important-defaults.md\nreplace:\n  {\n    'React': 'Angular',\n    'react-query': 'angular-query',\n    'useQuery': 'injectQuery',\n    'useInfiniteQuery': 'injectInfiniteQuery',\n    'useMemo and useCallback': 'setting signal values',\n  }\n---\n\n[//]: # 'Materials'\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/angular/guides/infinite-queries.md",
    "content": "---\nid: infinite-queries\ntitle: Infinite Queries\nref: docs/framework/react/guides/infinite-queries.md\nreplace:\n  { 'useQuery': 'injectQuery', 'useInfiniteQuery': 'injectInfiniteQuery' }\n---\n\n[//]: # 'Example'\n\n```angular-ts\nimport { Component, computed, inject } from '@angular/core'\nimport { injectInfiniteQuery } from '@tanstack/angular-query-experimental'\nimport { lastValueFrom } from 'rxjs'\nimport { ProjectsService } from './projects-service'\n\n@Component({\n  selector: 'example',\n  templateUrl: './example.component.html',\n})\nexport class Example {\n  projectsService = inject(ProjectsService)\n\n  query = injectInfiniteQuery(() => ({\n    queryKey: ['projects'],\n    queryFn: async ({ pageParam }) => {\n      return lastValueFrom(this.projectsService.getProjects(pageParam))\n    },\n    initialPageParam: 0,\n    getPreviousPageParam: (firstPage) => firstPage.previousId ?? undefined,\n    getNextPageParam: (lastPage) => lastPage.nextId ?? undefined,\n    maxPages: 3,\n  }))\n\n  nextButtonDisabled = computed(\n    () => !this.#hasNextPage() || this.#isFetchingNextPage(),\n  )\n  nextButtonText = computed(() =>\n    this.#isFetchingNextPage()\n      ? 'Loading more...'\n      : this.#hasNextPage()\n        ? 'Load newer'\n        : 'Nothing more to load',\n  )\n\n  #hasNextPage = this.query.hasNextPage\n  #isFetchingNextPage = this.query.isFetchingNextPage\n}\n```\n\n```angular-html\n<div>\n  @if (query.isPending()) {\n    <p>Loading...</p>\n  } @else if (query.isError()) {\n    <span>Error: {{ query?.error().message }}</span>\n  } @else {\n    @for (page of query?.data().pages; track $index) {\n      @for (project of page.data; track project.id) {\n        <p>{{ project.name }} {{ project.id }}</p>\n      }\n    }\n    <div>\n      <button (click)=\"query.fetchNextPage()\" [disabled]=\"nextButtonDisabled()\">\n        {{ nextButtonText() }}\n      </button>\n    </div>\n  }\n</div>\n```\n\n[//]: # 'Example'\n[//]: # 'Example1'\n\n```angular-ts\n@Component({\n  template: ` <list-component (endReached)=\"fetchNextPage()\" /> `,\n})\nexport class Example {\n  query = injectInfiniteQuery(() => ({\n    queryKey: ['projects'],\n    queryFn: async ({ pageParam }) => {\n      return lastValueFrom(this.projectsService.getProjects(pageParam))\n    },\n  }))\n\n  fetchNextPage() {\n    // Do nothing if already fetching\n    if (this.query.isFetching()) return\n    this.query.fetchNextPage()\n  }\n}\n```\n\n[//]: # 'Example1'\n[//]: # 'Example3'\n\n```ts\nquery = injectInfiniteQuery(() => ({\n  queryKey: ['projects'],\n  queryFn: fetchProjects,\n  getNextPageParam: (lastPage, pages) => lastPage.nextCursor,\n  getPreviousPageParam: (firstPage, pages) => firstPage.prevCursor,\n}))\n```\n\n[//]: # 'Example3'\n[//]: # 'Example4'\n\n```ts\nquery = injectInfiniteQuery(() => ({\n  queryKey: ['projects'],\n  queryFn: fetchProjects,\n  select: (data) => ({\n    pages: [...data.pages].reverse(),\n    pageParams: [...data.pageParams].reverse(),\n  }),\n}))\n```\n\n[//]: # 'Example4'\n[//]: # 'Example8'\n\n```ts\ninjectInfiniteQuery(() => ({\n  queryKey: ['projects'],\n  queryFn: fetchProjects,\n  initialPageParam: 0,\n  getNextPageParam: (lastPage, pages) => lastPage.nextCursor,\n  getPreviousPageParam: (firstPage, pages) => firstPage.prevCursor,\n  maxPages: 3,\n}))\n```\n\n[//]: # 'Example8'\n[//]: # 'Example9'\n\n```ts\ninjectInfiniteQuery(() => ({\n  queryKey: ['projects'],\n  queryFn: fetchProjects,\n  initialPageParam: 0,\n  getNextPageParam: (lastPage, allPages, lastPageParam) => {\n    if (lastPage.length === 0) {\n      return undefined\n    }\n    return lastPageParam + 1\n  },\n  getPreviousPageParam: (firstPage, allPages, firstPageParam) => {\n    if (firstPageParam <= 1) {\n      return undefined\n    }\n    return firstPageParam - 1\n  },\n}))\n```\n\n[//]: # 'Example9'\n"
  },
  {
    "path": "docs/framework/angular/guides/initial-query-data.md",
    "content": "---\nid: initial-query-data\ntitle: Initial Query Data\nref: docs/framework/react/guides/initial-query-data.md\nreplace:\n  {\n    'render': 'service or component instance',\n    ' when it mounts': '',\n    'after mount': 'after initialization',\n    'on mount': 'on initialization',\n  }\n---\n\n[//]: # 'Example'\n\n```ts\nresult = injectQuery(() => ({\n  queryKey: ['todos'],\n  queryFn: () => fetch('/todos'),\n  initialData: initialTodos,\n}))\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```ts\n// Will show initialTodos immediately, but also immediately refetch todos\n// when an instance of the component or service is created\nresult = injectQuery(() => ({\n  queryKey: ['todos'],\n  queryFn: () => fetch('/todos'),\n  initialData: initialTodos,\n}))\n```\n\n[//]: # 'Example2'\n[//]: # 'Example3'\n\n```ts\n// Show initialTodos immediately, but won't refetch until\n// another interaction event is encountered after 1000 ms\nresult = injectQuery(() => ({\n  queryKey: ['todos'],\n  queryFn: () => fetch('/todos'),\n  initialData: initialTodos,\n  staleTime: 1000,\n}))\n```\n\n[//]: # 'Example3'\n[//]: # 'Example4'\n\n```ts\n// Show initialTodos immediately, but won't refetch until\n// another interaction event is encountered after 1000 ms\nresult = injectQuery(() => ({\n  queryKey: ['todos'],\n  queryFn: () => fetch('/todos'),\n  initialData: initialTodos,\n  staleTime: 60 * 1000, // 1 minute\n  // This could be 10 seconds ago or 10 minutes ago\n  initialDataUpdatedAt: initialTodosUpdatedTimestamp, // eg. 1608412420052\n}))\n```\n\n[//]: # 'Example4'\n[//]: # 'Example5'\n\n```ts\nresult = injectQuery(() => ({\n  queryKey: ['todos'],\n  queryFn: () => fetch('/todos'),\n  initialData: () => getExpensiveTodos(),\n}))\n```\n\n[//]: # 'Example5'\n[//]: # 'Example6'\n\n```ts\nresult = injectQuery(() => ({\n  queryKey: ['todo', this.todoId()],\n  queryFn: () => fetch('/todos'),\n  initialData: () => {\n    // Use a todo from the 'todos' query as the initial data for this todo query\n    return this.queryClient\n      .getQueryData(['todos'])\n      ?.find((d) => d.id === this.todoId())\n  },\n}))\n```\n\n[//]: # 'Example6'\n[//]: # 'Example7'\n\n```ts\nresult = injectQuery(() => ({\n  queryKey: ['todos', this.todoId()],\n  queryFn: () => fetch(`/todos/${this.todoId()}`),\n  initialData: () =>\n    queryClient.getQueryData(['todos'])?.find((d) => d.id === this.todoId()),\n  initialDataUpdatedAt: () =>\n    queryClient.getQueryState(['todos'])?.dataUpdatedAt,\n}))\n```\n\n[//]: # 'Example7'\n[//]: # 'Example8'\n\n```ts\nresult = injectQuery(() => ({\n  queryKey: ['todo', this.todoId()],\n  queryFn: () => fetch(`/todos/${this.todoId()}`),\n  initialData: () => {\n    // Get the query state\n    const state = queryClient.getQueryState(['todos'])\n\n    // If the query exists and has data that is no older than 10 seconds...\n    if (state && Date.now() - state.dataUpdatedAt <= 10 * 1000) {\n      // return the individual todo\n      return state.data.find((d) => d.id === this.todoId())\n    }\n\n    // Otherwise, return undefined and let it fetch from a hard loading state!\n  },\n}))\n```\n\n[//]: # 'Example8'\n[//]: # 'Materials'\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/angular/guides/invalidations-from-mutations.md",
    "content": "---\nid: invalidations-from-mutations\ntitle: Invalidations from Mutations\nref: docs/framework/react/guides/invalidations-from-mutations.md\nreplace: { 'useMutation': 'injectMutation', 'hook': 'function' }\n---\n\n[//]: # 'Example'\n\n```ts\nmutation = injectMutation(() => ({\n  mutationFn: postTodo,\n}))\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```ts\nimport {\n  injectMutation,\n  QueryClient,\n} from '@tanstack/angular-query-experimental'\n\nexport class TodosComponent {\n  queryClient = inject(QueryClient)\n\n  // When this mutation succeeds, invalidate any queries with the `todos` or `reminders` query key\n  mutation = injectMutation(() => ({\n    mutationFn: addTodo,\n    onSuccess: () => {\n      this.queryClient.invalidateQueries({ queryKey: ['todos'] })\n      this.queryClient.invalidateQueries({ queryKey: ['reminders'] })\n    },\n  }))\n}\n```\n\n[//]: # 'Example2'\n\nYou can wire up your invalidations to happen using any of the callbacks available in the [`injectMutation` function](./mutations.md)\n"
  },
  {
    "path": "docs/framework/angular/guides/mutation-options.md",
    "content": "---\nid: query-options\ntitle: Mutation Options\n---\n\nOne of the best ways to share mutation options between multiple places,\nis to use the `mutationOptions` helper. At runtime, this helper just returns whatever you pass into it,\nbut it has a lot of advantages when using it [with TypeScript](../typescript.md#typing-query-options).\nYou can define all possible options for a mutation in one place,\nand you'll also get type inference and type safety for all of them.\n\n```ts\nexport class QueriesService {\n  private http = inject(HttpClient)\n\n  updatePost(id: number) {\n    return mutationOptions({\n      mutationFn: (post: Post) => Promise.resolve(post),\n      mutationKey: ['updatePost', id],\n      onSuccess: (newPost) => {\n        //           ^? newPost: Post\n        this.queryClient.setQueryData(['posts', id], newPost)\n      },\n    })\n  }\n}\n```\n"
  },
  {
    "path": "docs/framework/angular/guides/mutations.md",
    "content": "---\nid: mutations\ntitle: Mutations\nref: docs/framework/react/guides/mutations.md\nreplace:\n  {\n    'useMutation': 'injectMutation',\n    'hook': 'function',\n    'still mounted': 'still active',\n    'unmounts': 'gets destroyed',\n    'mounted': 'initialized',\n  }\n---\n\n[//]: # 'Example'\n\n```angular-ts\n@Component({\n  template: `\n    <div>\n      @if (mutation.isPending()) {\n        <span>Adding todo...</span>\n      } @else if (mutation.isError()) {\n        <div>An error occurred: {{ mutation.error()?.message }}</div>\n      } @else if (mutation.isSuccess()) {\n        <div>Todo added!</div>\n      }\n      <button (click)=\"mutation.mutate(1)\">Create Todo</button>\n    </div>\n  `,\n})\nexport class TodosComponent {\n  todoService = inject(TodoService)\n  mutation = injectMutation(() => ({\n    mutationFn: (todoId: number) =>\n      lastValueFrom(this.todoService.create(todoId)),\n  }))\n}\n```\n\n[//]: # 'Example'\n[//]: # 'Info1'\n[//]: # 'Info1'\n[//]: # 'Example2'\n[//]: # 'Example2'\n[//]: # 'Example3'\n\n```angular-ts\n@Component({\n  selector: 'todo-item',\n  imports: [ReactiveFormsModule],\n  template: `\n    <form [formGroup]=\"todoForm\" (ngSubmit)=\"onCreateTodo()\">\n      @if (mutation.error()) {\n        <h5 (click)=\"mutation.reset()\">{{ mutation.error() }}</h5>\n      }\n      <input type=\"text\" formControlName=\"title\" />\n      <br />\n      <button type=\"submit\">Create Todo</button>\n    </form>\n  `,\n})\nexport class TodosComponent {\n  mutation = injectMutation(() => ({\n    mutationFn: createTodo,\n  }))\n\n  fb = inject(NonNullableFormBuilder)\n\n  todoForm = this.fb.group({\n    title: this.fb.control('', {\n      validators: [Validators.required],\n    }),\n  })\n\n  title = toSignal(this.todoForm.controls.title.valueChanges, {\n    initialValue: '',\n  })\n\n  onCreateTodo = () => {\n    this.mutation.mutate(this.title())\n  }\n}\n```\n\n[//]: # 'Example3'\n[//]: # 'Example4'\n\n```ts\nmutation = injectMutation(() => ({\n  mutationFn: addTodo,\n  onMutate: (variables, context) => {\n    // A mutation is about to happen!\n\n    // Optionally return a result containing data to use when for example rolling back\n    return { id: 1 }\n  },\n  onError: (error, variables, onMutateResult, context) => {\n    // An error happened!\n    console.log(`rolling back optimistic update with id ${onMutateResult.id}`)\n  },\n  onSuccess: (data, variables, onMutateResult, context) => {\n    // Boom baby!\n  },\n  onSettled: (data, error, variables, onMutateResult, context) => {\n    // Error or success... doesn't matter!\n  },\n}))\n```\n\n[//]: # 'Example4'\n[//]: # 'Example5'\n\n```ts\nmutation = injectMutation(() => ({\n  mutationFn: addTodo,\n  onSuccess: async () => {\n    console.log(\"I'm first!\")\n  },\n  onSettled: async () => {\n    console.log(\"I'm second!\")\n  },\n}))\n```\n\n[//]: # 'Example5'\n[//]: # 'Example6'\n\n```ts\nmutation = injectMutation(() => ({\n  mutationFn: addTodo,\n  onSuccess: (data, variables, onMutateResult, context) => {\n    // I will fire first\n  },\n  onError: (error, variables, onMutateResult, context) => {\n    // I will fire first\n  },\n  onSettled: (data, error, variables, onMutateResult, context) => {\n    // I will fire first\n  },\n}))\n\nmutation.mutate(todo, {\n  onSuccess: (data, variables, onMutateResult, context) => {\n    // I will fire second!\n  },\n  onError: (error, variables, onMutateResult, context) => {\n    // I will fire second!\n  },\n  onSettled: (data, error, variables, onMutateResult, context) => {\n    // I will fire second!\n  },\n})\n```\n\n[//]: # 'Example6'\n[//]: # 'Example7'\n\n```ts\nexport class Example {\n  mutation = injectMutation(() => ({\n    mutationFn: addTodo,\n    onSuccess: (data, variables, onMutateResult, context) => {\n      // Will be called 3 times\n    },\n  }))\n\n  doMutations() {\n    ;['Todo 1', 'Todo 2', 'Todo 3'].forEach((todo) => {\n      this.mutation.mutate(todo, {\n        onSuccess: (data, variables, onMutateResult, context) => {\n          // Will execute only once, for the last mutation (Todo 3),\n          // regardless which mutation resolves first\n        },\n      })\n    })\n  }\n}\n```\n\n[//]: # 'Example7'\n[//]: # 'Example8'\n\n```ts\nmutation = injectMutation(() => ({ mutationFn: addTodo }))\n\ntry {\n  const todo = await mutation.mutateAsync(todo)\n  console.log(todo)\n} catch (error) {\n  console.error(error)\n} finally {\n  console.log('done')\n}\n```\n\n[//]: # 'Example8'\n[//]: # 'Example9'\n\n```ts\nmutation = injectMutation(() => ({\n  mutationFn: addTodo,\n  retry: 3,\n}))\n```\n\n[//]: # 'Example9'\n[//]: # 'Example10'\n\n```ts\nconst queryClient = new QueryClient()\n\n// Define the \"addTodo\" mutation\nqueryClient.setMutationDefaults(['addTodo'], {\n  mutationFn: addTodo,\n  onMutate: async (variables, context) => {\n    // Cancel current queries for the todos list\n    await context.client.cancelQueries({ queryKey: ['todos'] })\n\n    // Create optimistic todo\n    const optimisticTodo = { id: uuid(), title: variables.title }\n\n    // Add optimistic todo to todos list\n    context.client.setQueryData(['todos'], (old) => [...old, optimisticTodo])\n\n    // Return result with the optimistic todo\n    return { optimisticTodo }\n  },\n  onSuccess: (result, variables, onMutateResult, context) => {\n    // Replace optimistic todo in the todos list with the result\n    context.client.setQueryData(['todos'], (old) =>\n      old.map((todo) =>\n        todo.id === onMutateResult.optimisticTodo.id ? result : todo,\n      ),\n    )\n  },\n  onError: (error, variables, onMutateResult, context) => {\n    // Remove optimistic todo from the todos list\n    context.client.setQueryData(['todos'], (old) =>\n      old.filter((todo) => todo.id !== onMutateResult.optimisticTodo.id),\n    )\n  },\n  retry: 3,\n})\n\nclass someComponent {\n  // Start mutation in some component:\n  mutation = injectMutation(() => ({ mutationKey: ['addTodo'] }))\n\n  someMethod() {\n    mutation.mutate({ title: 'title' })\n  }\n}\n\n// If the mutation has been paused because the device is for example offline,\n// Then the paused mutation can be dehydrated when the application quits:\nconst state = dehydrate(queryClient)\n\n// The mutation can then be hydrated again when the application is started:\nhydrate(queryClient, state)\n\n// Resume the paused mutations:\nqueryClient.resumePausedMutations()\n```\n\n[//]: # 'Example10'\n[//]: # 'Example11'\n[//]: # 'Example11'\n[//]: # 'Materials'\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/angular/guides/network-mode.md",
    "content": "---\nid: network-mode\ntitle: Network Mode\nref: docs/framework/react/guides/network-mode.md\n---\n"
  },
  {
    "path": "docs/framework/angular/guides/optimistic-updates.md",
    "content": "---\nid: optimistic-updates\ntitle: Optimistic Updates\nref: docs/framework/react/guides/optimistic-updates.md\nreplace:\n  {\n    'React': 'Angular',\n    'useMutation': 'injectMutation',\n    'hook': 'function',\n    'useMutationState': 'injectMutationState',\n    'addTodoMutation': 'addTodo',\n  }\n---\n\n[//]: # 'ExampleUI1'\n\n```ts\naddTodo = injectMutation(() => ({\n  mutationFn: (newTodo: string) => axios.post('/api/data', { text: newTodo }),\n  // make sure to _return_ the Promise from the query invalidation\n  // so that the mutation stays in `pending` state until the refetch is finished\n  onSettled: async () => {\n    return await queryClient.invalidateQueries({ queryKey: ['todos'] })\n  },\n}))\n```\n\n[//]: # 'ExampleUI1'\n[//]: # 'ExampleUI2'\n\n```angular-ts\n@Component({\n  template: `\n    @for (todo of todos.data(); track todo.id) {\n      <li>{{ todo.title }}</li>\n    }\n    @if (addTodo.isPending()) {\n      <li style=\"opacity: 0.5\">{{ addTodo.variables() }}</li>\n    }\n  `,\n})\nclass TodosComponent {}\n```\n\n[//]: # 'ExampleUI2'\n[//]: # 'ExampleUI3'\n\n```angular-ts\n@Component({\n  template: `\n    @if (addTodo.isError()) {\n      <li style=\"color: red\">\n        {{ addTodo.variables() }}\n        <button (click)=\"addTodo.mutate(addTodo.variables())\">Retry</button>\n      </li>\n    }\n  `,\n})\nclass TodosComponent {}\n```\n\n[//]: # 'ExampleUI3'\n[//]: # 'ExampleUI4'\n\n```ts\n// somewhere in your app\naddTodo = injectMutation(() => ({\n  mutationFn: (newTodo: string) => axios.post('/api/data', { text: newTodo }),\n  onSettled: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),\n  mutationKey: ['addTodo'],\n}))\n\n// access variables somewhere else\n\nmutationState = injectMutationState<string>(() => ({\n  filters: { mutationKey: ['addTodo'], status: 'pending' },\n  select: (mutation) => mutation.state.variables,\n}))\n```\n\n[//]: # 'ExampleUI4'\n[//]: # 'Example'\n\n```ts\nqueryClient = inject(QueryClient)\n\nupdateTodo = injectMutation(() => ({\n  mutationFn: updateTodo,\n  // When mutate is called:\n  onMutate: async (newTodo, context) => {\n    // Cancel any outgoing refetches\n    // (so they don't overwrite our optimistic update)\n    await context.client.cancelQueries({ queryKey: ['todos'] })\n\n    // Snapshot the previous value\n    const previousTodos = context.client.getQueryData(['todos'])\n\n    // Optimistically update to the new value\n    context.client.setQueryData(['todos'], (old) => [...old, newTodo])\n\n    // Return a result object with the snapshotted value\n    return { previousTodos }\n  },\n  // If the mutation fails,\n  // use the result returned from onMutate to roll back\n  onError: (err, newTodo, onMutateResult, context) => {\n    context.client.setQueryData(['todos'], onMutateResult.previousTodos)\n  },\n  // Always refetch after error or success:\n  onSettled: (data, error, variables, onMutateResult, context) => {\n    context.client.invalidateQueries({ queryKey: ['todos'] })\n  },\n}))\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```ts\nqueryClient = inject(QueryClient)\n\nupdateTodo = injectMutation(() => ({\n  mutationFn: updateTodo,\n  // When mutate is called:\n  onMutate: async (newTodo, context) => {\n    // Cancel any outgoing refetches\n    // (so they don't overwrite our optimistic update)\n    await context.client.cancelQueries({ queryKey: ['todos', newTodo.id] })\n\n    // Snapshot the previous value\n    const previousTodo = context.client.getQueryData(['todos', newTodo.id])\n\n    // Optimistically update to the new value\n    context.client.setQueryData(['todos', newTodo.id], newTodo)\n\n    // Return a result with the previous and new todo\n    return { previousTodo, newTodo }\n  },\n  // If the mutation fails, use the result we returned above\n  onError: (err, newTodo, onMutateResult, context) => {\n    context.client.setQueryData(\n      ['todos', onMutateResult.newTodo.id],\n      onMutateResult.previousTodo,\n    )\n  },\n  // Always refetch after error or success:\n  onSettled: (newTodo, error, variables, onMutateResult, context) => {\n    context.client.invalidateQueries({ queryKey: ['todos', newTodo.id] })\n  },\n}))\n```\n\n[//]: # 'Example2'\n[//]: # 'Example3'\n\n```ts\ninjectMutation({\n  mutationFn: updateTodo,\n  // ...\n  onSettled: (newTodo, error, variables, onMutateResult, context) => {\n    if (error) {\n      // do something\n    }\n  },\n})\n```\n\n[//]: # 'Example3'\n"
  },
  {
    "path": "docs/framework/angular/guides/paginated-queries.md",
    "content": "---\nid: paginated-queries\ntitle: Paginated / Lagged Queries\nref: docs/framework/react/guides/paginated-queries.md\nreplace:\n  {\n    'useQuery': 'injectQuery',\n    'useInfiniteQuery': 'injectInfiniteQuery',\n    'hook': 'function',\n  }\n---\n\n[//]: # 'Example'\n\n```ts\nconst result = injectQuery(() => ({\n  queryKey: ['projects', page()],\n  queryFn: fetchProjects,\n}))\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```angular-ts\n@Component({\n  selector: 'pagination-example',\n  template: `\n    <div>\n      <p>\n        In this example, each page of data remains visible as the next page is\n        fetched. The buttons and capability to proceed to the next page are also\n        suppressed until the next page cursor is known. Each page is cached as a\n        normal query too, so when going to previous pages, you'll see them\n        instantaneously while they are also re-fetched invisibly in the\n        background.\n      </p>\n      @if (query.status() === 'pending') {\n        <div>Loading...</div>\n      } @else if (query.status() === 'error') {\n        <div>Error: {{ query.error().message }}</div>\n      } @else {\n        <!-- 'data' will either resolve to the latest page's data -->\n        <!-- or if fetching a new page, the last successful page's data -->\n        <div>\n          @for (project of query.data().projects; track project.id) {\n            <p>{{ project.name }}</p>\n          }\n        </div>\n      }\n\n      <div>Current Page: {{ page() + 1 }}</div>\n      <button (click)=\"previousPage()\" [disabled]=\"page() === 0\">\n        Previous Page\n      </button>\n      <button\n        (click)=\"nextPage()\"\n        [disabled]=\"query.isPlaceholderData() || !query.data()?.hasMore\"\n      >\n        Next Page\n      </button>\n      <!-- Since the last page's data potentially sticks around between page requests, -->\n      <!-- we can use 'isFetching' to show a background loading -->\n      <!-- indicator since our status === 'pending' state won't be triggered -->\n      @if (query.isFetching()) {\n        <span> Loading...</span>\n      }\n    </div>\n  `,\n})\nexport class PaginationExampleComponent {\n  page = signal(0)\n  #queryClient = inject(QueryClient)\n\n  query = injectQuery(() => ({\n    queryKey: ['projects', this.page()],\n    queryFn: () => lastValueFrom(fetchProjects(this.page())),\n    placeholderData: keepPreviousData,\n    staleTime: 5000,\n  }))\n\n  constructor() {\n    effect(() => {\n      // Prefetch the next page!\n      if (!this.query.isPlaceholderData() && this.query.data()?.hasMore) {\n        this.#queryClient.prefetchQuery({\n          queryKey: ['projects', this.page() + 1],\n          queryFn: () => lastValueFrom(fetchProjects(this.page() + 1)),\n        })\n      }\n    })\n  }\n\n  previousPage() {\n    this.page.update((old) => Math.max(old - 1, 0))\n  }\n\n  nextPage() {\n    this.page.update((old) => (this.query.data()?.hasMore ? old + 1 : old))\n  }\n}\n```\n\n[//]: # 'Example2'\n"
  },
  {
    "path": "docs/framework/angular/guides/parallel-queries.md",
    "content": "---\nid: parallel-queries\ntitle: Parallel Queries\nref: docs/framework/react/guides/parallel-queries.md\nreplace:\n  {\n    'If the number of queries you need to execute is changing from render to render, you cannot use manual querying since that would violate the rules of hooks. Instead, ': '',\n    'hook': 'function',\n    'React': 'Angular',\n    'hooks': 'functions',\n    'useQuery': 'injectQuery',\n    'useInfiniteQuery': 'injectInfiniteQuery',\n    'useQueries': 'injectQueries',\n  }\n---\n\n[//]: # 'Example'\n\n```ts\nexport class AppComponent {\n  // The following queries will execute in parallel\n  usersQuery = injectQuery(() => ({ queryKey: ['users'], queryFn: fetchUsers }))\n  teamsQuery = injectQuery(() => ({ queryKey: ['teams'], queryFn: fetchTeams }))\n  projectsQuery = injectQuery(() => ({\n    queryKey: ['projects'],\n    queryFn: fetchProjects,\n  }))\n}\n```\n\n[//]: # 'Example'\n[//]: # 'Info'\n[//]: # 'Info'\n[//]: # 'DynamicParallelIntro'\n\nTanStack Query provides `injectQueries`, which you can use to dynamically execute as many queries in parallel as you'd like.\n\n[//]: # 'DynamicParallelIntro'\n[//]: # 'Example2'\n\n```ts\nexport class AppComponent {\n  users = signal<Array<User>>([])\n\n  // Please note injectQueries is under development and this code does not work yet\n  userQueries = injectQueries(() => ({\n    queries: users().map((user) => {\n      return {\n        queryKey: ['user', user.id],\n        queryFn: () => fetchUserById(user.id),\n      }\n    }),\n  }))\n}\n```\n\n[//]: # 'Example2'\n"
  },
  {
    "path": "docs/framework/angular/guides/placeholder-query-data.md",
    "content": "---\nid: placeholder-query-data\ntitle: Placeholder Query Data\nref: docs/framework/react/guides/placeholder-query-data.md\n---\n\n[//]: # 'ExampleValue'\n\n```ts\nclass TodosComponent {\n  result = injectQuery(() => ({\n    queryKey: ['todos'],\n    queryFn: () => fetch('/todos'),\n    placeholderData: placeholderTodos,\n  }))\n}\n```\n\n[//]: # 'ExampleValue'\n[//]: # 'Memoization'\n[//]: # 'Memoization'\n[//]: # 'ExampleFunction'\n\n```ts\nclass TodosComponent {\n  result = injectQuery(() => ({\n    queryKey: ['todos', id()],\n    queryFn: () => fetch(`/todos/${id}`),\n    placeholderData: (previousData, previousQuery) => previousData,\n  }))\n}\n```\n\n[//]: # 'ExampleFunction'\n[//]: # 'ExampleCache'\n\n```ts\nexport class BlogPostComponent {\n  postId = input.required<number>()\n  queryClient = inject(QueryClient)\n\n  result = injectQuery(() => ({\n    queryKey: ['blogPost', this.postId()],\n    queryFn: () => fetch(`/blogPosts/${this.postId()}`),\n    placeholderData: () => {\n      // Use the smaller/preview version of the blogPost from the 'blogPosts'\n      // query as the placeholder data for this blogPost query\n      return this.queryClient\n        .getQueryData(['blogPosts'])\n        ?.find((d) => d.id === this.postId())\n    },\n  }))\n}\n```\n\n[//]: # 'ExampleCache'\n[//]: # 'Materials'\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/angular/guides/queries.md",
    "content": "---\nid: queries\ntitle: Queries\nref: docs/framework/react/guides/queries.md\nreplace:\n  {\n    'React': 'Angular',\n    'react-query': 'angular-query',\n    'promise': 'promise or observable',\n    'custom hooks': 'services',\n    'the `useQuery` hook': '`injectQuery`',\n    '`useQuery`': '`injectQuery`',\n    \"TypeScript will also narrow the type of data correctly if you've checked for pending and error before accessing it.\": 'TypeScript will only narrow the type when checking boolean signals such as `isPending` and `isError`.',\n  }\n---\n\n[//]: # 'Example'\n\n```ts\nimport { injectQuery } from '@tanstack/angular-query-experimental'\n\nexport class TodosComponent {\n  info = injectQuery(() => ({ queryKey: ['todos'], queryFn: fetchTodoList }))\n}\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```ts\nresult = injectQuery(() => ({ queryKey: ['todos'], queryFn: fetchTodoList }))\n```\n\n[//]: # 'Example2'\n[//]: # 'Example3'\n\n```angular-ts\n@Component({\n  selector: 'todos',\n  template: `\n    @if (todos.isPending()) {\n      <span>Loading...</span>\n    } @else if (todos.isError()) {\n      <span>Error: {{ todos.error()?.message }}</span>\n    } @else {\n      <!-- We can assume by this point that status === 'success' -->\n      @for (todo of todos.data(); track todo.id) {\n        <li>{{ todo.title }}</li>\n      } @empty {\n        <li>No todos found</li>\n      }\n    }\n  `,\n})\nexport class PostsComponent {\n  todos = injectQuery(() => ({\n    queryKey: ['todos'],\n    queryFn: fetchTodoList,\n  }))\n}\n```\n\n[//]: # 'Example3'\n\nIf booleans aren't your thing, you can always use the `status` state as well:\n\n[//]: # 'Example4'\n\n```angular-ts\n@Component({\n  selector: 'todos',\n  template: `\n    @switch (todos.status()) {\n      @case ('pending') {\n        <span>Loading...</span>\n      }\n      @case ('error') {\n        <span>Error: {{ todos.error()?.message }}</span>\n      }\n      <!-- also status === 'success', but \"else\" logic works, too -->\n      @default {\n        <ul>\n          @for (todo of todos.data(); track todo.id) {\n            <li>{{ todo.title }}</li>\n          } @empty {\n            <li>No todos found</li>\n          }\n        </ul>\n      }\n    }\n  `,\n})\nclass TodosComponent {}\n```\n\n[//]: # 'Example4'\n[//]: # 'Materials'\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/angular/guides/query-cancellation.md",
    "content": "---\nid: query-cancellation\ntitle: Query Cancellation\n---\n\nTanStack Query provides each query function with an [`AbortSignal` instance](https://developer.mozilla.org/docs/Web/API/AbortSignal). When a query becomes out-of-date or inactive, this `signal` will become aborted. This means that all queries are cancellable, and you can respond to the cancellation inside your query function if desired. The best part about this is that it allows you to continue to use normal async/await syntax while getting all the benefits of automatic cancellation.\n\n## Default behavior\n\nBy default, queries that unmount or become unused before their promises are resolved are _not_ cancelled. This means that after the promise has resolved, the resulting data will be available in the cache. This is helpful if you've started receiving a query, but then unmount the component before it finishes. If you mount the component again and the query has not been garbage collected yet, data will be available.\n\nHowever, if you consume the `AbortSignal`, the Promise will be cancelled (e.g. aborting the fetch) and therefore, also the Query must be cancelled. Cancelling the query will result in its state being _reverted_ to its previous state.\n\n## Using `HttpClient`\n\n```ts\nimport { HttpClient } from '@angular/common/http'\nimport { injectQuery } from '@tanstack/angular-query-experimental'\n\npostQuery = injectQuery(() => ({\n  enabled: this.postId() > 0,\n  queryKey: ['post', this.postId()],\n  queryFn: async (context): Promise<Post> => {\n    const abort$ = fromEvent(context.signal, 'abort')\n    return lastValueFrom(this.getPost$(this.postId()).pipe(takeUntil(abort$)))\n  },\n}))\n```\n\n## Using `fetch`\n\n[//]: # 'Example2'\n\n```ts\nquery = injectQuery(() => ({\n  queryKey: ['todos'],\n  queryFn: async ({ signal }) => {\n    const todosResponse = await fetch('/todos', {\n      // Pass the signal to one fetch\n      signal,\n    })\n    const todos = await todosResponse.json()\n\n    const todoDetails = todos.map(async ({ details }) => {\n      const response = await fetch(details, {\n        // Or pass it to several\n        signal,\n      })\n      return response.json()\n    })\n\n    return Promise.all(todoDetails)\n  },\n}))\n```\n\n[//]: # 'Example2'\n\n## Using `axios`\n\n[//]: # 'Example3'\n\n```ts\nimport axios from 'axios'\n\nconst query = injectQuery(() => ({\n  queryKey: ['todos'],\n  queryFn: ({ signal }) =>\n    axios.get('/todos', {\n      // Pass the signal to `axios`\n      signal,\n    }),\n}))\n```\n\n[//]: # 'Example3'\n\n## Manual Cancellation\n\nYou might want to cancel a query manually. For example, if the request takes a long time to finish, you can allow the user to click a cancel button to stop the request. To do this, you just need to call `queryClient.cancelQueries({ queryKey })`, which will cancel the query and revert it back to its previous state. If you have consumed the `signal` passed to the query function, TanStack Query will additionally also cancel the Promise.\n\n[//]: # 'Example7'\n\n```angular-ts\n@Component({\n  template: `<button (click)=\"onCancel()\">Cancel</button>`,\n})\nexport class TodosComponent {\n  query = injectQuery(() => ({\n    queryKey: ['todos'],\n    queryFn: async ({ signal }) => {\n      const resp = await fetch('/todos', { signal })\n      return resp.json()\n    },\n  }))\n\n  queryClient = inject(QueryClient)\n\n  onCancel() {\n    this.queryClient.cancelQueries(['todos'])\n  }\n}\n```\n\n[//]: # 'Example7'\n"
  },
  {
    "path": "docs/framework/angular/guides/query-functions.md",
    "content": "---\nid: query-functions\ntitle: Query Functions\nref: docs/framework/react/guides/query-functions.md\n---\n\n[//]: # 'Example'\n\n```ts\ninjectQuery(() => ({ queryKey: ['todos'], queryFn: fetchAllTodos }))\ninjectQuery(() => ({ queryKey: ['todos', todoId], queryFn: () => fetchTodoById(todoId) })\ninjectQuery(() => ({\n  queryKey: ['todos', todoId],\n  queryFn: async () => {\n    const data = await fetchTodoById(todoId)\n    return data\n  },\n}))\ninjectQuery(() => ({\n  queryKey: ['todos', todoId],\n  queryFn: ({ queryKey }) => fetchTodoById(queryKey[1]),\n}))\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```ts\ntodos = injectQuery(() => ({\n  queryKey: ['todos', todoId()],\n  queryFn: async () => {\n    if (somethingGoesWrong) {\n      throw new Error('Oh no!')\n    }\n    if (somethingElseGoesWrong) {\n      return Promise.reject(new Error('Oh no!'))\n    }\n\n    return data\n  },\n}))\n```\n\n[//]: # 'Example2'\n[//]: # 'Example3'\n\n```ts\ntodos = injectQuery(() => ({\n  queryKey: ['todos', todoId()],\n  queryFn: async () => {\n    const response = await fetch('/todos/' + todoId)\n    if (!response.ok) {\n      throw new Error('Network response was not ok')\n    }\n    return response.json()\n  },\n}))\n```\n\n[//]: # 'Example3'\n[//]: # 'Example4'\n\n```ts\nresult = injectQuery(() => ({\n  queryKey: ['todos', { status: status(), page: page() }],\n  queryFn: fetchTodoList,\n}))\n\n// Access the key, status and page variables in your query function!\nfunction fetchTodoList({ queryKey }) {\n  const [_key, { status, page }] = queryKey\n  return new Promise()\n}\n```\n\n[//]: # 'Example4'\n"
  },
  {
    "path": "docs/framework/angular/guides/query-invalidation.md",
    "content": "---\nid: query-invalidation\ntitle: Query Invalidation\nref: docs/framework/react/guides/query-invalidation.md\nreplace: { 'useQuery': 'injectQuery', 'hooks': 'functions' }\n---\n\n[//]: # 'Example2'\n\n```ts\nimport { injectQuery, QueryClient } from '@tanstack/angular-query-experimental'\n\nclass QueryInvalidationExample {\n  queryClient = inject(QueryClient)\n\n  invalidateQueries() {\n    this.queryClient.invalidateQueries({ queryKey: ['todos'] })\n  }\n\n  // Both queries below will be invalidated\n  todoListQuery = injectQuery(() => ({\n    queryKey: ['todos'],\n    queryFn: fetchTodoList,\n  }))\n  todoListQuery = injectQuery(() => ({\n    queryKey: ['todos', { page: 1 }],\n    queryFn: fetchTodoList,\n  }))\n}\n```\n\n[//]: # 'Example2'\n\nYou can even invalidate queries with specific variables by passing a more specific query key to the `invalidateQueries` method:\n\n[//]: # 'Example3'\n\n```ts\nqueryClient.invalidateQueries({\n  queryKey: ['todos', { type: 'done' }],\n})\n\n// The query below will be invalidated\ntodoListQuery = injectQuery(() => ({\n  queryKey: ['todos', { type: 'done' }],\n  queryFn: fetchTodoList,\n}))\n\n// However, the following query below will NOT be invalidated\ntodoListQuery = injectQuery(() => ({\n  queryKey: ['todos'],\n  queryFn: fetchTodoList,\n}))\n```\n\n[//]: # 'Example3'\n\nThe `invalidateQueries` API is very flexible, so even if you want to **only** invalidate `todos` queries that don't have any more variables or subkeys, you can pass an `exact: true` option to the `invalidateQueries` method:\n\n[//]: # 'Example4'\n\n```ts\nqueryClient.invalidateQueries({\n  queryKey: ['todos'],\n  exact: true,\n})\n\n// The query below will be invalidated\ntodoListQuery = injectQuery(() => ({\n  queryKey: ['todos'],\n  queryFn: fetchTodoList,\n}))\n\n// However, the following query below will NOT be invalidated\nconst todoListQuery = injectQuery(() => ({\n  queryKey: ['todos', { type: 'done' }],\n  queryFn: fetchTodoList,\n}))\n```\n\n[//]: # 'Example4'\n\nIf you find yourself wanting **even more** granularity, you can pass a predicate function to the `invalidateQueries` method. This function will receive each `Query` instance from the query cache and allow you to return `true` or `false` for whether you want to invalidate that query:\n\n[//]: # 'Example5'\n\n```ts\nqueryClient.invalidateQueries({\n  predicate: (query) =>\n    query.queryKey[0] === 'todos' && query.queryKey[1]?.version >= 10,\n})\n\n// The query below will be invalidated\ntodoListQuery = injectQuery(() => ({\n  queryKey: ['todos', { version: 20 }],\n  queryFn: fetchTodoList,\n}))\n\n// The query below will be invalidated\ntodoListQuery = injectQuery(() => ({\n  queryKey: ['todos', { version: 10 }],\n  queryFn: fetchTodoList,\n}))\n\n// However, the following query below will NOT be invalidated\ntodoListQuery = injectQuery(() => ({\n  queryKey: ['todos', { version: 5 }],\n  queryFn: fetchTodoList,\n}))\n```\n\n[//]: # 'Example5'\n"
  },
  {
    "path": "docs/framework/angular/guides/query-keys.md",
    "content": "---\nid: query-keys\ntitle: Query Keys\nref: docs/framework/react/guides/query-keys.md\n#todo: exhaustive-deps is at least for now React-only\n---\n\n[//]: # 'Example'\n\n```ts\n// A list of todos\ninjectQuery(() => ({ queryKey: ['todos'], ... }))\n\n// Something else, whatever!\ninjectQuery(() => ({ queryKey: ['something', 'special'], ... }))\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```ts\n// An individual todo\ninjectQuery(() => ({queryKey: ['todo', 5], ...}))\n\n// An individual todo in a \"preview\" format\ninjectQuery(() => ({queryKey: ['todo', 5, {preview: true}], ...}))\n\n// A list of todos that are \"done\"\ninjectQuery(() => ({queryKey: ['todos', {type: 'done'}], ...}))\n```\n\n[//]: # 'Example2'\n[//]: # 'Example3'\n\n```ts\ninjectQuery(() => ({ queryKey: ['todos', { status, page }], ... }))\ninjectQuery(() => ({ queryKey: ['todos', { page, status }], ...}))\ninjectQuery(() => ({ queryKey: ['todos', { page, status, other: undefined }], ... }))\n```\n\n[//]: # 'Example3'\n[//]: # 'Example4'\n\n```ts\ninjectQuery(() => ({ queryKey: ['todos', status, page], ... }))\ninjectQuery(() => ({ queryKey: ['todos', page, status], ...}))\ninjectQuery(() => ({ queryKey: ['todos', undefined, page, status], ...}))\n```\n\n[//]: # 'Example4'\n[//]: # 'Example5'\n\n```ts\ntodoId = signal(-1)\n\ninjectQuery(() => ({\n  enabled: todoId() > 0,\n  queryKey: ['todos', todoId()],\n  queryFn: () => fetchTodoById(todoId()),\n}))\n```\n\n[//]: # 'Example5'\n[//]: # 'Materials'\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/angular/guides/query-options.md",
    "content": "---\nid: query-options\ntitle: Query Options\nref: docs/framework/react/guides/query-options.md\n---\n\n[//]: # 'Example1'\n\n```ts\nimport { queryOptions } from '@tanstack/angular-query-experimental'\n\n@Injectable({\n  providedIn: 'root',\n})\nexport class QueriesService {\n  private http = inject(HttpClient)\n\n  post(postId: number) {\n    return queryOptions({\n      queryKey: ['post', postId],\n      queryFn: () => {\n        return lastValueFrom(\n          this.http.get<Post>(\n            `https://jsonplaceholder.typicode.com/posts/${postId}`,\n          ),\n        )\n      },\n    })\n  }\n}\n\n// usage:\n\npostId = input.required({\n  transform: numberAttribute,\n})\nqueries = inject(QueriesService)\n\npostQuery = injectQuery(() => this.queries.post(this.postId()))\n\nqueryClient.prefetchQuery(this.queries.post(23))\nqueryClient.setQueryData(this.queries.post(42).queryKey, newPost)\n```\n\n[//]: # 'Example1'\n[//]: # 'Example2'\n\n```ts\n// Type inference still works, so query.data will be the return type of select instead of queryFn\nqueries = inject(QueriesService)\n\nquery = injectQuery(() => ({\n  ...groupOptions(1),\n  select: (data) => data.title,\n}))\n```\n\n[//]: # 'Example2'\n"
  },
  {
    "path": "docs/framework/angular/guides/query-retries.md",
    "content": "---\nid: query-retries\ntitle: Query Retries\nref: docs/framework/react/guides/query-retries.md\nreplace:\n  {\n    'Provider': 'Plugin',\n    'useQuery': 'injectQuery',\n    'useMutation': 'injectMutation',\n  }\n---\n\n[//]: # 'Info'\n[//]: # 'Info'\n[//]: # 'Example'\n\n```ts\nimport { injectQuery } from '@tanstack/angular-query-experimental'\n\n// Make a specific query retry a certain number of times\nconst result = injectQuery(() => ({\n  queryKey: ['todos', 1],\n  queryFn: fetchTodoListPage,\n  retry: 10, // Will retry failed requests 10 times before displaying an error\n}))\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```ts\n// Configure for all queries\nimport {\n  QueryCache,\n  QueryClient,\n  QueryClientProvider,\n} from '@tanstack/angular-query-experimental'\n\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000),\n    },\n  },\n})\n\nbootstrapApplication(AppComponent, {\n  providers: [provideTanStackQuery(queryClient)],\n})\n```\n\n[//]: # 'Example2'\n\nThough it is not recommended, you can obviously override the `retryDelay` function/integer in both the Provider and individual query options. If set to an integer instead of a function the delay will always be the same amount of time:\n\n[//]: # 'Example3'\n\n```ts\nconst result = injectQuery(() => ({\n  queryKey: ['todos'],\n  queryFn: fetchTodoList,\n  retryDelay: 1000, // Will always wait 1000ms to retry, regardless of how many retries\n}))\n```\n\n[//]: # 'Example3'\n"
  },
  {
    "path": "docs/framework/angular/guides/scroll-restoration.md",
    "content": "---\nid: scroll-restoration\ntitle: Scroll Restoration\nref: docs/framework/react/guides/scroll-restoration.md\n---\n"
  },
  {
    "path": "docs/framework/angular/guides/testing.md",
    "content": "---\nid: testing\ntitle: Testing\n---\n\nMost Angular tests using TanStack Query will involve services or components that call `injectQuery`/`injectMutation`.\n\nTanStack Query's `inject*` functions integrate with [`PendingTasks`](https://angular.dev/api/core/PendingTasks) which ensures the framework is aware of in-progress queries and mutations.\n\nThis means tests and SSR can wait until mutations and queries resolve. In unit tests you can use `ApplicationRef.whenStable()` or `fixture.whenStable()` to await query completion. This works for both Zone.js and Zoneless setups.\n\n> This integration requires Angular 19 or later. Earlier versions of Angular do not support `PendingTasks`.\n\n## TestBed setup\n\nCreate a fresh `QueryClient` for every spec and provide it with `provideTanStackQuery` or `provideQueryClient`. This keeps caches isolated and lets you change default options per test:\n\n```ts\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      retry: false, // ✅ faster failure tests\n    },\n  },\n})\n\nTestBed.configureTestingModule({\n  providers: [provideTanStackQuery(queryClient)],\n})\n```\n\n> If your applications actual TanStack Query config is used in unit tests, make sure `withDevtools` is not accidentally included in test providers. This can cause slow tests. It is best to keep test and production configs separate.\n\nIf you share helpers, remember to call `queryClient.clear()` (or build a new instance) in `afterEach` so data from one test never bleeds into another.\n\n## First query test\n\nQuery tests typically run inside `TestBed.runInInjectionContext`, then wait for stability:\n\n```ts\nconst appRef = TestBed.inject(ApplicationRef)\nconst query = TestBed.runInInjectionContext(() =>\n  injectQuery(() => ({\n    queryKey: ['greeting'],\n    queryFn: () => 'Hello',\n  })),\n)\n\nTestBed.tick() // Trigger effect\n\n// Application is stable when queries are idle\nawait appRef.whenStable()\n\nexpect(query.status()).toBe('success')\nexpect(query.data()).toBe('Hello')\n```\n\nPendingTasks will have `whenStable()` resolve after the query settles. When using fake timers (Vitest), advance the clock and a microtask before awaiting stability:\n\n```ts\nawait vi.advanceTimersByTimeAsync(0)\nawait Promise.resolve()\nawait appRef.whenStable()\n```\n\n## Testing components\n\nFor components, bootstrap them through `TestBed.createComponent`, then await `fixture.whenStable()`:\n\n```ts\nconst fixture = TestBed.createComponent(ExampleComponent)\n\nawait fixture.whenStable()\nexpect(fixture.componentInstance.query.data()).toEqual({ value: 42 })\n```\n\n## Handling retries\n\nRetries slow failing tests because the default backoff runs three times. Set `retry: false` (or a specific number) through `defaultOptions` or per query to keep tests fast. If a query intentionally retries, assert on the final state rather than intermediate counts.\n\n## HttpClient & network stubs\n\nAngular's `HttpClientTestingModule` plays nicely with PendingTasks. Register it alongside the Query provider and flush responses through `HttpTestingController`:\n\n```ts\nTestBed.configureTestingModule({\n  imports: [HttpClientTestingModule],\n  providers: [provideTanStackQuery(queryClient)],\n})\n\nconst httpCtrl = TestBed.inject(HttpTestingController)\nconst query = TestBed.runInInjectionContext(() =>\n  injectQuery(() => ({\n    queryKey: ['todos'],\n    queryFn: () => lastValueFrom(TestBed.inject(HttpClient).get('/api/todos')),\n  })),\n)\n\nconst fixturePromise = TestBed.inject(ApplicationRef).whenStable()\nhttpCtrl.expectOne('/api/todos').flush([{ id: 1 }])\nawait fixturePromise\n\nexpect(query.data()).toEqual([{ id: 1 }])\nhttpCtrl.verify()\n```\n\n## Infinite queries & pagination\n\nUse the same pattern for infinite queries: call `fetchNextPage()`, advance timers if you are faking time, then await stability and assert on `data().pages`.\n\n```ts\nconst infinite = TestBed.runInInjectionContext(() =>\n  injectInfiniteQuery(() => ({\n    queryKey: ['pages'],\n    queryFn: ({ pageParam = 1 }) => fetchPage(pageParam),\n    getNextPageParam: (last, all) => all.length + 1,\n  })),\n)\n\nawait appRef.whenStable()\nexpect(infinite.data().pages).toHaveLength(1)\n\nawait infinite.fetchNextPage()\nawait vi.advanceTimersByTimeAsync(0)\nawait appRef.whenStable()\n\nexpect(infinite.data().pages).toHaveLength(2)\n```\n\n## Mutations and optimistic updates\n\n```ts\nconst mutation = TestBed.runInInjectionContext(() =>\n  injectMutation(() => ({\n    mutationFn: async (input: string) => input.toUpperCase(),\n  })),\n)\n\nmutation.mutate('test')\n\n// Trigger effect\nTestBed.tick()\n\nawait appRef.whenStable()\n\nexpect(mutation.isSuccess()).toBe(true)\nexpect(mutation.data()).toBe('TEST')\n```\n\n## Quick checklist\n\n- Fresh `QueryClient` per test (and clear it afterwards)\n- Disable or control retries to avoid timeouts\n- Advance timers + microtasks before `whenStable()` when using fake timers\n- Use `HttpClientTestingModule` or your preferred mock to assert network calls\n- Await `whenStable()` after every `refetch`, `fetchNextPage`, or mutation\n- Prefer `TestBed.runInInjectionContext` for service tests and `fixture.whenStable()` for component tests\n"
  },
  {
    "path": "docs/framework/angular/guides/window-focus-refetching.md",
    "content": "---\nid: window-focus-refetching\ntitle: Window Focus Refetching\nref: docs/framework/react/guides/window-focus-refetching.md\nreplace: { '@tanstack/react-query': '@tanstack/angular-query-experimental' }\n---\n\n[//]: # 'Example'\n\n```ts\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideTanStackQuery(\n      new QueryClient({\n        defaultOptions: {\n          queries: {\n            refetchOnWindowFocus: false, // default: true\n          },\n        },\n      }),\n    ),\n  ],\n}\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```ts\ninjectQuery(() => ({\n  queryKey: ['todos'],\n  queryFn: fetchTodos,\n  refetchOnWindowFocus: false,\n}))\n```\n\n[//]: # 'Example2'\n[//]: # 'ReactNative'\n[//]: # 'ReactNative'\n"
  },
  {
    "path": "docs/framework/angular/installation.md",
    "content": "---\nid: installation\ntitle: Installation\n---\n\n> IMPORTANT: This library is currently in an experimental stage. This means that breaking changes will happen in minor AND patch releases. Upgrade carefully. If you use this in production while in experimental stage, please lock your version to a patch-level version to avoid unexpected breaking changes.\n\n### NPM\n\n_Angular Query is compatible with Angular v16 and higher_\n\n```bash\nnpm i @tanstack/angular-query-experimental\n```\n\nor\n\n```bash\npnpm add @tanstack/angular-query-experimental\n```\n\nor\n\n```bash\nyarn add @tanstack/angular-query-experimental\n```\n\nor\n\n```bash\nbun add @tanstack/angular-query-experimental\n```\n\n> Wanna give it a spin before you download? Try out the [simple](./examples/simple) or [basic](./examples/basic) examples!\n"
  },
  {
    "path": "docs/framework/angular/overview.md",
    "content": "---\nid: overview\ntitle: Overview\n---\n\n> IMPORTANT: This library is currently in an experimental stage. This means that breaking changes will happen in minor AND patch releases. Upgrade carefully. If you use this in production while in experimental stage, please lock your version to a patch-level version to avoid unexpected breaking changes.\n\nThe `@tanstack/angular-query-experimental` package offers a 1st-class API for using TanStack Query via Angular.\n\n## Feedback welcome!\n\nWe are in the process of getting to a stable API for TanStack Query on Angular. If you have any feedback, please contact us at the [TanStack Discord](https://tlinz.com/discord) server or [visit this discussion](https://github.com/TanStack/query/discussions/6293) on Github.\n\n## Supported Angular Versions\n\nTanStack Query is compatible with Angular v16 and higher.\n\nTanStack Query (FKA React Query) is often described as the missing data-fetching library for web applications, but in more technical terms, it makes **fetching, caching, synchronizing and updating server state** in your web applications a breeze.\n\n## Motivation\n\nMost core web frameworks **do not** come with an opinionated way of fetching or updating data in a holistic way. Because of this developers end up building either meta-frameworks which encapsulate strict opinions about data-fetching, or they invent their own ways of fetching data. This usually means cobbling together component-based state and side-effects, or using more general purpose state management libraries to store and provide asynchronous data throughout their apps.\n\nWhile most traditional state management libraries are great for working with client state, they are **not so great at working with async or server state**. This is because **server state is totally different**. For starters, server state:\n\n- Is persisted remotely in a location you may not control or own\n- Requires asynchronous APIs for fetching and updating\n- Implies shared ownership and can be changed by other people without your knowledge\n- Can potentially become \"out of date\" in your applications if you're not careful\n\nOnce you grasp the nature of server state in your application, **even more challenges will arise** as you go, for example:\n\n- Caching... (possibly the hardest thing to do in programming)\n- Deduping multiple requests for the same data into a single request\n- Updating \"out of date\" data in the background\n- Knowing when data is \"out of date\"\n- Reflecting updates to data as quickly as possible\n- Performance optimizations like pagination and lazy loading data\n- Managing memory and garbage collection of server state\n- Memoizing query results with structural sharing\n\nIf you're not overwhelmed by that list, then that must mean that you've probably solved all of your server state problems already and deserve an award. However, if you are like a vast majority of people, you either have yet to tackle all or most of these challenges and we're only scratching the surface!\n\nTanStack Query is hands down one of the _best_ libraries for managing server state. It works amazingly well **out-of-the-box, with zero-config, and can be customized** to your liking as your application grows.\n\nTanStack Query allows you to defeat and overcome the tricky challenges and hurdles of _server state_ and control your app data before it starts to control you.\n\nOn a more technical note, TanStack Query will likely:\n\n- Help you remove **many** lines of complicated and misunderstood code from your application and replace with just a handful of lines of Angular Query logic.\n- Make your application more maintainable and easier to build new features without worrying about wiring up new server state data sources\n- Have a direct impact on your end-users by making your application feel faster and more responsive than ever before.\n- Potentially help you save on bandwidth and increase memory performance\n\n[//]: # 'Example'\n\n## Enough talk, show me some code already!\n\nIn the example below, you can see TanStack Query in its most basic and simple form being used to fetch the GitHub stats for the TanStack Query GitHub project itself:\n\n[Open in StackBlitz](https://stackblitz.com/github/TanStack/query/tree/main/examples/angular/simple)\n\n```angular-ts\nimport { ChangeDetectionStrategy, Component, inject } from '@angular/core'\nimport { HttpClient } from '@angular/common/http'\nimport { CommonModule } from '@angular/common'\nimport { injectQuery } from '@tanstack/angular-query-experimental'\nimport { lastValueFrom } from 'rxjs'\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  selector: 'simple-example',\n  template: `\n    @if (query.isPending()) {\n      Loading...\n    }\n    @if (query.error()) {\n      An error has occurred: {{ query.error().message }}\n    }\n    @if (query.data(); as data) {\n      <h1>{{ data.name }}</h1>\n      <p>{{ data.description }}</p>\n      <strong>👀 {{ data.subscribers_count }}</strong>\n      <strong>✨ {{ data.stargazers_count }}</strong>\n      <strong>🍴 {{ data.forks_count }}</strong>\n    }\n  `,\n})\nexport class SimpleExampleComponent {\n  http = inject(HttpClient)\n\n  query = injectQuery(() => ({\n    queryKey: ['repoData'],\n    queryFn: () =>\n      lastValueFrom(\n        this.http.get<Response>('https://api.github.com/repos/tanstack/query'),\n      ),\n  }))\n}\n\ninterface Response {\n  name: string\n  description: string\n  subscribers_count: number\n  stargazers_count: number\n  forks_count: number\n}\n```\n\n## You talked me into it, so what now?\n\n- Learn TanStack Query at your own pace with our amazingly thorough [Walkthrough Guide](./installation.md) and [API Reference](./reference/functions/injectQuery.md)\n"
  },
  {
    "path": "docs/framework/angular/quick-start.md",
    "content": "---\nid: quick-start\ntitle: Quick Start\n---\n\n> IMPORTANT: This library is currently in an experimental stage. This means that breaking changes will happen in minor AND patch releases. Upgrade carefully. If you use this in production while in experimental stage, please lock your version to a patch-level version to avoid unexpected breaking changes.\n\n[//]: # 'Example'\n\nIf you're looking for a fully functioning example, please have a look at our [basic codesandbox example](./examples/basic)\n\n### Provide the client to your App\n\n```ts\nimport { provideHttpClient } from '@angular/common/http'\nimport {\n  provideTanStackQuery,\n  QueryClient,\n} from '@tanstack/angular-query-experimental'\n\nbootstrapApplication(AppComponent, {\n  providers: [provideHttpClient(), provideTanStackQuery(new QueryClient())],\n})\n```\n\nor in a NgModule-based app\n\n```ts\nimport { provideHttpClient } from '@angular/common/http'\nimport {\n  provideTanStackQuery,\n  QueryClient,\n} from '@tanstack/angular-query-experimental'\n\n@NgModule({\n  declarations: [AppComponent],\n  imports: [BrowserModule],\n  providers: [provideTanStackQuery(new QueryClient())],\n  bootstrap: [AppComponent],\n})\nexport class AppModule {}\n```\n\n### Component with query and mutation\n\n```angular-ts\nimport { Component, Injectable, inject } from '@angular/core'\nimport { HttpClient } from '@angular/common/http'\nimport { lastValueFrom } from 'rxjs'\n\nimport {\n  injectMutation,\n  injectQuery,\n  QueryClient,\n} from '@tanstack/angular-query-experimental'\n\n@Component({\n  template: `\n    <div>\n      <button (click)=\"onAddTodo()\">Add Todo</button>\n\n      <ul>\n        @for (todo of query.data(); track todo.title) {\n          <li>{{ todo.title }}</li>\n        }\n      </ul>\n    </div>\n  `,\n})\nexport class TodosComponent {\n  todoService = inject(TodoService)\n  queryClient = inject(QueryClient)\n\n  query = injectQuery(() => ({\n    queryKey: ['todos'],\n    queryFn: () => this.todoService.getTodos(),\n  }))\n\n  mutation = injectMutation(() => ({\n    mutationFn: (todo: Todo) => this.todoService.addTodo(todo),\n    onSuccess: () => {\n      this.queryClient.invalidateQueries({ queryKey: ['todos'] })\n    },\n  }))\n\n  onAddTodo() {\n    this.mutation.mutate({\n      id: Date.now().toString(),\n      title: 'Do Laundry',\n    })\n  }\n}\n\n@Injectable({ providedIn: 'root' })\nexport class TodoService {\n  private http = inject(HttpClient)\n\n  getTodos(): Promise<Todo[]> {\n    return lastValueFrom(\n      this.http.get<Todo[]>('https://jsonplaceholder.typicode.com/todos'),\n    )\n  }\n\n  addTodo(todo: Todo): Promise<Todo> {\n    return lastValueFrom(\n      this.http.post<Todo>('https://jsonplaceholder.typicode.com/todos', todo),\n    )\n  }\n}\n\ninterface Todo {\n  id: string\n  title: string\n}\n```\n\n[//]: # 'Example'\n"
  },
  {
    "path": "docs/framework/angular/reference/functions/infiniteQueryOptions.md",
    "content": "---\nid: infiniteQueryOptions\ntitle: infiniteQueryOptions\n---\n\n# Function: infiniteQueryOptions()\n\nAllows to share and re-use infinite query options in a type-safe way.\n\nThe `queryKey` will be tagged with the type from `queryFn`.\n\n## Param\n\nThe infinite query options to tag with the type from `queryFn`.\n\n## Call Signature\n\n```ts\nfunction infiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>(options): CreateInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam> & object & object;\n```\n\nDefined in: [infinite-query-options.ts:88](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/infinite-query-options.ts#L88)\n\nAllows to share and re-use infinite query options in a type-safe way.\n\nThe `queryKey` will be tagged with the type from `queryFn`.\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `InfiniteData`\\<`TQueryFnData`, `unknown`\\>\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n#### TPageParam\n\n`TPageParam` = `unknown`\n\n### Parameters\n\n#### options\n\n[`DefinedInitialDataInfiniteOptions`](../type-aliases/DefinedInitialDataInfiniteOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\>\n\nThe infinite query options to tag with the type from `queryFn`.\n\n### Returns\n\n[`CreateInfiniteQueryOptions`](../interfaces/CreateInfiniteQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\> & `object` & `object`\n\nThe tagged infinite query options.\n\n## Call Signature\n\n```ts\nfunction infiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>(options): OmitKeyof<CreateInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>, \"queryFn\"> & object & object;\n```\n\nDefined in: [infinite-query-options.ts:119](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/infinite-query-options.ts#L119)\n\nAllows to share and re-use infinite query options in a type-safe way.\n\nThe `queryKey` will be tagged with the type from `queryFn`.\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `InfiniteData`\\<`TQueryFnData`, `unknown`\\>\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n#### TPageParam\n\n`TPageParam` = `unknown`\n\n### Parameters\n\n#### options\n\n[`UnusedSkipTokenInfiniteOptions`](../type-aliases/UnusedSkipTokenInfiniteOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\>\n\nThe infinite query options to tag with the type from `queryFn`.\n\n### Returns\n\n`OmitKeyof`\\<[`CreateInfiniteQueryOptions`](../interfaces/CreateInfiniteQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\>, `\"queryFn\"`\\> & `object` & `object`\n\nThe tagged infinite query options.\n\n## Call Signature\n\n```ts\nfunction infiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>(options): CreateInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam> & object & object;\n```\n\nDefined in: [infinite-query-options.ts:150](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/infinite-query-options.ts#L150)\n\nAllows to share and re-use infinite query options in a type-safe way.\n\nThe `queryKey` will be tagged with the type from `queryFn`.\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `InfiniteData`\\<`TQueryFnData`, `unknown`\\>\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n#### TPageParam\n\n`TPageParam` = `unknown`\n\n### Parameters\n\n#### options\n\n[`UndefinedInitialDataInfiniteOptions`](../type-aliases/UndefinedInitialDataInfiniteOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\>\n\nThe infinite query options to tag with the type from `queryFn`.\n\n### Returns\n\n[`CreateInfiniteQueryOptions`](../interfaces/CreateInfiniteQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\> & `object` & `object`\n\nThe tagged infinite query options.\n"
  },
  {
    "path": "docs/framework/angular/reference/functions/injectInfiniteQuery.md",
    "content": "---\nid: injectInfiniteQuery\ntitle: injectInfiniteQuery\n---\n\n# Function: injectInfiniteQuery()\n\nInjects an infinite query: a declarative dependency on an asynchronous source of data that is tied to a unique key.\nInfinite queries can additively \"load more\" data onto an existing set of data or \"infinite scroll\"\n\n## Param\n\nA function that returns infinite query options.\n\n## Param\n\nAdditional configuration.\n\n## Call Signature\n\n```ts\nfunction injectInfiniteQuery<TQueryFnData, TError, TData, TQueryKey, TPageParam>(injectInfiniteQueryFn, options?): DefinedCreateInfiniteQueryResult<TData, TError>;\n```\n\nDefined in: [inject-infinite-query.ts:41](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-infinite-query.ts#L41)\n\nInjects an infinite query: a declarative dependency on an asynchronous source of data that is tied to a unique key.\nInfinite queries can additively \"load more\" data onto an existing set of data or \"infinite scroll\"\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `InfiniteData`\\<`TQueryFnData`, `unknown`\\>\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n#### TPageParam\n\n`TPageParam` = `unknown`\n\n### Parameters\n\n#### injectInfiniteQueryFn\n\n() => [`DefinedInitialDataInfiniteOptions`](../type-aliases/DefinedInitialDataInfiniteOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\>\n\nA function that returns infinite query options.\n\n#### options?\n\n[`InjectInfiniteQueryOptions`](../interfaces/InjectInfiniteQueryOptions.md)\n\nAdditional configuration.\n\n### Returns\n\n[`DefinedCreateInfiniteQueryResult`](../type-aliases/DefinedCreateInfiniteQueryResult.md)\\<`TData`, `TError`\\>\n\nThe infinite query result.\n\n## Call Signature\n\n```ts\nfunction injectInfiniteQuery<TQueryFnData, TError, TData, TQueryKey, TPageParam>(injectInfiniteQueryFn, options?): CreateInfiniteQueryResult<TData, TError>;\n```\n\nDefined in: [inject-infinite-query.ts:65](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-infinite-query.ts#L65)\n\nInjects an infinite query: a declarative dependency on an asynchronous source of data that is tied to a unique key.\nInfinite queries can additively \"load more\" data onto an existing set of data or \"infinite scroll\"\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `InfiniteData`\\<`TQueryFnData`, `unknown`\\>\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n#### TPageParam\n\n`TPageParam` = `unknown`\n\n### Parameters\n\n#### injectInfiniteQueryFn\n\n() => [`UndefinedInitialDataInfiniteOptions`](../type-aliases/UndefinedInitialDataInfiniteOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\>\n\nA function that returns infinite query options.\n\n#### options?\n\n[`InjectInfiniteQueryOptions`](../interfaces/InjectInfiniteQueryOptions.md)\n\nAdditional configuration.\n\n### Returns\n\n[`CreateInfiniteQueryResult`](../type-aliases/CreateInfiniteQueryResult.md)\\<`TData`, `TError`\\>\n\nThe infinite query result.\n\n## Call Signature\n\n```ts\nfunction injectInfiniteQuery<TQueryFnData, TError, TData, TQueryKey, TPageParam>(injectInfiniteQueryFn, options?): CreateInfiniteQueryResult<TData, TError>;\n```\n\nDefined in: [inject-infinite-query.ts:89](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-infinite-query.ts#L89)\n\nInjects an infinite query: a declarative dependency on an asynchronous source of data that is tied to a unique key.\nInfinite queries can additively \"load more\" data onto an existing set of data or \"infinite scroll\"\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `InfiniteData`\\<`TQueryFnData`, `unknown`\\>\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n#### TPageParam\n\n`TPageParam` = `unknown`\n\n### Parameters\n\n#### injectInfiniteQueryFn\n\n() => [`CreateInfiniteQueryOptions`](../interfaces/CreateInfiniteQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\>\n\nA function that returns infinite query options.\n\n#### options?\n\n[`InjectInfiniteQueryOptions`](../interfaces/InjectInfiniteQueryOptions.md)\n\nAdditional configuration.\n\n### Returns\n\n[`CreateInfiniteQueryResult`](../type-aliases/CreateInfiniteQueryResult.md)\\<`TData`, `TError`\\>\n\nThe infinite query result.\n"
  },
  {
    "path": "docs/framework/angular/reference/functions/injectIsFetching.md",
    "content": "---\nid: injectIsFetching\ntitle: injectIsFetching\n---\n\n# Function: injectIsFetching()\n\n```ts\nfunction injectIsFetching(filters?, options?): Signal<number>;\n```\n\nDefined in: [inject-is-fetching.ts:31](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-is-fetching.ts#L31)\n\nInjects a signal that tracks the number of queries that your application is loading or\nfetching in the background.\n\nCan be used for app-wide loading indicators\n\n## Parameters\n\n### filters?\n\n`QueryFilters`\\<readonly `unknown`[]\\>\n\nThe filters to apply to the query.\n\n### options?\n\n[`InjectIsFetchingOptions`](../interfaces/InjectIsFetchingOptions.md)\n\nAdditional configuration\n\n## Returns\n\n`Signal`\\<`number`\\>\n\nsignal with number of loading or fetching queries.\n"
  },
  {
    "path": "docs/framework/angular/reference/functions/injectIsMutating.md",
    "content": "---\nid: injectIsMutating\ntitle: injectIsMutating\n---\n\n# Function: injectIsMutating()\n\n```ts\nfunction injectIsMutating(filters?, options?): Signal<number>;\n```\n\nDefined in: [inject-is-mutating.ts:30](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-is-mutating.ts#L30)\n\nInjects a signal that tracks the number of mutations that your application is fetching.\n\nCan be used for app-wide loading indicators\n\n## Parameters\n\n### filters?\n\n`MutationFilters`\\<`unknown`, `Error`, `unknown`, `unknown`\\>\n\nThe filters to apply to the query.\n\n### options?\n\n[`InjectIsMutatingOptions`](../interfaces/InjectIsMutatingOptions.md)\n\nAdditional configuration\n\n## Returns\n\n`Signal`\\<`number`\\>\n\nA read-only signal with the number of fetching mutations.\n"
  },
  {
    "path": "docs/framework/angular/reference/functions/injectIsRestoring.md",
    "content": "---\nid: injectIsRestoring\ntitle: injectIsRestoring\n---\n\n# Function: injectIsRestoring()\n\n```ts\nfunction injectIsRestoring(options?): Signal<boolean>;\n```\n\nDefined in: [inject-is-restoring.ts:32](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-is-restoring.ts#L32)\n\nInjects a signal that tracks whether a restore is currently in progress. [injectQuery](injectQuery.md) and friends also check this internally to avoid race conditions between the restore and initializing queries.\n\n## Parameters\n\n### options?\n\n`InjectIsRestoringOptions`\n\nOptions for injectIsRestoring.\n\n## Returns\n\n`Signal`\\<`boolean`\\>\n\nreadonly signal with boolean that indicates whether a restore is in progress.\n"
  },
  {
    "path": "docs/framework/angular/reference/functions/injectMutation.md",
    "content": "---\nid: injectMutation\ntitle: injectMutation\n---\n\n# Function: injectMutation()\n\n```ts\nfunction injectMutation<TData, TError, TVariables, TOnMutateResult>(injectMutationFn, options?): CreateMutationResult<TData, TError, TVariables, TOnMutateResult>;\n```\n\nDefined in: [inject-mutation.ts:45](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-mutation.ts#L45)\n\nInjects a mutation: an imperative function that can be invoked which typically performs server side effects.\n\nUnlike queries, mutations are not run automatically.\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `Error`\n\n### TVariables\n\n`TVariables` = `void`\n\n### TOnMutateResult\n\n`TOnMutateResult` = `unknown`\n\n## Parameters\n\n### injectMutationFn\n\n() => [`CreateMutationOptions`](../interfaces/CreateMutationOptions.md)\\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\\>\n\nA function that returns mutation options.\n\n### options?\n\n[`InjectMutationOptions`](../interfaces/InjectMutationOptions.md)\n\nAdditional configuration\n\n## Returns\n\n[`CreateMutationResult`](../type-aliases/CreateMutationResult.md)\\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\\>\n\nThe mutation.\n"
  },
  {
    "path": "docs/framework/angular/reference/functions/injectMutationState.md",
    "content": "---\nid: injectMutationState\ntitle: injectMutationState\n---\n\n# Function: injectMutationState()\n\n```ts\nfunction injectMutationState<TResult>(injectMutationStateFn, options?): Signal<TResult[]>;\n```\n\nDefined in: [inject-mutation-state.ts:60](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-mutation-state.ts#L60)\n\nInjects a signal that tracks the state of all mutations.\n\n## Type Parameters\n\n### TResult\n\n`TResult` = `MutationState`\\<`unknown`, `Error`, `unknown`, `unknown`\\>\n\n## Parameters\n\n### injectMutationStateFn\n\n() => `MutationStateOptions`\\<`TResult`\\>\n\nA function that returns mutation state options.\n\n### options?\n\n[`InjectMutationStateOptions`](../interfaces/InjectMutationStateOptions.md)\n\nThe Angular injector to use.\n\n## Returns\n\n`Signal`\\<`TResult`[]\\>\n\nThe signal that tracks the state of all mutations.\n"
  },
  {
    "path": "docs/framework/angular/reference/functions/injectQuery.md",
    "content": "---\nid: injectQuery\ntitle: injectQuery\n---\n\n# Function: injectQuery()\n\nInjects a query: a declarative dependency on an asynchronous source of data that is tied to a unique key.\n\n**Basic example**\n```ts\nclass ServiceOrComponent {\n  query = injectQuery(() => ({\n    queryKey: ['repoData'],\n    queryFn: () =>\n      this.#http.get<Response>('https://api.github.com/repos/tanstack/query'),\n  }))\n}\n```\n\nSimilar to `computed` from Angular, the function passed to `injectQuery` will be run in the reactive context.\nIn the example below, the query will be automatically enabled and executed when the filter signal changes\nto a truthy value. When the filter signal changes back to a falsy value, the query will be disabled.\n\n**Reactive example**\n```ts\nclass ServiceOrComponent {\n  filter = signal('')\n\n  todosQuery = injectQuery(() => ({\n    queryKey: ['todos', this.filter()],\n    queryFn: () => fetchTodos(this.filter()),\n    // Signals can be combined with expressions\n    enabled: !!this.filter(),\n  }))\n}\n```\n\n## Param\n\nA function that returns query options.\n\n## Param\n\nAdditional configuration\n\n## See\n\nhttps://tanstack.com/query/latest/docs/framework/angular/guides/queries\n\n## Call Signature\n\n```ts\nfunction injectQuery<TQueryFnData, TError, TData, TQueryKey>(injectQueryFn, options?): DefinedCreateQueryResult<TData, TError>;\n```\n\nDefined in: [inject-query.ts:65](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-query.ts#L65)\n\nInjects a query: a declarative dependency on an asynchronous source of data that is tied to a unique key.\n\n**Basic example**\n```ts\nclass ServiceOrComponent {\n  query = injectQuery(() => ({\n    queryKey: ['repoData'],\n    queryFn: () =>\n      this.#http.get<Response>('https://api.github.com/repos/tanstack/query'),\n  }))\n}\n```\n\nSimilar to `computed` from Angular, the function passed to `injectQuery` will be run in the reactive context.\nIn the example below, the query will be automatically enabled and executed when the filter signal changes\nto a truthy value. When the filter signal changes back to a falsy value, the query will be disabled.\n\n**Reactive example**\n```ts\nclass ServiceOrComponent {\n  filter = signal('')\n\n  todosQuery = injectQuery(() => ({\n    queryKey: ['todos', this.filter()],\n    queryFn: () => fetchTodos(this.filter()),\n    // Signals can be combined with expressions\n    enabled: !!this.filter(),\n  }))\n}\n```\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `TQueryFnData`\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n### Parameters\n\n#### injectQueryFn\n\n() => [`DefinedInitialDataOptions`](../type-aliases/DefinedInitialDataOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>\n\nA function that returns query options.\n\n#### options?\n\n[`InjectQueryOptions`](../interfaces/InjectQueryOptions.md)\n\nAdditional configuration\n\n### Returns\n\n[`DefinedCreateQueryResult`](../type-aliases/DefinedCreateQueryResult.md)\\<`TData`, `TError`\\>\n\nThe query result.\n\n### See\n\nhttps://tanstack.com/query/latest/docs/framework/angular/guides/queries\n\n## Call Signature\n\n```ts\nfunction injectQuery<TQueryFnData, TError, TData, TQueryKey>(injectQueryFn, options?): CreateQueryResult<TData, TError>;\n```\n\nDefined in: [inject-query.ts:116](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-query.ts#L116)\n\nInjects a query: a declarative dependency on an asynchronous source of data that is tied to a unique key.\n\n**Basic example**\n```ts\nclass ServiceOrComponent {\n  query = injectQuery(() => ({\n    queryKey: ['repoData'],\n    queryFn: () =>\n      this.#http.get<Response>('https://api.github.com/repos/tanstack/query'),\n  }))\n}\n```\n\nSimilar to `computed` from Angular, the function passed to `injectQuery` will be run in the reactive context.\nIn the example below, the query will be automatically enabled and executed when the filter signal changes\nto a truthy value. When the filter signal changes back to a falsy value, the query will be disabled.\n\n**Reactive example**\n```ts\nclass ServiceOrComponent {\n  filter = signal('')\n\n  todosQuery = injectQuery(() => ({\n    queryKey: ['todos', this.filter()],\n    queryFn: () => fetchTodos(this.filter()),\n    // Signals can be combined with expressions\n    enabled: !!this.filter(),\n  }))\n}\n```\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `TQueryFnData`\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n### Parameters\n\n#### injectQueryFn\n\n() => [`UndefinedInitialDataOptions`](../type-aliases/UndefinedInitialDataOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>\n\nA function that returns query options.\n\n#### options?\n\n[`InjectQueryOptions`](../interfaces/InjectQueryOptions.md)\n\nAdditional configuration\n\n### Returns\n\n[`CreateQueryResult`](../type-aliases/CreateQueryResult.md)\\<`TData`, `TError`\\>\n\nThe query result.\n\n### See\n\nhttps://tanstack.com/query/latest/docs/framework/angular/guides/queries\n\n## Call Signature\n\n```ts\nfunction injectQuery<TQueryFnData, TError, TData, TQueryKey>(injectQueryFn, options?): CreateQueryResult<TData, TError>;\n```\n\nDefined in: [inject-query.ts:167](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-query.ts#L167)\n\nInjects a query: a declarative dependency on an asynchronous source of data that is tied to a unique key.\n\n**Basic example**\n```ts\nclass ServiceOrComponent {\n  query = injectQuery(() => ({\n    queryKey: ['repoData'],\n    queryFn: () =>\n      this.#http.get<Response>('https://api.github.com/repos/tanstack/query'),\n  }))\n}\n```\n\nSimilar to `computed` from Angular, the function passed to `injectQuery` will be run in the reactive context.\nIn the example below, the query will be automatically enabled and executed when the filter signal changes\nto a truthy value. When the filter signal changes back to a falsy value, the query will be disabled.\n\n**Reactive example**\n```ts\nclass ServiceOrComponent {\n  filter = signal('')\n\n  todosQuery = injectQuery(() => ({\n    queryKey: ['todos', this.filter()],\n    queryFn: () => fetchTodos(this.filter()),\n    // Signals can be combined with expressions\n    enabled: !!this.filter(),\n  }))\n}\n```\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `TQueryFnData`\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n### Parameters\n\n#### injectQueryFn\n\n() => [`CreateQueryOptions`](../interfaces/CreateQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>\n\nA function that returns query options.\n\n#### options?\n\n[`InjectQueryOptions`](../interfaces/InjectQueryOptions.md)\n\nAdditional configuration\n\n### Returns\n\n[`CreateQueryResult`](../type-aliases/CreateQueryResult.md)\\<`TData`, `TError`\\>\n\nThe query result.\n\n### See\n\nhttps://tanstack.com/query/latest/docs/framework/angular/guides/queries\n"
  },
  {
    "path": "docs/framework/angular/reference/functions/injectQueryClient.md",
    "content": "---\nid: injectQueryClient\ntitle: injectQueryClient\n---\n\n# ~~Function: injectQueryClient()~~\n\n```ts\nfunction injectQueryClient(injectOptions): QueryClient;\n```\n\nDefined in: [inject-query-client.ts:18](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-query-client.ts#L18)\n\nInjects a `QueryClient` instance and allows passing a custom injector.\n\n## Parameters\n\n### injectOptions\n\n`InjectOptions` & `object` = `{}`\n\nType of the options argument to inject and optionally a custom injector.\n\n## Returns\n\n`QueryClient`\n\nThe `QueryClient` instance.\n\n## Deprecated\n\nUse `inject(QueryClient)` instead.\nIf you need to get a `QueryClient` from a custom injector, use `injector.get(QueryClient)`.\n\n**Example**\n```ts\nconst queryClient = injectQueryClient();\n```\n"
  },
  {
    "path": "docs/framework/angular/reference/functions/mutationOptions.md",
    "content": "---\nid: mutationOptions\ntitle: mutationOptions\n---\n\n# Function: mutationOptions()\n\nAllows to share and re-use mutation options in a type-safe way.\n\n**Example**\n\n```ts\nexport class QueriesService {\n  private http = inject(HttpClient)\n  private queryClient = inject(QueryClient)\n\n  updatePost(id: number) {\n    return mutationOptions({\n      mutationFn: (post: Post) => Promise.resolve(post),\n      mutationKey: [\"updatePost\", id],\n      onSuccess: (newPost) => {\n        //           ^? newPost: Post\n        this.queryClient.setQueryData([\"posts\", id], newPost)\n      },\n    });\n  }\n}\n\nclass ComponentOrService {\n  queries = inject(QueriesService)\n  id = signal(0)\n  mutation = injectMutation(() => this.queries.updatePost(this.id()))\n\n  save() {\n    this.mutation.mutate({ title: 'New Title' })\n  }\n}\n```\n\n## Param\n\nThe mutation options.\n\n## Call Signature\n\n```ts\nfunction mutationOptions<TData, TError, TVariables, TOnMutateResult>(options): WithRequired<CreateMutationOptions<TData, TError, TVariables, TOnMutateResult>, \"mutationKey\">;\n```\n\nDefined in: [mutation-options.ts:39](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/mutation-options.ts#L39)\n\nAllows to share and re-use mutation options in a type-safe way.\n\n**Example**\n\n```ts\nexport class QueriesService {\n  private http = inject(HttpClient)\n  private queryClient = inject(QueryClient)\n\n  updatePost(id: number) {\n    return mutationOptions({\n      mutationFn: (post: Post) => Promise.resolve(post),\n      mutationKey: [\"updatePost\", id],\n      onSuccess: (newPost) => {\n        //           ^? newPost: Post\n        this.queryClient.setQueryData([\"posts\", id], newPost)\n      },\n    });\n  }\n}\n\nclass ComponentOrService {\n  queries = inject(QueriesService)\n  id = signal(0)\n  mutation = injectMutation(() => this.queries.updatePost(this.id()))\n\n  save() {\n    this.mutation.mutate({ title: 'New Title' })\n  }\n}\n```\n\n### Type Parameters\n\n#### TData\n\n`TData` = `unknown`\n\n#### TError\n\n`TError` = `Error`\n\n#### TVariables\n\n`TVariables` = `void`\n\n#### TOnMutateResult\n\n`TOnMutateResult` = `unknown`\n\n### Parameters\n\n#### options\n\n`WithRequired`\\<[`CreateMutationOptions`](../interfaces/CreateMutationOptions.md)\\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\\>, `\"mutationKey\"`\\>\n\nThe mutation options.\n\n### Returns\n\n`WithRequired`\\<[`CreateMutationOptions`](../interfaces/CreateMutationOptions.md)\\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\\>, `\"mutationKey\"`\\>\n\nMutation options.\n\n## Call Signature\n\n```ts\nfunction mutationOptions<TData, TError, TVariables, TOnMutateResult>(options): Omit<CreateMutationOptions<TData, TError, TVariables, TOnMutateResult>, \"mutationKey\">;\n```\n\nDefined in: [mutation-options.ts:53](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/mutation-options.ts#L53)\n\nAllows to share and re-use mutation options in a type-safe way.\n\n**Example**\n\n```ts\nexport class QueriesService {\n  private http = inject(HttpClient)\n  private queryClient = inject(QueryClient)\n\n  updatePost(id: number) {\n    return mutationOptions({\n      mutationFn: (post: Post) => Promise.resolve(post),\n      mutationKey: [\"updatePost\", id],\n      onSuccess: (newPost) => {\n        //           ^? newPost: Post\n        this.queryClient.setQueryData([\"posts\", id], newPost)\n      },\n    });\n  }\n}\n\nclass ComponentOrService {\n  queries = inject(QueriesService)\n  id = signal(0)\n  mutation = injectMutation(() => this.queries.updatePost(this.id()))\n\n  save() {\n    this.mutation.mutate({ title: 'New Title' })\n  }\n}\n```\n\n### Type Parameters\n\n#### TData\n\n`TData` = `unknown`\n\n#### TError\n\n`TError` = `Error`\n\n#### TVariables\n\n`TVariables` = `void`\n\n#### TOnMutateResult\n\n`TOnMutateResult` = `unknown`\n\n### Parameters\n\n#### options\n\n`Omit`\\<[`CreateMutationOptions`](../interfaces/CreateMutationOptions.md)\\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\\>, `\"mutationKey\"`\\>\n\nThe mutation options.\n\n### Returns\n\n`Omit`\\<[`CreateMutationOptions`](../interfaces/CreateMutationOptions.md)\\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\\>, `\"mutationKey\"`\\>\n\nMutation options.\n"
  },
  {
    "path": "docs/framework/angular/reference/functions/provideAngularQuery.md",
    "content": "---\nid: provideAngularQuery\ntitle: provideAngularQuery\n---\n\n# ~~Function: provideAngularQuery()~~\n\n```ts\nfunction provideAngularQuery(queryClient): Provider[];\n```\n\nDefined in: [providers.ts:124](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/providers.ts#L124)\n\nSets up providers necessary to enable TanStack Query functionality for Angular applications.\n\nAllows to configure a `QueryClient`.\n\n## Parameters\n\n### queryClient\n\n`QueryClient`\n\nA `QueryClient` instance.\n\n## Returns\n\n`Provider`[]\n\nA set of providers to set up TanStack Query.\n\n## See\n\nhttps://tanstack.com/query/v5/docs/framework/angular/quick-start\n\n## Deprecated\n\nUse `provideTanStackQuery` instead.\n"
  },
  {
    "path": "docs/framework/angular/reference/functions/provideIsRestoring.md",
    "content": "---\nid: provideIsRestoring\ntitle: provideIsRestoring\n---\n\n# Function: provideIsRestoring()\n\n```ts\nfunction provideIsRestoring(isRestoring): Provider;\n```\n\nDefined in: [inject-is-restoring.ts:43](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-is-restoring.ts#L43)\n\nUsed by TanStack Query Angular persist client plugin to provide the signal that tracks the restore state\n\n## Parameters\n\n### isRestoring\n\n`Signal`\\<`boolean`\\>\n\na readonly signal that returns a boolean\n\n## Returns\n\n`Provider`\n\nProvider for the `isRestoring` signal\n"
  },
  {
    "path": "docs/framework/angular/reference/functions/provideQueryClient.md",
    "content": "---\nid: provideQueryClient\ntitle: provideQueryClient\n---\n\n# Function: provideQueryClient()\n\n```ts\nfunction provideQueryClient(queryClient): Provider;\n```\n\nDefined in: [providers.ts:14](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/providers.ts#L14)\n\nUsually [provideTanStackQuery](provideTanStackQuery.md) is used once to set up TanStack Query and the\n[https://tanstack.com/query/latest/docs/reference/QueryClient\\|QueryClient](https://tanstack.com/query/latest/docs/reference/QueryClient|QueryClient)\nfor the entire application. Internally it calls `provideQueryClient`.\nYou can use `provideQueryClient` to provide a different `QueryClient` instance for a part\nof the application or for unit testing purposes.\n\n## Parameters\n\n### queryClient\n\nA `QueryClient` instance, or an `InjectionToken` which provides a `QueryClient`.\n\n`QueryClient` | `InjectionToken`\\<`QueryClient`\\>\n\n## Returns\n\n`Provider`\n\na provider object that can be used to provide the `QueryClient` instance.\n"
  },
  {
    "path": "docs/framework/angular/reference/functions/provideTanStackQuery.md",
    "content": "---\nid: provideTanStackQuery\ntitle: provideTanStackQuery\n---\n\n# Function: provideTanStackQuery()\n\n```ts\nfunction provideTanStackQuery(queryClient, ...features): Provider[];\n```\n\nDefined in: [providers.ts:105](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/providers.ts#L105)\n\nSets up providers necessary to enable TanStack Query functionality for Angular applications.\n\nAllows to configure a `QueryClient` and optional features such as developer tools.\n\n**Example - standalone**\n\n```ts\nimport {\n  provideTanStackQuery,\n  QueryClient,\n} from '@tanstack/angular-query-experimental'\n\nbootstrapApplication(AppComponent, {\n  providers: [provideTanStackQuery(new QueryClient())],\n})\n```\n\n**Example - NgModule-based**\n\n```ts\nimport {\n  provideTanStackQuery,\n  QueryClient,\n} from '@tanstack/angular-query-experimental'\n\n@NgModule({\n  declarations: [AppComponent],\n  imports: [BrowserModule],\n  providers: [provideTanStackQuery(new QueryClient())],\n  bootstrap: [AppComponent],\n})\nexport class AppModule {}\n```\n\nYou can also enable optional developer tools by adding `withDevtools`. By\ndefault the tools will then be loaded when your app is in development mode.\n```ts\nimport {\n  provideTanStackQuery,\n  withDevtools\n  QueryClient,\n} from '@tanstack/angular-query-experimental'\n\nbootstrapApplication(AppComponent,\n  {\n    providers: [\n      provideTanStackQuery(new QueryClient(), withDevtools())\n    ]\n  }\n)\n```\n\n**Example: using an InjectionToken**\n\n```ts\nexport const MY_QUERY_CLIENT = new InjectionToken('', {\n  factory: () => new QueryClient(),\n})\n\n// In a lazy loaded route or lazy loaded component's providers array:\nproviders: [provideTanStackQuery(MY_QUERY_CLIENT)]\n```\nUsing an InjectionToken for the QueryClient is an advanced optimization which allows TanStack Query to be absent from the main application bundle.\nThis can be beneficial if you want to include TanStack Query on lazy loaded routes only while still sharing a `QueryClient`.\n\nNote that this is a small optimization and for most applications it's preferable to provide the `QueryClient` in the main application config.\n\n## Parameters\n\n### queryClient\n\nA `QueryClient` instance, or an `InjectionToken` which provides a `QueryClient`.\n\n`QueryClient` | `InjectionToken`\\<`QueryClient`\\>\n\n### features\n\n...[`QueryFeatures`](../type-aliases/QueryFeatures.md)[]\n\nOptional features to configure additional Query functionality.\n\n## Returns\n\n`Provider`[]\n\nA set of providers to set up TanStack Query.\n\n## See\n\n - https://tanstack.com/query/v5/docs/framework/angular/quick-start\n - withDevtools\n"
  },
  {
    "path": "docs/framework/angular/reference/functions/queryFeature.md",
    "content": "---\nid: queryFeature\ntitle: queryFeature\n---\n\n# Function: queryFeature()\n\n```ts\nfunction queryFeature<TFeatureKind>(kind, providers): QueryFeature<TFeatureKind>;\n```\n\nDefined in: [providers.ts:146](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/providers.ts#L146)\n\nHelper function to create an object that represents a Query feature.\n\n## Type Parameters\n\n### TFeatureKind\n\n`TFeatureKind` *extends* `\"Devtools\"` \\| `\"PersistQueryClient\"`\n\n## Parameters\n\n### kind\n\n`TFeatureKind`\n\n### providers\n\n`Provider`[]\n\n## Returns\n\n[`QueryFeature`](../interfaces/QueryFeature.md)\\<`TFeatureKind`\\>\n\nA Query feature.\n"
  },
  {
    "path": "docs/framework/angular/reference/functions/queryOptions.md",
    "content": "---\nid: queryOptions\ntitle: queryOptions\n---\n\n# Function: queryOptions()\n\nAllows to share and re-use query options in a type-safe way.\n\nThe `queryKey` will be tagged with the type from `queryFn`.\n\n**Example**\n\n```ts\n const { queryKey } = queryOptions({\n    queryKey: ['key'],\n    queryFn: () => Promise.resolve(5),\n    //  ^?  Promise<number>\n  })\n\n  const queryClient = new QueryClient()\n  const data = queryClient.getQueryData(queryKey)\n  //    ^?  number | undefined\n```\n\n## Param\n\nThe query options to tag with the type from `queryFn`.\n\n## Call Signature\n\n```ts\nfunction queryOptions<TQueryFnData, TError, TData, TQueryKey>(options): Omit<CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>, \"queryFn\"> & object & object;\n```\n\nDefined in: [query-options.ts:76](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/query-options.ts#L76)\n\nAllows to share and re-use query options in a type-safe way.\n\nThe `queryKey` will be tagged with the type from `queryFn`.\n\n**Example**\n\n```ts\n const { queryKey } = queryOptions({\n    queryKey: ['key'],\n    queryFn: () => Promise.resolve(5),\n    //  ^?  Promise<number>\n  })\n\n  const queryClient = new QueryClient()\n  const data = queryClient.getQueryData(queryKey)\n  //    ^?  number | undefined\n```\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `TQueryFnData`\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n### Parameters\n\n#### options\n\n[`DefinedInitialDataOptions`](../type-aliases/DefinedInitialDataOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>\n\nThe query options to tag with the type from `queryFn`.\n\n### Returns\n\n`Omit`\\<[`CreateQueryOptions`](../interfaces/CreateQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>, `\"queryFn\"`\\> & `object` & `object`\n\nThe tagged query options.\n\n## Call Signature\n\n```ts\nfunction queryOptions<TQueryFnData, TError, TData, TQueryKey>(options): OmitKeyof<CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>, \"queryFn\"> & object & object;\n```\n\nDefined in: [query-options.ts:108](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/query-options.ts#L108)\n\nAllows to share and re-use query options in a type-safe way.\n\nThe `queryKey` will be tagged with the type from `queryFn`.\n\n**Example**\n\n```ts\n const { queryKey } = queryOptions({\n    queryKey: ['key'],\n    queryFn: () => Promise.resolve(5),\n    //  ^?  Promise<number>\n  })\n\n  const queryClient = new QueryClient()\n  const data = queryClient.getQueryData(queryKey)\n  //    ^?  number | undefined\n```\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `TQueryFnData`\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n### Parameters\n\n#### options\n\n[`UnusedSkipTokenOptions`](../type-aliases/UnusedSkipTokenOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>\n\nThe query options to tag with the type from `queryFn`.\n\n### Returns\n\n`OmitKeyof`\\<[`CreateQueryOptions`](../interfaces/CreateQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>, `\"queryFn\"`\\> & `object` & `object`\n\nThe tagged query options.\n\n## Call Signature\n\n```ts\nfunction queryOptions<TQueryFnData, TError, TData, TQueryKey>(options): CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey> & object & object;\n```\n\nDefined in: [query-options.ts:140](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/query-options.ts#L140)\n\nAllows to share and re-use query options in a type-safe way.\n\nThe `queryKey` will be tagged with the type from `queryFn`.\n\n**Example**\n\n```ts\n const { queryKey } = queryOptions({\n    queryKey: ['key'],\n    queryFn: () => Promise.resolve(5),\n    //  ^?  Promise<number>\n  })\n\n  const queryClient = new QueryClient()\n  const data = queryClient.getQueryData(queryKey)\n  //    ^?  number | undefined\n```\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `TQueryFnData`\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n### Parameters\n\n#### options\n\n[`UndefinedInitialDataOptions`](../type-aliases/UndefinedInitialDataOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>\n\nThe query options to tag with the type from `queryFn`.\n\n### Returns\n\n[`CreateQueryOptions`](../interfaces/CreateQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\> & `object` & `object`\n\nThe tagged query options.\n"
  },
  {
    "path": "docs/framework/angular/reference/index.md",
    "content": "---\nid: \"@tanstack/angular-query-experimental\"\ntitle: \"@tanstack/angular-query-experimental\"\n---\n\n# @tanstack/angular-query-experimental\n\n## Interfaces\n\n- [BaseMutationNarrowing](interfaces/BaseMutationNarrowing.md)\n- [BaseQueryNarrowing](interfaces/BaseQueryNarrowing.md)\n- [CreateBaseQueryOptions](interfaces/CreateBaseQueryOptions.md)\n- [CreateInfiniteQueryOptions](interfaces/CreateInfiniteQueryOptions.md)\n- [CreateMutationOptions](interfaces/CreateMutationOptions.md)\n- [CreateQueryOptions](interfaces/CreateQueryOptions.md)\n- [InjectInfiniteQueryOptions](interfaces/InjectInfiniteQueryOptions.md)\n- [InjectIsFetchingOptions](interfaces/InjectIsFetchingOptions.md)\n- [InjectIsMutatingOptions](interfaces/InjectIsMutatingOptions.md)\n- [InjectMutationOptions](interfaces/InjectMutationOptions.md)\n- [InjectMutationStateOptions](interfaces/InjectMutationStateOptions.md)\n- [InjectQueryOptions](interfaces/InjectQueryOptions.md)\n- [QueryFeature](interfaces/QueryFeature.md)\n\n## Type Aliases\n\n- [CreateBaseMutationResult](type-aliases/CreateBaseMutationResult.md)\n- [CreateBaseQueryResult](type-aliases/CreateBaseQueryResult.md)\n- [CreateInfiniteQueryResult](type-aliases/CreateInfiniteQueryResult.md)\n- [CreateMutateAsyncFunction](type-aliases/CreateMutateAsyncFunction.md)\n- [CreateMutateFunction](type-aliases/CreateMutateFunction.md)\n- [CreateMutationResult](type-aliases/CreateMutationResult.md)\n- [CreateQueryResult](type-aliases/CreateQueryResult.md)\n- [DefinedCreateInfiniteQueryResult](type-aliases/DefinedCreateInfiniteQueryResult.md)\n- [DefinedCreateQueryResult](type-aliases/DefinedCreateQueryResult.md)\n- [DefinedInitialDataInfiniteOptions](type-aliases/DefinedInitialDataInfiniteOptions.md)\n- [DefinedInitialDataOptions](type-aliases/DefinedInitialDataOptions.md)\n- [DevtoolsFeature](type-aliases/DevtoolsFeature.md)\n- [PersistQueryClientFeature](type-aliases/PersistQueryClientFeature.md)\n- [QueriesOptions](type-aliases/QueriesOptions.md)\n- [QueriesResults](type-aliases/QueriesResults.md)\n- [QueryFeatures](type-aliases/QueryFeatures.md)\n- [UndefinedInitialDataInfiniteOptions](type-aliases/UndefinedInitialDataInfiniteOptions.md)\n- [UndefinedInitialDataOptions](type-aliases/UndefinedInitialDataOptions.md)\n- [UnusedSkipTokenInfiniteOptions](type-aliases/UnusedSkipTokenInfiniteOptions.md)\n- [UnusedSkipTokenOptions](type-aliases/UnusedSkipTokenOptions.md)\n\n## Functions\n\n- [infiniteQueryOptions](functions/infiniteQueryOptions.md)\n- [injectInfiniteQuery](functions/injectInfiniteQuery.md)\n- [injectIsFetching](functions/injectIsFetching.md)\n- [injectIsMutating](functions/injectIsMutating.md)\n- [injectIsRestoring](functions/injectIsRestoring.md)\n- [injectMutation](functions/injectMutation.md)\n- [injectMutationState](functions/injectMutationState.md)\n- [injectQuery](functions/injectQuery.md)\n- [~~injectQueryClient~~](functions/injectQueryClient.md)\n- [mutationOptions](functions/mutationOptions.md)\n- [~~provideAngularQuery~~](functions/provideAngularQuery.md)\n- [provideIsRestoring](functions/provideIsRestoring.md)\n- [provideQueryClient](functions/provideQueryClient.md)\n- [provideTanStackQuery](functions/provideTanStackQuery.md)\n- [queryFeature](functions/queryFeature.md)\n- [queryOptions](functions/queryOptions.md)\n"
  },
  {
    "path": "docs/framework/angular/reference/interfaces/BaseMutationNarrowing.md",
    "content": "---\nid: BaseMutationNarrowing\ntitle: BaseMutationNarrowing\n---\n\n# Interface: BaseMutationNarrowing\\<TData, TError, TVariables, TOnMutateResult\\>\n\nDefined in: [types.ts:190](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L190)\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TVariables\n\n`TVariables` = `unknown`\n\n### TOnMutateResult\n\n`TOnMutateResult` = `unknown`\n\n## Properties\n\n### isError\n\n```ts\nisError: SignalFunction<(this) => this is CreateMutationResult<TData, TError, TVariables, TOnMutateResult, Override<MutationObserverErrorResult<TData, TError, TVariables, TOnMutateResult>, { mutate: CreateMutateFunction<TData, TError, TVariables, TOnMutateResult> }> & { mutateAsync: CreateMutateAsyncFunction<TData, TError, TVariables, TOnMutateResult> }>>;\n```\n\nDefined in: [types.ts:213](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L213)\n\n***\n\n### isIdle\n\n```ts\nisIdle: SignalFunction<(this) => this is CreateMutationResult<TData, TError, TVariables, TOnMutateResult, Override<MutationObserverIdleResult<TData, TError, TVariables, TOnMutateResult>, { mutate: CreateMutateFunction<TData, TError, TVariables, TOnMutateResult> }> & { mutateAsync: CreateMutateAsyncFunction<TData, TError, TVariables, TOnMutateResult> }>>;\n```\n\nDefined in: [types.ts:247](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L247)\n\n***\n\n### isPending\n\n```ts\nisPending: SignalFunction<(this) => this is CreateMutationResult<TData, TError, TVariables, TOnMutateResult, Override<MutationObserverLoadingResult<TData, TError, TVariables, TOnMutateResult>, { mutate: CreateMutateFunction<TData, TError, TVariables, TOnMutateResult> }> & { mutateAsync: CreateMutateAsyncFunction<TData, TError, TVariables, TOnMutateResult> }>>;\n```\n\nDefined in: [types.ts:230](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L230)\n\n***\n\n### isSuccess\n\n```ts\nisSuccess: SignalFunction<(this) => this is CreateMutationResult<TData, TError, TVariables, TOnMutateResult, Override<MutationObserverSuccessResult<TData, TError, TVariables, TOnMutateResult>, { mutate: CreateMutateFunction<TData, TError, TVariables, TOnMutateResult> }> & { mutateAsync: CreateMutateAsyncFunction<TData, TError, TVariables, TOnMutateResult> }>>;\n```\n\nDefined in: [types.ts:196](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L196)\n"
  },
  {
    "path": "docs/framework/angular/reference/interfaces/BaseQueryNarrowing.md",
    "content": "---\nid: BaseQueryNarrowing\ntitle: BaseQueryNarrowing\n---\n\n# Interface: BaseQueryNarrowing\\<TData, TError\\>\n\nDefined in: [types.ts:57](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L57)\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n## Properties\n\n### isError()\n\n```ts\nisError: (this) => this is CreateBaseQueryResult<TData, TError, CreateStatusBasedQueryResult<\"error\", TData, TError>>;\n```\n\nDefined in: [types.ts:65](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L65)\n\n#### Parameters\n\n##### this\n\n[`CreateBaseQueryResult`](../type-aliases/CreateBaseQueryResult.md)\\<`TData`, `TError`\\>\n\n#### Returns\n\n`this is CreateBaseQueryResult<TData, TError, CreateStatusBasedQueryResult<\"error\", TData, TError>>`\n\n***\n\n### isPending()\n\n```ts\nisPending: (this) => this is CreateBaseQueryResult<TData, TError, CreateStatusBasedQueryResult<\"pending\", TData, TError>>;\n```\n\nDefined in: [types.ts:72](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L72)\n\n#### Parameters\n\n##### this\n\n[`CreateBaseQueryResult`](../type-aliases/CreateBaseQueryResult.md)\\<`TData`, `TError`\\>\n\n#### Returns\n\n`this is CreateBaseQueryResult<TData, TError, CreateStatusBasedQueryResult<\"pending\", TData, TError>>`\n\n***\n\n### isSuccess()\n\n```ts\nisSuccess: (this) => this is CreateBaseQueryResult<TData, TError, CreateStatusBasedQueryResult<\"success\", TData, TError>>;\n```\n\nDefined in: [types.ts:58](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L58)\n\n#### Parameters\n\n##### this\n\n[`CreateBaseQueryResult`](../type-aliases/CreateBaseQueryResult.md)\\<`TData`, `TError`\\>\n\n#### Returns\n\n`this is CreateBaseQueryResult<TData, TError, CreateStatusBasedQueryResult<\"success\", TData, TError>>`\n"
  },
  {
    "path": "docs/framework/angular/reference/interfaces/CreateBaseQueryOptions.md",
    "content": "---\nid: CreateBaseQueryOptions\ntitle: CreateBaseQueryOptions\n---\n\n# Interface: CreateBaseQueryOptions\\<TQueryFnData, TError, TData, TQueryData, TQueryKey\\>\n\nDefined in: [types.ts:21](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L21)\n\n## Extends\n\n- `QueryObserverOptions`\\<`TQueryFnData`, `TError`, `TData`, `TQueryData`, `TQueryKey`\\>\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `TQueryFnData`\n\n### TQueryData\n\n`TQueryData` = `TQueryFnData`\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n"
  },
  {
    "path": "docs/framework/angular/reference/interfaces/CreateInfiniteQueryOptions.md",
    "content": "---\nid: CreateInfiniteQueryOptions\ntitle: CreateInfiniteQueryOptions\n---\n\n# Interface: CreateInfiniteQueryOptions\\<TQueryFnData, TError, TData, TQueryKey, TPageParam\\>\n\nDefined in: [types.ts:81](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L81)\n\n## Extends\n\n- `OmitKeyof`\\<`InfiniteQueryObserverOptions`\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\>, `\"suspense\"`\\>\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `TQueryFnData`\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n\n### TPageParam\n\n`TPageParam` = `unknown`\n"
  },
  {
    "path": "docs/framework/angular/reference/interfaces/CreateMutationOptions.md",
    "content": "---\nid: CreateMutationOptions\ntitle: CreateMutationOptions\n---\n\n# Interface: CreateMutationOptions\\<TData, TError, TVariables, TOnMutateResult\\>\n\nDefined in: [types.ts:132](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L132)\n\n## Extends\n\n- `OmitKeyof`\\<`MutationObserverOptions`\\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\\>, `\"_defaulted\"`\\>\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TVariables\n\n`TVariables` = `void`\n\n### TOnMutateResult\n\n`TOnMutateResult` = `unknown`\n"
  },
  {
    "path": "docs/framework/angular/reference/interfaces/CreateQueryOptions.md",
    "content": "---\nid: CreateQueryOptions\ntitle: CreateQueryOptions\n---\n\n# Interface: CreateQueryOptions\\<TQueryFnData, TError, TData, TQueryKey\\>\n\nDefined in: [types.ts:35](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L35)\n\n## Extends\n\n- `OmitKeyof`\\<[`CreateBaseQueryOptions`](CreateBaseQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryFnData`, `TQueryKey`\\>, `\"suspense\"`\\>\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `TQueryFnData`\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n"
  },
  {
    "path": "docs/framework/angular/reference/interfaces/InjectInfiniteQueryOptions.md",
    "content": "---\nid: InjectInfiniteQueryOptions\ntitle: InjectInfiniteQueryOptions\n---\n\n# Interface: InjectInfiniteQueryOptions\n\nDefined in: [inject-infinite-query.ts:25](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-infinite-query.ts#L25)\n\n## Properties\n\n### injector?\n\n```ts\noptional injector: Injector;\n```\n\nDefined in: [inject-infinite-query.ts:31](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-infinite-query.ts#L31)\n\nThe `Injector` in which to create the infinite query.\n\nIf this is not provided, the current injection context will be used instead (via `inject`).\n"
  },
  {
    "path": "docs/framework/angular/reference/interfaces/InjectIsFetchingOptions.md",
    "content": "---\nid: InjectIsFetchingOptions\ntitle: InjectIsFetchingOptions\n---\n\n# Interface: InjectIsFetchingOptions\n\nDefined in: [inject-is-fetching.ts:13](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-is-fetching.ts#L13)\n\n## Properties\n\n### injector?\n\n```ts\noptional injector: Injector;\n```\n\nDefined in: [inject-is-fetching.ts:19](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-is-fetching.ts#L19)\n\nThe `Injector` in which to create the isFetching signal.\n\nIf this is not provided, the current injection context will be used instead (via `inject`).\n"
  },
  {
    "path": "docs/framework/angular/reference/interfaces/InjectIsMutatingOptions.md",
    "content": "---\nid: InjectIsMutatingOptions\ntitle: InjectIsMutatingOptions\n---\n\n# Interface: InjectIsMutatingOptions\n\nDefined in: [inject-is-mutating.ts:13](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-is-mutating.ts#L13)\n\n## Properties\n\n### injector?\n\n```ts\noptional injector: Injector;\n```\n\nDefined in: [inject-is-mutating.ts:19](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-is-mutating.ts#L19)\n\nThe `Injector` in which to create the isMutating signal.\n\nIf this is not provided, the current injection context will be used instead (via `inject`).\n"
  },
  {
    "path": "docs/framework/angular/reference/interfaces/InjectMutationOptions.md",
    "content": "---\nid: InjectMutationOptions\ntitle: InjectMutationOptions\n---\n\n# Interface: InjectMutationOptions\n\nDefined in: [inject-mutation.ts:28](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-mutation.ts#L28)\n\n## Properties\n\n### injector?\n\n```ts\noptional injector: Injector;\n```\n\nDefined in: [inject-mutation.ts:34](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-mutation.ts#L34)\n\nThe `Injector` in which to create the mutation.\n\nIf this is not provided, the current injection context will be used instead (via `inject`).\n"
  },
  {
    "path": "docs/framework/angular/reference/interfaces/InjectMutationStateOptions.md",
    "content": "---\nid: InjectMutationStateOptions\ntitle: InjectMutationStateOptions\n---\n\n# Interface: InjectMutationStateOptions\n\nDefined in: [inject-mutation-state.ts:45](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-mutation-state.ts#L45)\n\n## Properties\n\n### injector?\n\n```ts\noptional injector: Injector;\n```\n\nDefined in: [inject-mutation-state.ts:51](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-mutation-state.ts#L51)\n\nThe `Injector` in which to create the mutation state signal.\n\nIf this is not provided, the current injection context will be used instead (via `inject`).\n"
  },
  {
    "path": "docs/framework/angular/reference/interfaces/InjectQueryOptions.md",
    "content": "---\nid: InjectQueryOptions\ntitle: InjectQueryOptions\n---\n\n# Interface: InjectQueryOptions\n\nDefined in: [inject-query.ts:20](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-query.ts#L20)\n\n## Properties\n\n### injector?\n\n```ts\noptional injector: Injector;\n```\n\nDefined in: [inject-query.ts:26](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-query.ts#L26)\n\nThe `Injector` in which to create the query.\n\nIf this is not provided, the current injection context will be used instead (via `inject`).\n"
  },
  {
    "path": "docs/framework/angular/reference/interfaces/QueryFeature.md",
    "content": "---\nid: QueryFeature\ntitle: QueryFeature\n---\n\n# Interface: QueryFeature\\<TFeatureKind\\>\n\nDefined in: [providers.ts:135](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/providers.ts#L135)\n\nHelper type to represent a Query feature.\n\n## Type Parameters\n\n### TFeatureKind\n\n`TFeatureKind` *extends* `QueryFeatureKind`\n\n## Properties\n\n### ɵkind\n\n```ts\nɵkind: TFeatureKind;\n```\n\nDefined in: [providers.ts:136](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/providers.ts#L136)\n\n***\n\n### ɵproviders\n\n```ts\nɵproviders: Provider[];\n```\n\nDefined in: [providers.ts:137](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/providers.ts#L137)\n"
  },
  {
    "path": "docs/framework/angular/reference/type-aliases/CreateBaseMutationResult.md",
    "content": "---\nid: CreateBaseMutationResult\ntitle: CreateBaseMutationResult\n---\n\n# Type Alias: CreateBaseMutationResult\\<TData, TError, TVariables, TOnMutateResult\\>\n\n```ts\ntype CreateBaseMutationResult<TData, TError, TVariables, TOnMutateResult> = Override<MutationObserverResult<TData, TError, TVariables, TOnMutateResult>, {\n  mutate: CreateMutateFunction<TData, TError, TVariables, TOnMutateResult>;\n}> & object;\n```\n\nDefined in: [types.ts:160](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L160)\n\n## Type Declaration\n\n### mutateAsync\n\n```ts\nmutateAsync: CreateMutateAsyncFunction<TData, TError, TVariables, TOnMutateResult>;\n```\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TVariables\n\n`TVariables` = `unknown`\n\n### TOnMutateResult\n\n`TOnMutateResult` = `unknown`\n"
  },
  {
    "path": "docs/framework/angular/reference/type-aliases/CreateBaseQueryResult.md",
    "content": "---\nid: CreateBaseQueryResult\ntitle: CreateBaseQueryResult\n---\n\n# Type Alias: CreateBaseQueryResult\\<TData, TError, TState\\>\n\n```ts\ntype CreateBaseQueryResult<TData, TError, TState> = BaseQueryNarrowing<TData, TError> & MapToSignals<OmitKeyof<TState, keyof BaseQueryNarrowing, \"safely\">>;\n```\n\nDefined in: [types.ts:98](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L98)\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TState\n\n`TState` = `QueryObserverResult`\\<`TData`, `TError`\\>\n"
  },
  {
    "path": "docs/framework/angular/reference/type-aliases/CreateInfiniteQueryResult.md",
    "content": "---\nid: CreateInfiniteQueryResult\ntitle: CreateInfiniteQueryResult\n---\n\n# Type Alias: CreateInfiniteQueryResult\\<TData, TError\\>\n\n```ts\ntype CreateInfiniteQueryResult<TData, TError> = BaseQueryNarrowing<TData, TError> & MapToSignals<InfiniteQueryObserverResult<TData, TError>>;\n```\n\nDefined in: [types.ts:117](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L117)\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n"
  },
  {
    "path": "docs/framework/angular/reference/type-aliases/CreateMutateAsyncFunction.md",
    "content": "---\nid: CreateMutateAsyncFunction\ntitle: CreateMutateAsyncFunction\n---\n\n# Type Alias: CreateMutateAsyncFunction\\<TData, TError, TVariables, TOnMutateResult\\>\n\n```ts\ntype CreateMutateAsyncFunction<TData, TError, TVariables, TOnMutateResult> = MutateFunction<TData, TError, TVariables, TOnMutateResult>;\n```\n\nDefined in: [types.ts:153](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L153)\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TVariables\n\n`TVariables` = `void`\n\n### TOnMutateResult\n\n`TOnMutateResult` = `unknown`\n"
  },
  {
    "path": "docs/framework/angular/reference/type-aliases/CreateMutateFunction.md",
    "content": "---\nid: CreateMutateFunction\ntitle: CreateMutateFunction\n---\n\n# Type Alias: CreateMutateFunction()\\<TData, TError, TVariables, TOnMutateResult\\>\n\n```ts\ntype CreateMutateFunction<TData, TError, TVariables, TOnMutateResult> = (...args) => void;\n```\n\nDefined in: [types.ts:142](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L142)\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TVariables\n\n`TVariables` = `void`\n\n### TOnMutateResult\n\n`TOnMutateResult` = `unknown`\n\n## Parameters\n\n### args\n\n...`Parameters`\\<`MutateFunction`\\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\\>\\>\n\n## Returns\n\n`void`\n"
  },
  {
    "path": "docs/framework/angular/reference/type-aliases/CreateMutationResult.md",
    "content": "---\nid: CreateMutationResult\ntitle: CreateMutationResult\n---\n\n# Type Alias: CreateMutationResult\\<TData, TError, TVariables, TOnMutateResult, TState\\>\n\n```ts\ntype CreateMutationResult<TData, TError, TVariables, TOnMutateResult, TState> = BaseMutationNarrowing<TData, TError, TVariables, TOnMutateResult> & MapToSignals<OmitKeyof<TState, keyof BaseMutationNarrowing, \"safely\">>;\n```\n\nDefined in: [types.ts:266](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L266)\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TVariables\n\n`TVariables` = `unknown`\n\n### TOnMutateResult\n\n`TOnMutateResult` = `unknown`\n\n### TState\n\n`TState` = `CreateStatusBasedMutationResult`\\<[`CreateBaseMutationResult`](CreateBaseMutationResult.md)\\[`\"status\"`\\], `TData`, `TError`, `TVariables`, `TOnMutateResult`\\>\n"
  },
  {
    "path": "docs/framework/angular/reference/type-aliases/CreateQueryResult.md",
    "content": "---\nid: CreateQueryResult\ntitle: CreateQueryResult\n---\n\n# Type Alias: CreateQueryResult\\<TData, TError\\>\n\n```ts\ntype CreateQueryResult<TData, TError> = CreateBaseQueryResult<TData, TError>;\n```\n\nDefined in: [types.ts:105](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L105)\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n"
  },
  {
    "path": "docs/framework/angular/reference/type-aliases/DefinedCreateInfiniteQueryResult.md",
    "content": "---\nid: DefinedCreateInfiniteQueryResult\ntitle: DefinedCreateInfiniteQueryResult\n---\n\n# Type Alias: DefinedCreateInfiniteQueryResult\\<TData, TError, TDefinedInfiniteQueryObserver\\>\n\n```ts\ntype DefinedCreateInfiniteQueryResult<TData, TError, TDefinedInfiniteQueryObserver> = MapToSignals<TDefinedInfiniteQueryObserver>;\n```\n\nDefined in: [types.ts:123](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L123)\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TDefinedInfiniteQueryObserver\n\n`TDefinedInfiniteQueryObserver` = `DefinedInfiniteQueryObserverResult`\\<`TData`, `TError`\\>\n"
  },
  {
    "path": "docs/framework/angular/reference/type-aliases/DefinedCreateQueryResult.md",
    "content": "---\nid: DefinedCreateQueryResult\ntitle: DefinedCreateQueryResult\n---\n\n# Type Alias: DefinedCreateQueryResult\\<TData, TError, TState\\>\n\n```ts\ntype DefinedCreateQueryResult<TData, TError, TState> = BaseQueryNarrowing<TData, TError> & MapToSignals<OmitKeyof<TState, keyof BaseQueryNarrowing, \"safely\">>;\n```\n\nDefined in: [types.ts:110](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/types.ts#L110)\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TState\n\n`TState` = `DefinedQueryObserverResult`\\<`TData`, `TError`\\>\n"
  },
  {
    "path": "docs/framework/angular/reference/type-aliases/DefinedInitialDataInfiniteOptions.md",
    "content": "---\nid: DefinedInitialDataInfiniteOptions\ntitle: DefinedInitialDataInfiniteOptions\n---\n\n# Type Alias: DefinedInitialDataInfiniteOptions\\<TQueryFnData, TError, TData, TQueryKey, TPageParam\\>\n\n```ts\ntype DefinedInitialDataInfiniteOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam> = CreateInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam> & object;\n```\n\nDefined in: [infinite-query-options.ts:62](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/infinite-query-options.ts#L62)\n\n## Type Declaration\n\n### initialData\n\n```ts\ninitialData: \n  | NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>\n  | () => NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>\n  | undefined;\n```\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `InfiniteData`\\<`TQueryFnData`\\>\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n\n### TPageParam\n\n`TPageParam` = `unknown`\n"
  },
  {
    "path": "docs/framework/angular/reference/type-aliases/DefinedInitialDataOptions.md",
    "content": "---\nid: DefinedInitialDataOptions\ntitle: DefinedInitialDataOptions\n---\n\n# Type Alias: DefinedInitialDataOptions\\<TQueryFnData, TError, TData, TQueryKey\\>\n\n```ts\ntype DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> = Omit<CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>, \"queryFn\"> & object;\n```\n\nDefined in: [query-options.ts:40](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/query-options.ts#L40)\n\n## Type Declaration\n\n### initialData\n\n```ts\ninitialData: \n  | NonUndefinedGuard<TQueryFnData>\n| () => NonUndefinedGuard<TQueryFnData>;\n```\n\n### queryFn?\n\n```ts\noptional queryFn: QueryFunction<TQueryFnData, TQueryKey>;\n```\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `TQueryFnData`\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n"
  },
  {
    "path": "docs/framework/angular/reference/type-aliases/DevtoolsFeature.md",
    "content": "---\nid: DevtoolsFeature\ntitle: DevtoolsFeature\n---\n\n# Type Alias: DevtoolsFeature\n\n```ts\ntype DevtoolsFeature = QueryFeature<\"Devtools\">;\n```\n\nDefined in: [providers.ts:158](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/providers.ts#L158)\n\nA type alias that represents a feature which enables developer tools.\nThe type is used to describe the return value of the `withDevtools` function.\n\n## See\n\nwithDevtools\n"
  },
  {
    "path": "docs/framework/angular/reference/type-aliases/PersistQueryClientFeature.md",
    "content": "---\nid: PersistQueryClientFeature\ntitle: PersistQueryClientFeature\n---\n\n# Type Alias: PersistQueryClientFeature\n\n```ts\ntype PersistQueryClientFeature = QueryFeature<\"PersistQueryClient\">;\n```\n\nDefined in: [providers.ts:164](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/providers.ts#L164)\n\nA type alias that represents a feature which enables persistence.\nThe type is used to describe the return value of the `withPersistQueryClient` function.\n"
  },
  {
    "path": "docs/framework/angular/reference/type-aliases/QueriesOptions.md",
    "content": "---\nid: QueriesOptions\ntitle: QueriesOptions\n---\n\n# Type Alias: QueriesOptions\\<T, TResults, TDepth\\>\n\n```ts\ntype QueriesOptions<T, TResults, TDepth> = TDepth[\"length\"] extends MAXIMUM_DEPTH ? QueryObserverOptionsForCreateQueries[] : T extends [] ? [] : T extends [infer Head] ? [...TResults, GetCreateQueryOptionsForCreateQueries<Head>] : T extends [infer Head, ...(infer Tails)] ? QueriesOptions<[...Tails], [...TResults, GetCreateQueryOptionsForCreateQueries<Head>], [...TDepth, 1]> : ReadonlyArray<unknown> extends T ? T : T extends QueryObserverOptionsForCreateQueries<infer TQueryFnData, infer TError, infer TData, infer TQueryKey>[] ? QueryObserverOptionsForCreateQueries<TQueryFnData, TError, TData, TQueryKey>[] : QueryObserverOptionsForCreateQueries[];\n```\n\nDefined in: [inject-queries.ts:144](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-queries.ts#L144)\n\nQueriesOptions reducer recursively unwraps function arguments to infer/enforce type param\n\n## Type Parameters\n\n### T\n\n`T` *extends* `any`[]\n\n### TResults\n\n`TResults` *extends* `any`[] = \\[\\]\n\n### TDepth\n\n`TDepth` *extends* `ReadonlyArray`\\<`number`\\> = \\[\\]\n"
  },
  {
    "path": "docs/framework/angular/reference/type-aliases/QueriesResults.md",
    "content": "---\nid: QueriesResults\ntitle: QueriesResults\n---\n\n# Type Alias: QueriesResults\\<T, TResults, TDepth\\>\n\n```ts\ntype QueriesResults<T, TResults, TDepth> = TDepth[\"length\"] extends MAXIMUM_DEPTH ? CreateQueryResult[] : T extends [] ? [] : T extends [infer Head] ? [...TResults, GetCreateQueryResult<Head>] : T extends [infer Head, ...(infer Tails)] ? QueriesResults<[...Tails], [...TResults, GetCreateQueryResult<Head>], [...TDepth, 1]> : { [K in keyof T]: GetCreateQueryResult<T[K]> };\n```\n\nDefined in: [inject-queries.ts:186](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-queries.ts#L186)\n\nQueriesResults reducer recursively maps type param to results\n\n## Type Parameters\n\n### T\n\n`T` *extends* `any`[]\n\n### TResults\n\n`TResults` *extends* `any`[] = \\[\\]\n\n### TDepth\n\n`TDepth` *extends* `ReadonlyArray`\\<`number`\\> = \\[\\]\n"
  },
  {
    "path": "docs/framework/angular/reference/type-aliases/QueryFeatures.md",
    "content": "---\nid: QueryFeatures\ntitle: QueryFeatures\n---\n\n# Type Alias: QueryFeatures\n\n```ts\ntype QueryFeatures = \n  | DevtoolsFeature\n  | PersistQueryClientFeature;\n```\n\nDefined in: [providers.ts:173](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/providers.ts#L173)\n\nA type alias that represents all Query features available for use with `provideTanStackQuery`.\nFeatures can be enabled by adding special functions to the `provideTanStackQuery` call.\nSee documentation for each symbol to find corresponding function name. See also `provideTanStackQuery`\ndocumentation on how to use those functions.\n\n## See\n\n[provideTanStackQuery](../functions/provideTanStackQuery.md)\n"
  },
  {
    "path": "docs/framework/angular/reference/type-aliases/UndefinedInitialDataInfiniteOptions.md",
    "content": "---\nid: UndefinedInitialDataInfiniteOptions\ntitle: UndefinedInitialDataInfiniteOptions\n---\n\n# Type Alias: UndefinedInitialDataInfiniteOptions\\<TQueryFnData, TError, TData, TQueryKey, TPageParam\\>\n\n```ts\ntype UndefinedInitialDataInfiniteOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam> = CreateInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam> & object;\n```\n\nDefined in: [infinite-query-options.ts:13](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/infinite-query-options.ts#L13)\n\n## Type Declaration\n\n### initialData?\n\n```ts\noptional initialData: \n  | NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>\n| InitialDataFunction<NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>>;\n```\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `InfiniteData`\\<`TQueryFnData`\\>\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n\n### TPageParam\n\n`TPageParam` = `unknown`\n"
  },
  {
    "path": "docs/framework/angular/reference/type-aliases/UndefinedInitialDataOptions.md",
    "content": "---\nid: UndefinedInitialDataOptions\ntitle: UndefinedInitialDataOptions\n---\n\n# Type Alias: UndefinedInitialDataOptions\\<TQueryFnData, TError, TData, TQueryKey\\>\n\n```ts\ntype UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> = CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey> & object;\n```\n\nDefined in: [query-options.ts:13](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/query-options.ts#L13)\n\n## Type Declaration\n\n### initialData?\n\n```ts\noptional initialData: \n  | InitialDataFunction<NonUndefinedGuard<TQueryFnData>>\n| NonUndefinedGuard<TQueryFnData>;\n```\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `TQueryFnData`\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n"
  },
  {
    "path": "docs/framework/angular/reference/type-aliases/UnusedSkipTokenInfiniteOptions.md",
    "content": "---\nid: UnusedSkipTokenInfiniteOptions\ntitle: UnusedSkipTokenInfiniteOptions\n---\n\n# Type Alias: UnusedSkipTokenInfiniteOptions\\<TQueryFnData, TError, TData, TQueryKey, TPageParam\\>\n\n```ts\ntype UnusedSkipTokenInfiniteOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam> = OmitKeyof<CreateInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>, \"queryFn\"> & object;\n```\n\nDefined in: [infinite-query-options.ts:34](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/infinite-query-options.ts#L34)\n\n## Type Declaration\n\n### queryFn?\n\n```ts\noptional queryFn: Exclude<CreateInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>[\"queryFn\"], SkipToken | undefined>;\n```\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `InfiniteData`\\<`TQueryFnData`\\>\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n\n### TPageParam\n\n`TPageParam` = `unknown`\n"
  },
  {
    "path": "docs/framework/angular/reference/type-aliases/UnusedSkipTokenOptions.md",
    "content": "---\nid: UnusedSkipTokenOptions\ntitle: UnusedSkipTokenOptions\n---\n\n# Type Alias: UnusedSkipTokenOptions\\<TQueryFnData, TError, TData, TQueryKey\\>\n\n```ts\ntype UnusedSkipTokenOptions<TQueryFnData, TError, TData, TQueryKey> = OmitKeyof<CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>, \"queryFn\"> & object;\n```\n\nDefined in: [query-options.ts:25](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/query-options.ts#L25)\n\n## Type Declaration\n\n### queryFn?\n\n```ts\noptional queryFn: Exclude<CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>[\"queryFn\"], SkipToken | undefined>;\n```\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `TQueryFnData`\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n"
  },
  {
    "path": "docs/framework/angular/typescript.md",
    "content": "---\nid: typescript\ntitle: TypeScript\nref: docs/framework/react/typescript.md\nreplace:\n  {\n    'useQuery': 'injectQuery',\n    'useMutation': 'injectMutation',\n    'react-query': 'angular-query-experimental',\n    'public API of React Query': 'public API of TanStack Query and - after the experimental phase, the angular-query package',\n    'still follows': 'still follow',\n    'React Query': 'TanStack Query',\n    '`success`': '`isSuccess()`',\n    'function:': 'function.',\n  }\n---\n\n[//]: # 'TypeInference1'\n\n```angular-ts\n@Component({\n  // ...\n  template: `@let data = query.data();`,\n  //               ^? data: number | undefined\n})\nclass MyComponent {\n  query = injectQuery(() => ({\n    queryKey: ['test'],\n    queryFn: () => Promise.resolve(5),\n  }))\n}\n```\n\n[//]: # 'TypeInference1'\n[//]: # 'TypeInference2'\n\n```angular-ts\n@Component({\n  // ...\n  template: `@let data = query.data();`,\n  //               ^? data: string | undefined\n})\nclass MyComponent {\n  query = injectQuery(() => ({\n    queryKey: ['test'],\n    queryFn: () => Promise.resolve(5),\n    select: (data) => data.toString(),\n  }))\n}\n```\n\n[//]: # 'TypeInference2'\n[//]: # 'TypeInference3'\n\nIn this example we pass Group[] to the type parameter of HttpClient's `get` method.\n\n```angular-ts\n@Component({\n  template: `@let data = query.data();`,\n  //               ^? data: Group[] | undefined\n})\nclass MyComponent {\n  http = inject(HttpClient)\n\n  query = injectQuery(() => ({\n    queryKey: ['groups'],\n    queryFn: () => lastValueFrom(this.http.get<Group[]>('/groups')),\n  }))\n}\n```\n\n[//]: # 'TypeInference3'\n[//]: # 'TypeNarrowing'\n\n```angular-ts\n@Component({\n  // ...\n  template: `\n    @if (query.isSuccess()) {\n      @let data = query.data();\n      // ^? data: number\n    }\n  `,\n})\nclass MyComponent {\n  query = injectQuery(() => ({\n    queryKey: ['test'],\n    queryFn: () => Promise.resolve(5),\n  }))\n}\n```\n\n> TypeScript currently does not support discriminated unions on object methods. Narrowing on signal fields on objects such as query results only works on signals returning a boolean. Prefer using `isSuccess()` and similar boolean status signals over `status() === 'success'`.\n\n[//]: # 'TypeNarrowing'\n[//]: # 'TypingError'\n\n```angular-ts\n@Component({\n  // ...\n  template: `@let error = query.error();`,\n  //                ^? error: Error | null\n})\nclass MyComponent {\n  query = injectQuery(() => ({\n    queryKey: ['groups'],\n    queryFn: fetchGroups,\n  }))\n}\n```\n\n[//]: # 'TypingError'\n[//]: # 'TypingError2'\n\n```angular-ts\n@Component({\n  // ...\n  template: `@let error = query.error();`,\n  //                ^? error: string | null\n})\nclass MyComponent {\n  query = injectQuery<Group[], string>(() => ({\n    queryKey: ['groups'],\n    queryFn: fetchGroups,\n  }))\n}\n```\n\n[//]: # 'TypingError2'\n[//]: # 'TypingError3'\n\n```ts\nimport axios from 'axios'\n\nquery = injectQuery(() => ({ queryKey: ['groups'], queryFn: fetchGroups }))\n\ncomputed(() => {\n  const error = query.error()\n  //     ^? error: Error | null\n\n  if (axios.isAxiosError(error)) {\n    error\n    // ^? const error: AxiosError\n  }\n})\n```\n\n[//]: # 'TypingError3'\n[//]: # 'RegisterErrorType'\n\n```ts\nimport '@tanstack/angular-query-experimental'\n\ndeclare module '@tanstack/angular-query-experimental' {\n  interface Register {\n    // Use unknown so call sites must narrow explicitly.\n    defaultError: unknown\n  }\n}\n\nconst query = injectQuery(() => ({\n  queryKey: ['groups'],\n  queryFn: fetchGroups,\n}))\n\ncomputed(() => {\n  const error = query.error()\n  //      ^? error: unknown | null\n})\n```\n\n[//]: # 'RegisterErrorType'\n[//]: # 'TypingQueryOptions'\n\n## Typing Query Options\n\nIf you inline query options into `injectQuery`, you'll get automatic type inference. However, you might want to extract the query options into a separate function to share them between `injectQuery` and e.g. `prefetchQuery` or manage them in a service. In that case, you'd lose type inference. To get it back, you can use the `queryOptions` helper:\n\n```ts\n@Injectable({\n  providedIn: 'root',\n})\nexport class QueriesService {\n  private http = inject(HttpClient)\n\n  post(postId: number) {\n    return queryOptions({\n      queryKey: ['post', postId],\n      queryFn: () => {\n        return lastValueFrom(\n          this.http.get<Post>(\n            `https://jsonplaceholder.typicode.com/posts/${postId}`,\n          ),\n        )\n      },\n    })\n  }\n}\n\n@Component({\n  // ...\n})\nexport class Component {\n  queryClient = inject(QueryClient)\n\n  postId = signal(1)\n\n  queries = inject(QueriesService)\n  optionsSignal = computed(() => this.queries.post(this.postId()))\n\n  postQuery = injectQuery(() => this.queries.post(1))\n  postQuery = injectQuery(() => this.queries.post(this.postId()))\n\n  // You can also pass a signal which returns query options\n  postQuery = injectQuery(this.optionsSignal)\n\n  someMethod() {\n    this.queryClient.prefetchQuery(this.queries.post(23))\n  }\n}\n```\n\nFurther, the `queryKey` returned from `queryOptions` knows about the `queryFn` associated with it, and we can leverage that type information to make functions like `queryClient.getQueryData` aware of those types as well:\n\n```ts\ndata = this.queryClient.getQueryData(groupOptions().queryKey)\n// ^? data: Post | undefined\n```\n\nWithout `queryOptions`, the type of data would be unknown, unless we'd pass a type parameter:\n\n```ts\ndata = queryClient.getQueryData<Post>(['post', 1])\n```\n\n## Typing Mutation Options\n\nSimilarly to `queryOptions`, you can use `mutationOptions` to extract mutation options into a separate function:\n\n```ts\nexport class QueriesService {\n  private http = inject(HttpClient)\n\n  updatePost(id: number) {\n    return mutationOptions({\n      mutationFn: (post: Post) => Promise.resolve(post),\n      mutationKey: ['updatePost', id],\n      onSuccess: (newPost) => {\n        //           ^? newPost: Post\n        this.queryClient.setQueryData(['posts', id], newPost)\n      },\n    })\n  }\n}\n```\n\n[//]: # 'TypingQueryOptions'\n[//]: # 'Materials'\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/angular/zoneless.md",
    "content": "---\nid: zoneless\ntitle: Zoneless Angular\n---\n\nBecause the Angular adapter for TanStack Query is built on signals, it fully supports Zoneless!\n\nAmong Zoneless benefits are improved performance and debugging experience. For details see the [Angular documentation](https://angular.dev/guide/zoneless).\n\n> Besides Zoneless, ZoneJS change detection is also fully supported.\n\n> When using Zoneless, ensure you are on Angular v19 or later to take advantage of the `PendingTasks` integration that keeps `ApplicationRef.whenStable()` in sync with ongoing queries and mutations.\n"
  },
  {
    "path": "docs/framework/preact/devtools.md",
    "content": "---\nid: devtools\ntitle: Devtools\n---\n\nWave your hands in the air and shout hooray because Preact Query comes with dedicated devtools! 🥳\n\nWhen you begin your Preact Query journey, you'll want these devtools by your side. They help visualize all of the inner workings of Preact Query and will likely save you hours of debugging if you find yourself in a pinch!\n\n> For Chrome, Firefox, and Edge users: Third-party browser extensions are available for debugging TanStack Query directly in browser DevTools. These provide the same functionality as the framework-specific devtools packages:\n>\n> - <img alt=\"Chrome logo\" src=\"https://www.google.com/chrome/static/images/chrome-logo.svg\" width=\"16\" height=\"16\" class=\"inline mr-1 not-prose\" /> [Devtools for Chrome](https://chromewebstore.google.com/detail/tanstack-query-devtools/annajfchloimdhceglpgglpeepfghfai)\n> - <img alt=\"Firefox logo\" src=\"https://upload.wikimedia.org/wikipedia/commons/a/a0/Firefox_logo%2C_2019.svg\" width=\"16\" height=\"16\" class=\"inline mr-1 not-prose\" /> [Devtools for Firefox](https://addons.mozilla.org/en-US/firefox/addon/tanstack-query-devtools/)\n> - <img alt=\"Edge logo\" src=\"https://upload.wikimedia.org/wikipedia/commons/9/98/Microsoft_Edge_logo_%282019%29.svg\" width=\"16\" height=\"16\" class=\"inline mr-1 not-prose\" /> [Devtools for Edge](https://microsoftedge.microsoft.com/addons/detail/tanstack-query-devtools/edmdpkgkacmjopodhfolmphdenmddobj)\n\n## Install and Import the Devtools\n\nThe devtools are a separate package that you need to install:\n\n```bash\nnpm i @tanstack/preact-query-devtools\n```\n\nor\n\n```bash\npnpm add @tanstack/preact-query-devtools\n```\n\nor\n\n```bash\nyarn add @tanstack/preact-query-devtools\n```\n\nor\n\n```bash\nbun add @tanstack/preact-query-devtools\n```\n\nYou can import the devtools like this:\n\n```tsx\nimport { PreactQueryDevtools } from '@tanstack/preact-query-devtools'\n```\n\nBy default, Preact Query Devtools are only included in bundles when `process.env.NODE_ENV === 'development'`, so you don't need to worry about excluding them during a production build.\n\n## Floating Mode\n\nFloating Mode will mount the devtools as a fixed, floating element in your app and provide a toggle in the corner of the screen to show and hide the devtools. This toggle state will be stored and remembered in localStorage across reloads.\n\nPlace the following code as high in your Preact app as you can. The closer it is to the root of the page, the better it will work!\n\n```tsx\nimport { PreactQueryDevtools } from '@tanstack/preact-query-devtools'\n\nfunction App() {\n  return (\n    <QueryClientProvider client={queryClient}>\n      {/* The rest of your application */}\n      <PreactQueryDevtools initialIsOpen={false} />\n    </QueryClientProvider>\n  )\n}\n```\n\n### Options\n\n- `initialIsOpen: boolean`\n  - Set this `true` if you want the dev tools to default to being open\n- `buttonPosition?: \"top-left\" | \"top-right\" | \"bottom-left\" | \"bottom-right\"`\n  - Defaults to `bottom-right`\n  - The position of the Preact Query logo to open and close the devtools panel\n- `position?: \"top\" | \"bottom\" | \"left\" | \"right\"`\n  - Defaults to `bottom`\n  - The position of the Preact Query devtools panel\n- `client?: QueryClient`,\n  - Use this to use a custom QueryClient. Otherwise, the one from the nearest context will be used.\n- `errorTypes?: { name: string; initializer: (query: Query) => TError}`\n  - Use this to predefine some errors that can be triggered on your queries. Initializer will be called (with the specific query) when that error is toggled on from the UI. It must return an Error.\n- `styleNonce?: string`\n  - 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.\n- `shadowDOMTarget?: ShadowRoot`\n  - Default behavior will apply the devtool's styles to the head tag within the DOM.\n  - Use this to pass a shadow DOM target to the devtools so that the styles will be applied within the shadow DOM instead of within the head tag in the light DOM.\n"
  },
  {
    "path": "docs/framework/preact/graphql.md",
    "content": "---\nid: graphql\ntitle: GraphQL\nref: docs/framework/react/graphql.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n"
  },
  {
    "path": "docs/framework/preact/guides/background-fetching-indicators.md",
    "content": "---\nid: background-fetching-indicators\ntitle: Background Fetching Indicators\nref: docs/framework/react/guides/background-fetching-indicators.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n"
  },
  {
    "path": "docs/framework/preact/guides/caching.md",
    "content": "---\nid: caching\ntitle: Caching Examples\nref: docs/framework/react/guides/caching.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n"
  },
  {
    "path": "docs/framework/preact/guides/default-query-function.md",
    "content": "---\nid: default-query-function\ntitle: Default Query Function\nref: docs/framework/react/guides/default-query-function.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n"
  },
  {
    "path": "docs/framework/preact/guides/dependent-queries.md",
    "content": "---\nid: dependent-queries\ntitle: Dependent Queries\nref: docs/framework/react/guides/dependent-queries.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n"
  },
  {
    "path": "docs/framework/preact/guides/disabling-queries.md",
    "content": "---\nid: disabling-queries\ntitle: Disabling/Pausing Queries\nref: docs/framework/react/guides/disabling-queries.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n\n[//]: # 'Example2'\n\n```tsx\nfunction Todos() {\n  const [filter, setFilter] = useState('')\n\n  const { data } = useQuery({\n    queryKey: ['todos', filter],\n    queryFn: () => fetchTodos(filter),\n    // ⬇️ disabled as long as the filter is empty\n    enabled: !!filter,\n  })\n\n  return (\n    <div>\n      // 🚀 applying the filter will enable and execute the query\n      <FiltersForm onApply={setFilter} />\n      {data && <TodosTable data={data} />}\n    </div>\n  )\n}\n```\n\n[//]: # 'Example2'\n[//]: # 'Example3'\n\n```tsx\nimport { skipToken, useQuery } from '@tanstack/preact-query'\n\nfunction Todos() {\n  const [filter, setFilter] = useState<string | undefined>()\n\n  const { data } = useQuery({\n    queryKey: ['todos', filter],\n    // ⬇️ disabled as long as the filter is undefined or empty\n    queryFn: filter ? () => fetchTodos(filter) : skipToken,\n  })\n\n  return (\n    <div>\n      // 🚀 applying the filter will enable and execute the query\n      <FiltersForm onApply={setFilter} />\n      {data && <TodosTable data={data} />}\n    </div>\n  )\n}\n```\n\n[//]: # 'Example3'\n"
  },
  {
    "path": "docs/framework/preact/guides/does-this-replace-client-state.md",
    "content": "---\nid: does-this-replace-client-state\ntitle: Does TanStack Query replace Redux, MobX or other global state managers?\nref: docs/framework/react/guides/does-this-replace-client-state.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n"
  },
  {
    "path": "docs/framework/preact/guides/filters.md",
    "content": "---\nid: filters\ntitle: Filters\nref: docs/framework/react/guides/filters.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n"
  },
  {
    "path": "docs/framework/preact/guides/important-defaults.md",
    "content": "---\nid: important-defaults\ntitle: Important Defaults\nref: docs/framework/react/guides/important-defaults.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n"
  },
  {
    "path": "docs/framework/preact/guides/infinite-queries.md",
    "content": "---\nid: infinite-queries\ntitle: Infinite Queries\nref: docs/framework/react/guides/infinite-queries.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n\n[//]: # 'Example'\n\n```tsx\nimport { useInfiniteQuery } from '@tanstack/preact-query'\n\nfunction Projects() {\n  const fetchProjects = async ({ pageParam }) => {\n    const res = await fetch('/api/projects?cursor=' + pageParam)\n    return res.json()\n  }\n\n  const {\n    data,\n    error,\n    fetchNextPage,\n    hasNextPage,\n    isFetching,\n    isFetchingNextPage,\n    status,\n  } = useInfiniteQuery({\n    queryKey: ['projects'],\n    queryFn: fetchProjects,\n    initialPageParam: 0,\n    getNextPageParam: (lastPage, pages) => lastPage.nextCursor,\n  })\n\n  return status === 'pending' ? (\n    <p>Loading...</p>\n  ) : status === 'error' ? (\n    <p>Error: {error.message}</p>\n  ) : (\n    <>\n      {data.pages.map((group, i) => (\n        <div key={i}>\n          {group.data.map((project) => (\n            <p key={project.id}>{project.name}</p>\n          ))}\n        </div>\n      ))}\n      <div>\n        <button\n          onClick={() => fetchNextPage()}\n          disabled={!hasNextPage || isFetching}\n        >\n          {isFetchingNextPage\n            ? 'Loading more...'\n            : hasNextPage\n              ? 'Load More'\n              : 'Nothing more to load'}\n        </button>\n      </div>\n      <div>{isFetching && !isFetchingNextPage ? 'Fetching...' : null}</div>\n    </>\n  )\n}\n```\n\n[//]: # 'Example'\n"
  },
  {
    "path": "docs/framework/preact/guides/initial-query-data.md",
    "content": "---\nid: initial-query-data\ntitle: Initial Query Data\nref: docs/framework/react/guides/initial-query-data.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n"
  },
  {
    "path": "docs/framework/preact/guides/invalidations-from-mutations.md",
    "content": "---\nid: invalidations-from-mutations\ntitle: Invalidations from Mutations\nref: docs/framework/react/guides/invalidations-from-mutations.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n"
  },
  {
    "path": "docs/framework/preact/guides/mutations.md",
    "content": "---\nid: mutations\ntitle: Mutations\nref: docs/framework/react/guides/mutations.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n\n[//]: # 'Info1'\n[//]: # 'Info1'\n[//]: # 'Example2'\n[//]: # 'Example2'\n"
  },
  {
    "path": "docs/framework/preact/guides/network-mode.md",
    "content": "---\nid: network-mode\ntitle: Network Mode\nref: docs/framework/react/guides/network-mode.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n"
  },
  {
    "path": "docs/framework/preact/guides/optimistic-updates.md",
    "content": "---\nid: optimistic-updates\ntitle: Optimistic Updates\nref: docs/framework/react/guides/optimistic-updates.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n"
  },
  {
    "path": "docs/framework/preact/guides/paginated-queries.md",
    "content": "---\nid: paginated-queries\ntitle: Paginated / Lagged Queries\nref: docs/framework/react/guides/paginated-queries.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n\n[//]: # 'Example2'\n\n```tsx\nimport { keepPreviousData, useQuery } from '@tanstack/preact-query'\nimport { useState } from 'preact/hooks'\n\nfunction Todos() {\n  const [page, setPage] = useState(0)\n\n  const fetchProjects = (page = 0) =>\n    fetch('/api/projects?page=' + page).then((res) => res.json())\n\n  const { isPending, isError, error, data, isFetching, isPlaceholderData } =\n    useQuery({\n      queryKey: ['projects', page],\n      queryFn: () => fetchProjects(page),\n      placeholderData: keepPreviousData,\n    })\n\n  return (\n    <div>\n      {isPending ? (\n        <div>Loading...</div>\n      ) : isError ? (\n        <div>Error: {error.message}</div>\n      ) : (\n        <div>\n          {data.projects.map((project) => (\n            <p key={project.id}>{project.name}</p>\n          ))}\n        </div>\n      )}\n      <span>Current Page: {page + 1}</span>\n      <button\n        onClick={() => setPage((old) => Math.max(old - 1, 0))}\n        disabled={page === 0}\n      >\n        Previous Page\n      </button>\n      <button\n        onClick={() => {\n          if (!isPlaceholderData && data.hasMore) {\n            setPage((old) => old + 1)\n          }\n        }}\n        // Disable the Next Page button until we know a next page is available\n        disabled={isPlaceholderData || !data?.hasMore}\n      >\n        Next Page\n      </button>\n      {isFetching ? <span> Loading...</span> : null}\n    </div>\n  )\n}\n```\n\n[//]: # 'Example2'\n"
  },
  {
    "path": "docs/framework/preact/guides/parallel-queries.md",
    "content": "---\nid: parallel-queries\ntitle: Parallel Queries\nref: docs/framework/react/guides/parallel-queries.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n\n[//]: # 'Info'\n\n> When using Preact Query with compat's Suspense, this pattern of parallelism does not work, since the first query would throw a promise internally and would suspend the component before the other queries run. To get around this, you'll either need to use the `useSuspenseQueries` hook (which is suggested) or orchestrate your own parallelism with separate components for each `useSuspenseQuery` instance.\n\n[//]: # 'Info'\n"
  },
  {
    "path": "docs/framework/preact/guides/placeholder-query-data.md",
    "content": "---\nid: placeholder-query-data\ntitle: Placeholder Query Data\nref: docs/framework/react/guides/placeholder-query-data.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n"
  },
  {
    "path": "docs/framework/preact/guides/prefetching.md",
    "content": "---\nid: prefetching\ntitle: Prefetching & Router Integration\nref: docs/framework/react/guides/prefetching.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n\n[//]: # 'ExampleConditionally1'\n\n```tsx\n// This lazy loads the GraphFeedItem component, meaning\n// it wont start loading until something renders it\nimport { lazy } from 'preact/iso'\n\nconst GraphFeedItem = lazy(() => import('./GraphFeedItem'))\n\nfunction Feed() {\n  const { data, isPending } = useQuery({\n    queryKey: ['feed'],\n    queryFn: getFeed,\n  })\n\n  if (isPending) {\n    return 'Loading feed...'\n  }\n\n  return (\n    <>\n      {data.map((feedItem) => {\n        if (feedItem.type === 'GRAPH') {\n          return <GraphFeedItem key={feedItem.id} feedItem={feedItem} />\n        }\n\n        return <StandardFeedItem key={feedItem.id} feedItem={feedItem} />\n      })}\n    </>\n  )\n}\n\n// GraphFeedItem.tsx\nfunction GraphFeedItem({ feedItem }) {\n  const { data, isPending } = useQuery({\n    queryKey: ['graph', feedItem.id],\n    queryFn: getGraphDataById,\n  })\n\n  ...\n}\n```\n\n[//]: # 'ExampleConditionally1'\n"
  },
  {
    "path": "docs/framework/preact/guides/queries.md",
    "content": "---\nid: queries\ntitle: Queries\nref: docs/framework/react/guides/queries.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n"
  },
  {
    "path": "docs/framework/preact/guides/query-cancellation.md",
    "content": "---\nid: query-cancellation\ntitle: Query Cancellation\nref: docs/framework/react/guides/query-cancellation.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n"
  },
  {
    "path": "docs/framework/preact/guides/query-functions.md",
    "content": "---\nid: query-functions\ntitle: Query Functions\nref: docs/framework/react/guides/query-functions.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n"
  },
  {
    "path": "docs/framework/preact/guides/query-invalidation.md",
    "content": "---\nid: query-invalidation\ntitle: Query Invalidation\nref: docs/framework/react/guides/query-invalidation.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n"
  },
  {
    "path": "docs/framework/preact/guides/query-keys.md",
    "content": "---\nid: query-keys\ntitle: Query Keys\nref: docs/framework/react/guides/query-keys.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n"
  },
  {
    "path": "docs/framework/preact/guides/query-options.md",
    "content": "---\nid: query-options\ntitle: Query Options\nref: docs/framework/react/guides/query-options.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n"
  },
  {
    "path": "docs/framework/preact/guides/query-retries.md",
    "content": "---\nid: query-retries\ntitle: Query Retries\nref: docs/framework/react/guides/query-retries.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n"
  },
  {
    "path": "docs/framework/preact/guides/render-optimizations.md",
    "content": "---\nid: render-optimizations\ntitle: Render Optimizations\nref: docs/framework/react/guides/render-optimizations.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n"
  },
  {
    "path": "docs/framework/preact/guides/request-waterfalls.md",
    "content": "---\nid: request-waterfalls\ntitle: Performance & Request Waterfalls\nref: docs/framework/react/guides/request-waterfalls.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n\n[//]: # 'LazyExample'\n\n```tsx\nimport { lazy } from 'preact/iso'\n// This lazy loads the GraphFeedItem component, meaning\n// it wont start loading until something renders it\nconst GraphFeedItem = lazy(() => import('./GraphFeedItem'))\n\nfunction Feed() {\n  const { data, isPending } = useQuery({\n    queryKey: ['feed'],\n    queryFn: getFeed,\n  })\n\n  if (isPending) {\n    return 'Loading feed...'\n  }\n\n  return (\n    <>\n      {data.map((feedItem) => {\n        if (feedItem.type === 'GRAPH') {\n          return <GraphFeedItem key={feedItem.id} feedItem={feedItem} />\n        }\n\n        return <StandardFeedItem key={feedItem.id} feedItem={feedItem} />\n      })}\n    </>\n  )\n}\n\n// GraphFeedItem.tsx\nfunction GraphFeedItem({ feedItem }) {\n  const { data, isPending } = useQuery({\n    queryKey: ['graph', feedItem.id],\n    queryFn: getGraphDataById,\n  })\n\n  ...\n}\n```\n\n[//]: # 'LazyExample'\n"
  },
  {
    "path": "docs/framework/preact/guides/scroll-restoration.md",
    "content": "---\nid: scroll-restoration\ntitle: Scroll Restoration\nref: docs/framework/react/guides/scroll-restoration.md\n---\n"
  },
  {
    "path": "docs/framework/preact/guides/updates-from-mutation-responses.md",
    "content": "---\nid: updates-from-mutation-responses\ntitle: Updates from Mutation Responses\nref: docs/framework/react/guides/updates-from-mutation-responses.md\n---\n"
  },
  {
    "path": "docs/framework/preact/guides/window-focus-refetching.md",
    "content": "---\nid: window-focus-refetching\ntitle: Window Focus Refetching\nref: docs/framework/react/guides/window-focus-refetching.md\nreplace: { 'react-query': 'preact-query' }\n---\n\n[//]: # 'ReactNative'\n[//]: # 'ReactNative'\n"
  },
  {
    "path": "docs/framework/preact/installation.md",
    "content": "---\nid: installation\ntitle: Installation\nref: docs/framework/react/installation.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n\n[//]: # 'Compatibility'\n\n> Wanna give it a spin before you download? Try out the [simple](./examples/simple) example\n\n[//]: # 'Compatibility'\n[//]: # 'CDNExample'\n\n```html\n<script type=\"module\">\n  import { render } from 'https://esm.sh/preact@10.23.1'\n  import { QueryClient } from 'https://esm.sh/@tanstack/preact-query'\n</script>\n```\n\n[//]: # 'CDNExample'\n"
  },
  {
    "path": "docs/framework/preact/overview.md",
    "content": "---\nid: overview\ntitle: Overview\nref: docs/framework/react/overview.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n"
  },
  {
    "path": "docs/framework/preact/plugins/broadcastQueryClient.md",
    "content": "---\nid: broadcastQueryClient\ntitle: broadcastQueryClient (Experimental)\nref: docs/framework/react/plugins/broadcastQueryClient.md\n---\n"
  },
  {
    "path": "docs/framework/preact/plugins/createAsyncStoragePersister.md",
    "content": "---\nid: createAsyncStoragePersister\ntitle: createAsyncStoragePersister\nref: docs/framework/react/plugins/createAsyncStoragePersister.md\nreplace: { 'react-query': 'preact-query' }\n---\n"
  },
  {
    "path": "docs/framework/preact/plugins/createPersister.md",
    "content": "---\nid: createPersister\ntitle: experimental_createPersister\nref: docs/framework/react/plugins/createPersister.md\nreplace: { 'react-query': 'preact-query' }\n---\n"
  },
  {
    "path": "docs/framework/preact/plugins/createSyncStoragePersister.md",
    "content": "---\nid: createSyncStoragePersister\ntitle: createSyncStoragePersister\nref: docs/framework/react/plugins/createSyncStoragePersister.md\nreplace: { 'react-query': 'preact-query' }\n---\n"
  },
  {
    "path": "docs/framework/preact/plugins/persistQueryClient.md",
    "content": "---\nid: persistQueryClient\ntitle: persistQueryClient\nref: docs/framework/react/plugins/persistQueryClient.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n"
  },
  {
    "path": "docs/framework/preact/quick-start.md",
    "content": "---\nid: quick-start\ntitle: Quick Start\nref: docs/framework/react/quick-start.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n"
  },
  {
    "path": "docs/framework/preact/reference/functions/HydrationBoundary.md",
    "content": "---\nid: HydrationBoundary\ntitle: HydrationBoundary\n---\n\n# Function: HydrationBoundary()\n\n```ts\nfunction HydrationBoundary(__namedParameters): ComponentChildren;\n```\n\nDefined in: [preact-query/src/HydrationBoundary.tsx:24](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/HydrationBoundary.tsx#L24)\n\n## Parameters\n\n### \\_\\_namedParameters\n\n[`HydrationBoundaryProps`](../interfaces/HydrationBoundaryProps.md)\n\n## Returns\n\n`ComponentChildren`\n"
  },
  {
    "path": "docs/framework/preact/reference/functions/QueryClientProvider.md",
    "content": "---\nid: QueryClientProvider\ntitle: QueryClientProvider\n---\n\n# Function: QueryClientProvider()\n\n```ts\nfunction QueryClientProvider(__namedParameters): VNode;\n```\n\nDefined in: [preact-query/src/QueryClientProvider.tsx:28](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/QueryClientProvider.tsx#L28)\n\n## Parameters\n\n### \\_\\_namedParameters\n\n[`QueryClientProviderProps`](../type-aliases/QueryClientProviderProps.md)\n\n## Returns\n\n`VNode`\n"
  },
  {
    "path": "docs/framework/preact/reference/functions/QueryErrorResetBoundary.md",
    "content": "---\nid: QueryErrorResetBoundary\ntitle: QueryErrorResetBoundary\n---\n\n# Function: QueryErrorResetBoundary()\n\n```ts\nfunction QueryErrorResetBoundary(__namedParameters): Element;\n```\n\nDefined in: [preact-query/src/QueryErrorResetBoundary.tsx:47](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/QueryErrorResetBoundary.tsx#L47)\n\n## Parameters\n\n### \\_\\_namedParameters\n\n[`QueryErrorResetBoundaryProps`](../interfaces/QueryErrorResetBoundaryProps.md)\n\n## Returns\n\n`Element`\n"
  },
  {
    "path": "docs/framework/preact/reference/functions/infiniteQueryOptions.md",
    "content": "---\nid: infiniteQueryOptions\ntitle: infiniteQueryOptions\n---\n\n# Function: infiniteQueryOptions()\n\n## Call Signature\n\n```ts\nfunction infiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>(options): UseInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam> & object & object;\n```\n\nDefined in: [preact-query/src/infiniteQueryOptions.ts:75](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/infiniteQueryOptions.ts#L75)\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `InfiniteData`\\<`TQueryFnData`, `unknown`\\>\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n#### TPageParam\n\n`TPageParam` = `unknown`\n\n### Parameters\n\n#### options\n\n[`DefinedInitialDataInfiniteOptions`](../type-aliases/DefinedInitialDataInfiniteOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\>\n\n### Returns\n\n[`UseInfiniteQueryOptions`](../interfaces/UseInfiniteQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\> & `object` & `object`\n\n## Call Signature\n\n```ts\nfunction infiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>(options): OmitKeyof<UseInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>, \"queryFn\"> & object & object;\n```\n\nDefined in: [preact-query/src/infiniteQueryOptions.ts:99](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/infiniteQueryOptions.ts#L99)\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `InfiniteData`\\<`TQueryFnData`, `unknown`\\>\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n#### TPageParam\n\n`TPageParam` = `unknown`\n\n### Parameters\n\n#### options\n\n[`UnusedSkipTokenInfiniteOptions`](../type-aliases/UnusedSkipTokenInfiniteOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\>\n\n### Returns\n\n`OmitKeyof`\\<[`UseInfiniteQueryOptions`](../interfaces/UseInfiniteQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\>, `\"queryFn\"`\\> & `object` & `object`\n\n## Call Signature\n\n```ts\nfunction infiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>(options): UseInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam> & object & object;\n```\n\nDefined in: [preact-query/src/infiniteQueryOptions.ts:123](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/infiniteQueryOptions.ts#L123)\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `InfiniteData`\\<`TQueryFnData`, `unknown`\\>\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n#### TPageParam\n\n`TPageParam` = `unknown`\n\n### Parameters\n\n#### options\n\n[`UndefinedInitialDataInfiniteOptions`](../type-aliases/UndefinedInitialDataInfiniteOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\>\n\n### Returns\n\n[`UseInfiniteQueryOptions`](../interfaces/UseInfiniteQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\> & `object` & `object`\n"
  },
  {
    "path": "docs/framework/preact/reference/functions/mutationOptions.md",
    "content": "---\nid: mutationOptions\ntitle: mutationOptions\n---\n\n# Function: mutationOptions()\n\n## Call Signature\n\n```ts\nfunction mutationOptions<TData, TError, TVariables, TOnMutateResult>(options): WithRequired<UseMutationOptions<TData, TError, TVariables, TOnMutateResult>, \"mutationKey\">;\n```\n\nDefined in: [preact-query/src/mutationOptions.ts:4](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/mutationOptions.ts#L4)\n\n### Type Parameters\n\n#### TData\n\n`TData` = `unknown`\n\n#### TError\n\n`TError` = `Error`\n\n#### TVariables\n\n`TVariables` = `void`\n\n#### TOnMutateResult\n\n`TOnMutateResult` = `unknown`\n\n### Parameters\n\n#### options\n\n`WithRequired`\\<[`UseMutationOptions`](../interfaces/UseMutationOptions.md)\\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\\>, `\"mutationKey\"`\\>\n\n### Returns\n\n`WithRequired`\\<[`UseMutationOptions`](../interfaces/UseMutationOptions.md)\\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\\>, `\"mutationKey\"`\\>\n\n## Call Signature\n\n```ts\nfunction mutationOptions<TData, TError, TVariables, TOnMutateResult>(options): Omit<UseMutationOptions<TData, TError, TVariables, TOnMutateResult>, \"mutationKey\">;\n```\n\nDefined in: [preact-query/src/mutationOptions.ts:18](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/mutationOptions.ts#L18)\n\n### Type Parameters\n\n#### TData\n\n`TData` = `unknown`\n\n#### TError\n\n`TError` = `Error`\n\n#### TVariables\n\n`TVariables` = `void`\n\n#### TOnMutateResult\n\n`TOnMutateResult` = `unknown`\n\n### Parameters\n\n#### options\n\n`Omit`\\<[`UseMutationOptions`](../interfaces/UseMutationOptions.md)\\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\\>, `\"mutationKey\"`\\>\n\n### Returns\n\n`Omit`\\<[`UseMutationOptions`](../interfaces/UseMutationOptions.md)\\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\\>, `\"mutationKey\"`\\>\n"
  },
  {
    "path": "docs/framework/preact/reference/functions/queryOptions.md",
    "content": "---\nid: queryOptions\ntitle: queryOptions\n---\n\n# Function: queryOptions()\n\n## Call Signature\n\n```ts\nfunction queryOptions<TQueryFnData, TError, TData, TQueryKey>(options): Omit<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, \"queryFn\"> & object & object;\n```\n\nDefined in: [preact-query/src/queryOptions.ts:52](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/queryOptions.ts#L52)\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `TQueryFnData`\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n### Parameters\n\n#### options\n\n[`DefinedInitialDataOptions`](../type-aliases/DefinedInitialDataOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>\n\n### Returns\n\n`Omit`\\<[`UseQueryOptions`](../interfaces/UseQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>, `\"queryFn\"`\\> & `object` & `object`\n\n## Call Signature\n\n```ts\nfunction queryOptions<TQueryFnData, TError, TData, TQueryKey>(options): OmitKeyof<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, \"queryFn\"> & object & object;\n```\n\nDefined in: [preact-query/src/queryOptions.ts:63](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/queryOptions.ts#L63)\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `TQueryFnData`\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n### Parameters\n\n#### options\n\n[`UnusedSkipTokenOptions`](../type-aliases/UnusedSkipTokenOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>\n\n### Returns\n\n`OmitKeyof`\\<[`UseQueryOptions`](../interfaces/UseQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>, `\"queryFn\"`\\> & `object` & `object`\n\n## Call Signature\n\n```ts\nfunction queryOptions<TQueryFnData, TError, TData, TQueryKey>(options): UseQueryOptions<TQueryFnData, TError, TData, TQueryKey> & object & object;\n```\n\nDefined in: [preact-query/src/queryOptions.ts:74](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/queryOptions.ts#L74)\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `TQueryFnData`\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n### Parameters\n\n#### options\n\n[`UndefinedInitialDataOptions`](../type-aliases/UndefinedInitialDataOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>\n\n### Returns\n\n[`UseQueryOptions`](../interfaces/UseQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\> & `object` & `object`\n"
  },
  {
    "path": "docs/framework/preact/reference/functions/useInfiniteQuery.md",
    "content": "---\nid: useInfiniteQuery\ntitle: useInfiniteQuery\n---\n\n# Function: useInfiniteQuery()\n\n## Call Signature\n\n```ts\nfunction useInfiniteQuery<TQueryFnData, TError, TData, TQueryKey, TPageParam>(options, queryClient?): DefinedUseInfiniteQueryResult<TData, TError>;\n```\n\nDefined in: [preact-query/src/useInfiniteQuery.ts:20](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/useInfiniteQuery.ts#L20)\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `InfiniteData`\\<`TQueryFnData`, `unknown`\\>\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n#### TPageParam\n\n`TPageParam` = `unknown`\n\n### Parameters\n\n#### options\n\n[`DefinedInitialDataInfiniteOptions`](../type-aliases/DefinedInitialDataInfiniteOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\>\n\n#### queryClient?\n\n`QueryClient`\n\n### Returns\n\n[`DefinedUseInfiniteQueryResult`](../type-aliases/DefinedUseInfiniteQueryResult.md)\\<`TData`, `TError`\\>\n\n## Call Signature\n\n```ts\nfunction useInfiniteQuery<TQueryFnData, TError, TData, TQueryKey, TPageParam>(options, queryClient?): UseInfiniteQueryResult<TData, TError>;\n```\n\nDefined in: [preact-query/src/useInfiniteQuery.ts:37](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/useInfiniteQuery.ts#L37)\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `InfiniteData`\\<`TQueryFnData`, `unknown`\\>\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n#### TPageParam\n\n`TPageParam` = `unknown`\n\n### Parameters\n\n#### options\n\n[`UndefinedInitialDataInfiniteOptions`](../type-aliases/UndefinedInitialDataInfiniteOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\>\n\n#### queryClient?\n\n`QueryClient`\n\n### Returns\n\n[`UseInfiniteQueryResult`](../type-aliases/UseInfiniteQueryResult.md)\\<`TData`, `TError`\\>\n\n## Call Signature\n\n```ts\nfunction useInfiniteQuery<TQueryFnData, TError, TData, TQueryKey, TPageParam>(options, queryClient?): UseInfiniteQueryResult<TData, TError>;\n```\n\nDefined in: [preact-query/src/useInfiniteQuery.ts:54](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/useInfiniteQuery.ts#L54)\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `InfiniteData`\\<`TQueryFnData`, `unknown`\\>\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n#### TPageParam\n\n`TPageParam` = `unknown`\n\n### Parameters\n\n#### options\n\n[`UseInfiniteQueryOptions`](../interfaces/UseInfiniteQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\>\n\n#### queryClient?\n\n`QueryClient`\n\n### Returns\n\n[`UseInfiniteQueryResult`](../type-aliases/UseInfiniteQueryResult.md)\\<`TData`, `TError`\\>\n"
  },
  {
    "path": "docs/framework/preact/reference/functions/useIsFetching.md",
    "content": "---\nid: useIsFetching\ntitle: useIsFetching\n---\n\n# Function: useIsFetching()\n\n```ts\nfunction useIsFetching(filters?, queryClient?): number;\n```\n\nDefined in: [preact-query/src/useIsFetching.ts:8](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/useIsFetching.ts#L8)\n\n## Parameters\n\n### filters?\n\n`QueryFilters`\\<readonly `unknown`[]\\>\n\n### queryClient?\n\n`QueryClient`\n\n## Returns\n\n`number`\n"
  },
  {
    "path": "docs/framework/preact/reference/functions/useIsMutating.md",
    "content": "---\nid: useIsMutating\ntitle: useIsMutating\n---\n\n# Function: useIsMutating()\n\n```ts\nfunction useIsMutating(filters?, queryClient?): number;\n```\n\nDefined in: [preact-query/src/useMutationState.ts:13](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/useMutationState.ts#L13)\n\n## Parameters\n\n### filters?\n\n`MutationFilters`\\<`unknown`, `Error`, `unknown`, `unknown`\\>\n\n### queryClient?\n\n`QueryClient`\n\n## Returns\n\n`number`\n"
  },
  {
    "path": "docs/framework/preact/reference/functions/useIsRestoring.md",
    "content": "---\nid: useIsRestoring\ntitle: useIsRestoring\n---\n\n# Function: useIsRestoring()\n\n```ts\nfunction useIsRestoring(): boolean;\n```\n\nDefined in: [preact-query/src/IsRestoringProvider.ts:6](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/IsRestoringProvider.ts#L6)\n\n## Returns\n\n`boolean`\n"
  },
  {
    "path": "docs/framework/preact/reference/functions/useMutation.md",
    "content": "---\nid: useMutation\ntitle: useMutation\n---\n\n# Function: useMutation()\n\n```ts\nfunction useMutation<TData, TError, TVariables, TOnMutateResult>(options, queryClient?): UseMutationResult<TData, TError, TVariables, TOnMutateResult>;\n```\n\nDefined in: [preact-query/src/useMutation.ts:19](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/useMutation.ts#L19)\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `Error`\n\n### TVariables\n\n`TVariables` = `void`\n\n### TOnMutateResult\n\n`TOnMutateResult` = `unknown`\n\n## Parameters\n\n### options\n\n[`UseMutationOptions`](../interfaces/UseMutationOptions.md)\\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\\>\n\n### queryClient?\n\n`QueryClient`\n\n## Returns\n\n[`UseMutationResult`](../type-aliases/UseMutationResult.md)\\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\\>\n"
  },
  {
    "path": "docs/framework/preact/reference/functions/useMutationState.md",
    "content": "---\nid: useMutationState\ntitle: useMutationState\n---\n\n# Function: useMutationState()\n\n```ts\nfunction useMutationState<TResult>(options, queryClient?): TResult[];\n```\n\nDefined in: [preact-query/src/useMutationState.ts:41](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/useMutationState.ts#L41)\n\n## Type Parameters\n\n### TResult\n\n`TResult` = `MutationState`\\<`unknown`, `Error`, `unknown`, `unknown`\\>\n\n## Parameters\n\n### options\n\n`MutationStateOptions`\\<`TResult`\\> = `{}`\n\n### queryClient?\n\n`QueryClient`\n\n## Returns\n\n`TResult`[]\n"
  },
  {
    "path": "docs/framework/preact/reference/functions/usePrefetchInfiniteQuery.md",
    "content": "---\nid: usePrefetchInfiniteQuery\ntitle: usePrefetchInfiniteQuery\n---\n\n# Function: usePrefetchInfiniteQuery()\n\n```ts\nfunction usePrefetchInfiniteQuery<TQueryFnData, TError, TData, TQueryKey, TPageParam>(options, queryClient?): void;\n```\n\nDefined in: [preact-query/src/usePrefetchInfiniteQuery.tsx:9](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/usePrefetchInfiniteQuery.tsx#L9)\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n### TError\n\n`TError` = `Error`\n\n### TData\n\n`TData` = `TQueryFnData`\n\n### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n### TPageParam\n\n`TPageParam` = `unknown`\n\n## Parameters\n\n### options\n\n`FetchInfiniteQueryOptions`\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\>\n\n### queryClient?\n\n`QueryClient`\n\n## Returns\n\n`void`\n"
  },
  {
    "path": "docs/framework/preact/reference/functions/usePrefetchQuery.md",
    "content": "---\nid: usePrefetchQuery\ntitle: usePrefetchQuery\n---\n\n# Function: usePrefetchQuery()\n\n```ts\nfunction usePrefetchQuery<TQueryFnData, TError, TData, TQueryKey>(options, queryClient?): void;\n```\n\nDefined in: [preact-query/src/usePrefetchQuery.tsx:5](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/usePrefetchQuery.tsx#L5)\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n### TError\n\n`TError` = `Error`\n\n### TData\n\n`TData` = `TQueryFnData`\n\n### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n## Parameters\n\n### options\n\n[`UsePrefetchQueryOptions`](../interfaces/UsePrefetchQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>\n\n### queryClient?\n\n`QueryClient`\n\n## Returns\n\n`void`\n"
  },
  {
    "path": "docs/framework/preact/reference/functions/useQueries.md",
    "content": "---\nid: useQueries\ntitle: useQueries\n---\n\n# Function: useQueries()\n\n```ts\nfunction useQueries<T, TCombinedResult>(__namedParameters, queryClient?): TCombinedResult;\n```\n\nDefined in: [preact-query/src/useQueries.ts:207](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/useQueries.ts#L207)\n\n## Type Parameters\n\n### T\n\n`T` *extends* `any`[]\n\n### TCombinedResult\n\n`TCombinedResult` = `T` *extends* \\[\\] ? \\[\\] : `T` *extends* \\[`Head`\\] ? \\[`GetUseQueryResult`\\<`Head`\\>\\] : `T` *extends* \\[`Head`, `...Tails[]`\\] ? \\[`...Tails[]`\\] *extends* \\[\\] ? \\[\\] : \\[`...Tails[]`\\] *extends* \\[`Head`\\] ? \\[`GetUseQueryResult`\\<`Head`\\>, `GetUseQueryResult`\\<`Head`\\>\\] : \\[`...Tails[]`\\] *extends* \\[`Head`, `...Tails[]`\\] ? \\[`...Tails[]`\\] *extends* \\[\\] ? \\[\\] : \\[`...Tails[]`\\] *extends* \\[`Head`\\] ? \\[`GetUseQueryResult`\\<`Head`\\>, `GetUseQueryResult`\\<`Head`\\>, `GetUseQueryResult`\\<`Head`\\>\\] : \\[`...Tails[]`\\] *extends* \\[`Head`, `...Tails[]`\\] ? \\[`...(...)[]`\\] *extends* \\[\\] ? \\[\\] : ... *extends* ... ? ... : ... : \\[`...{ [K in (...)]: (...) }[]`\\] : \\[...\\{ \\[K in string \\| number \\| symbol\\]: GetUseQueryResult\\<Tails\\[K\\<(...)\\>\\]\\> \\}\\[\\]\\] : \\{ \\[K in string \\| number \\| symbol\\]: GetUseQueryResult\\<T\\[K\\<K\\>\\]\\> \\}\n\n## Parameters\n\n### \\_\\_namedParameters\n\n#### combine?\n\n(`result`) => `TCombinedResult`\n\n#### queries\n\n  \\| readonly \\[`T` *extends* \\[\\] ? \\[\\] : `T` *extends* \\[`Head`\\] ? \\[`GetUseQueryOptionsForUseQueries`\\<`Head`\\>\\] : `T` *extends* \\[`Head`, `...Tails[]`\\] ? \\[`...Tails[]`\\] *extends* \\[\\] ? \\[\\] : \\[`...Tails[]`\\] *extends* \\[`Head`\\] ? \\[`GetUseQueryOptionsForUseQueries`\\<`Head`\\>, `GetUseQueryOptionsForUseQueries`\\<`Head`\\>\\] : \\[`...Tails[]`\\] *extends* \\[`Head`, `...Tails[]`\\] ? \\[`...(...)[]`\\] *extends* \\[\\] ? \\[\\] : ... *extends* ... ? ... : ... : readonly ...[] *extends* \\[`...(...)[]`\\] ? \\[`...(...)[]`\\] : ... *extends* ... ? ... : ... : readonly `unknown`[] *extends* `T` ? `T` : `T` *extends* `UseQueryOptionsForUseQueries`\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>[] ? `UseQueryOptionsForUseQueries`\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>[] : `UseQueryOptionsForUseQueries`\\<`unknown`, `Error`, `unknown`, readonly ...[]\\>[]\\]\n  \\| readonly \\[\\{ \\[K in string \\| number \\| symbol\\]: GetUseQueryOptionsForUseQueries\\<T\\[K\\<K\\>\\]\\> \\}\\]\n\n#### subscribed?\n\n`boolean`\n\n### queryClient?\n\n`QueryClient`\n\n## Returns\n\n`TCombinedResult`\n"
  },
  {
    "path": "docs/framework/preact/reference/functions/useQuery.md",
    "content": "---\nid: useQuery\ntitle: useQuery\n---\n\n# Function: useQuery()\n\n## Call Signature\n\n```ts\nfunction useQuery<TQueryFnData, TError, TData, TQueryKey>(options, queryClient?): DefinedUseQueryResult<NoInfer<TData>, TError>;\n```\n\nDefined in: [preact-query/src/useQuery.ts:19](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/useQuery.ts#L19)\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `TQueryFnData`\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n### Parameters\n\n#### options\n\n[`DefinedInitialDataOptions`](../type-aliases/DefinedInitialDataOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>\n\n#### queryClient?\n\n`QueryClient`\n\n### Returns\n\n[`DefinedUseQueryResult`](../type-aliases/DefinedUseQueryResult.md)\\<`NoInfer`\\<`TData`\\>, `TError`\\>\n\n## Call Signature\n\n```ts\nfunction useQuery<TQueryFnData, TError, TData, TQueryKey>(options, queryClient?): UseQueryResult<NoInfer<TData>, TError>;\n```\n\nDefined in: [preact-query/src/useQuery.ts:29](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/useQuery.ts#L29)\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `TQueryFnData`\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n### Parameters\n\n#### options\n\n[`UndefinedInitialDataOptions`](../type-aliases/UndefinedInitialDataOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>\n\n#### queryClient?\n\n`QueryClient`\n\n### Returns\n\n[`UseQueryResult`](../type-aliases/UseQueryResult.md)\\<`NoInfer`\\<`TData`\\>, `TError`\\>\n\n## Call Signature\n\n```ts\nfunction useQuery<TQueryFnData, TError, TData, TQueryKey>(options, queryClient?): UseQueryResult<NoInfer<TData>, TError>;\n```\n\nDefined in: [preact-query/src/useQuery.ts:39](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/useQuery.ts#L39)\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `TQueryFnData`\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n### Parameters\n\n#### options\n\n[`UseQueryOptions`](../interfaces/UseQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>\n\n#### queryClient?\n\n`QueryClient`\n\n### Returns\n\n[`UseQueryResult`](../type-aliases/UseQueryResult.md)\\<`NoInfer`\\<`TData`\\>, `TError`\\>\n"
  },
  {
    "path": "docs/framework/preact/reference/functions/useQueryClient.md",
    "content": "---\nid: useQueryClient\ntitle: useQueryClient\n---\n\n# Function: useQueryClient()\n\n```ts\nfunction useQueryClient(queryClient?): QueryClient;\n```\n\nDefined in: [preact-query/src/QueryClientProvider.tsx:9](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/QueryClientProvider.tsx#L9)\n\n## Parameters\n\n### queryClient?\n\n`QueryClient`\n\n## Returns\n\n`QueryClient`\n"
  },
  {
    "path": "docs/framework/preact/reference/functions/useQueryErrorResetBoundary.md",
    "content": "---\nid: useQueryErrorResetBoundary\ntitle: useQueryErrorResetBoundary\n---\n\n# Function: useQueryErrorResetBoundary()\n\n```ts\nfunction useQueryErrorResetBoundary(): QueryErrorResetBoundaryValue;\n```\n\nDefined in: [preact-query/src/QueryErrorResetBoundary.tsx:34](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/QueryErrorResetBoundary.tsx#L34)\n\n## Returns\n\n`QueryErrorResetBoundaryValue`\n"
  },
  {
    "path": "docs/framework/preact/reference/functions/useSuspenseInfiniteQuery.md",
    "content": "---\nid: useSuspenseInfiniteQuery\ntitle: useSuspenseInfiniteQuery\n---\n\n# Function: useSuspenseInfiniteQuery()\n\n```ts\nfunction useSuspenseInfiniteQuery<TQueryFnData, TError, TData, TQueryKey, TPageParam>(options, queryClient?): UseSuspenseInfiniteQueryResult<TData, TError>;\n```\n\nDefined in: [preact-query/src/useSuspenseInfiniteQuery.ts:17](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/useSuspenseInfiniteQuery.ts#L17)\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData`\n\n### TError\n\n`TError` = `Error`\n\n### TData\n\n`TData` = `InfiniteData`\\<`TQueryFnData`, `unknown`\\>\n\n### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n### TPageParam\n\n`TPageParam` = `unknown`\n\n## Parameters\n\n### options\n\n[`UseSuspenseInfiniteQueryOptions`](../interfaces/UseSuspenseInfiniteQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\>\n\n### queryClient?\n\n`QueryClient`\n\n## Returns\n\n[`UseSuspenseInfiniteQueryResult`](../type-aliases/UseSuspenseInfiniteQueryResult.md)\\<`TData`, `TError`\\>\n"
  },
  {
    "path": "docs/framework/preact/reference/functions/useSuspenseQueries.md",
    "content": "---\nid: useSuspenseQueries\ntitle: useSuspenseQueries\n---\n\n# Function: useSuspenseQueries()\n\n## Call Signature\n\n```ts\nfunction useSuspenseQueries<T, TCombinedResult>(options, queryClient?): TCombinedResult;\n```\n\nDefined in: [preact-query/src/useSuspenseQueries.ts:164](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/useSuspenseQueries.ts#L164)\n\n### Type Parameters\n\n#### T\n\n`T` *extends* `any`[]\n\n#### TCombinedResult\n\n`TCombinedResult` = `T` *extends* \\[\\] ? \\[\\] : `T` *extends* \\[`Head`\\] ? \\[`GetUseSuspenseQueryResult`\\<`Head`\\>\\] : `T` *extends* \\[`Head`, `...Tails[]`\\] ? \\[`...Tails[]`\\] *extends* \\[\\] ? \\[\\] : \\[`...Tails[]`\\] *extends* \\[`Head`\\] ? \\[`GetUseSuspenseQueryResult`\\<`Head`\\>, `GetUseSuspenseQueryResult`\\<`Head`\\>\\] : \\[`...Tails[]`\\] *extends* \\[`Head`, `...Tails[]`\\] ? \\[`...Tails[]`\\] *extends* \\[\\] ? \\[\\] : \\[`...Tails[]`\\] *extends* \\[`Head`\\] ? \\[`GetUseSuspenseQueryResult`\\<`Head`\\>, `GetUseSuspenseQueryResult`\\<`Head`\\>, `GetUseSuspenseQueryResult`\\<`Head`\\>\\] : \\[`...Tails[]`\\] *extends* \\[`Head`, `...Tails[]`\\] ? \\[`...(...)[]`\\] *extends* \\[\\] ? \\[\\] : ... *extends* ... ? ... : ... : \\[`...{ [K in (...)]: (...) }[]`\\] : \\[...\\{ \\[K in string \\| number \\| symbol\\]: GetUseSuspenseQueryResult\\<Tails\\[K\\<(...)\\>\\]\\> \\}\\[\\]\\] : \\{ \\[K in string \\| number \\| symbol\\]: GetUseSuspenseQueryResult\\<T\\[K\\<K\\>\\]\\> \\}\n\n### Parameters\n\n#### options\n\n##### combine?\n\n(`result`) => `TCombinedResult`\n\n##### queries\n\n  \\| readonly \\[`T` *extends* \\[\\] ? \\[\\] : `T` *extends* \\[`Head`\\] ? \\[`GetUseSuspenseQueryOptions`\\<`Head`\\>\\] : `T` *extends* \\[`Head`, `...Tails[]`\\] ? \\[`...Tails[]`\\] *extends* \\[\\] ? \\[\\] : \\[`...Tails[]`\\] *extends* \\[`Head`\\] ? \\[`GetUseSuspenseQueryOptions`\\<`Head`\\>, `GetUseSuspenseQueryOptions`\\<`Head`\\>\\] : \\[`...Tails[]`\\] *extends* \\[`Head`, `...Tails[]`\\] ? \\[`...(...)[]`\\] *extends* \\[\\] ? \\[\\] : ... *extends* ... ? ... : ... : ...[] *extends* \\[`...(...)[]`\\] ? \\[`...(...)[]`\\] : ... *extends* ... ? ... : ... : `unknown`[] *extends* `T` ? `T` : `T` *extends* [`UseSuspenseQueryOptions`](../interfaces/UseSuspenseQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>[] ? [`UseSuspenseQueryOptions`](../interfaces/UseSuspenseQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>[] : [`UseSuspenseQueryOptions`](../interfaces/UseSuspenseQueryOptions.md)\\<`unknown`, `Error`, `unknown`, readonly ...[]\\>[]\\]\n  \\| readonly \\[\\{ \\[K in string \\| number \\| symbol\\]: GetUseSuspenseQueryOptions\\<T\\[K\\<K\\>\\]\\> \\}\\]\n\n#### queryClient?\n\n`QueryClient`\n\n### Returns\n\n`TCombinedResult`\n\n## Call Signature\n\n```ts\nfunction useSuspenseQueries<T, TCombinedResult>(options, queryClient?): TCombinedResult;\n```\n\nDefined in: [preact-query/src/useSuspenseQueries.ts:177](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/useSuspenseQueries.ts#L177)\n\n### Type Parameters\n\n#### T\n\n`T` *extends* `any`[]\n\n#### TCombinedResult\n\n`TCombinedResult` = `T` *extends* \\[\\] ? \\[\\] : `T` *extends* \\[`Head`\\] ? \\[`GetUseSuspenseQueryResult`\\<`Head`\\>\\] : `T` *extends* \\[`Head`, `...Tails[]`\\] ? \\[`...Tails[]`\\] *extends* \\[\\] ? \\[\\] : \\[`...Tails[]`\\] *extends* \\[`Head`\\] ? \\[`GetUseSuspenseQueryResult`\\<`Head`\\>, `GetUseSuspenseQueryResult`\\<`Head`\\>\\] : \\[`...Tails[]`\\] *extends* \\[`Head`, `...Tails[]`\\] ? \\[`...Tails[]`\\] *extends* \\[\\] ? \\[\\] : \\[`...Tails[]`\\] *extends* \\[`Head`\\] ? \\[`GetUseSuspenseQueryResult`\\<`Head`\\>, `GetUseSuspenseQueryResult`\\<`Head`\\>, `GetUseSuspenseQueryResult`\\<`Head`\\>\\] : \\[`...Tails[]`\\] *extends* \\[`Head`, `...Tails[]`\\] ? \\[`...(...)[]`\\] *extends* \\[\\] ? \\[\\] : ... *extends* ... ? ... : ... : \\[`...{ [K in (...)]: (...) }[]`\\] : \\[...\\{ \\[K in string \\| number \\| symbol\\]: GetUseSuspenseQueryResult\\<Tails\\[K\\<(...)\\>\\]\\> \\}\\[\\]\\] : \\{ \\[K in string \\| number \\| symbol\\]: GetUseSuspenseQueryResult\\<T\\[K\\<K\\>\\]\\> \\}\n\n### Parameters\n\n#### options\n\n##### combine?\n\n(`result`) => `TCombinedResult`\n\n##### queries\n\nreadonly \\[`T` *extends* \\[\\] ? \\[\\] : `T` *extends* \\[`Head`\\] ? \\[`GetUseSuspenseQueryOptions`\\<`Head`\\>\\] : `T` *extends* \\[`Head`, `...Tails[]`\\] ? \\[`...Tails[]`\\] *extends* \\[\\] ? \\[\\] : \\[`...Tails[]`\\] *extends* \\[`Head`\\] ? \\[`GetUseSuspenseQueryOptions`\\<`Head`\\>, `GetUseSuspenseQueryOptions`\\<`Head`\\>\\] : \\[`...Tails[]`\\] *extends* \\[`Head`, `...Tails[]`\\] ? \\[`...Tails[]`\\] *extends* \\[\\] ? \\[\\] : \\[`...(...)[]`\\] *extends* \\[...\\] ? \\[..., ..., ...\\] : ... *extends* ... ? ... : ... : `unknown`[] *extends* \\[`...Tails[]`\\] ? \\[`...Tails[]`\\] : \\[`...(...)[]`\\] *extends* ...[] ? ...[] : ...[] : `unknown`[] *extends* `T` ? `T` : `T` *extends* [`UseSuspenseQueryOptions`](../interfaces/UseSuspenseQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>[] ? [`UseSuspenseQueryOptions`](../interfaces/UseSuspenseQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>[] : [`UseSuspenseQueryOptions`](../interfaces/UseSuspenseQueryOptions.md)\\<`unknown`, `Error`, `unknown`, readonly `unknown`[]\\>[]\\]\n\n#### queryClient?\n\n`QueryClient`\n\n### Returns\n\n`TCombinedResult`\n"
  },
  {
    "path": "docs/framework/preact/reference/functions/useSuspenseQuery.md",
    "content": "---\nid: useSuspenseQuery\ntitle: useSuspenseQuery\n---\n\n# Function: useSuspenseQuery()\n\n```ts\nfunction useSuspenseQuery<TQueryFnData, TError, TData, TQueryKey>(options, queryClient?): UseSuspenseQueryResult<TData, TError>;\n```\n\nDefined in: [preact-query/src/useSuspenseQuery.ts:7](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/useSuspenseQuery.ts#L7)\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n### TError\n\n`TError` = `Error`\n\n### TData\n\n`TData` = `TQueryFnData`\n\n### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n## Parameters\n\n### options\n\n[`UseSuspenseQueryOptions`](../interfaces/UseSuspenseQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>\n\n### queryClient?\n\n`QueryClient`\n\n## Returns\n\n[`UseSuspenseQueryResult`](../type-aliases/UseSuspenseQueryResult.md)\\<`TData`, `TError`\\>\n"
  },
  {
    "path": "docs/framework/preact/reference/index.md",
    "content": "---\nid: \"@tanstack/preact-query\"\ntitle: \"@tanstack/preact-query\"\n---\n\n# @tanstack/preact-query\n\n## Interfaces\n\n- [HydrationBoundaryProps](interfaces/HydrationBoundaryProps.md)\n- [QueryErrorResetBoundaryProps](interfaces/QueryErrorResetBoundaryProps.md)\n- [UseBaseQueryOptions](interfaces/UseBaseQueryOptions.md)\n- [UseInfiniteQueryOptions](interfaces/UseInfiniteQueryOptions.md)\n- [UseMutationOptions](interfaces/UseMutationOptions.md)\n- [UsePrefetchQueryOptions](interfaces/UsePrefetchQueryOptions.md)\n- [UseQueryOptions](interfaces/UseQueryOptions.md)\n- [UseSuspenseInfiniteQueryOptions](interfaces/UseSuspenseInfiniteQueryOptions.md)\n- [UseSuspenseQueryOptions](interfaces/UseSuspenseQueryOptions.md)\n\n## Type Aliases\n\n- [AnyUseBaseQueryOptions](type-aliases/AnyUseBaseQueryOptions.md)\n- [AnyUseInfiniteQueryOptions](type-aliases/AnyUseInfiniteQueryOptions.md)\n- [AnyUseMutationOptions](type-aliases/AnyUseMutationOptions.md)\n- [AnyUseQueryOptions](type-aliases/AnyUseQueryOptions.md)\n- [AnyUseSuspenseInfiniteQueryOptions](type-aliases/AnyUseSuspenseInfiniteQueryOptions.md)\n- [AnyUseSuspenseQueryOptions](type-aliases/AnyUseSuspenseQueryOptions.md)\n- [DefinedInitialDataInfiniteOptions](type-aliases/DefinedInitialDataInfiniteOptions.md)\n- [DefinedInitialDataOptions](type-aliases/DefinedInitialDataOptions.md)\n- [DefinedUseInfiniteQueryResult](type-aliases/DefinedUseInfiniteQueryResult.md)\n- [DefinedUseQueryResult](type-aliases/DefinedUseQueryResult.md)\n- [QueriesOptions](type-aliases/QueriesOptions.md)\n- [QueriesResults](type-aliases/QueriesResults.md)\n- [QueryClientProviderProps](type-aliases/QueryClientProviderProps.md)\n- [QueryErrorClearResetFunction](type-aliases/QueryErrorClearResetFunction.md)\n- [QueryErrorIsResetFunction](type-aliases/QueryErrorIsResetFunction.md)\n- [QueryErrorResetBoundaryFunction](type-aliases/QueryErrorResetBoundaryFunction.md)\n- [QueryErrorResetFunction](type-aliases/QueryErrorResetFunction.md)\n- [SuspenseQueriesOptions](type-aliases/SuspenseQueriesOptions.md)\n- [SuspenseQueriesResults](type-aliases/SuspenseQueriesResults.md)\n- [UndefinedInitialDataInfiniteOptions](type-aliases/UndefinedInitialDataInfiniteOptions.md)\n- [UndefinedInitialDataOptions](type-aliases/UndefinedInitialDataOptions.md)\n- [UnusedSkipTokenInfiniteOptions](type-aliases/UnusedSkipTokenInfiniteOptions.md)\n- [UnusedSkipTokenOptions](type-aliases/UnusedSkipTokenOptions.md)\n- [UseBaseMutationResult](type-aliases/UseBaseMutationResult.md)\n- [UseBaseQueryResult](type-aliases/UseBaseQueryResult.md)\n- [UseInfiniteQueryResult](type-aliases/UseInfiniteQueryResult.md)\n- [UseMutateAsyncFunction](type-aliases/UseMutateAsyncFunction.md)\n- [UseMutateFunction](type-aliases/UseMutateFunction.md)\n- [UseMutationResult](type-aliases/UseMutationResult.md)\n- [UseQueryResult](type-aliases/UseQueryResult.md)\n- [UseSuspenseInfiniteQueryResult](type-aliases/UseSuspenseInfiniteQueryResult.md)\n- [UseSuspenseQueryResult](type-aliases/UseSuspenseQueryResult.md)\n\n## Variables\n\n- [IsRestoringProvider](variables/IsRestoringProvider.md)\n- [QueryClientContext](variables/QueryClientContext.md)\n\n## Functions\n\n- [HydrationBoundary](functions/HydrationBoundary.md)\n- [infiniteQueryOptions](functions/infiniteQueryOptions.md)\n- [mutationOptions](functions/mutationOptions.md)\n- [QueryClientProvider](functions/QueryClientProvider.md)\n- [QueryErrorResetBoundary](functions/QueryErrorResetBoundary.md)\n- [queryOptions](functions/queryOptions.md)\n- [useInfiniteQuery](functions/useInfiniteQuery.md)\n- [useIsFetching](functions/useIsFetching.md)\n- [useIsMutating](functions/useIsMutating.md)\n- [useIsRestoring](functions/useIsRestoring.md)\n- [useMutation](functions/useMutation.md)\n- [useMutationState](functions/useMutationState.md)\n- [usePrefetchInfiniteQuery](functions/usePrefetchInfiniteQuery.md)\n- [usePrefetchQuery](functions/usePrefetchQuery.md)\n- [useQueries](functions/useQueries.md)\n- [useQuery](functions/useQuery.md)\n- [useQueryClient](functions/useQueryClient.md)\n- [useQueryErrorResetBoundary](functions/useQueryErrorResetBoundary.md)\n- [useSuspenseInfiniteQuery](functions/useSuspenseInfiniteQuery.md)\n- [useSuspenseQueries](functions/useSuspenseQueries.md)\n- [useSuspenseQuery](functions/useSuspenseQuery.md)\n"
  },
  {
    "path": "docs/framework/preact/reference/interfaces/HydrationBoundaryProps.md",
    "content": "---\nid: HydrationBoundaryProps\ntitle: HydrationBoundaryProps\n---\n\n# Interface: HydrationBoundaryProps\n\nDefined in: [preact-query/src/HydrationBoundary.tsx:12](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/HydrationBoundary.tsx#L12)\n\n## Properties\n\n### children?\n\n```ts\noptional children: ComponentChildren;\n```\n\nDefined in: [preact-query/src/HydrationBoundary.tsx:20](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/HydrationBoundary.tsx#L20)\n\n***\n\n### options?\n\n```ts\noptional options: OmitKeyof<HydrateOptions, \"defaultOptions\"> & object;\n```\n\nDefined in: [preact-query/src/HydrationBoundary.tsx:14](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/HydrationBoundary.tsx#L14)\n\n#### Type Declaration\n\n##### defaultOptions?\n\n```ts\noptional defaultOptions: OmitKeyof<{\n}, \"mutations\">;\n```\n\n***\n\n### queryClient?\n\n```ts\noptional queryClient: QueryClient;\n```\n\nDefined in: [preact-query/src/HydrationBoundary.tsx:21](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/HydrationBoundary.tsx#L21)\n\n***\n\n### state\n\n```ts\nstate: DehydratedState | null | undefined;\n```\n\nDefined in: [preact-query/src/HydrationBoundary.tsx:13](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/HydrationBoundary.tsx#L13)\n"
  },
  {
    "path": "docs/framework/preact/reference/interfaces/QueryErrorResetBoundaryProps.md",
    "content": "---\nid: QueryErrorResetBoundaryProps\ntitle: QueryErrorResetBoundaryProps\n---\n\n# Interface: QueryErrorResetBoundaryProps\n\nDefined in: [preact-query/src/QueryErrorResetBoundary.tsx:43](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/QueryErrorResetBoundary.tsx#L43)\n\n## Properties\n\n### children\n\n```ts\nchildren: \n  | ComponentChildren\n  | QueryErrorResetBoundaryFunction;\n```\n\nDefined in: [preact-query/src/QueryErrorResetBoundary.tsx:44](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/QueryErrorResetBoundary.tsx#L44)\n"
  },
  {
    "path": "docs/framework/preact/reference/interfaces/UseBaseQueryOptions.md",
    "content": "---\nid: UseBaseQueryOptions\ntitle: UseBaseQueryOptions\n---\n\n# Interface: UseBaseQueryOptions\\<TQueryFnData, TError, TData, TQueryData, TQueryKey\\>\n\nDefined in: [preact-query/src/types.ts:29](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L29)\n\n## Extends\n\n- `QueryObserverOptions`\\<`TQueryFnData`, `TError`, `TData`, `TQueryData`, `TQueryKey`\\>\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `TQueryFnData`\n\n### TQueryData\n\n`TQueryData` = `TQueryFnData`\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n\n## Properties\n\n### subscribed?\n\n```ts\noptional subscribed: boolean;\n```\n\nDefined in: [preact-query/src/types.ts:46](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L46)\n\nSet this to `false` to unsubscribe this observer from updates to the query cache.\nDefaults to `true`.\n"
  },
  {
    "path": "docs/framework/preact/reference/interfaces/UseInfiniteQueryOptions.md",
    "content": "---\nid: UseInfiniteQueryOptions\ntitle: UseInfiniteQueryOptions\n---\n\n# Interface: UseInfiniteQueryOptions\\<TQueryFnData, TError, TData, TQueryKey, TPageParam\\>\n\nDefined in: [preact-query/src/types.ts:103](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L103)\n\n## Extends\n\n- `OmitKeyof`\\<`InfiniteQueryObserverOptions`\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\>, `\"suspense\"`\\>\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `TQueryFnData`\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n\n### TPageParam\n\n`TPageParam` = `unknown`\n\n## Properties\n\n### subscribed?\n\n```ts\noptional subscribed: boolean;\n```\n\nDefined in: [preact-query/src/types.ts:123](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L123)\n\nSet this to `false` to unsubscribe this observer from updates to the query cache.\nDefaults to `true`.\n"
  },
  {
    "path": "docs/framework/preact/reference/interfaces/UseMutationOptions.md",
    "content": "---\nid: UseMutationOptions\ntitle: UseMutationOptions\n---\n\n# Interface: UseMutationOptions\\<TData, TError, TVariables, TOnMutateResult\\>\n\nDefined in: [preact-query/src/types.ts:192](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L192)\n\n## Extends\n\n- `OmitKeyof`\\<`MutationObserverOptions`\\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\\>, `\"_defaulted\"`\\>\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TVariables\n\n`TVariables` = `void`\n\n### TOnMutateResult\n\n`TOnMutateResult` = `unknown`\n"
  },
  {
    "path": "docs/framework/preact/reference/interfaces/UsePrefetchQueryOptions.md",
    "content": "---\nid: UsePrefetchQueryOptions\ntitle: UsePrefetchQueryOptions\n---\n\n# Interface: UsePrefetchQueryOptions\\<TQueryFnData, TError, TData, TQueryKey\\>\n\nDefined in: [preact-query/src/types.ts:49](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L49)\n\n## Extends\n\n- `OmitKeyof`\\<`FetchQueryOptions`\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>, `\"queryFn\"`\\>\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `TQueryFnData`\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n\n## Properties\n\n### queryFn?\n\n```ts\noptional queryFn: QueryFunction<TQueryFnData, TQueryKey, never>;\n```\n\nDefined in: [preact-query/src/types.ts:58](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L58)\n"
  },
  {
    "path": "docs/framework/preact/reference/interfaces/UseQueryOptions.md",
    "content": "---\nid: UseQueryOptions\ntitle: UseQueryOptions\n---\n\n# Interface: UseQueryOptions\\<TQueryFnData, TError, TData, TQueryKey\\>\n\nDefined in: [preact-query/src/types.ts:65](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L65)\n\n## Extends\n\n- `OmitKeyof`\\<[`UseBaseQueryOptions`](UseBaseQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryFnData`, `TQueryKey`\\>, `\"suspense\"`\\>\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `TQueryFnData`\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n\n## Properties\n\n### subscribed?\n\n```ts\noptional subscribed: boolean;\n```\n\nDefined in: [preact-query/src/types.ts:46](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L46)\n\nSet this to `false` to unsubscribe this observer from updates to the query cache.\nDefaults to `true`.\n\n#### Inherited from\n\n```ts\nOmitKeyof.subscribed\n```\n"
  },
  {
    "path": "docs/framework/preact/reference/interfaces/UseSuspenseInfiniteQueryOptions.md",
    "content": "---\nid: UseSuspenseInfiniteQueryOptions\ntitle: UseSuspenseInfiniteQueryOptions\n---\n\n# Interface: UseSuspenseInfiniteQueryOptions\\<TQueryFnData, TError, TData, TQueryKey, TPageParam\\>\n\nDefined in: [preact-query/src/types.ts:128](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L128)\n\n## Extends\n\n- `OmitKeyof`\\<[`UseInfiniteQueryOptions`](UseInfiniteQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\>, `\"queryFn\"` \\| `\"enabled\"` \\| `\"throwOnError\"` \\| `\"placeholderData\"`\\>\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `TQueryFnData`\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n\n### TPageParam\n\n`TPageParam` = `unknown`\n\n## Properties\n\n### queryFn?\n\n```ts\noptional queryFn: QueryFunction<TQueryFnData, TQueryKey, TPageParam>;\n```\n\nDefined in: [preact-query/src/types.ts:138](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L138)\n\n***\n\n### subscribed?\n\n```ts\noptional subscribed: boolean;\n```\n\nDefined in: [preact-query/src/types.ts:123](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L123)\n\nSet this to `false` to unsubscribe this observer from updates to the query cache.\nDefaults to `true`.\n\n#### Inherited from\n\n```ts\nOmitKeyof.subscribed\n```\n"
  },
  {
    "path": "docs/framework/preact/reference/interfaces/UseSuspenseQueryOptions.md",
    "content": "---\nid: UseSuspenseQueryOptions\ntitle: UseSuspenseQueryOptions\n---\n\n# Interface: UseSuspenseQueryOptions\\<TQueryFnData, TError, TData, TQueryKey\\>\n\nDefined in: [preact-query/src/types.ts:81](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L81)\n\n## Extends\n\n- `OmitKeyof`\\<[`UseQueryOptions`](UseQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>, `\"queryFn\"` \\| `\"enabled\"` \\| `\"throwOnError\"` \\| `\"placeholderData\"`\\>\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `TQueryFnData`\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n\n## Properties\n\n### queryFn?\n\n```ts\noptional queryFn: QueryFunction<TQueryFnData, TQueryKey, never>;\n```\n\nDefined in: [preact-query/src/types.ts:90](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L90)\n\n***\n\n### subscribed?\n\n```ts\noptional subscribed: boolean;\n```\n\nDefined in: [preact-query/src/types.ts:46](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L46)\n\nSet this to `false` to unsubscribe this observer from updates to the query cache.\nDefaults to `true`.\n\n#### Inherited from\n\n```ts\nOmitKeyof.subscribed\n```\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/AnyUseBaseQueryOptions.md",
    "content": "---\nid: AnyUseBaseQueryOptions\ntitle: AnyUseBaseQueryOptions\n---\n\n# Type Alias: AnyUseBaseQueryOptions\n\n```ts\ntype AnyUseBaseQueryOptions = UseBaseQueryOptions<any, any, any, any, any>;\n```\n\nDefined in: [preact-query/src/types.ts:22](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L22)\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/AnyUseInfiniteQueryOptions.md",
    "content": "---\nid: AnyUseInfiniteQueryOptions\ntitle: AnyUseInfiniteQueryOptions\n---\n\n# Type Alias: AnyUseInfiniteQueryOptions\n\n```ts\ntype AnyUseInfiniteQueryOptions = UseInfiniteQueryOptions<any, any, any, any, any>;\n```\n\nDefined in: [preact-query/src/types.ts:96](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L96)\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/AnyUseMutationOptions.md",
    "content": "---\nid: AnyUseMutationOptions\ntitle: AnyUseMutationOptions\n---\n\n# Type Alias: AnyUseMutationOptions\n\n```ts\ntype AnyUseMutationOptions = UseMutationOptions<any, any, any, any>;\n```\n\nDefined in: [preact-query/src/types.ts:191](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L191)\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/AnyUseQueryOptions.md",
    "content": "---\nid: AnyUseQueryOptions\ntitle: AnyUseQueryOptions\n---\n\n# Type Alias: AnyUseQueryOptions\n\n```ts\ntype AnyUseQueryOptions = UseQueryOptions<any, any, any, any>;\n```\n\nDefined in: [preact-query/src/types.ts:64](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L64)\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/AnyUseSuspenseInfiniteQueryOptions.md",
    "content": "---\nid: AnyUseSuspenseInfiniteQueryOptions\ntitle: AnyUseSuspenseInfiniteQueryOptions\n---\n\n# Type Alias: AnyUseSuspenseInfiniteQueryOptions\n\n```ts\ntype AnyUseSuspenseInfiniteQueryOptions = UseSuspenseInfiniteQueryOptions<any, any, any, any, any>;\n```\n\nDefined in: [preact-query/src/types.ts:126](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L126)\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/AnyUseSuspenseQueryOptions.md",
    "content": "---\nid: AnyUseSuspenseQueryOptions\ntitle: AnyUseSuspenseQueryOptions\n---\n\n# Type Alias: AnyUseSuspenseQueryOptions\n\n```ts\ntype AnyUseSuspenseQueryOptions = UseSuspenseQueryOptions<any, any, any, any>;\n```\n\nDefined in: [preact-query/src/types.ts:75](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L75)\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/DefinedInitialDataInfiniteOptions.md",
    "content": "---\nid: DefinedInitialDataInfiniteOptions\ntitle: DefinedInitialDataInfiniteOptions\n---\n\n# Type Alias: DefinedInitialDataInfiniteOptions\\<TQueryFnData, TError, TData, TQueryKey, TPageParam\\>\n\n```ts\ntype DefinedInitialDataInfiniteOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam> = UseInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam> & object;\n```\n\nDefined in: [preact-query/src/infiniteQueryOptions.ts:56](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/infiniteQueryOptions.ts#L56)\n\n## Type Declaration\n\n### initialData\n\n```ts\ninitialData: \n  | NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>\n  | () => NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>\n  | undefined;\n```\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `InfiniteData`\\<`TQueryFnData`\\>\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n\n### TPageParam\n\n`TPageParam` = `unknown`\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/DefinedInitialDataOptions.md",
    "content": "---\nid: DefinedInitialDataOptions\ntitle: DefinedInitialDataOptions\n---\n\n# Type Alias: DefinedInitialDataOptions\\<TQueryFnData, TError, TData, TQueryKey\\>\n\n```ts\ntype DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> = Omit<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, \"queryFn\"> & object;\n```\n\nDefined in: [preact-query/src/queryOptions.ts:40](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/queryOptions.ts#L40)\n\n## Type Declaration\n\n### initialData\n\n```ts\ninitialData: \n  | NonUndefinedGuard<TQueryFnData>\n| () => NonUndefinedGuard<TQueryFnData>;\n```\n\n### queryFn?\n\n```ts\noptional queryFn: QueryFunction<TQueryFnData, TQueryKey>;\n```\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `TQueryFnData`\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/DefinedUseInfiniteQueryResult.md",
    "content": "---\nid: DefinedUseInfiniteQueryResult\ntitle: DefinedUseInfiniteQueryResult\n---\n\n# Type Alias: DefinedUseInfiniteQueryResult\\<TData, TError\\>\n\n```ts\ntype DefinedUseInfiniteQueryResult<TData, TError> = DefinedInfiniteQueryObserverResult<TData, TError>;\n```\n\nDefined in: [preact-query/src/types.ts:178](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L178)\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/DefinedUseQueryResult.md",
    "content": "---\nid: DefinedUseQueryResult\ntitle: DefinedUseQueryResult\n---\n\n# Type Alias: DefinedUseQueryResult\\<TData, TError\\>\n\n```ts\ntype DefinedUseQueryResult<TData, TError> = DefinedQueryObserverResult<TData, TError>;\n```\n\nDefined in: [preact-query/src/types.ts:168](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L168)\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/QueriesOptions.md",
    "content": "---\nid: QueriesOptions\ntitle: QueriesOptions\n---\n\n# Type Alias: QueriesOptions\\<T, TResults, TDepth\\>\n\n```ts\ntype QueriesOptions<T, TResults, TDepth> = TDepth[\"length\"] extends MAXIMUM_DEPTH ? UseQueryOptionsForUseQueries[] : T extends [] ? [] : T extends [infer Head] ? [...TResults, GetUseQueryOptionsForUseQueries<Head>] : T extends [infer Head, ...(infer Tails)] ? QueriesOptions<[...Tails], [...TResults, GetUseQueryOptionsForUseQueries<Head>], [...TDepth, 1]> : ReadonlyArray<unknown> extends T ? T : T extends UseQueryOptionsForUseQueries<infer TQueryFnData, infer TError, infer TData, infer TQueryKey>[] ? UseQueryOptionsForUseQueries<TQueryFnData, TError, TData, TQueryKey>[] : UseQueryOptionsForUseQueries[];\n```\n\nDefined in: [preact-query/src/useQueries.ts:147](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/useQueries.ts#L147)\n\nQueriesOptions reducer recursively unwraps function arguments to infer/enforce type param\n\n## Type Parameters\n\n### T\n\n`T` *extends* `any`[]\n\n### TResults\n\n`TResults` *extends* `any`[] = \\[\\]\n\n### TDepth\n\n`TDepth` *extends* `ReadonlyArray`\\<`number`\\> = \\[\\]\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/QueriesResults.md",
    "content": "---\nid: QueriesResults\ntitle: QueriesResults\n---\n\n# Type Alias: QueriesResults\\<T, TResults, TDepth\\>\n\n```ts\ntype QueriesResults<T, TResults, TDepth> = TDepth[\"length\"] extends MAXIMUM_DEPTH ? UseQueryResult[] : T extends [] ? [] : T extends [infer Head] ? [...TResults, GetUseQueryResult<Head>] : T extends [infer Head, ...(infer Tails)] ? QueriesResults<[...Tails], [...TResults, GetUseQueryResult<Head>], [...TDepth, 1]> : { [K in keyof T]: GetUseQueryResult<T[K]> };\n```\n\nDefined in: [preact-query/src/useQueries.ts:189](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/useQueries.ts#L189)\n\nQueriesResults reducer recursively maps type param to results\n\n## Type Parameters\n\n### T\n\n`T` *extends* `any`[]\n\n### TResults\n\n`TResults` *extends* `any`[] = \\[\\]\n\n### TDepth\n\n`TDepth` *extends* `ReadonlyArray`\\<`number`\\> = \\[\\]\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/QueryClientProviderProps.md",
    "content": "---\nid: QueryClientProviderProps\ntitle: QueryClientProviderProps\n---\n\n# Type Alias: QueryClientProviderProps\n\n```ts\ntype QueryClientProviderProps = object;\n```\n\nDefined in: [preact-query/src/QueryClientProvider.tsx:23](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/QueryClientProvider.tsx#L23)\n\n## Properties\n\n### children?\n\n```ts\noptional children: ComponentChildren;\n```\n\nDefined in: [preact-query/src/QueryClientProvider.tsx:25](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/QueryClientProvider.tsx#L25)\n\n***\n\n### client\n\n```ts\nclient: QueryClient;\n```\n\nDefined in: [preact-query/src/QueryClientProvider.tsx:24](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/QueryClientProvider.tsx#L24)\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/QueryErrorClearResetFunction.md",
    "content": "---\nid: QueryErrorClearResetFunction\ntitle: QueryErrorClearResetFunction\n---\n\n# Type Alias: QueryErrorClearResetFunction()\n\n```ts\ntype QueryErrorClearResetFunction = () => void;\n```\n\nDefined in: [preact-query/src/QueryErrorResetBoundary.tsx:7](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/QueryErrorResetBoundary.tsx#L7)\n\n## Returns\n\n`void`\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/QueryErrorIsResetFunction.md",
    "content": "---\nid: QueryErrorIsResetFunction\ntitle: QueryErrorIsResetFunction\n---\n\n# Type Alias: QueryErrorIsResetFunction()\n\n```ts\ntype QueryErrorIsResetFunction = () => boolean;\n```\n\nDefined in: [preact-query/src/QueryErrorResetBoundary.tsx:6](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/QueryErrorResetBoundary.tsx#L6)\n\n## Returns\n\n`boolean`\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/QueryErrorResetBoundaryFunction.md",
    "content": "---\nid: QueryErrorResetBoundaryFunction\ntitle: QueryErrorResetBoundaryFunction\n---\n\n# Type Alias: QueryErrorResetBoundaryFunction()\n\n```ts\ntype QueryErrorResetBoundaryFunction = (value) => ComponentChildren;\n```\n\nDefined in: [preact-query/src/QueryErrorResetBoundary.tsx:39](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/QueryErrorResetBoundary.tsx#L39)\n\n## Parameters\n\n### value\n\n`QueryErrorResetBoundaryValue`\n\n## Returns\n\n`ComponentChildren`\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/QueryErrorResetFunction.md",
    "content": "---\nid: QueryErrorResetFunction\ntitle: QueryErrorResetFunction\n---\n\n# Type Alias: QueryErrorResetFunction()\n\n```ts\ntype QueryErrorResetFunction = () => void;\n```\n\nDefined in: [preact-query/src/QueryErrorResetBoundary.tsx:5](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/QueryErrorResetBoundary.tsx#L5)\n\n## Returns\n\n`void`\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/SuspenseQueriesOptions.md",
    "content": "---\nid: SuspenseQueriesOptions\ntitle: SuspenseQueriesOptions\n---\n\n# Type Alias: SuspenseQueriesOptions\\<T, TResults, TDepth\\>\n\n```ts\ntype SuspenseQueriesOptions<T, TResults, TDepth> = TDepth[\"length\"] extends MAXIMUM_DEPTH ? UseSuspenseQueryOptions[] : T extends [] ? [] : T extends [infer Head] ? [...TResults, GetUseSuspenseQueryOptions<Head>] : T extends [infer Head, ...(infer Tails)] ? SuspenseQueriesOptions<[...Tails], [...TResults, GetUseSuspenseQueryOptions<Head>], [...TDepth, 1]> : unknown[] extends T ? T : T extends UseSuspenseQueryOptions<infer TQueryFnData, infer TError, infer TData, infer TQueryKey>[] ? UseSuspenseQueryOptions<TQueryFnData, TError, TData, TQueryKey>[] : UseSuspenseQueryOptions[];\n```\n\nDefined in: [preact-query/src/useSuspenseQueries.ts:109](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/useSuspenseQueries.ts#L109)\n\nSuspenseQueriesOptions reducer recursively unwraps function arguments to infer/enforce type param\n\n## Type Parameters\n\n### T\n\n`T` *extends* `any`[]\n\n### TResults\n\n`TResults` *extends* `any`[] = \\[\\]\n\n### TDepth\n\n`TDepth` *extends* `ReadonlyArray`\\<`number`\\> = \\[\\]\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/SuspenseQueriesResults.md",
    "content": "---\nid: SuspenseQueriesResults\ntitle: SuspenseQueriesResults\n---\n\n# Type Alias: SuspenseQueriesResults\\<T, TResults, TDepth\\>\n\n```ts\ntype SuspenseQueriesResults<T, TResults, TDepth> = TDepth[\"length\"] extends MAXIMUM_DEPTH ? UseSuspenseQueryResult[] : T extends [] ? [] : T extends [infer Head] ? [...TResults, GetUseSuspenseQueryResult<Head>] : T extends [infer Head, ...(infer Tails)] ? SuspenseQueriesResults<[...Tails], [...TResults, GetUseSuspenseQueryResult<Head>], [...TDepth, 1]> : { [K in keyof T]: GetUseSuspenseQueryResult<T[K]> };\n```\n\nDefined in: [preact-query/src/useSuspenseQueries.ts:146](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/useSuspenseQueries.ts#L146)\n\nSuspenseQueriesResults reducer recursively maps type param to results\n\n## Type Parameters\n\n### T\n\n`T` *extends* `any`[]\n\n### TResults\n\n`TResults` *extends* `any`[] = \\[\\]\n\n### TDepth\n\n`TDepth` *extends* `ReadonlyArray`\\<`number`\\> = \\[\\]\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/UndefinedInitialDataInfiniteOptions.md",
    "content": "---\nid: UndefinedInitialDataInfiniteOptions\ntitle: UndefinedInitialDataInfiniteOptions\n---\n\n# Type Alias: UndefinedInitialDataInfiniteOptions\\<TQueryFnData, TError, TData, TQueryKey, TPageParam\\>\n\n```ts\ntype UndefinedInitialDataInfiniteOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam> = UseInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam> & object;\n```\n\nDefined in: [preact-query/src/infiniteQueryOptions.ts:13](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/infiniteQueryOptions.ts#L13)\n\n## Type Declaration\n\n### initialData?\n\n```ts\noptional initialData: \n  | NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>\n| InitialDataFunction<NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>>;\n```\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `InfiniteData`\\<`TQueryFnData`\\>\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n\n### TPageParam\n\n`TPageParam` = `unknown`\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/UndefinedInitialDataOptions.md",
    "content": "---\nid: UndefinedInitialDataOptions\ntitle: UndefinedInitialDataOptions\n---\n\n# Type Alias: UndefinedInitialDataOptions\\<TQueryFnData, TError, TData, TQueryKey\\>\n\n```ts\ntype UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> = UseQueryOptions<TQueryFnData, TError, TData, TQueryKey> & object;\n```\n\nDefined in: [preact-query/src/queryOptions.ts:13](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/queryOptions.ts#L13)\n\n## Type Declaration\n\n### initialData?\n\n```ts\noptional initialData: \n  | InitialDataFunction<NonUndefinedGuard<TQueryFnData>>\n| NonUndefinedGuard<TQueryFnData>;\n```\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `TQueryFnData`\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/UnusedSkipTokenInfiniteOptions.md",
    "content": "---\nid: UnusedSkipTokenInfiniteOptions\ntitle: UnusedSkipTokenInfiniteOptions\n---\n\n# Type Alias: UnusedSkipTokenInfiniteOptions\\<TQueryFnData, TError, TData, TQueryKey, TPageParam\\>\n\n```ts\ntype UnusedSkipTokenInfiniteOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam> = OmitKeyof<UseInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>, \"queryFn\"> & object;\n```\n\nDefined in: [preact-query/src/infiniteQueryOptions.ts:34](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/infiniteQueryOptions.ts#L34)\n\n## Type Declaration\n\n### queryFn?\n\n```ts\noptional queryFn: Exclude<UseInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>[\"queryFn\"], SkipToken | undefined>;\n```\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `InfiniteData`\\<`TQueryFnData`\\>\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n\n### TPageParam\n\n`TPageParam` = `unknown`\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/UnusedSkipTokenOptions.md",
    "content": "---\nid: UnusedSkipTokenOptions\ntitle: UnusedSkipTokenOptions\n---\n\n# Type Alias: UnusedSkipTokenOptions\\<TQueryFnData, TError, TData, TQueryKey\\>\n\n```ts\ntype UnusedSkipTokenOptions<TQueryFnData, TError, TData, TQueryKey> = OmitKeyof<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, \"queryFn\"> & object;\n```\n\nDefined in: [preact-query/src/queryOptions.ts:25](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/queryOptions.ts#L25)\n\n## Type Declaration\n\n### queryFn?\n\n```ts\noptional queryFn: Exclude<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>[\"queryFn\"], SkipToken | undefined>;\n```\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `TQueryFnData`\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/UseBaseMutationResult.md",
    "content": "---\nid: UseBaseMutationResult\ntitle: UseBaseMutationResult\n---\n\n# Type Alias: UseBaseMutationResult\\<TData, TError, TVariables, TOnMutateResult\\>\n\n```ts\ntype UseBaseMutationResult<TData, TError, TVariables, TOnMutateResult> = Override<MutationObserverResult<TData, TError, TVariables, TOnMutateResult>, {\n  mutate: UseMutateFunction<TData, TError, TVariables, TOnMutateResult>;\n}> & object;\n```\n\nDefined in: [preact-query/src/types.ts:220](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L220)\n\n## Type Declaration\n\n### mutateAsync\n\n```ts\nmutateAsync: UseMutateAsyncFunction<TData, TError, TVariables, TOnMutateResult>;\n```\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TVariables\n\n`TVariables` = `unknown`\n\n### TOnMutateResult\n\n`TOnMutateResult` = `unknown`\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/UseBaseQueryResult.md",
    "content": "---\nid: UseBaseQueryResult\ntitle: UseBaseQueryResult\n---\n\n# Type Alias: UseBaseQueryResult\\<TData, TError\\>\n\n```ts\ntype UseBaseQueryResult<TData, TError> = QueryObserverResult<TData, TError>;\n```\n\nDefined in: [preact-query/src/types.ts:150](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L150)\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/UseInfiniteQueryResult.md",
    "content": "---\nid: UseInfiniteQueryResult\ntitle: UseInfiniteQueryResult\n---\n\n# Type Alias: UseInfiniteQueryResult\\<TData, TError\\>\n\n```ts\ntype UseInfiniteQueryResult<TData, TError> = InfiniteQueryObserverResult<TData, TError>;\n```\n\nDefined in: [preact-query/src/types.ts:173](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L173)\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/UseMutateAsyncFunction.md",
    "content": "---\nid: UseMutateAsyncFunction\ntitle: UseMutateAsyncFunction\n---\n\n# Type Alias: UseMutateAsyncFunction\\<TData, TError, TVariables, TOnMutateResult\\>\n\n```ts\ntype UseMutateAsyncFunction<TData, TError, TVariables, TOnMutateResult> = MutateFunction<TData, TError, TVariables, TOnMutateResult>;\n```\n\nDefined in: [preact-query/src/types.ts:213](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L213)\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TVariables\n\n`TVariables` = `void`\n\n### TOnMutateResult\n\n`TOnMutateResult` = `unknown`\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/UseMutateFunction.md",
    "content": "---\nid: UseMutateFunction\ntitle: UseMutateFunction\n---\n\n# Type Alias: UseMutateFunction()\\<TData, TError, TVariables, TOnMutateResult\\>\n\n```ts\ntype UseMutateFunction<TData, TError, TVariables, TOnMutateResult> = (...args) => void;\n```\n\nDefined in: [preact-query/src/types.ts:202](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L202)\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TVariables\n\n`TVariables` = `void`\n\n### TOnMutateResult\n\n`TOnMutateResult` = `unknown`\n\n## Parameters\n\n### args\n\n...`Parameters`\\<`MutateFunction`\\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\\>\\>\n\n## Returns\n\n`void`\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/UseMutationResult.md",
    "content": "---\nid: UseMutationResult\ntitle: UseMutationResult\n---\n\n# Type Alias: UseMutationResult\\<TData, TError, TVariables, TOnMutateResult\\>\n\n```ts\ntype UseMutationResult<TData, TError, TVariables, TOnMutateResult> = UseBaseMutationResult<TData, TError, TVariables, TOnMutateResult>;\n```\n\nDefined in: [preact-query/src/types.ts:237](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L237)\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TVariables\n\n`TVariables` = `unknown`\n\n### TOnMutateResult\n\n`TOnMutateResult` = `unknown`\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/UseQueryResult.md",
    "content": "---\nid: UseQueryResult\ntitle: UseQueryResult\n---\n\n# Type Alias: UseQueryResult\\<TData, TError\\>\n\n```ts\ntype UseQueryResult<TData, TError> = UseBaseQueryResult<TData, TError>;\n```\n\nDefined in: [preact-query/src/types.ts:155](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L155)\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/UseSuspenseInfiniteQueryResult.md",
    "content": "---\nid: UseSuspenseInfiniteQueryResult\ntitle: UseSuspenseInfiniteQueryResult\n---\n\n# Type Alias: UseSuspenseInfiniteQueryResult\\<TData, TError\\>\n\n```ts\ntype UseSuspenseInfiniteQueryResult<TData, TError> = OmitKeyof<DefinedInfiniteQueryObserverResult<TData, TError>, \"isPlaceholderData\" | \"promise\">;\n```\n\nDefined in: [preact-query/src/types.ts:183](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L183)\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n"
  },
  {
    "path": "docs/framework/preact/reference/type-aliases/UseSuspenseQueryResult.md",
    "content": "---\nid: UseSuspenseQueryResult\ntitle: UseSuspenseQueryResult\n---\n\n# Type Alias: UseSuspenseQueryResult\\<TData, TError\\>\n\n```ts\ntype UseSuspenseQueryResult<TData, TError> = DistributiveOmit<DefinedQueryObserverResult<TData, TError>, \"isPlaceholderData\" | \"promise\">;\n```\n\nDefined in: [preact-query/src/types.ts:160](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/types.ts#L160)\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n"
  },
  {
    "path": "docs/framework/preact/reference/variables/IsRestoringProvider.md",
    "content": "---\nid: IsRestoringProvider\ntitle: IsRestoringProvider\n---\n\n# Variable: IsRestoringProvider\n\n```ts\nconst IsRestoringProvider: Provider<boolean> = IsRestoringContext.Provider;\n```\n\nDefined in: [preact-query/src/IsRestoringProvider.ts:7](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/IsRestoringProvider.ts#L7)\n"
  },
  {
    "path": "docs/framework/preact/reference/variables/QueryClientContext.md",
    "content": "---\nid: QueryClientContext\ntitle: QueryClientContext\n---\n\n# Variable: QueryClientContext\n\n```ts\nconst QueryClientContext: Context<QueryClient | undefined>;\n```\n\nDefined in: [preact-query/src/QueryClientProvider.tsx:5](https://github.com/theVedanta/query/blob/main/packages/preact-query/src/QueryClientProvider.tsx#L5)\n"
  },
  {
    "path": "docs/framework/preact/typescript.md",
    "content": "---\nid: typescript\ntitle: TypeScript\nref: docs/framework/react/typescript.md\nreplace: { 'react-query': 'preact-query', 'React': 'Preact' }\n---\n"
  },
  {
    "path": "docs/framework/react/comparison.md",
    "content": "---\nid: comparison\ntitle: Comparison | React Query vs SWR vs Apollo vs RTK Query vs React Router\n---\n\n> This comparison table strives to be as accurate and as unbiased as possible. If you use any of these libraries and feel the information could be improved, feel free to suggest changes (with notes or evidence of claims) using the \"Edit this page on Github\" link at the bottom of this page.\n\nFeature/Capability Key:\n\n- ✅ 1st-class, built-in, and ready to use with no added configuration or code\n- 🟡 Supported, but as an unofficial 3rd party or community library/contribution\n- 🔶 Supported and documented, but requires extra user-code to implement\n- 🛑 Not officially supported or documented.\n\n|                                                    | React Query                              | SWR [_(Website)_][swr]                   | Apollo Client [_(Website)_][apollo]        | RTK-Query [_(Website)_][rtk-query]   | React Router [_(Website)_][react-router]                                  |\n| -------------------------------------------------- | ---------------------------------------- | ---------------------------------------- | ------------------------------------------ | ------------------------------------ | ------------------------------------------------------------------------- |\n| Github Repo / Stars                                | [![][stars-react-query]][gh-react-query] | [![][stars-swr]][gh-swr]                 | [![][stars-apollo]][gh-apollo]             | [![][stars-rtk-query]][gh-rtk-query] | [![][stars-react-router]][gh-react-router]                                |\n| Platform Requirements                              | React                                    | React                                    | React, GraphQL                             | Redux                                | React                                                                     |\n| Their Comparison                                   |                                          | (none)                                   | (none)                                     | [Comparison][rtk-query-comparison]   | (none)                                                                    |\n| Supported Query Syntax                             | Promise, REST, GraphQL                   | Promise, REST, GraphQL                   | GraphQL, Any (Reactive Variables)          | Promise, REST, GraphQL               | Promise, REST, GraphQL                                                    |\n| Supported Frameworks                               | React                                    | React                                    | React + Others                             | Any                                  | React                                                                     |\n| Caching Strategy                                   | Hierarchical Key -> Value                | Unique Key -> Value                      | Normalized Schema                          | Unique Key -> Value                  | Nested Route -> value                                                     |\n| Cache Key Strategy                                 | JSON                                     | JSON                                     | GraphQL Query                              | JSON                                 | Route Path                                                                |\n| Cache Change Detection                             | Deep Compare Keys (Stable Serialization) | Deep Compare Keys (Stable Serialization) | Deep Compare Keys (Unstable Serialization) | Key Referential Equality (===)       | Route Change                                                              |\n| Data Change Detection                              | Deep Comparison + Structural Sharing     | Deep Compare (via `stable-hash`)         | Deep Compare (Unstable Serialization)      | Key Referential Equality (===)       | Loader Run                                                                |\n| Data Memoization                                   | Full Structural Sharing                  | Identity (===)                           | Normalized Identity                        | Identity (===)                       | Identity (===)                                                            |\n| Bundle Size                                        | [![][bp-react-query]][bpl-react-query]   | [![][bp-swr]][bpl-swr]                   | [![][bp-apollo]][bpl-apollo]               | [![][bp-rtk-query]][bpl-rtk-query]   | [![][bp-react-router]][bpl-react-router] + [![][bp-history]][bpl-history] |\n| API Definition Location                            | Component, External Config               | Component                                | GraphQL Schema                             | External Config                      | Route Tree Configuration                                                  |\n| Queries                                            | ✅                                       | ✅                                       | ✅                                         | ✅                                   | ✅                                                                        |\n| Cache Persistence                                  | ✅                                       | ✅                                       | ✅                                         | ✅                                   | 🛑 Active Routes Only <sup>8</sup>                                        |\n| Devtools                                           | ✅                                       | ✅                                       | ✅                                         | ✅                                   | 🛑                                                                        |\n| Polling/Intervals                                  | ✅                                       | ✅                                       | ✅                                         | ✅                                   | 🛑                                                                        |\n| Parallel Queries                                   | ✅                                       | ✅                                       | ✅                                         | ✅                                   | ✅                                                                        |\n| Dependent Queries                                  | ✅                                       | ✅                                       | ✅                                         | ✅                                   | ✅                                                                        |\n| Paginated Queries                                  | ✅                                       | ✅                                       | ✅                                         | ✅                                   | ✅                                                                        |\n| Infinite Queries                                   | ✅                                       | ✅                                       | ✅                                         | ✅                                   | 🛑                                                                        |\n| Bi-directional Infinite Queries                    | ✅                                       | 🔶                                       | 🔶                                         | ✅                                   | 🛑                                                                        |\n| Infinite Query Refetching                          | ✅                                       | ✅                                       | 🛑                                         | ✅                                   | 🛑                                                                        |\n| Lagged Query Data<sup>1</sup>                      | ✅                                       | ✅                                       | ✅                                         | ✅                                   | ✅                                                                        |\n| Selectors                                          | ✅                                       | 🛑                                       | ✅                                         | ✅                                   | N/A                                                                       |\n| Initial Data                                       | ✅                                       | ✅                                       | ✅                                         | ✅                                   | ✅                                                                        |\n| Scroll Recovery                                    | ✅                                       | ✅                                       | ✅                                         | ✅                                   | ✅                                                                        |\n| Cache Manipulation                                 | ✅                                       | ✅                                       | ✅                                         | ✅                                   | 🛑                                                                        |\n| Outdated Query Dismissal                           | ✅                                       | ✅                                       | ✅                                         | ✅                                   | ✅                                                                        |\n| Render Batching & Optimization<sup>2</sup>         | ✅                                       | ✅                                       | 🛑                                         | ✅                                   | ✅                                                                        |\n| Auto Garbage Collection                            | ✅                                       | 🛑                                       | 🛑                                         | ✅                                   | N/A                                                                       |\n| Mutation Hooks                                     | ✅                                       | ✅                                       | ✅                                         | ✅                                   | ✅                                                                        |\n| Offline Mutation Support                           | ✅                                       | 🛑                                       | 🟡                                         | 🛑                                   | 🛑                                                                        |\n| Prefetching APIs                                   | ✅                                       | ✅                                       | ✅                                         | ✅                                   | ✅                                                                        |\n| Query Cancellation                                 | ✅                                       | 🛑                                       | 🛑                                         | 🛑                                   | ✅                                                                        |\n| Partial Query Matching<sup>3</sup>                 | ✅                                       | 🔶                                       | ✅                                         | ✅                                   | N/A                                                                       |\n| Stale While Revalidate                             | ✅                                       | ✅                                       | ✅                                         | ✅                                   | 🛑                                                                        |\n| Stale Time Configuration                           | ✅                                       | 🛑<sup>7</sup>                           | 🛑                                         | ✅                                   | 🛑                                                                        |\n| Pre-usage Query/Mutation Configuration<sup>4</sup> | ✅                                       | 🛑                                       | ✅                                         | ✅                                   | ✅                                                                        |\n| Window Focus Refetching                            | ✅                                       | ✅                                       | 🛑                                         | ✅                                   | 🛑                                                                        |\n| Network Status Refetching                          | ✅                                       | ✅                                       | ✅                                         | ✅                                   | 🛑                                                                        |\n| General Cache Dehydration/Rehydration              | ✅                                       | 🛑                                       | ✅                                         | ✅                                   | ✅                                                                        |\n| Offline Caching                                    | ✅                                       | 🛑                                       | ✅                                         | 🔶                                   | 🛑                                                                        |\n| React Suspense                                     | ✅                                       | ✅                                       | ✅                                         | 🛑                                   | ✅                                                                        |\n| Abstracted/Agnostic Core                           | ✅                                       | 🛑                                       | ✅                                         | ✅                                   | 🛑                                                                        |\n| Automatic Refetch after Mutation<sup>5</sup>       | 🔶                                       | 🔶                                       | ✅                                         | ✅                                   | ✅                                                                        |\n| Normalized Caching<sup>6</sup>                     | 🛑                                       | 🛑                                       | ✅                                         | 🛑                                   | 🛑                                                                        |\n\n### Notes\n\n> **<sup>1</sup> Lagged Query Data** - React Query provides a way to continue to see an existing query's data while the next query loads (similar to the same UX that suspense will soon provide natively). This is extremely important when writing pagination UIs or infinite loading UIs where you do not want to show a hard loading state whenever a new query is requested. Other libraries do not have this capability and render a hard loading state for the new query (unless it has been prefetched), while the new query loads.\n\n> **<sup>2</sup> Render Optimization** - React Query has excellent rendering performance. By default, it will automatically track which fields are accessed and only re-render if one of them changes. If you would like to opt-out of this optimization, setting `notifyOnChangeProps` to `'all'` will re-render your components whenever the query is updated. For example because it has new data, or to indicate it is fetching. React Query also batches updates together to make sure your application only re-renders once when multiple components are using the same query. If you are only interested in the `data` or `error` properties, you can reduce the number of renders even more by setting `notifyOnChangeProps` to `['data', 'error']`.\n\n> **<sup>3</sup> Partial query matching** - Because React Query uses deterministic query key serialization, this allows you to manipulate variable groups of queries without having to know each individual query-key that you want to match, eg. you can refetch every query that starts with `todos` in its key, regardless of variables, or you can target specific queries with (or without) variables or nested properties, and even use a filter function to only match queries that pass your specific conditions.\n\n> **<sup>4</sup> Pre-usage Query Configuration** - This is simply a fancy name for being able to configure how queries and mutations will behave before they are used. For instance, a query can be fully configured with defaults beforehand and when the time comes to use it, only `useQuery({ queryKey })` is necessary, instead of being required to pass the fetcher and/or options with every usage. SWR does have a partial form of this feature by allowing you to pre-configure a default fetcher, but only as a global fetcher, not on a per-query basis and definitely not for mutations.\n\n> **<sup>5</sup> Automatic Refetch after Mutation** - For truly automatic refetching to happen after a mutation occurs, a schema is necessary (like the one graphQL provides) along with heuristics that help the library know how to identify individual entities and entities types in that schema.\n\n> **<sup>6</sup> Normalized Caching** - React Query, SWR and RTK-Query do not currently support automatic-normalized caching which describes storing entities in a flat architecture to avoid some high-level data duplication.\n\n> **<sup>7</sup> SWR's Immutable Mode** - SWR ships with an \"immutable\" mode that does allow you to only fetch a query once for the life of the cache, but it still does not have the concept of stale-time or conditional auto-revalidation\n\n> **<sup>8</sup> React Router cache persistence** - React Router does not cache data beyond the currently matched routes. If a route is left, its data is lost.\n\n[bpl-react-query]: https://bundlephobia.com/result?p=@tanstack/react-query\n[bp-react-query]: https://badgen.net/bundlephobia/minzip/@tanstack/react-query?label=💾\n[gh-react-query]: https://github.com/TanStack/query\n[stars-react-query]: https://img.shields.io/github/stars/TanStack/query?label=%F0%9F%8C%9F\n[swr]: https://github.com/vercel/swr\n[bp-swr]: https://badgen.net/bundlephobia/minzip/swr?label=💾\n[gh-swr]: https://github.com/vercel/swr\n[stars-swr]: https://img.shields.io/github/stars/vercel/swr?label=%F0%9F%8C%9F\n[bpl-swr]: https://bundlephobia.com/result?p=swr\n[apollo]: https://github.com/apollographql/apollo-client\n[bp-apollo]: https://badgen.net/bundlephobia/minzip/@apollo/client?label=💾\n[gh-apollo]: https://github.com/apollographql/apollo-client\n[stars-apollo]: https://img.shields.io/github/stars/apollographql/apollo-client?label=%F0%9F%8C%9F\n[bpl-apollo]: https://bundlephobia.com/result?p=@apollo/client\n[rtk-query]: https://redux-toolkit.js.org/rtk-query/overview\n[rtk-query-comparison]: https://redux-toolkit.js.org/rtk-query/comparison\n[rtk-query-bundle-size]: https://redux-toolkit.js.org/rtk-query/comparison#bundle-size\n[bp-rtk]: https://badgen.net/bundlephobia/minzip/@reduxjs/toolkit?label=💾\n[bp-rtk-query]: https://badgen.net/bundlephobia/minzip/@reduxjs/toolkit?label=💾\n[gh-rtk-query]: https://github.com/reduxjs/redux-toolkit\n[stars-rtk-query]: https://img.shields.io/github/stars/reduxjs/redux-toolkit?label=🌟\n[bpl-rtk]: https://bundlephobia.com/result?p=@reduxjs/toolkit\n[bpl-rtk-query]: https://bundlephobia.com/package/@reduxjs/toolkit\n[react-router]: https://github.com/remix-run/react-router\n[bp-react-router]: https://badgen.net/bundlephobia/minzip/react-router-dom?label=💾\n[gh-react-router]: https://github.com/remix-run/react-router\n[stars-react-router]: https://img.shields.io/github/stars/remix-run/react-router?label=%F0%9F%8C%9F\n[bpl-react-router]: https://bundlephobia.com/result?p=react-router-dom\n[bp-history]: https://badgen.net/bundlephobia/minzip/history?label=💾\n[bpl-history]: https://bundlephobia.com/result?p=history\n"
  },
  {
    "path": "docs/framework/react/devtools.md",
    "content": "---\nid: devtools\ntitle: Devtools\n---\n\nWave your hands in the air and shout hooray because React Query comes with dedicated devtools! 🥳\n\nWhen you begin your React Query journey, you'll want these devtools by your side. They help visualize all the inner workings of React Query and will likely save you hours of debugging if you find yourself in a pinch!\n\n> For Chrome, Firefox, and Edge users: Third-party browser extensions are available for debugging TanStack Query directly in browser DevTools. These provide the same functionality as the framework-specific devtools packages:\n>\n> - <img alt=\"Chrome logo\" src=\"https://www.google.com/chrome/static/images/chrome-logo.svg\" width=\"16\" height=\"16\" class=\"inline mr-1 not-prose\" /> [Devtools for Chrome](https://chromewebstore.google.com/detail/tanstack-query-devtools/annajfchloimdhceglpgglpeepfghfai)\n> - <img alt=\"Firefox logo\" src=\"https://upload.wikimedia.org/wikipedia/commons/a/a0/Firefox_logo%2C_2019.svg\" width=\"16\" height=\"16\" class=\"inline mr-1 not-prose\" /> [Devtools for Firefox](https://addons.mozilla.org/en-US/firefox/addon/tanstack-query-devtools/)\n> - <img alt=\"Edge logo\" src=\"https://upload.wikimedia.org/wikipedia/commons/9/98/Microsoft_Edge_logo_%282019%29.svg\" width=\"16\" height=\"16\" class=\"inline mr-1 not-prose\" /> [Devtools for Edge](https://microsoftedge.microsoft.com/addons/detail/tanstack-query-devtools/edmdpkgkacmjopodhfolmphdenmddobj)\n\n> For React Native users: A third-party native macOS app is available for debugging React Query in ANY js-based application. Monitor queries across devices in real-time. Check it out here: [rn-better-dev-tools](https://github.com/LovesWorking/rn-better-dev-tools)\n\n> Note that since version 5, the dev tools support observing mutations as well.\n\n## Install and Import the Devtools\n\nThe devtools are a separate package that you need to install:\n\n```bash\nnpm i @tanstack/react-query-devtools\n```\n\nor\n\n```bash\npnpm add @tanstack/react-query-devtools\n```\n\nor\n\n```bash\nyarn add @tanstack/react-query-devtools\n```\n\nor\n\n```bash\nbun add @tanstack/react-query-devtools\n```\n\nFor Next 13+ App Dir you must install it as a dev dependency for it to work.\n\nYou can import the devtools like this:\n\n```tsx\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\n```\n\nBy default, React Query Devtools are only included in bundles when `process.env.NODE_ENV === 'development'`, so you don't need to worry about excluding them during a production build.\n\n## Floating Mode\n\nFloating Mode will mount the devtools as a fixed, floating element in your app and provide a toggle in the corner of the screen to show and hide the devtools. This toggle state will be stored and remembered in localStorage across reloads.\n\nPlace the following code as high in your React app as you can. The closer it is to the root of the page, the better it will work!\n\n```tsx\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\n\nfunction App() {\n  return (\n    <QueryClientProvider client={queryClient}>\n      {/* The rest of your application */}\n      <ReactQueryDevtools initialIsOpen={false} />\n    </QueryClientProvider>\n  )\n}\n```\n\n### Options\n\n- `initialIsOpen: boolean`\n  - Set this `true` if you want the dev tools to default to being open\n- `buttonPosition?: \"top-left\" | \"top-right\" | \"bottom-left\" | \"bottom-right\" | \"relative\"`\n  - Defaults to `bottom-right`\n  - The position of the React Query logo to open and close the devtools panel\n  - If `relative`, the button is placed in the location that you render the devtools.\n- `position?: \"top\" | \"bottom\" | \"left\" | \"right\"`\n  - Defaults to `bottom`\n  - The position of the React Query devtools panel\n- `client?: QueryClient`,\n  - Use this to use a custom QueryClient. Otherwise, the one from the nearest context will be used.\n- `errorTypes?: { name: string; initializer: (query: Query) => TError}[]`\n  - Use this to predefine some errors that can be triggered on your queries. Initializer will be called (with the specific query) when that error is toggled on from the UI. It must return an Error.\n- `styleNonce?: string`\n  - 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.\n- `shadowDOMTarget?: ShadowRoot`\n  - Default behavior will apply the devtool's styles to the head tag within the DOM.\n  - Use this to pass a shadow DOM target to the devtools so that the styles will be applied within the shadow DOM instead of within the head tag in the light DOM.\n\n## Embedded Mode\n\nEmbedded mode will show the development tools as a fixed element in your application, so you can use our panel in your own development tools.\n\nPlace the following code as high in your React app as you can. The closer it is to the root of the page, the better it will work!\n\n```tsx\nimport { ReactQueryDevtoolsPanel } from '@tanstack/react-query-devtools'\n\nfunction App() {\n  const [isOpen, setIsOpen] = React.useState(false)\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      {/* The rest of your application */}\n      <button\n        onClick={() => setIsOpen(!isOpen)}\n      >{`${isOpen ? 'Close' : 'Open'} the devtools panel`}</button>\n      {isOpen && <ReactQueryDevtoolsPanel onClose={() => setIsOpen(false)} />}\n    </QueryClientProvider>\n  )\n}\n```\n\n### Options\n\n- `style?: React.CSSProperties`\n  - Custom styles for the devtools panel\n  - Default: `{ height: '500px' }`\n  - Example: `{ height: '100%' }`\n  - Example: `{ height: '100%', width: '100%' }`\n- `onClose?: () => unknown`\n  - Callback function that is called when the devtools panel is closed\n- `client?: QueryClient`,\n  - Use this to use a custom QueryClient. Otherwise, the one from the nearest context will be used.\n- `errorTypes?: { name: string; initializer: (query: Query) => TError}[]`\n  - Use this to predefine some errors that can be triggered on your queries. Initializer will be called (with the specific query) when that error is toggled on from the UI. It must return an Error.\n- `styleNonce?: string`\n  - 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.\n- `shadowDOMTarget?: ShadowRoot`\n  - Default behavior will apply the devtool's styles to the head tag within the DOM.\n  - Use this to pass a shadow DOM target to the devtools so that the styles will be applied within the shadow DOM instead of within the head tag in the light DOM.\n\n## Devtools in production\n\nDevtools are excluded in production builds. However, it might be desirable to lazy load the devtools in production:\n\n```tsx\nimport * as React from 'react'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\nimport { Example } from './Example'\n\nconst queryClient = new QueryClient()\n\nconst ReactQueryDevtoolsProduction = React.lazy(() =>\n  import('@tanstack/react-query-devtools/build/modern/production.js').then(\n    (d) => ({\n      default: d.ReactQueryDevtools,\n    }),\n  ),\n)\n\nfunction App() {\n  const [showDevtools, setShowDevtools] = React.useState(false)\n\n  React.useEffect(() => {\n    // @ts-expect-error\n    window.toggleDevtools = () => setShowDevtools((old) => !old)\n  }, [])\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      <Example />\n      <ReactQueryDevtools initialIsOpen />\n      {showDevtools && (\n        <React.Suspense fallback={null}>\n          <ReactQueryDevtoolsProduction />\n        </React.Suspense>\n      )}\n    </QueryClientProvider>\n  )\n}\n\nexport default App\n```\n\nWith this, calling `window.toggleDevtools()` will download the devtools bundle and show them.\n\n### Modern bundlers\n\nIf your bundler supports package exports, you can use the following import path:\n\n```tsx\nconst ReactQueryDevtoolsProduction = React.lazy(() =>\n  import('@tanstack/react-query-devtools/production').then((d) => ({\n    default: d.ReactQueryDevtools,\n  })),\n)\n```\n\nFor TypeScript, you would need to set `moduleResolution: 'nodenext'` in your tsconfig, which requires at least TypeScript v4.7.\n"
  },
  {
    "path": "docs/framework/react/graphql.md",
    "content": "---\nid: graphql\ntitle: GraphQL\n---\n\nBecause React Query's fetching mechanisms are agnostically built on Promises, you can use React Query with literally any asynchronous data fetching client, including GraphQL!\n\n> Keep in mind that React Query does not support normalized caching. While a vast majority of users do not actually need a normalized cache or even benefit from it as much as they believe they do, there may be very rare circumstances that may warrant it so be sure to check with us first to make sure it's truly something you need!\n\n[//]: # 'Codegen'\n\n## Type-Safety and Code Generation\n\nReact Query, used in combination with `graphql-request^5` and [GraphQL Code Generator](https://graphql-code-generator.com/) provides full-typed GraphQL operations:\n\n```tsx\nimport request from 'graphql-request'\nimport { useQuery } from '@tanstack/react-query'\n\nimport { graphql } from './gql/gql'\n\nconst allFilmsWithVariablesQueryDocument = graphql(/* GraphQL */ `\n  query allFilmsWithVariablesQuery($first: Int!) {\n    allFilms(first: $first) {\n      edges {\n        node {\n          id\n          title\n        }\n      }\n    }\n  }\n`)\n\nfunction App() {\n  // `data` is fully typed!\n  const { data } = useQuery({\n    queryKey: ['films'],\n    queryFn: async () =>\n      request(\n        'https://swapi-graphql.netlify.app/.netlify/functions/index',\n        allFilmsWithVariablesQueryDocument,\n        // variables are type-checked too!\n        { first: 10 },\n      ),\n  })\n  // ...\n}\n```\n\n_You can find a [complete example in the repo](https://github.com/dotansimha/graphql-code-generator/tree/7c25c4eeb77f88677fd79da557b7b5326e3f3950/examples/front-end/react/tanstack-react-query)_\n\nGet started with the [dedicated guide on GraphQL Code Generator documentation](https://www.the-guild.dev/graphql/codegen/docs/guides/react-vue).\n\n[//]: # 'Codegen'\n"
  },
  {
    "path": "docs/framework/react/guides/advanced-ssr.md",
    "content": "---\nid: advanced-ssr\ntitle: Advanced Server Rendering\n---\n\nWelcome to the Advanced Server Rendering guide, where you will learn all about using React Query with streaming, Server Components and the Next.js app router.\n\nYou might want to read the [Server Rendering & Hydration guide](./ssr.md) before this one as it teaches the basics for using React Query with SSR, and [Performance & Request Waterfalls](./request-waterfalls.md) as well as [Prefetching & Router Integration](./prefetching.md) also contains valuable background.\n\nBefore we start, let's note that while the `initialData` approach outlined in the SSR guide also works with Server Components, we'll focus this guide on the hydration APIs.\n\n## Server Components & Next.js app router\n\nWe won't cover Server Components in depth here, but the short version is that they are components that are guaranteed to _only_ run on the server, both for the initial page view and **also on page transitions**. This is similar to how Next.js `getServerSideProps`/`getStaticProps` and Remix `loader` works, as these also always run on the server but while those can only return data, Server Components can do a lot more. The data part is central to React Query however, so let's focus on that.\n\nHow do we take what we learned in the Server Rendering guide about [passing data prefetched in framework loaders to the app](./ssr.md#using-the-hydration-apis) and apply that to Server Components and the Next.js app router? The best way to start thinking about this is to consider Server Components as \"just\" another framework loader.\n\n### A quick note on terminology\n\nSo far in these guides, we've been talking about the _server_ and the _client_. It's important to note that confusingly enough this does not match 1-1 with _Server Components_ and _Client Components_. Server Components are guaranteed to only run on the server, but Client Components can actually run in both places. The reason for this is that they can also render during the initial _server rendering_ pass.\n\nOne way to think of this is that even though Server Components also _render_, they happen during a \"loader phase\" (always happens on the server), while Client Components run during the \"application phase\". That application can run both on the server during SSR, and in for example a browser. Where exactly that application runs and if it runs during SSR or not might differ between frameworks.\n\n### Initial setup\n\nThe first step of any React Query setup is always to create a `queryClient` and wrap your application in a `QueryClientProvider`. With Server Components, this looks mostly the same across frameworks, one difference being the filename conventions:\n\n```tsx\n// In Next.js, this file would be called: app/providers.tsx\n'use client'\n\n// Since QueryClientProvider relies on useContext under the hood, we have to put 'use client' on top\nimport {\n  isServer,\n  QueryClient,\n  QueryClientProvider,\n} from '@tanstack/react-query'\n\nfunction makeQueryClient() {\n  return new QueryClient({\n    defaultOptions: {\n      queries: {\n        // With SSR, we usually want to set some default staleTime\n        // above 0 to avoid refetching immediately on the client\n        staleTime: 60 * 1000,\n      },\n    },\n  })\n}\n\nlet browserQueryClient: QueryClient | undefined = undefined\n\nfunction getQueryClient() {\n  if (isServer) {\n    // Server: always make a new query client\n    return makeQueryClient()\n  } else {\n    // Browser: make a new query client if we don't already have one\n    // This is very important, so we don't re-make a new client if React\n    // suspends during the initial render. This may not be needed if we\n    // have a suspense boundary BELOW the creation of the query client\n    if (!browserQueryClient) browserQueryClient = makeQueryClient()\n    return browserQueryClient\n  }\n}\n\nexport default function Providers({ children }: { children: React.ReactNode }) {\n  // NOTE: Avoid useState when initializing the query client if you don't\n  //       have a suspense boundary between this and the code that may\n  //       suspend because React will throw away the client on the initial\n  //       render if it suspends and there is no boundary\n  const queryClient = getQueryClient()\n\n  return (\n    <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>\n  )\n}\n```\n\n```tsx\n// In Next.js, this file would be called: app/layout.tsx\nimport Providers from './providers'\n\nexport default function RootLayout({\n  children,\n}: {\n  children: React.ReactNode\n}) {\n  return (\n    <html lang=\"en\">\n      <head />\n      <body>\n        <Providers>{children}</Providers>\n      </body>\n    </html>\n  )\n}\n```\n\nThis part is pretty similar to what we did in the SSR guide, we just need to split things up into two different files.\n\n### Prefetching and de/hydrating data\n\nNext, let’s look at how to actually prefetch data, then dehydrate and hydrate it. This is what it looked like using the **Next.js Pages Router**:\n\n```tsx\n// pages/posts.tsx\nimport {\n  dehydrate,\n  HydrationBoundary,\n  QueryClient,\n  useQuery,\n} from '@tanstack/react-query'\n\n// This could also be getServerSideProps\nexport async function getStaticProps() {\n  const queryClient = new QueryClient()\n\n  await queryClient.prefetchQuery({\n    queryKey: ['posts'],\n    queryFn: getPosts,\n  })\n\n  return {\n    props: {\n      dehydratedState: dehydrate(queryClient),\n    },\n  }\n}\n\nfunction Posts() {\n  // This useQuery could just as well happen in some deeper child to\n  // the <PostsRoute>, data will be available immediately either way\n  //\n  // Note that we are using useQuery here instead of useSuspenseQuery.\n  // Because this data has already been prefetched, there is no need to\n  // ever suspend in the component itself. If we forget or remove the\n  // prefetch, this will instead fetch the data on the client, while\n  // using useSuspenseQuery would have had worse side effects.\n  const { data } = useQuery({ queryKey: ['posts'], queryFn: getPosts })\n\n  // This query was not prefetched on the server and will not start\n  // fetching until on the client, both patterns are fine to mix\n  const { data: commentsData } = useQuery({\n    queryKey: ['posts-comments'],\n    queryFn: getComments,\n  })\n\n  // ...\n}\n\nexport default function PostsRoute({ dehydratedState }) {\n  return (\n    <HydrationBoundary state={dehydratedState}>\n      <Posts />\n    </HydrationBoundary>\n  )\n}\n```\n\nConverting this to the app router actually looks pretty similar, we just need to move things around a bit. First, we'll create a Server Component to do the prefetching part:\n\n```tsx\n// app/posts/page.tsx\nimport {\n  dehydrate,\n  HydrationBoundary,\n  QueryClient,\n} from '@tanstack/react-query'\nimport Posts from './posts'\n\nexport default async function PostsPage() {\n  const queryClient = new QueryClient()\n\n  await queryClient.prefetchQuery({\n    queryKey: ['posts'],\n    queryFn: getPosts,\n  })\n\n  return (\n    // Neat! Serialization is now as easy as passing props.\n    // HydrationBoundary is a Client Component, so hydration will happen there.\n    <HydrationBoundary state={dehydrate(queryClient)}>\n      <Posts />\n    </HydrationBoundary>\n  )\n}\n```\n\nNext, we'll look at what the Client Component part looks like:\n\n```tsx\n// app/posts/posts.tsx\n'use client'\n\nexport default function Posts() {\n  // This useQuery could just as well happen in some deeper\n  // child to <Posts>, data will be available immediately either way\n  const { data } = useQuery({\n    queryKey: ['posts'],\n    queryFn: () => getPosts(),\n  })\n\n  // This query was not prefetched on the server and will not start\n  // fetching until on the client, both patterns are fine to mix.\n  const { data: commentsData } = useQuery({\n    queryKey: ['posts-comments'],\n    queryFn: getComments,\n  })\n\n  // ...\n}\n```\n\nOne neat thing about the examples above is that the only thing that is Next.js-specific here are the file names, everything else would look the same in any other framework that supports Server Components.\n\nIn the SSR guide, we noted that you could get rid of the boilerplate of having `<HydrationBoundary>` in every route. This is not possible with Server Components.\n\n> NOTE: If you encounter a type error while using async Server Components with TypeScript versions lower than `5.1.3` and `@types/react` versions lower than `18.2.8`, it is recommended to update to the latest versions of both. Alternatively, you can use the temporary workaround of adding `{/* @ts-expect-error Server Component */}` when calling this component inside another. For more information, see [Async Server Component TypeScript Error](https://nextjs.org/docs/app/building-your-application/configuring/typescript#async-server-component-typescript-error) in the Next.js 13 docs.\n\n> NOTE: If you encounter an error `Only plain objects, and a few built-ins, can be passed to Server Actions. Classes or null prototypes are not supported.` make sure that you're **not** passing to queryFn a function reference, instead call the function because queryFn args has a bunch of properties and not all of it would be serializable. see [Server Action only works when queryFn isn't a reference](https://github.com/TanStack/query/issues/6264).\n\n### Nesting Server Components\n\nA nice thing about Server Components is that they can be nested and exist on many levels in the React tree, making it possible to prefetch data closer to where it's actually used instead of only at the top of the application (just like Remix loaders). This can be as simple as a Server Component rendering another Server Component (we'll leave the Client Components out in this example for brevity):\n\n```tsx\n// app/posts/page.tsx\nimport {\n  dehydrate,\n  HydrationBoundary,\n  QueryClient,\n} from '@tanstack/react-query'\nimport Posts from './posts'\nimport CommentsServerComponent from './comments-server'\n\nexport default async function PostsPage() {\n  const queryClient = new QueryClient()\n\n  await queryClient.prefetchQuery({\n    queryKey: ['posts'],\n    queryFn: getPosts,\n  })\n\n  return (\n    <HydrationBoundary state={dehydrate(queryClient)}>\n      <Posts />\n      <CommentsServerComponent />\n    </HydrationBoundary>\n  )\n}\n\n// app/posts/comments-server.tsx\nimport {\n  dehydrate,\n  HydrationBoundary,\n  QueryClient,\n} from '@tanstack/react-query'\nimport Comments from './comments'\n\nexport default async function CommentsServerComponent() {\n  const queryClient = new QueryClient()\n\n  await queryClient.prefetchQuery({\n    queryKey: ['posts-comments'],\n    queryFn: getComments,\n  })\n\n  return (\n    <HydrationBoundary state={dehydrate(queryClient)}>\n      <Comments />\n    </HydrationBoundary>\n  )\n}\n```\n\nAs you can see, it's perfectly fine to use `<HydrationBoundary>` in multiple places, and create and dehydrate multiple `queryClient` for prefetching.\n\nNote that because we are awaiting `getPosts` before rendering `CommentsServerComponent` this would lead to a server side waterfall:\n\n```\n1. |> getPosts()\n2.   |> getComments()\n```\n\nIf the server latency to the data is low, this might not be a huge issue, but is still worth pointing out.\n\nIn Next.js, besides prefetching data in `page.tsx`, you can also do it in `layout.tsx`, and in [parallel routes](https://nextjs.org/docs/app/building-your-application/routing/parallel-routes). Because these are all part of the routing, Next.js knows how to fetch them all in parallel. So if `CommentsServerComponent` above was instead expressed as a parallel route, the waterfall would be flattened automatically.\n\nAs more frameworks start supporting Server Components, they might have other routing conventions. Read your framework docs for details.\n\n### Alternative: Use a single `queryClient` for prefetching\n\nIn the example above, we create a new `queryClient` for each Server Component that fetches data. This is the recommended approach, but if you want to, you can alternatively create a single one that is reused across all Server Components:\n\n```tsx\n// app/getQueryClient.tsx\nimport { QueryClient } from '@tanstack/react-query'\nimport { cache } from 'react'\n\n// cache() is scoped per request, so we don't leak data between requests\nconst getQueryClient = cache(() => new QueryClient())\nexport default getQueryClient\n```\n\nThe benefit of this is that you can call `getQueryClient()` to get a hold of this client anywhere that gets called from a Server Component, including utility functions. The downside is that every time you call `dehydrate(getQueryClient())`, you serialize _the entire_ `queryClient`, including queries that have already been serialized before and are unrelated to the current Server Component which is unnecessary overhead.\n\nNext.js already dedupes requests that utilize `fetch()`, but if you are using something else in your `queryFn`, or if you use a framework that does _not_ dedupe these requests automatically, using a single `queryClient` as described above might make sense, despite the duplicated serialization.\n\n> As a future improvement, we might look into creating a `dehydrateNew()` function (name pending) that only dehydrate queries that are _new_ since the last call to `dehydrateNew()`. Feel free to get in touch if this sounds interesting and like something you want to help out with!\n\n### Data ownership and revalidation\n\nWith Server Components, it's important to think about data ownership and revalidation. To explain why, let's look at a modified example from above:\n\n```tsx\n// app/posts/page.tsx\nimport {\n  dehydrate,\n  HydrationBoundary,\n  QueryClient,\n} from '@tanstack/react-query'\nimport Posts from './posts'\n\nexport default async function PostsPage() {\n  const queryClient = new QueryClient()\n\n  // Note we are now using fetchQuery()\n  const posts = await queryClient.fetchQuery({\n    queryKey: ['posts'],\n    queryFn: getPosts,\n  })\n\n  return (\n    <HydrationBoundary state={dehydrate(queryClient)}>\n      {/* This is the new part */}\n      <div>Nr of posts: {posts.length}</div>\n      <Posts />\n    </HydrationBoundary>\n  )\n}\n```\n\nWe are now rendering data from the `getPosts` query both in a Server Component and in a Client Component. This will be fine for the initial page render, but what happens when the query revalidates on the client for some reason when `staleTime` has been passed?\n\nReact Query has no idea of how to _revalidate the Server Component_, so if it refetches the data on the client, causing React to rerender the list of posts, the `Nr of posts: {posts.length}` will end up out of sync.\n\nThis is fine if you set `staleTime: Infinity`, so that React Query never revalidates, but this is probably not what you want if you are using React Query in the first place.\n\nUsing React Query with Server Components makes most sense if:\n\n- You have an app using React Query and want to migrate to Server Components without rewriting all the data fetching\n- You want a familiar programming paradigm, but want to still sprinkle in the benefits of Server Components where it makes most sense\n- You have some use case that React Query covers, but that your framework of choice does not cover\n\nIt's hard to give general advice on when it makes sense to pair React Query with Server Components and not. **If you are just starting out with a new Server Components app, we suggest you start out with any tools for data fetching your framework provides you with and avoid bringing in React Query until you actually need it.** This might be never, and that's fine, use the right tool for the job!\n\nIf you do use it, a good rule of thumb is to avoid `queryClient.fetchQuery` unless you need to catch errors. If you do use it, don't render its result on the server or pass the result to another component, even a Client Component one.\n\nFrom the React Query perspective, treat Server Components as a place to prefetch data, nothing more.\n\nOf course, it's fine to have Server Components own some data, and Client Components own other, just make sure those two realities don't get out of sync.\n\n## Streaming with Server Components\n\nThe Next.js app router automatically streams any part of the application that is ready to be displayed to the browser as soon as possible, so finished content can be displayed immediately without waiting for still pending content. It does this along `<Suspense>` boundary lines. Note that if you create a file `loading.tsx`, this automatically creates a `<Suspense>` boundary behind the scenes.\n\nWith the prefetching patterns described above, React Query is perfectly compatible with this form of streaming. As the data for each Suspense boundary resolves, Next.js can render and stream the finished content to the browser. This works even if you are using `useQuery` as outlined above because the suspending actually happens when you `await` the prefetch.\n\nAs of React Query v5.40.0, you don't have to `await` all prefetches for this to work, as `pending` Queries can also be dehydrated and sent to the client. This lets you kick off prefetches as early as possible without letting them block an entire Suspense boundary, and streams the _data_ to the client as the query finishes. This can be useful for example if you want to prefetch some content that is only visible after some user interaction, or say if you want to `await` and render the first page of an infinite query, but start prefetching page 2 without blocking rendering.\n\nTo make this work, we have to instruct the `queryClient` to also `dehydrate` pending Queries. We can do this globally, or by passing that option directly to `dehydrate`.\n\nWe will also need to move the `getQueryClient()` function out of our `app/providers.tsx` file as we want to use it in our server component and our client provider.\n\n```tsx\n// app/get-query-client.ts\nimport {\n  isServer,\n  QueryClient,\n  defaultShouldDehydrateQuery,\n} from '@tanstack/react-query'\n\nfunction makeQueryClient() {\n  return new QueryClient({\n    defaultOptions: {\n      queries: {\n        staleTime: 60 * 1000,\n      },\n      dehydrate: {\n        // include pending queries in dehydration\n        shouldDehydrateQuery: (query) =>\n          defaultShouldDehydrateQuery(query) ||\n          query.state.status === 'pending',\n        shouldRedactErrors: (error) => {\n          // We should not catch Next.js server errors\n          // as that's how Next.js detects dynamic pages\n          // so we cannot redact them.\n          // Next.js also automatically redacts errors for us\n          // with better digests.\n          return false\n        },\n      },\n    },\n  })\n}\n\nlet browserQueryClient: QueryClient | undefined = undefined\n\nexport function getQueryClient() {\n  if (isServer) {\n    // Server: always make a new query client\n    return makeQueryClient()\n  } else {\n    // Browser: make a new query client if we don't already have one\n    // This is very important, so we don't re-make a new client if React\n    // suspends during the initial render. This may not be needed if we\n    // have a suspense boundary BELOW the creation of the query client\n    if (!browserQueryClient) browserQueryClient = makeQueryClient()\n    return browserQueryClient\n  }\n}\n```\n\n> Note: This works in NextJs and Server Components because React can serialize Promises over the wire when you pass them down to Client Components.\n\nThen, all we need to do is provide a `HydrationBoundary`, but we don't need to `await` prefetches anymore:\n\n```tsx\n// app/posts/page.tsx\nimport { dehydrate, HydrationBoundary } from '@tanstack/react-query'\nimport { getQueryClient } from './get-query-client'\nimport Posts from './posts'\n\n// the function doesn't need to be `async` because we don't `await` anything\nexport default function PostsPage() {\n  const queryClient = getQueryClient()\n\n  // look ma, no await\n  queryClient.prefetchQuery({\n    queryKey: ['posts'],\n    queryFn: getPosts,\n  })\n\n  return (\n    <HydrationBoundary state={dehydrate(queryClient)}>\n      <Posts />\n    </HydrationBoundary>\n  )\n}\n```\n\nOn the client, the Promise will be put into the QueryCache for us. That means we can now call `useSuspenseQuery` inside the `Posts` component to \"use\" that Promise (which was created on the Server):\n\n```tsx\n// app/posts/posts.tsx\n'use client'\n\nexport default function Posts() {\n  const { data } = useSuspenseQuery({ queryKey: ['posts'], queryFn: getPosts })\n\n  // ...\n}\n```\n\n> Note that you could also `useQuery` instead of `useSuspenseQuery`, and the Promise would still be picked up correctly. However, NextJs won't suspend in that case and the component will render in the `pending` status, which also opts out of server rendering the content.\n\nIf you're using non-JSON data types and serialize the query results on the server, you can specify the `dehydrate.serializeData` and `hydrate.deserializeData` options to serialize and deserialize the data on each side of the boundary to ensure the data in the cache is the same format both on the server and the client:\n\n```tsx\n// app/get-query-client.ts\nimport { QueryClient, defaultShouldDehydrateQuery } from '@tanstack/react-query'\nimport { deserialize, serialize } from './transformer'\n\nfunction makeQueryClient() {\n  return new QueryClient({\n    defaultOptions: {\n      // ...\n      hydrate: {\n        deserializeData: deserialize,\n      },\n      dehydrate: {\n        serializeData: serialize,\n      },\n    },\n  })\n}\n\n// ...\n```\n\n```tsx\n// app/posts/page.tsx\nimport {\n  dehydrate,\n  HydrationBoundary,\n  QueryClient,\n} from '@tanstack/react-query'\nimport { getQueryClient } from './get-query-client'\nimport { serialize } from './transformer'\nimport Posts from './posts'\n\nexport default function PostsPage() {\n  const queryClient = getQueryClient()\n\n  // look ma, no await\n  queryClient.prefetchQuery({\n    queryKey: ['posts'],\n    queryFn: () => getPosts().then(serialize), // <-- serialize the data on the server\n  })\n\n  return (\n    <HydrationBoundary state={dehydrate(queryClient)}>\n      <Posts />\n    </HydrationBoundary>\n  )\n}\n```\n\n```tsx\n// app/posts/posts.tsx\n'use client'\n\nexport default function Posts() {\n  const { data } = useSuspenseQuery({ queryKey: ['posts'], queryFn: getPosts })\n\n  // ...\n}\n```\n\nNow, your `getPosts` function can return e.g. `Temporal` datetime objects and the data will be serialized and deserialized on the client, assuming your transformer can serialize and deserialize those data types.\n\nFor more information, check out the [Next.js App with Prefetching Example](../examples/nextjs-app-prefetching).\n\n### Using the Persist Adapter with Streaming\n\nIf you're using the persist adapter with the [Streaming with Server Components](#streaming-with-server-components) feature, you need to be careful not to save promises to storage. Since pending queries can be dehydrated and streamed to the client, you should configure the persister to only persist successful queries:\n\n```tsx\n<PersistQueryClientProvider\n  client={queryClient}\n  persistOptions={{\n    persister,\n    // We don't want to save promises into the storage, so we only persist successful queries\n    dehydrateOptions: { shouldDehydrateQuery: defaultShouldDehydrateQuery },\n  }}\n>\n  {children}\n</PersistQueryClientProvider>\n```\n\nThis ensures that only successfully resolved queries are persisted to storage, preventing serialization issues with pending promises.\n\n## Experimental streaming without prefetching in Next.js\n\nWhile we recommend the prefetching solution detailed above because it flattens request waterfalls both on the initial page load **and** any subsequent page navigation, there is an experimental way to skip prefetching altogether and still have streaming SSR work: `@tanstack/react-query-next-experimental`\n\nThis package will allow you to fetch data on the server (in a Client Component) by just calling `useSuspenseQuery` in your component. Results will then be streamed from the server to the client as SuspenseBoundaries resolve. If you call `useSuspenseQuery` without wrapping it in a `<Suspense>` boundary, the HTML response won't start until the fetch resolves. This can be when you want depending on the situation, but keep in mind that this will hurt your TTFB.\n\nTo achieve this, wrap your app in the `ReactQueryStreamedHydration` component:\n\n```tsx\n// app/providers.tsx\n'use client'\n\nimport {\n  isServer,\n  QueryClient,\n  QueryClientProvider,\n} from '@tanstack/react-query'\nimport * as React from 'react'\nimport { ReactQueryStreamedHydration } from '@tanstack/react-query-next-experimental'\n\nfunction makeQueryClient() {\n  return new QueryClient({\n    defaultOptions: {\n      queries: {\n        // With SSR, we usually want to set some default staleTime\n        // above 0 to avoid refetching immediately on the client\n        staleTime: 60 * 1000,\n      },\n    },\n  })\n}\n\nlet browserQueryClient: QueryClient | undefined = undefined\n\nfunction getQueryClient() {\n  if (isServer) {\n    // Server: always make a new query client\n    return makeQueryClient()\n  } else {\n    // Browser: make a new query client if we don't already have one\n    // This is very important, so we don't re-make a new client if React\n    // suspends during the initial render. This may not be needed if we\n    // have a suspense boundary BELOW the creation of the query client\n    if (!browserQueryClient) browserQueryClient = makeQueryClient()\n    return browserQueryClient\n  }\n}\n\nexport function Providers(props: { children: React.ReactNode }) {\n  // NOTE: Avoid useState when initializing the query client if you don't\n  //       have a suspense boundary between this and the code that may\n  //       suspend because React will throw away the client on the initial\n  //       render if it suspends and there is no boundary\n  const queryClient = getQueryClient()\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      <ReactQueryStreamedHydration>\n        {props.children}\n      </ReactQueryStreamedHydration>\n    </QueryClientProvider>\n  )\n}\n```\n\nFor more information, check out the [NextJs Suspense Streaming Example](../examples/nextjs-suspense-streaming).\n\nThe big upside is that you no longer need to prefetch queries manually to have SSR work, and it even still streams in the result! This gives you phenomenal DX and lower code complexity.\n\nThe downside is easiest to explain if we look back at [the complex request waterfall example](./request-waterfalls.md#code-splitting) in the Performance & Request Waterfalls guide. Server Components with prefetching effectively eliminates the request waterfalls both for the initial page load **and** any subsequent navigation. This prefetch-less approach however will only flatten the waterfalls on the initial page load but ends up the same deep waterfall as the original example on page navigations:\n\n```\n1. |> JS for <Feed>\n2.   |> getFeed()\n3.     |> JS for <GraphFeedItem>\n4.       |> getGraphDataById()\n```\n\nThis is even worse than with `getServerSideProps`/`getStaticProps`, since with those we could at least parallelize data- and code-fetching.\n\nIf you value DX/iteration/shipping speed with low code complexity over performance, don't have deeply nested queries, or are on top of your request waterfalls with parallel fetching using tools like `useSuspenseQueries`, this can be a good tradeoff.\n\n> It might be possible to combine the two approaches, but even we haven't tried that out yet. If you do try this, please report back your findings, or even update these docs with some tips!\n\n## Final words\n\nServer Components and streaming are still fairly new concepts and we are still figuring out how React Query fits in and what improvements we can make to the API. We welcome suggestions, feedback and bug reports!\n\nSimilarly, it would be impossible to teach all the intricacies of this new paradigm all in one guide, on the first try. If you are missing some piece of information here or have suggestions on how to improve this content, also get in touch, or even better, click the \"Edit on GitHub\" button below and help us out.\n\n[//]: # 'Materials'\n\n## Further reading\n\nTo understand if your application can benefit from React Query when also using Server Components, see the article [You Might Not Need React Query](https://tkdodo.eu/blog/you-might-not-need-react-query).\n\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/react/guides/background-fetching-indicators.md",
    "content": "---\nid: background-fetching-indicators\ntitle: Background Fetching Indicators\n---\n\nA query's `status === 'pending'` state is sufficient enough to show the initial hard-loading state for a query, but sometimes you may want to display an additional indicator that a query is refetching in the background. To do this, queries also supply you with an `isFetching` boolean that you can use to show that it's in a fetching state, regardless of the state of the `status` variable:\n\n[//]: # 'Example'\n\n```tsx\nfunction Todos() {\n  const {\n    status,\n    data: todos,\n    error,\n    isFetching,\n  } = useQuery({\n    queryKey: ['todos'],\n    queryFn: fetchTodos,\n  })\n\n  return status === 'pending' ? (\n    <span>Loading...</span>\n  ) : status === 'error' ? (\n    <span>Error: {error.message}</span>\n  ) : (\n    <>\n      {isFetching ? <div>Refreshing...</div> : null}\n\n      <div>\n        {todos.map((todo) => (\n          <Todo todo={todo} />\n        ))}\n      </div>\n    </>\n  )\n}\n```\n\n[//]: # 'Example'\n\n## Displaying Global Background Fetching Loading State\n\nIn addition to individual query loading states, if you would like to show a global loading indicator when **any** queries are fetching (including in the background), you can use the `useIsFetching` hook:\n\n[//]: # 'Example2'\n\n```tsx\nimport { useIsFetching } from '@tanstack/react-query'\n\nfunction GlobalLoadingIndicator() {\n  const isFetching = useIsFetching()\n\n  return isFetching ? (\n    <div>Queries are fetching in the background...</div>\n  ) : null\n}\n```\n\n[//]: # 'Example2'\n"
  },
  {
    "path": "docs/framework/react/guides/caching.md",
    "content": "---\nid: caching\ntitle: Caching Examples\n---\n\n> Please thoroughly read the [Important Defaults](./important-defaults.md) before reading this guide\n\n## Basic Example\n\nThis caching example illustrates the story and lifecycle of:\n\n- Query Instances with and without cache data\n- Background Refetching\n- Inactive Queries\n- Garbage Collection\n\nLet's assume we are using the default `gcTime` of **5 minutes** and the default `staleTime` of `0`.\n\n- A new instance of `useQuery({ queryKey: ['todos'], queryFn: fetchTodos })` mounts.\n  - Since no other queries have been made with the `['todos']` query key, this query will show a hard loading state and make a network request to fetch the data.\n  - When the network request has completed, the returned data will be cached under the `['todos']` key.\n  - The data will be marked as stale after the configured `staleTime` (defaults to `0`, or immediately).\n- A second instance of `useQuery({ queryKey: ['todos'], queryFn: fetchTodos })` mounts elsewhere.\n  - Since the cache already has data for the `['todos']` key from the first query, that data is immediately returned from the cache.\n  - The new instance triggers a new network request using its query function.\n    - Note that regardless of whether both `fetchTodos` query functions are identical or not, both queries' [`status`](../reference/useQuery.md) are updated (including `isFetching`, `isPending`, and other related values) because they have the same query key.\n  - When the request completes successfully, the cache's data under the `['todos']` key is updated with the new data, and both instances are updated with the new data.\n- Both instances of the `useQuery({ queryKey: ['todos'], queryFn: fetchTodos })` query are unmounted and no longer in use.\n  - Since there are no more active instances of this query, a garbage collection timeout is set using `gcTime` to delete and garbage collect the query (defaults to **5 minutes**).\n- Before the cache timeout (gcTime) has completed, another instance of `useQuery({ queryKey: ['todos'], queryFn: fetchTodos })` mounts. The query immediately returns the available cached data while the `fetchTodos` function is being run in the background. When it completes successfully, it will populate the cache with fresh data.\n- The final instance of `useQuery({ queryKey: ['todos'], queryFn: fetchTodos })` unmounts.\n- No more instances of `useQuery({ queryKey: ['todos'], queryFn: fetchTodos })` appear within **5 minutes**.\n  - The cached data under the `['todos']` key is deleted and garbage collected.\n"
  },
  {
    "path": "docs/framework/react/guides/default-query-function.md",
    "content": "---\nid: default-query-function\ntitle: Default Query Function\n---\n\nIf you find yourself wishing for whatever reason that you could just share the same query function for your entire app and just use query keys to identify what it should fetch, you can do that by providing a **default query function** to TanStack Query:\n\n[//]: # 'Example'\n\n```tsx\n// Define a default query function that will receive the query key\nconst defaultQueryFn = async ({ queryKey }) => {\n  const { data } = await axios.get(\n    `https://jsonplaceholder.typicode.com${queryKey[0]}`,\n  )\n  return data\n}\n\n// provide the default query function to your app with defaultOptions\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      queryFn: defaultQueryFn,\n    },\n  },\n})\n\nfunction App() {\n  return (\n    <QueryClientProvider client={queryClient}>\n      <YourApp />\n    </QueryClientProvider>\n  )\n}\n\n// All you have to do now is pass a key!\nfunction Posts() {\n  const { status, data, error, isFetching } = useQuery({ queryKey: ['/posts'] })\n\n  // ...\n}\n\n// You can even leave out the queryFn and just go straight into options\nfunction Post({ postId }) {\n  const { status, data, error, isFetching } = useQuery({\n    queryKey: [`/posts/${postId}`],\n    enabled: !!postId,\n  })\n\n  // ...\n}\n```\n\n[//]: # 'Example'\n\nIf you ever want to override the default queryFn, you can just provide your own like you normally would.\n"
  },
  {
    "path": "docs/framework/react/guides/dependent-queries.md",
    "content": "---\nid: dependent-queries\ntitle: Dependent Queries\n---\n\n## useQuery dependent Query\n\nDependent (or serial) queries depend on previous ones to finish before they can execute. To achieve this, it's as easy as using the `enabled` option to tell a query when it is ready to run:\n\n[//]: # 'Example'\n\n```tsx\n// Get the user\nconst { data: user } = useQuery({\n  queryKey: ['user', email],\n  queryFn: getUserByEmail,\n})\n\nconst userId = user?.id\n\n// Then get the user's projects\nconst {\n  status,\n  fetchStatus,\n  data: projects,\n} = useQuery({\n  queryKey: ['projects', userId],\n  queryFn: getProjectsByUser,\n  // The query will not execute until the userId exists\n  enabled: !!userId,\n})\n```\n\n[//]: # 'Example'\n\nThe `projects` query will start in:\n\n```tsx\nstatus: 'pending'\nisPending: true\nfetchStatus: 'idle'\n```\n\nAs soon as the `user` is available, the `projects` query will be `enabled` and will then transition to:\n\n```tsx\nstatus: 'pending'\nisPending: true\nfetchStatus: 'fetching'\n```\n\nOnce we have the projects, it will go to:\n\n```tsx\nstatus: 'success'\nisPending: false\nfetchStatus: 'idle'\n```\n\n## useQueries dependent Query\n\nDynamic parallel query - `useQueries` can depend on a previous query also, here's how to achieve this:\n\n[//]: # 'Example2'\n\n```tsx\n// Get the users ids\nconst { data: userIds } = useQuery({\n  queryKey: ['users'],\n  queryFn: getUsersData,\n  select: (users) => users.map((user) => user.id),\n})\n\n// Then get the users messages\nconst usersMessages = useQueries({\n  queries: userIds\n    ? userIds.map((id) => {\n        return {\n          queryKey: ['messages', id],\n          queryFn: () => getMessagesByUsers(id),\n        }\n      })\n    : [], // if userIds is undefined, an empty array will be returned\n})\n```\n\n[//]: # 'Example2'\n\n**Note** that `useQueries` return an **array of query results**\n\n## A note about performance\n\nDependent queries by definition constitutes a form of [request waterfall](./request-waterfalls.md), which hurts performance. If we pretend both queries take the same amount of time, doing them serially instead of in parallel always takes twice as much time, which is especially hurtful when it happens on a client that has high latency. If you can, it's always better to restructure the backend APIs so that both queries can be fetched in parallel, though that might not always be practically feasible.\n\nIn the example above, instead of first fetching `getUserByEmail` to be able to `getProjectsByUser`, introducing a new `getProjectsByUserEmail` query would flatten the waterfall.\n"
  },
  {
    "path": "docs/framework/react/guides/disabling-queries.md",
    "content": "---\nid: disabling-queries\ntitle: Disabling/Pausing Queries\n---\n\nIf you ever want to disable a query from automatically running, you can use the `enabled = false` option. The enabled option also accepts a callback that returns a boolean.\n\nWhen `enabled` is `false`:\n\n- If the query has cached data, then the query will be initialized in the `status === 'success'` or `isSuccess` state.\n- If the query does not have cached data, then the query will start in the `status === 'pending'` and `fetchStatus === 'idle'` state.\n- The query will not automatically fetch on mount.\n- The query will not automatically refetch in the background.\n- The query will ignore query client `invalidateQueries` and `refetchQueries` calls that would normally result in the query refetching.\n- `refetch` returned from `useQuery` can be used to manually trigger the query to fetch. However, it will not work with `skipToken`.\n\n> TypeScript users may prefer to use [skipToken](#typesafe-disabling-of-queries-using-skiptoken) as an alternative to `enabled = false`.\n\n[//]: # 'Example'\n\n```tsx\nfunction Todos() {\n  const { isLoading, isError, data, error, refetch, isFetching } = useQuery({\n    queryKey: ['todos'],\n    queryFn: fetchTodoList,\n    enabled: false,\n  })\n\n  return (\n    <div>\n      <button onClick={() => refetch()}>Fetch Todos</button>\n\n      {data ? (\n        <ul>\n          {data.map((todo) => (\n            <li key={todo.id}>{todo.title}</li>\n          ))}\n        </ul>\n      ) : isError ? (\n        <span>Error: {error.message}</span>\n      ) : isLoading ? (\n        <span>Loading...</span>\n      ) : (\n        <span>Not ready ...</span>\n      )}\n\n      <div>{isFetching ? 'Fetching...' : null}</div>\n    </div>\n  )\n}\n```\n\n[//]: # 'Example'\n\nPermanently disabling a query opts out of many great features that TanStack Query has to offer (like background refetches), and it's also not the idiomatic way. It takes you from the declarative approach (defining dependencies when your query should run) into an imperative mode (fetch whenever I click here). It is also not possible to pass parameters to `refetch`. Oftentimes, all you want is a lazy query that defers the initial fetch:\n\n## Lazy Queries\n\nThe enabled option can not only be used to permanently disable a query, but also to enable / disable it at a later time. A good example would be a filter form where you only want to fire off the first request once the user has entered a filter value:\n\n[//]: # 'Example2'\n\n```tsx\nfunction Todos() {\n  const [filter, setFilter] = React.useState('')\n\n  const { data } = useQuery({\n    queryKey: ['todos', filter],\n    queryFn: () => fetchTodos(filter),\n    // ⬇️ disabled as long as the filter is empty\n    enabled: !!filter,\n  })\n\n  return (\n    <div>\n      // 🚀 applying the filter will enable and execute the query\n      <FiltersForm onApply={setFilter} />\n      {data && <TodosTable data={data} />}\n    </div>\n  )\n}\n```\n\n[//]: # 'Example2'\n\n### isLoading (Previously: `isInitialLoading`)\n\nLazy queries will be in `status: 'pending'` right from the start because `pending` means that there is no data yet. This is technically true, however, since we are not currently fetching any data (as the query is not _enabled_), it also means you likely cannot use this flag to show a loading spinner.\n\nIf you are using disabled or lazy queries, you can use the `isLoading` flag instead. It's a derived flag that is computed from:\n\n`isPending && isFetching`\n\nso it will only be true if the query is currently fetching for the first time.\n\n## Typesafe disabling of queries using `skipToken`\n\nIf you are using TypeScript, you can use the `skipToken` to disable a query. This is useful when you want to disable a query based on a condition, but you still want the query to be type safe.\n\n> **IMPORTANT**: `refetch` from `useQuery` will not work with `skipToken`. Calling `refetch()` on a query that uses `skipToken` will result in a `Missing queryFn` error because there is no valid query function to execute. If you need to manually trigger queries, consider using `enabled: false` instead, which allows `refetch()` to work properly. Other than this limitation, `skipToken` works the same as `enabled: false`.\n\n[//]: # 'Example3'\n\n```tsx\nimport { skipToken, useQuery } from '@tanstack/react-query'\n\nfunction Todos() {\n  const [filter, setFilter] = React.useState<string | undefined>()\n\n  const { data } = useQuery({\n    queryKey: ['todos', filter],\n    // ⬇️ disabled as long as the filter is undefined or empty\n    queryFn: filter ? () => fetchTodos(filter) : skipToken,\n  })\n\n  return (\n    <div>\n      // 🚀 applying the filter will enable and execute the query\n      <FiltersForm onApply={setFilter} />\n      {data && <TodosTable data={data} />}\n    </div>\n  )\n}\n```\n\n[//]: # 'Example3'\n"
  },
  {
    "path": "docs/framework/react/guides/does-this-replace-client-state.md",
    "content": "---\nid: does-this-replace-client-state\ntitle: Does TanStack Query replace Redux, MobX or other global state managers?\n---\n\nWell, let's start with a few important items:\n\n- TanStack Query is a **server-state** library, responsible for managing asynchronous operations between your server and client\n- Redux, MobX, Zustand, etc. are **client-state** libraries that _can be used to store asynchronous data, albeit inefficiently when compared to a tool like TanStack Query_\n\nWith those points in mind, the short answer is that TanStack Query **replaces the boilerplate code and related wiring used to manage cache data in your client-state and replaces it with just a few lines of code.**\n\nFor a vast majority of applications, the truly **globally accessible client state** that is left over after migrating all of your async code to TanStack Query is usually very tiny.\n\n> There are still some circumstances where an application might indeed have a massive amount of synchronous client-only state (like a visual designer or music production application), in which case, you will probably still want a client state manager. In this situation it's important to note that **TanStack Query is not a replacement for local/client state management**. However, you can use TanStack Query alongside most client state managers with zero issues.\n\n## A Contrived Example\n\nHere we have some \"global\" state being managed by a global state library:\n\n```tsx\nconst globalState = {\n  projects,\n  teams,\n  tasks,\n  users,\n  themeMode,\n  sidebarStatus,\n}\n```\n\nCurrently, the global state manager is caching 4 types of server-state: `projects`, `teams`, `tasks`, and `users`. If we were to move these server-state assets to TanStack Query, our remaining global state would look more like this:\n\n```tsx\nconst globalState = {\n  themeMode,\n  sidebarStatus,\n}\n```\n\nThis also means that with a few hook calls to `useQuery` and `useMutation`, we also get to remove any boilerplate code that was used to manage our server state e.g.\n\n- Connectors\n- Action Creators\n- Middlewares\n- Reducers\n- Loading/Error/Result states\n- Contexts\n\nWith all of those things removed, you may ask yourself, **\"Is it worth it to keep using our client state manager for this tiny global state?\"**\n\n**And that's up to you!**\n\nBut TanStack Query's role is clear. It removes asynchronous wiring and boilerplate from your application and replaces it with just a few lines of code.\n\nWhat are you waiting for, give it a go already!\n"
  },
  {
    "path": "docs/framework/react/guides/filters.md",
    "content": "---\nid: filters\ntitle: Filters\n---\n\nSome methods within TanStack Query accept a `QueryFilters` or `MutationFilters` object.\n\n## `Query Filters`\n\nA query filter is an object with certain conditions to match a query with:\n\n```tsx\n// Cancel all queries\nawait queryClient.cancelQueries()\n\n// Remove all inactive queries that begin with `posts` in the key\nqueryClient.removeQueries({ queryKey: ['posts'], type: 'inactive' })\n\n// Refetch all active queries\nawait queryClient.refetchQueries({ type: 'active' })\n\n// Refetch all active queries that begin with `posts` in the key\nawait queryClient.refetchQueries({ queryKey: ['posts'], type: 'active' })\n```\n\nA query filter object supports the following properties:\n\n- `queryKey?: QueryKey`\n  - Set this property to define a query key to match on.\n- `exact?: boolean`\n  - If you don't want to search queries inclusively by query key, you can pass the `exact: true` option to return only the query with the exact query key you have passed.\n- `type?: 'active' | 'inactive' | 'all'`\n  - Defaults to `all`\n  - When set to `active` it will match active queries.\n  - When set to `inactive` it will match inactive queries.\n- `stale?: boolean`\n  - When set to `true` it will match stale queries.\n  - When set to `false` it will match fresh queries.\n- `fetchStatus?: FetchStatus`\n  - When set to `fetching` it will match queries that are currently fetching.\n  - When set to `paused` it will match queries that wanted to fetch, but have been `paused`.\n  - When set to `idle` it will match queries that are not fetching.\n- `predicate?: (query: Query) => boolean`\n  - This predicate function will be used as a final filter on all matching queries. If no other filters are specified, this function will be evaluated against every query in the cache.\n\n## `Mutation Filters`\n\nA mutation filter is an object with certain conditions to match a mutation with:\n\n```tsx\n// Get the number of all fetching mutations\nawait queryClient.isMutating()\n\n// Filter mutations by mutationKey\nawait queryClient.isMutating({ mutationKey: ['post'] })\n\n// Filter mutations using a predicate function\nawait queryClient.isMutating({\n  predicate: (mutation) => mutation.state.variables?.id === 1,\n})\n```\n\nA mutation filter object supports the following properties:\n\n- `mutationKey?: MutationKey`\n  - Set this property to define a mutation key to match on.\n- `exact?: boolean`\n  - If you don't want to search mutations inclusively by mutation key, you can pass the `exact: true` option to return only the mutation with the exact mutation key you have passed.\n- `status?: MutationStatus`\n  - Allows for filtering mutations according to their status.\n- `predicate?: (mutation: Mutation) => boolean`\n  - This predicate function will be used as a final filter on all matching mutations. If no other filters are specified, this function will be evaluated against every mutation in the cache.\n\n## Utils\n\n### `matchQuery`\n\n```tsx\nconst isMatching = matchQuery(filters, query)\n```\n\nReturns a boolean that indicates whether a query matches the provided set of query filters.\n\n### `matchMutation`\n\n```tsx\nconst isMatching = matchMutation(filters, mutation)\n```\n\nReturns a boolean that indicates whether a mutation matches the provided set of mutation filters.\n"
  },
  {
    "path": "docs/framework/react/guides/important-defaults.md",
    "content": "---\nid: important-defaults\ntitle: Important Defaults\n---\n\nOut of the box, TanStack Query is configured with **aggressive but sane** defaults. **Sometimes these defaults can catch new users off guard or make learning/debugging difficult if they are unknown by the user.** Keep them in mind as you continue to learn and use TanStack Query:\n\n- Query instances via `useQuery` or `useInfiniteQuery` by default **consider cached data as stale**.\n\n> To change this behavior, you can configure your queries both globally and per-query using the `staleTime` option. Specifying a longer `staleTime` means queries will not refetch their data as often\n\n- A Query that has a `staleTime` set is considered **fresh** until that `staleTime` has elapsed.\n  - set `staleTime` to e.g. `2 * 60 * 1000` to make sure data is read from the cache, without triggering any kinds of refetches, for 2 minutes, or until the Query is [invalidated manually](./query-invalidation.md).\n  - set `staleTime` to `Infinity` to never trigger a refetch until the Query is [invalidated manually](./query-invalidation.md).\n  - set `staleTime` to `'static'` to **never** trigger a refetch, even if the Query is [invalidated manually](./query-invalidation.md).\n\n- Stale queries are refetched automatically in the background when:\n  - New instances of the query mount\n  - The window is refocused\n  - The network is reconnected\n\n> Setting `staleTime` is the recommended way to avoid excessive refetches, but you can also customize the points in time for refetches by setting options like `refetchOnMount`, `refetchOnWindowFocus` and `refetchOnReconnect`.\n\n- Queries can optionally be configured with a `refetchInterval` to trigger refetches periodically, which is independent of the `staleTime` setting.\n\n- Query results that have no more active instances of `useQuery`, `useInfiniteQuery` or query observers are labeled as \"inactive\" and remain in the cache in case they are used again at a later time.\n- By default, \"inactive\" queries are garbage collected after **5 minutes**.\n\n  > To change this, you can alter the default `gcTime` for queries to something other than `1000 * 60 * 5` milliseconds.\n\n- Queries that fail are **silently retried 3 times, with exponential backoff delay** before capturing and displaying an error to the UI.\n\n  > To change this, you can alter the default `retry` and `retryDelay` options for queries to something other than `3` and the default exponential backoff function.\n\n[//]: # 'StructuralSharing'\n\n- Query results by default are **structurally shared to detect if data has actually changed** and if not, **the data reference remains unchanged** to better help with value stabilization with regards to useMemo and useCallback. If this concept sounds foreign, then don't worry about it! 99.9% of the time you will not need to disable this and it makes your app more performant at zero cost to you.\n\n[//]: # 'StructuralSharing'\n\n> Structural sharing only works with JSON-compatible values, any other value types will always be considered as changed. If you are seeing performance issues because of large responses for example, you can disable this feature with the `config.structuralSharing` flag. If you are dealing with non-JSON compatible values in your query responses and still want to detect if data has changed or not, you can provide your own custom function as `config.structuralSharing` to compute a value from the old and new responses, retaining references as required.\n\n[//]: # 'Materials'\n\n## Further Reading\n\nHave a look at the following articles from our [Community Resources](../../../community-resources) for further explanations of the defaults:\n\n- [Practical React Query](https://tkdodo.eu/blog/practical-react-query)\n- [React Query as a State Manager](https://tkdodo.eu/blog/react-query-as-a-state-manager)\n- [Thinking in React Query](https://tkdodo.eu/blog/thinking-in-react-query)\n\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/react/guides/infinite-queries.md",
    "content": "---\nid: infinite-queries\ntitle: Infinite Queries\n---\n\nRendering lists that can additively \"load more\" data onto an existing set of data or \"infinite scroll\" is also a very common UI pattern. TanStack Query supports a useful version of `useQuery` called `useInfiniteQuery` for querying these types of lists.\n\nWhen using `useInfiniteQuery`, you'll notice a few things are different:\n\n- `data` is now an object containing infinite query data:\n- `data.pages` array containing the fetched pages\n- `data.pageParams` array containing the page params used to fetch the pages\n- The `fetchNextPage` and `fetchPreviousPage` functions are now available (`fetchNextPage` is required)\n- The `initialPageParam` option is now available (and required) to specify the initial page param\n- The `getNextPageParam` and `getPreviousPageParam` options are available for both determining if there is more data to load and the information to fetch it. This information is supplied as an additional parameter in the query function\n- A `hasNextPage` boolean is now available and is `true` if `getNextPageParam` returns a value other than `null` or `undefined`\n- A `hasPreviousPage` boolean is now available and is `true` if `getPreviousPageParam` returns a value other than `null` or `undefined`\n- The `isFetchingNextPage` and `isFetchingPreviousPage` booleans are now available to distinguish between a background refresh state and a loading more state\n\n> Note: Options `initialData` or `placeholderData` need to conform to the same structure of an object with `data.pages` and `data.pageParams` properties.\n\n## Example\n\nLet's assume we have an API that returns pages of `projects` 3 at a time based on a `cursor` index along with a cursor that can be used to fetch the next group of projects:\n\n```tsx\nfetch('/api/projects?cursor=0')\n// { data: [...], nextCursor: 3}\nfetch('/api/projects?cursor=3')\n// { data: [...], nextCursor: 6}\nfetch('/api/projects?cursor=6')\n// { data: [...], nextCursor: 9}\nfetch('/api/projects?cursor=9')\n// { data: [...] }\n```\n\nWith this information, we can create a \"Load More\" UI by:\n\n- Waiting for `useInfiniteQuery` to request the first group of data by default\n- Returning the information for the next query in `getNextPageParam`\n- Calling `fetchNextPage` function\n\n[//]: # 'Example'\n\n```tsx\nimport { useInfiniteQuery } from '@tanstack/react-query'\n\nfunction Projects() {\n  const fetchProjects = async ({ pageParam }) => {\n    const res = await fetch('/api/projects?cursor=' + pageParam)\n    return res.json()\n  }\n\n  const {\n    data,\n    error,\n    fetchNextPage,\n    hasNextPage,\n    isFetching,\n    isFetchingNextPage,\n    status,\n  } = useInfiniteQuery({\n    queryKey: ['projects'],\n    queryFn: fetchProjects,\n    initialPageParam: 0,\n    getNextPageParam: (lastPage, pages) => lastPage.nextCursor,\n  })\n\n  return status === 'pending' ? (\n    <p>Loading...</p>\n  ) : status === 'error' ? (\n    <p>Error: {error.message}</p>\n  ) : (\n    <>\n      {data.pages.map((group, i) => (\n        <React.Fragment key={i}>\n          {group.data.map((project) => (\n            <p key={project.id}>{project.name}</p>\n          ))}\n        </React.Fragment>\n      ))}\n      <div>\n        <button\n          onClick={() => fetchNextPage()}\n          disabled={!hasNextPage || isFetching}\n        >\n          {isFetchingNextPage\n            ? 'Loading more...'\n            : hasNextPage\n              ? 'Load More'\n              : 'Nothing more to load'}\n        </button>\n      </div>\n      <div>{isFetching && !isFetchingNextPage ? 'Fetching...' : null}</div>\n    </>\n  )\n}\n```\n\n[//]: # 'Example'\n\nIt's essential to understand that calling `fetchNextPage` while an ongoing fetch is in progress runs the risk of overwriting data refreshes happening in the background. This situation becomes particularly critical when rendering a list and triggering `fetchNextPage` simultaneously.\n\nRemember, there can only be a single ongoing fetch for an InfiniteQuery. A single cache entry is shared for all pages, attempting to fetch twice simultaneously might lead to data overwrites.\n\nIf you intend to enable simultaneous fetching, you can utilize the `{ cancelRefetch: false }` option (default: true) within `fetchNextPage`.\n\nTo ensure a seamless querying process without conflicts, it's highly recommended to verify that the query is not in an `isFetching` state, especially if the user won't directly control that call.\n\n[//]: # 'Example1'\n\n```jsx\n<List onEndReached={() => hasNextPage && !isFetching && fetchNextPage()} />\n```\n\n[//]: # 'Example1'\n\n## What happens when an infinite query needs to be refetched?\n\nWhen an infinite query becomes `stale` and needs to be refetched, each group is fetched `sequentially`, starting from the first one. This ensures that even if the underlying data is mutated, we're not using stale cursors and potentially getting duplicates or skipping records. If an infinite query's results are ever removed from the queryCache, the pagination restarts at the initial state with only the initial group being requested.\n\n## What if I want to implement a bi-directional infinite list?\n\nBi-directional lists can be implemented by using the `getPreviousPageParam`, `fetchPreviousPage`, `hasPreviousPage` and `isFetchingPreviousPage` properties and functions.\n\n[//]: # 'Example3'\n\n```tsx\nuseInfiniteQuery({\n  queryKey: ['projects'],\n  queryFn: fetchProjects,\n  initialPageParam: 0,\n  getNextPageParam: (lastPage, pages) => lastPage.nextCursor,\n  getPreviousPageParam: (firstPage, pages) => firstPage.prevCursor,\n})\n```\n\n[//]: # 'Example3'\n\n## What if I want to show the pages in reversed order?\n\nSometimes you may want to show the pages in reversed order. If this is case, you can use the `select` option:\n\n[//]: # 'Example4'\n\n```tsx\nuseInfiniteQuery({\n  queryKey: ['projects'],\n  queryFn: fetchProjects,\n  select: (data) => ({\n    pages: [...data.pages].reverse(),\n    pageParams: [...data.pageParams].reverse(),\n  }),\n})\n```\n\n[//]: # 'Example4'\n\n## What if I want to manually update the infinite query?\n\n### Manually removing first page:\n\n[//]: # 'Example5'\n\n```tsx\nqueryClient.setQueryData(['projects'], (data) => ({\n  pages: data.pages.slice(1),\n  pageParams: data.pageParams.slice(1),\n}))\n```\n\n[//]: # 'Example5'\n\n### Manually removing a single value from an individual page:\n\n[//]: # 'Example6'\n\n```tsx\nconst newPagesArray =\n  oldPagesArray?.pages.map((page) =>\n    page.filter((val) => val.id !== updatedId),\n  ) ?? []\n\nqueryClient.setQueryData(['projects'], (data) => ({\n  pages: newPagesArray,\n  pageParams: data.pageParams,\n}))\n```\n\n[//]: # 'Example6'\n\n### Keep only the first page:\n\n[//]: # 'Example7'\n\n```tsx\nqueryClient.setQueryData(['projects'], (data) => ({\n  pages: data.pages.slice(0, 1),\n  pageParams: data.pageParams.slice(0, 1),\n}))\n```\n\n[//]: # 'Example7'\n\nMake sure to always keep the same data structure of pages and pageParams!\n\n## What if I want to limit the number of pages?\n\nIn some use cases you may want to limit the number of pages stored in the query data to improve the performance and UX:\n\n- when the user can load a large number of pages (memory usage)\n- when you have to refetch an infinite query that contains dozens of pages (network usage: all the pages are sequentially fetched)\n\nThe solution is to use a \"Limited Infinite Query\". This is made possible by using the `maxPages` option in conjunction with `getNextPageParam` and `getPreviousPageParam` to allow fetching pages when needed in both directions.\n\nIn the following example only 3 pages are kept in the query data pages array. If a refetch is needed, only 3 pages will be refetched sequentially.\n\n[//]: # 'Example8'\n\n```tsx\nuseInfiniteQuery({\n  queryKey: ['projects'],\n  queryFn: fetchProjects,\n  initialPageParam: 0,\n  getNextPageParam: (lastPage, pages) => lastPage.nextCursor,\n  getPreviousPageParam: (firstPage, pages) => firstPage.prevCursor,\n  maxPages: 3,\n})\n```\n\n[//]: # 'Example8'\n\n## What if my API doesn't return a cursor?\n\nIf your API doesn't return a cursor, you can use the `pageParam` as a cursor. Because `getNextPageParam` and `getPreviousPageParam` also get the `pageParam`of the current page, you can use it to calculate the next / previous page param.\n\n[//]: # 'Example9'\n\n```tsx\nreturn useInfiniteQuery({\n  queryKey: ['projects'],\n  queryFn: fetchProjects,\n  initialPageParam: 0,\n  getNextPageParam: (lastPage, allPages, lastPageParam) => {\n    if (lastPage.length === 0) {\n      return undefined\n    }\n    return lastPageParam + 1\n  },\n  getPreviousPageParam: (firstPage, allPages, firstPageParam) => {\n    if (firstPageParam <= 1) {\n      return undefined\n    }\n    return firstPageParam - 1\n  },\n})\n```\n\n[//]: # 'Example9'\n[//]: # 'Materials'\n\n## Further reading\n\nTo get a better understanding of how Infinite Queries work under the hood, see the article [How Infinite Queries work](https://tkdodo.eu/blog/how-infinite-queries-work).\n\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/react/guides/initial-query-data.md",
    "content": "---\nid: initial-query-data\ntitle: Initial Query Data\n---\n\nThere are many ways to supply initial data for a query to the cache before you need it:\n\n- Declaratively:\n  - Provide `initialData` to a query to prepopulate its cache if empty\n- Imperatively:\n  - [Prefetch the data using `queryClient.prefetchQuery`](./prefetching.md)\n  - [Manually place the data into the cache using `queryClient.setQueryData`](./prefetching.md)\n\n## Using `initialData` to prepopulate a query\n\nThere may be times when you already have the initial data for a query available in your app and can simply provide it directly to your query. If and when this is the case, you can use the `config.initialData` option to set the initial data for a query and skip the initial loading state!\n\n> IMPORTANT: `initialData` is persisted to the cache, so it is not recommended to provide placeholder, partial or incomplete data to this option and instead use `placeholderData`\n\n[//]: # 'Example'\n\n```tsx\nconst result = useQuery({\n  queryKey: ['todos'],\n  queryFn: () => fetch('/todos'),\n  initialData: initialTodos,\n})\n```\n\n[//]: # 'Example'\n\n### `staleTime` and `initialDataUpdatedAt`\n\nBy default, `initialData` is treated as totally fresh, as if it were just fetched. This also means that it will affect how it is interpreted by the `staleTime` option.\n\n- If you configure your query observer with `initialData`, and no `staleTime` (the default `staleTime: 0`), the query will immediately refetch when it mounts:\n\n  [//]: # 'Example2'\n\n  ```tsx\n  // Will show initialTodos immediately, but also immediately refetch todos after mount\n  const result = useQuery({\n    queryKey: ['todos'],\n    queryFn: () => fetch('/todos'),\n    initialData: initialTodos,\n  })\n  ```\n\n  [//]: # 'Example2'\n\n- If you configure your query observer with `initialData` and a `staleTime` of `1000` ms, the data will be considered fresh for that same amount of time, as if it was just fetched from your query function.\n\n  [//]: # 'Example3'\n\n  ```tsx\n  // Show initialTodos immediately, but won't refetch until another interaction event is encountered after 1000 ms\n  const result = useQuery({\n    queryKey: ['todos'],\n    queryFn: () => fetch('/todos'),\n    initialData: initialTodos,\n    staleTime: 1000,\n  })\n  ```\n\n  [//]: # 'Example3'\n\n- So what if your `initialData` isn't totally fresh? That leaves us with the last configuration that is actually the most accurate and uses an option called `initialDataUpdatedAt`. This option allows you to pass a numeric JS timestamp in milliseconds of when the initialData itself was last updated, e.g. what `Date.now()` provides. Take note that if you have a unix timestamp, you'll need to convert it to a JS timestamp by multiplying it by `1000`.\n\n  [//]: # 'Example4'\n\n  ```tsx\n  // Show initialTodos immediately, but won't refetch until another interaction event is encountered after 1000 ms\n  const result = useQuery({\n    queryKey: ['todos'],\n    queryFn: () => fetch('/todos'),\n    initialData: initialTodos,\n    staleTime: 60 * 1000, // 1 minute\n    // This could be 10 seconds ago or 10 minutes ago\n    initialDataUpdatedAt: initialTodosUpdatedTimestamp, // eg. 1608412420052\n  })\n  ```\n\n  [//]: # 'Example4'\n\n  This option allows the staleTime to be used for its original purpose, determining how fresh the data needs to be, while also allowing the data to be refetched on mount if the `initialData` is older than the `staleTime`. In the example above, our data needs to be fresh within 1 minute, and we can hint to the query when the initialData was last updated so the query can decide for itself whether the data needs to be refetched again or not.\n\n  > If you would rather treat your data as **prefetched data**, we recommend that you use the `prefetchQuery` or `fetchQuery` APIs to populate the cache beforehand, thus letting you configure your `staleTime` independently from your initialData\n\n### Initial Data Function\n\nIf the process for accessing a query's initial data is intensive or just not something you want to perform on every render, you can pass a function as the `initialData` value. This function will be executed only once when the query is initialized, saving you precious memory and/or CPU:\n\n[//]: # 'Example5'\n\n```tsx\nconst result = useQuery({\n  queryKey: ['todos'],\n  queryFn: () => fetch('/todos'),\n  initialData: () => getExpensiveTodos(),\n})\n```\n\n[//]: # 'Example5'\n\n### Initial Data from Cache\n\nIn some circumstances, you may be able to provide the initial data for a query from the cached result of another. A good example of this would be searching the cached data from a todos list query for an individual todo item, then using that as the initial data for your individual todo query:\n\n[//]: # 'Example6'\n\n```tsx\nconst result = useQuery({\n  queryKey: ['todo', todoId],\n  queryFn: () => fetch('/todos'),\n  initialData: () => {\n    // Use a todo from the 'todos' query as the initial data for this todo query\n    return queryClient.getQueryData(['todos'])?.find((d) => d.id === todoId)\n  },\n})\n```\n\n[//]: # 'Example6'\n\n### Initial Data from the cache with `initialDataUpdatedAt`\n\nGetting initial data from the cache means the source query you're using to look up the initial data from is likely old. Instead of using an artificial `staleTime` to keep your query from refetching immediately, it's suggested that you pass the source query's `dataUpdatedAt` to `initialDataUpdatedAt`. This provides the query instance with all the information it needs to determine if and when the query needs to be refetched, regardless of initial data being provided.\n\n[//]: # 'Example7'\n\n```tsx\nconst result = useQuery({\n  queryKey: ['todos', todoId],\n  queryFn: () => fetch(`/todos/${todoId}`),\n  initialData: () =>\n    queryClient.getQueryData(['todos'])?.find((d) => d.id === todoId),\n  initialDataUpdatedAt: () =>\n    queryClient.getQueryState(['todos'])?.dataUpdatedAt,\n})\n```\n\n[//]: # 'Example7'\n\n### Conditional Initial Data from Cache\n\nIf the source query you're using to look up the initial data from is old, you may not want to use the cached data at all and just fetch from the server. To make this decision easier, you can use the `queryClient.getQueryState` method instead to get more information about the source query, including a `state.dataUpdatedAt` timestamp you can use to decide if the query is \"fresh\" enough for your needs:\n\n[//]: # 'Example8'\n\n```tsx\nconst result = useQuery({\n  queryKey: ['todo', todoId],\n  queryFn: () => fetch(`/todos/${todoId}`),\n  initialData: () => {\n    // Get the query state\n    const state = queryClient.getQueryState(['todos'])\n\n    // If the query exists and has data that is no older than 10 seconds...\n    if (state && Date.now() - state.dataUpdatedAt <= 10 * 1000) {\n      // return the individual todo\n      return state.data.find((d) => d.id === todoId)\n    }\n\n    // Otherwise, return undefined and let it fetch from a hard loading state!\n  },\n})\n```\n\n[//]: # 'Example8'\n[//]: # 'Materials'\n\n## Further reading\n\nFor a comparison between `Initial Data` and `Placeholder Data`, see the [article by TkDodo](https://tkdodo.eu/blog/placeholder-and-initial-data-in-react-query).\n\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/react/guides/invalidations-from-mutations.md",
    "content": "---\nid: invalidations-from-mutations\ntitle: Invalidations from Mutations\n---\n\nInvalidating queries is only half the battle. Knowing **when** to invalidate them is the other half. Usually when a mutation in your app succeeds, it's VERY likely that there are related queries in your application that need to be invalidated and possibly refetched to account for the new changes from your mutation.\n\nFor example, assume we have a mutation to post a new todo:\n\n[//]: # 'Example'\n\n```tsx\nconst mutation = useMutation({ mutationFn: postTodo })\n```\n\n[//]: # 'Example'\n\nWhen a successful `postTodo` mutation happens, we likely want all `todos` queries to get invalidated and possibly refetched to show the new todo item. To do this, you can use `useMutation`'s `onSuccess` options and the `client`'s `invalidateQueries` function:\n\n[//]: # 'Example2'\n\n```tsx\nimport { useMutation, useQueryClient } from '@tanstack/react-query'\n\nconst queryClient = useQueryClient()\n\n// When this mutation succeeds, invalidate any queries with the `todos` or `reminders` query key\nconst mutation = useMutation({\n  mutationFn: addTodo,\n  onSuccess: async () => {\n    // If you're invalidating a single query\n    await queryClient.invalidateQueries({ queryKey: ['todos'] })\n\n    // If you're invalidating multiple queries\n    await Promise.all([\n      queryClient.invalidateQueries({ queryKey: ['todos'] }),\n      queryClient.invalidateQueries({ queryKey: ['reminders'] }),\n    ])\n  },\n})\n```\n\n[//]: # 'Example2'\n\nReturning a Promise on `onSuccess` makes sure the data is updated before the mutation is entirely complete (i.e., isPending is true until onSuccess is fulfilled)\n\n[//]: # 'Example2'\n\nYou can wire up your invalidations to happen using any of the callbacks available in the [`useMutation` hook](./mutations.md)\n\n[//]: # 'Materials'\n\n## Further reading\n\nFor a technique to automatically invalidate Queries after Mutations, have a look at [TkDodo's article on Automatic Query Invalidation after Mutations](https://tkdodo.eu/blog/automatic-query-invalidation-after-mutations).\n\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/react/guides/migrating-to-react-query-3.md",
    "content": "---\nid: migrating-to-react-query-3\ntitle: Migrating to React Query 3\n---\n\nPrevious versions of React Query were awesome and brought some amazing new features, more magic, and an overall better experience to the library. They also brought on massive adoption and likewise a lot of refining fire (issues/contributions) to the library and brought to light a few things that needed more polish to make the library even better. v3 contains that very polish.\n\n## Overview\n\n- More scalable and testable cache configuration\n- Better SSR support\n- Data-lag (previously usePaginatedQuery) anywhere!\n- Bi-directional Infinite Queries\n- Query data selectors!\n- Fully configure defaults for queries and/or mutations before use\n- More granularity for optional rendering optimization\n- New `useQueries` hook! (Variable-length parallel query execution)\n- Query filter support for the `useIsFetching()` hook!\n- Retry/offline/replay support for mutations\n- Observe queries/mutations outside of React\n- Use the React Query core logic anywhere you want!\n- Bundled/Colocated Devtools via `react-query/devtools`\n- Cache Persistence to web storage (experimental via `react-query/persistQueryClient-experimental` and `react-query/createWebStoragePersistor-experimental`)\n\n## Breaking Changes\n\n### The `QueryCache` has been split into a `QueryClient` and lower-level `QueryCache` and `MutationCache` instances.\n\nThe `QueryCache` contains all queries, the `MutationCache` contains all mutations, and the `QueryClient` can be used to set configuration and to interact with them.\n\nThis has some benefits:\n\n- Allows for different types of caches.\n- Multiple clients with different configurations can use the same cache.\n- Clients can be used to track queries, which can be used for shared caches on SSR.\n- The client API is more focused towards general usage.\n- Easier to test the individual components.\n\nWhen creating a `new QueryClient()`, a `QueryCache` and `MutationCache` are automatically created for you if you don't supply them.\n\n```tsx\nimport { QueryClient } from 'react-query'\n\nconst queryClient = new QueryClient()\n```\n\n### `ReactQueryConfigProvider` and `ReactQueryCacheProvider` have both been replaced by `QueryClientProvider`\n\nDefault options for queries and mutations can now be specified in `QueryClient`:\n\n**Notice that it's now defaultOptions instead of defaultConfig**\n\n```tsx\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      // query options\n    },\n    mutations: {\n      // mutation options\n    },\n  },\n})\n```\n\nThe `QueryClientProvider` component is now used to connect a `QueryClient` to your application:\n\n```tsx\nimport { QueryClient, QueryClientProvider } from 'react-query'\n\nconst queryClient = new QueryClient()\n\nfunction App() {\n  return <QueryClientProvider client={queryClient}>...</QueryClientProvider>\n}\n```\n\n### The default `QueryCache` is gone. **For real this time!**\n\nAs previously noted with a deprecation, there is no longer a default `QueryCache` that is created or exported from the main package. **You must create your own via `new QueryClient()` or `new QueryCache()` (which you can then pass to `new QueryClient({ queryCache })` )**\n\n### The deprecated `makeQueryCache` utility has been removed.\n\nIt's been a long time coming, but it's finally gone :)\n\n### `QueryCache.prefetchQuery()` has been moved to `QueryClient.prefetchQuery()`\n\nThe new `QueryClient.prefetchQuery()` function is async, but **does not return the data from the query**. If you require the data, use the new `QueryClient.fetchQuery()` function\n\n```tsx\n// Prefetch a query:\nawait queryClient.prefetchQuery('posts', fetchPosts)\n\n// Fetch a query:\ntry {\n  const data = await queryClient.fetchQuery('posts', fetchPosts)\n} catch (error) {\n  // Error handling\n}\n```\n\n### `ReactQueryErrorResetBoundary` and `QueryCache.resetErrorBoundaries()` have been replaced by `QueryErrorResetBoundary` and `useQueryErrorResetBoundary()`.\n\nTogether, these provide the same experience as before, but with added control to choose which component trees you want to reset. For more information, see:\n\n- [QueryErrorResetBoundary](../reference/QueryErrorResetBoundary.md)\n- [useQueryErrorResetBoundary](../reference/useQueryErrorResetBoundary.md)\n\n### `QueryCache.getQuery()` has been replaced by `QueryCache.find()`.\n\n`QueryCache.find()` should now be used to look up individual queries from a cache\n\n### `QueryCache.getQueries()` has been moved to `QueryCache.findAll()`.\n\n`QueryCache.findAll()` should now be used to look up multiple queries from a cache\n\n### `QueryCache.isFetching` has been moved to `QueryClient.isFetching()`.\n\n**Notice that it's now a function instead of a property**\n\n### The `useQueryCache` hook has been replaced by the `useQueryClient` hook.\n\nIt returns the provided `queryClient` for its component tree and shouldn't need much tweaking beyond a rename.\n\n### Query key parts/pieces are no longer automatically spread to the query function.\n\nInline functions are now the suggested way of passing parameters to your query functions:\n\n```tsx\n// Old\nuseQuery(['post', id], (_key, id) => fetchPost(id))\n\n// New\nuseQuery(['post', id], () => fetchPost(id))\n```\n\nIf you still insist on not using inline functions, you can use the newly passed `QueryFunctionContext`:\n\n```tsx\nuseQuery(['post', id], (context) => fetchPost(context.queryKey[1]))\n```\n\n### Infinite Query Page params are now passed via `QueryFunctionContext.pageParam`\n\nThey were previously added as the last query key parameter in your query function, but this proved to be difficult for some patterns\n\n```tsx\n// Old\nuseInfiniteQuery(['posts'], (_key, pageParam = 0) => fetchPosts(pageParam))\n\n// New\nuseInfiniteQuery(['posts'], ({ pageParam = 0 }) => fetchPosts(pageParam))\n```\n\n### usePaginatedQuery() has been removed in favor of the `keepPreviousData` option\n\nThe new `keepPreviousData` options is available for both `useQuery` and `useInfiniteQuery` and will have the same \"lagging\" effect on your data:\n\n```tsx\nimport { useQuery } from 'react-query'\n\nfunction Page({ page }) {\n  const { data } = useQuery(['page', page], fetchPage, {\n    keepPreviousData: true,\n  })\n}\n```\n\n### useInfiniteQuery() is now bi-directional\n\nThe `useInfiniteQuery()` interface has changed to fully support bi-directional infinite lists.\n\n- `options.getFetchMore` has been renamed to `options.getNextPageParam`\n- `queryResult.canFetchMore` has been renamed to `queryResult.hasNextPage`\n- `queryResult.fetchMore` has been renamed to `queryResult.fetchNextPage`\n- `queryResult.isFetchingMore` has been renamed to `queryResult.isFetchingNextPage`\n- Added the `options.getPreviousPageParam` option\n- Added the `queryResult.hasPreviousPage` property\n- Added the `queryResult.fetchPreviousPage` property\n- Added the `queryResult.isFetchingPreviousPage`\n- The `data` of an infinite query is now an object containing the `pages` and the `pageParams` used to fetch the pages: `{ pages: [data, data, data], pageParams: [...]}`\n\nOne direction:\n\n```tsx\nconst { data, fetchNextPage, hasNextPage, isFetchingNextPage } =\n  useInfiniteQuery(\n    'projects',\n    ({ pageParam = 0 }) => fetchProjects(pageParam),\n    {\n      getNextPageParam: (lastPage, pages) => lastPage.nextCursor,\n    },\n  )\n```\n\nBoth directions:\n\n```tsx\nconst {\n  data,\n  fetchNextPage,\n  fetchPreviousPage,\n  hasNextPage,\n  hasPreviousPage,\n  isFetchingNextPage,\n  isFetchingPreviousPage,\n} = useInfiniteQuery(\n  'projects',\n  ({ pageParam = 0 }) => fetchProjects(pageParam),\n  {\n    getNextPageParam: (lastPage, pages) => lastPage.nextCursor,\n    getPreviousPageParam: (firstPage, pages) => firstPage.prevCursor,\n  },\n)\n```\n\nOne direction reversed:\n\n```tsx\nconst { data, fetchNextPage, hasNextPage, isFetchingNextPage } =\n  useInfiniteQuery(\n    'projects',\n    ({ pageParam = 0 }) => fetchProjects(pageParam),\n    {\n      select: (data) => ({\n        pages: [...data.pages].reverse(),\n        pageParams: [...data.pageParams].reverse(),\n      }),\n      getNextPageParam: (lastPage, pages) => lastPage.nextCursor,\n    },\n  )\n```\n\n### Infinite Query data now contains the array of pages and pageParams used to fetch those pages.\n\nThis allows for easier manipulation of the data and the page params, like, for example, removing the first page of data along with it's params:\n\n```tsx\nqueryClient.setQueryData(['projects'], (data) => ({\n  pages: data.pages.slice(1),\n  pageParams: data.pageParams.slice(1),\n}))\n```\n\n### useMutation now returns an object instead of an array\n\nThough the old way gave us warm fuzzy feelings of when we first discovered `useState` for the first time, they didn't last long. Now the mutation return is a single object.\n\n```tsx\n// Old:\nconst [mutate, { status, reset }] = useMutation()\n\n// New:\nconst { mutate, status, reset } = useMutation()\n```\n\n### `mutation.mutate` no longer return a promise\n\n- The `[mutate]` variable has been changed to the `mutation.mutate` function\n- Added the `mutation.mutateAsync` function\n\nWe got a lot of questions regarding this behavior as users expected the promise to behave like a regular promise.\n\nBecause of this the `mutate` function is now split into a `mutate` and `mutateAsync` function.\n\nThe `mutate` function can be used when using callbacks:\n\n```tsx\nconst { mutate } = useMutation({ mutationFn: addTodo })\n\nmutate('todo', {\n  onSuccess: (data) => {\n    console.log(data)\n  },\n  onError: (error) => {\n    console.error(error)\n  },\n  onSettled: () => {\n    console.log('settled')\n  },\n})\n```\n\nThe `mutateAsync` function can be used when using async/await:\n\n```tsx\nconst { mutateAsync } = useMutation({ mutationFn: addTodo })\n\ntry {\n  const data = await mutateAsync('todo')\n  console.log(data)\n} catch (error) {\n  console.error(error)\n} finally {\n  console.log('settled')\n}\n```\n\n### The object syntax for useQuery now uses a collapsed config:\n\n```tsx\n// Old:\nuseQuery({\n  queryKey: 'posts',\n  queryFn: fetchPosts,\n  config: { staleTime: Infinity },\n})\n\n// New:\nuseQuery({\n  queryKey: 'posts',\n  queryFn: fetchPosts,\n  staleTime: Infinity,\n})\n```\n\n### If set, the QueryOptions.enabled option must be a boolean (`true`/`false`)\n\nThe `enabled` query option will now only disable a query when the value is `false`.\nIf needed, values can be casted with `!!userId` or `Boolean(userId)` and a handy error will be thrown if a non-boolean value is passed.\n\n### The QueryOptions.initialStale option has been removed\n\nThe `initialStale` query option has been removed and initial data is now treated as regular data.\nWhich means that if `initialData` is provided, the query will refetch on mount by default.\nIf you do not want to refetch immediately, you can define a `staleTime`.\n\n### The `QueryOptions.forceFetchOnMount` option has been replaced by `refetchOnMount: 'always'`\n\nHonestly, we were accruing way too many `refetchOn____` options, so this should clean things up.\n\n### The `QueryOptions.refetchOnMount` options now only applies to its parent component instead of all query observers\n\nWhen `refetchOnMount` was set to `false` any additional components were prevented from refetching on mount.\nIn version 3 only the component where the option has been set will not refetch on mount.\n\n### The `QueryOptions.queryFnParamsFilter` has been removed in favor of the new `QueryFunctionContext` object.\n\nThe `queryFnParamsFilter` option has been removed because query functions now get a `QueryFunctionContext` object instead of the query key.\n\nParameters can still be filtered within the query function itself as the `QueryFunctionContext` also contains the query key.\n\n### The `QueryOptions.notifyOnStatusChange` option has been superseded by the new `notifyOnChangeProps` and `notifyOnChangePropsExclusions` options.\n\nWith these new options it is possible to configure when a component should re-render on a granular level.\n\nOnly re-render when the `data` or `error` properties change:\n\n```tsx\nimport { useQuery } from 'react-query'\n\nfunction User() {\n  const { data } = useQuery(['user'], fetchUser, {\n    notifyOnChangeProps: ['data', 'error'],\n  })\n  return <div>Username: {data.username}</div>\n}\n```\n\nPrevent re-render when the `isStale` property changes:\n\n```tsx\nimport { useQuery } from 'react-query'\n\nfunction User() {\n  const { data } = useQuery(['user'], fetchUser, {\n    notifyOnChangePropsExclusions: ['isStale'],\n  })\n  return <div>Username: {data.username}</div>\n}\n```\n\n### The `QueryResult.clear()` function has been renamed to `QueryResult.remove()`\n\nAlthough it was called `clear`, it really just removed the query from the cache. The name now matches the functionality.\n\n### The `QueryResult.updatedAt` property has been split into `QueryResult.dataUpdatedAt` and `QueryResult.errorUpdatedAt` properties\n\nBecause data and errors can be present at the same time, the `updatedAt` property has been split into `dataUpdatedAt` and `errorUpdatedAt`.\n\n### `setConsole()` has been replaced by the new `setLogger()` function\n\n```tsx\nimport { setLogger } from 'react-query'\n\n// Log with Sentry\nsetLogger({\n  error: (error) => {\n    Sentry.captureException(error)\n  },\n})\n\n// Log with Winston\nsetLogger(winston.createLogger())\n```\n\n### React Native no longer requires overriding the logger\n\nTo prevent showing error screens in React Native when a query fails it was necessary to manually change the Console:\n\n```tsx\nimport { setConsole } from 'react-query'\n\nsetConsole({\n  log: console.log,\n  warn: console.warn,\n  error: console.warn,\n})\n```\n\nIn version 3 **this is done automatically when React Query is used in React Native**.\n\n### Typescript\n\n#### `QueryStatus` has been changed from an [enum](https://www.typescriptlang.org/docs/handbook/enums.html#string-enums) to a [union type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types)\n\nSo, if you were checking the status property of a query or mutation against a QueryStatus enum property you will have to check it now against the string literal the enum previously held for each property.\n\nTherefore you have to change the enum properties to their equivalent string literal, like this:\n\n- `QueryStatus.Idle` -> `'idle'`\n- `QueryStatus.Loading` -> `'loading'`\n- `QueryStatus.Error` -> `'error'`\n- `QueryStatus.Success` -> `'success'`\n\nHere is an example of the changes you would have to make:\n\n```tsx\n- import { useQuery, QueryStatus } from 'react-query'; // [!code --]\n+ import { useQuery } from 'react-query'; // [!code ++]\n\nconst { data, status } = useQuery(['post', id], () => fetchPost(id))\n\n- if (status === QueryStatus.Loading) { // [!code --]\n+ if (status === 'loading') { // [!code ++]\n  ...\n}\n\n- if (status === QueryStatus.Error) { // [!code --]\n+ if (status === 'error') { // [!code ++]\n  ...\n}\n```\n\n## New features\n\n#### Query Data Selectors\n\nThe `useQuery` and `useInfiniteQuery` hooks now have a `select` option to select or transform parts of the query result.\n\n```tsx\nimport { useQuery } from 'react-query'\n\nfunction User() {\n  const { data } = useQuery(['user'], fetchUser, {\n    select: (user) => user.username,\n  })\n  return <div>Username: {data}</div>\n}\n```\n\nSet the `notifyOnChangeProps` option to `['data', 'error']` to only re-render when the selected data changes.\n\n#### The useQueries() hook, for variable-length parallel query execution\n\nWish you could run `useQuery` in a loop? The rules of hooks say no, but with the new `useQueries()` hook, you can!\n\n```tsx\nimport { useQueries } from 'react-query'\n\nfunction Overview() {\n  const results = useQueries([\n    { queryKey: ['post', 1], queryFn: fetchPost },\n    { queryKey: ['post', 2], queryFn: fetchPost },\n  ])\n  return (\n    <ul>\n      {results.map(({ data }) => data && <li key={data.id}>{data.title})</li>)}\n    </ul>\n  )\n}\n```\n\n#### Retry/offline mutations\n\nBy default React Query will not retry a mutation on error, but it is possible with the `retry` option:\n\n```tsx\nconst mutation = useMutation({\n  mutationFn: addTodo,\n  retry: 3,\n})\n```\n\nIf mutations fail because the device is offline, they will be retried in the same order when the device reconnects.\n\n#### Persist mutations\n\nMutations can now be persisted to storage and resumed at a later point. More information can be found in the mutations documentation.\n\n#### QueryObserver\n\nA `QueryObserver` can be used to create and/or watch a query:\n\n```tsx\nconst observer = new QueryObserver(queryClient, { queryKey: 'posts' })\n\nconst unsubscribe = observer.subscribe((result) => {\n  console.log(result)\n  unsubscribe()\n})\n```\n\n#### InfiniteQueryObserver\n\nA `InfiniteQueryObserver` can be used to create and/or watch an infinite query:\n\n```tsx\nconst observer = new InfiniteQueryObserver(queryClient, {\n  queryKey: 'posts',\n  queryFn: fetchPosts,\n  getNextPageParam: (lastPage, allPages) => lastPage.nextCursor,\n  getPreviousPageParam: (firstPage, allPages) => firstPage.prevCursor,\n})\n\nconst unsubscribe = observer.subscribe((result) => {\n  console.log(result)\n  unsubscribe()\n})\n```\n\n#### QueriesObserver\n\nA `QueriesObserver` can be used to create and/or watch multiple queries:\n\n```tsx\nconst observer = new QueriesObserver(queryClient, [\n  { queryKey: ['post', 1], queryFn: fetchPost },\n  { queryKey: ['post', 2], queryFn: fetchPost },\n])\n\nconst unsubscribe = observer.subscribe((result) => {\n  console.log(result)\n  unsubscribe()\n})\n```\n\n#### Set default options for specific queries\n\nThe `QueryClient.setQueryDefaults()` method can be used to set default options for specific queries:\n\n```tsx\nqueryClient.setQueryDefaults(['posts'], { queryFn: fetchPosts })\n\nfunction Component() {\n  const { data } = useQuery(['posts'])\n}\n```\n\n#### Set default options for specific mutations\n\nThe `QueryClient.setMutationDefaults()` method can be used to set default options for specific mutations:\n\n```tsx\nqueryClient.setMutationDefaults(['addPost'], { mutationFn: addPost })\n\nfunction Component() {\n  const { mutate } = useMutation({ mutationKey: ['addPost'] })\n}\n```\n\n#### useIsFetching()\n\nThe `useIsFetching()` hook now accepts filters which can be used to for example only show a spinner for certain type of queries:\n\n```tsx\nconst fetches = useIsFetching({ queryKey: ['posts'] })\n```\n\n#### Core separation\n\nThe core of React Query is now fully separated from React, which means it can also be used standalone or in other frameworks. Use the `react-query/core` entry point to only import the core functionality:\n\n```tsx\nimport { QueryClient } from 'react-query/core'\n```\n\n### Devtools are now part of the main repo and npm package\n\nThe devtools are now included in the `react-query` package itself under the import `react-query/devtools`. Simply replace `react-query-devtools` imports with `react-query/devtools`\n"
  },
  {
    "path": "docs/framework/react/guides/migrating-to-react-query-4.md",
    "content": "---\nid: migrating-to-react-query-4\ntitle: Migrating to React Query 4\n---\n\n## Breaking Changes\n\nv4 is a major version, so there are some breaking changes to be aware of:\n\n### react-query is now @tanstack/react-query\n\nYou will need to un-/install dependencies and change the imports:\n\n```\nnpm uninstall react-query\nnpm install @tanstack/react-query\nnpm install @tanstack/react-query-devtools\n```\n\n```tsx\n- import { useQuery } from 'react-query' // [!code --]\n- import { ReactQueryDevtools } from 'react-query/devtools' // [!code --]\n\n+ import { useQuery } from '@tanstack/react-query' // [!code ++]\n+ import { ReactQueryDevtools } from '@tanstack/react-query-devtools' // [!code ++]\n```\n\n#### Codemod\n\nTo make the import migration easier, v4 comes with a codemod.\n\n> The codemod is a best efforts attempt to help you migrate the breaking change. Please review the generated code thoroughly! Also, there are edge cases that cannot be found by the code mod, so please keep an eye on the log output.\n\nYou can easily apply it by using one (or both) of the following commands:\n\nIf you want to run it against `.js` or `.jsx` files, please use the command below:\n\n```\nnpx jscodeshift ./path/to/src/ \\\n  --extensions=js,jsx \\\n  --transform=./node_modules/@tanstack/react-query/codemods/v4/replace-import-specifier.js\n```\n\nIf you want to run it against `.ts` or `.tsx` files, please use the command below:\n\n```\nnpx jscodeshift ./path/to/src/ \\\n  --extensions=ts,tsx \\\n  --parser=tsx \\\n  --transform=./node_modules/@tanstack/react-query/codemods/v4/replace-import-specifier.js\n```\n\nPlease note in the case of `TypeScript` you need to use `tsx` as the parser; otherwise, the codemod won't be applied properly!\n\n**Note:** Applying the codemod might break your code formatting, so please don't forget to run `prettier` and/or `eslint` after you've applied the codemod!\n\n**Note:** The codemod will _only_ change the imports - you still have to install the separate devtools package manually.\n\n### Query Keys (and Mutation Keys) need to be an Array\n\nIn v3, Query and Mutation Keys could be a String or an Array. Internally, React Query has always worked with Array Keys only, and we've sometimes exposed this to consumers. For example, in the `queryFn`, you would always get the key as an Array to make working with [Default Query Functions](./default-query-function.md) easier.\n\nHowever, we have not followed this concept through to all apis. For example, when using the `predicate` function on [Query Filters](./filters.md) you would get the raw Query Key. This makes it difficult to work with such functions if you use Query Keys that are mixed Arrays and Strings. The same was true when using global callbacks.\n\nTo streamline all apis, we've decided to make all keys Arrays only:\n\n```tsx\n;-useQuery('todos', fetchTodos) + // [!code --]\n  useQuery(['todos'], fetchTodos) // [!code ++]\n```\n\n#### Codemod\n\nTo make this migration easier, we decided to deliver a codemod.\n\n> The codemod is a best efforts attempt to help you migrate the breaking change. Please review the generated code thoroughly! Also, there are edge cases that cannot be found by the code mod, so please keep an eye on the log output.\n\nYou can easily apply it by using one (or both) of the following commands:\n\nIf you want to run it against `.js` or `.jsx` files, please use the command below:\n\n```\nnpx jscodeshift ./path/to/src/ \\\n  --extensions=js,jsx \\\n  --transform=./node_modules/@tanstack/react-query/codemods/v4/key-transformation.js\n```\n\nIf you want to run it against `.ts` or `.tsx` files, please use the command below:\n\n```\nnpx jscodeshift ./path/to/src/ \\\n  --extensions=ts,tsx \\\n  --parser=tsx \\\n  --transform=./node_modules/@tanstack/react-query/codemods/v4/key-transformation.js\n```\n\nPlease note in the case of `TypeScript` you need to use `tsx` as the parser; otherwise, the codemod won't be applied properly!\n\n**Note:** Applying the codemod might break your code formatting, so please don't forget to run `prettier` and/or `eslint` after you've applied the codemod!\n\n### The idle state has been removed\n\nWith the introduction of the new [fetchStatus](./queries.md#fetchstatus) for better offline support, the `idle` state became irrelevant, because `fetchStatus: 'idle'` captures the same state better. For more information, please read [Why two different states](./queries.md#why-two-different-states).\n\nThis will mostly affect `disabled` queries that don't have any `data` yet, as those were in `idle` state before:\n\n```tsx\n- status: 'idle' // [!code --]\n+ status: 'loading'  // [!code ++]\n+ fetchStatus: 'idle' // [!code ++]\n```\n\nAlso, have a look at [the guide on dependent queries](./dependent-queries.md)\n\n#### disabled queries\n\nDue to this change, disabled queries (even temporarily disabled ones) will start in `loading` state. To make migration easier, especially for having a good flag to know when to display a loading spinner, you can check for `isInitialLoading` instead of `isLoading`:\n\n```tsx\n;-isLoading + // [!code --]\n  isInitialLoading // [!code ++]\n```\n\nSee also the guide on [disabling queries](./disabling-queries.md#isloading-previously-isinitialloading)\n\n### new API for `useQueries`\n\nThe `useQueries` hook now accepts an object with a `queries` prop as its input. The value of the `queries` prop is an array of queries (this array is identical to what was passed into `useQueries` in v3).\n\n```tsx\n;-useQueries([\n  { queryKey1, queryFn1, options1 },\n  { queryKey2, queryFn2, options2 },\n]) + // [!code --]\n  useQueries({\n    queries: [\n      { queryKey1, queryFn1, options1 },\n      { queryKey2, queryFn2, options2 },\n    ],\n  }) // [!code ++]\n```\n\n### Undefined is an illegal cache value for successful queries\n\nIn order to make bailing out of updates possible by returning `undefined`, we had to make `undefined` an illegal cache value. This is in-line with other concepts of react-query, for example, returning `undefined` from the [initialData function](./initial-query-data.md#initial-data-function) will also _not_ set data.\n\nFurther, it is an easy bug to produce `Promise<void>` by adding logging in the queryFn:\n\n```tsx\nuseQuery(['key'], () =>\n  axios.get(url).then((result) => console.log(result.data)),\n)\n```\n\nThis is now disallowed on type level; at runtime, `undefined` will be transformed to a _failed Promise_, which means you will get an `error`, which will also be logged to the console in development mode.\n\n### Queries and mutations, per default, need network connection to run\n\nPlease read the [New Features announcement](#proper-offline-support) about online / offline support, and also the dedicated page about [Network mode](./network-mode.md)\n\nEven though React Query is an Async State Manager that can be used for anything that produces a Promise, it is most often used for data fetching in combination with data fetching libraries. That is why, per default, queries and mutations will be `paused` if there is no network connection. If you want to opt-in to the previous behavior, you can globally set `networkMode: offlineFirst` for both queries and mutations:\n\n```tsx\nnew QueryClient({\n  defaultOptions: {\n    queries: {\n      networkMode: 'offlineFirst',\n    },\n    mutations: {\n      networkMode: 'offlineFirst',\n    },\n  },\n})\n```\n\n### `notifyOnChangeProps` property no longer accepts `\"tracked\"` as a value\n\nThe `notifyOnChangeProps` option no longer accepts a `\"tracked\"` value. Instead, `useQuery` defaults to tracking properties. All queries using `notifyOnChangeProps: \"tracked\"` should be updated by removing this option.\n\nIf you would like to bypass this in any queries to emulate the v3 default behavior of re-rendering whenever a query changes, `notifyOnChangeProps` now accepts an `\"all\"` value to opt-out of the default smart tracking optimization.\n\n### `notifyOnChangePropsExclusion` has been removed\n\nIn v4, `notifyOnChangeProps` defaults to the `\"tracked\"` behavior of v3 instead of `undefined`. Now that `\"tracked\"` is the default behavior for v4, it no longer makes sense to include this config option.\n\n### Consistent behavior for `cancelRefetch`\n\nThe `cancelRefetch` option can be passed to all functions that imperatively fetch a query, namely:\n\n- `queryClient.refetchQueries`\n- `queryClient.invalidateQueries`\n- `queryClient.resetQueries`\n- `refetch` returned from `useQuery`\n- `fetchNextPage` and `fetchPreviousPage` returned from `useInfiniteQuery`\n\nExcept for `fetchNextPage` and `fetchPreviousPage`, this flag was defaulting to `false`, which was inconsistent and potentially troublesome: Calling `refetchQueries` or `invalidateQueries` after a mutation might not yield the latest result if a previous slow fetch was already ongoing, because this refetch would have been skipped.\n\nWe believe that if a query is actively refetched by some code you write, it should, per default, re-start the fetch.\n\nThat is why this flag now defaults to _true_ for all methods mentioned above. It also means that if you call `refetchQueries` twice in a row, without awaiting it, it will now cancel the first fetch and re-start it with the second one:\n\n```\nqueryClient.refetchQueries({ queryKey: ['todos'] })\n// this will abort the previous refetch and start a new fetch\nqueryClient.refetchQueries({ queryKey: ['todos'] })\n```\n\nYou can opt-out of this behaviour by explicitly passing `cancelRefetch:false`:\n\n```\nqueryClient.refetchQueries({ queryKey: ['todos'] })\n// this will not abort the previous refetch - it will just be ignored\nqueryClient.refetchQueries({ queryKey: ['todos'] }, { cancelRefetch: false })\n```\n\n> Note: There is no change in behaviour for automatically triggered fetches, e.g. because a query mounts or because of a window focus refetch.\n\n### Query Filters\n\nA [query filter](./filters.md) is an object with certain conditions to match a query. Historically, the filter options have mostly been a combination of boolean flags. However, combining those flags can lead to impossible states. Specifically:\n\n```\nactive?: boolean\n  - When set to true it will match active queries.\n  - When set to false it will match inactive queries.\ninactive?: boolean\n  - When set to true it will match inactive queries.\n  - When set to false it will match active queries.\n```\n\nThose flags don't work well when used together, because they are mutually exclusive. Setting `false` for both flags could match all queries, judging from the description, or no queries, which doesn't make much sense.\n\nWith v4, those filters have been combined into a single filter to better show the intent:\n\n```tsx\n- active?: boolean // [!code --]\n- inactive?: boolean // [!code --]\n+ type?: 'active' | 'inactive' | 'all' // [!code ++]\n```\n\nThe filter defaults to `all`, and you can choose to only match `active` or `inactive` queries.\n\n#### refetchActive / refetchInactive\n\n[queryClient.invalidateQueries](../../../reference/QueryClient.md#queryclientinvalidatequeries) had two additional, similar flags:\n\n```\nrefetchActive: Boolean\n  - Defaults to true\n  - When set to false, queries that match the refetch predicate and are actively being rendered\n    via useQuery and friends will NOT be refetched in the background, and only marked as invalid.\nrefetchInactive: Boolean\n  - Defaults to false\n  - When set to true, queries that match the refetch predicate and are not being rendered\n    via useQuery and friends will be both marked as invalid and also refetched in the background\n```\n\nFor the same reason, those have also been combined:\n\n```tsx\n- refetchActive?: boolean // [!code --]\n- refetchInactive?: boolean // [!code --]\n+ refetchType?: 'active' | 'inactive' | 'all' | 'none' // [!code ++]\n```\n\nThis flag defaults to `active` because `refetchActive` defaulted to `true`. This means we also need a way to tell `invalidateQueries` to not refetch at all, which is why a fourth option (`none`) is also allowed here.\n\n### `onSuccess` is no longer called from `setQueryData`\n\nThis was confusing to many and also created infinite loops if `setQueryData` was called from within `onSuccess`. It was also a frequent source of error when combined with `staleTime`, because if data was read from the cache only, `onSuccess` was _not_ called.\n\nSimilar to `onError` and `onSettled`, the `onSuccess` callback is now tied to a request being made. No request -> no callback.\n\nIf you want to listen to changes of the `data` field, you can best do this with a `useEffect`, where `data` is part of the dependency Array. Since React Query ensures stable data through structural sharing, the effect will not execute with every background refetch, but only if something within data has changed:\n\n```\nconst { data } = useQuery({ queryKey, queryFn })\nReact.useEffect(() => mySideEffectHere(data), [data])\n```\n\n### `persistQueryClient` and the corresponding persister plugins are no longer experimental and have been renamed\n\nThe plugins `createWebStoragePersistor` and `createAsyncStoragePersistor` have been renamed to [`createSyncStoragePersister`](../plugins/createSyncStoragePersister.md) and [`createAsyncStoragePersister`](../plugins/createAsyncStoragePersister.md) respectively. The interface `Persistor` in `persistQueryClient` has also been renamed to `Persister`. Checkout [this stackexchange](https://english.stackexchange.com/questions/206893/persister-or-persistor) for the motivation of this change.\n\nSince these plugins are no longer experimental, their import paths have also been updated:\n\n```tsx\n- import { persistQueryClient } from 'react-query/persistQueryClient-experimental' // [!code --]\n- import { createWebStoragePersistor } from 'react-query/createWebStoragePersistor-experimental' // [!code --]\n- import { createAsyncStoragePersistor } from 'react-query/createAsyncStoragePersistor-experimental' // [!code --]\n\n+ import { persistQueryClient } from '@tanstack/react-query-persist-client' // [!code ++]\n+ import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister' // [!code ++]\n+ import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister'  // [!code ++]\n```\n\n### The `cancel` method on promises is no longer supported\n\nThe old `cancel` method (which allowed you to define a `cancel` function on promises and was used by the library to support query cancellation) has been removed. We recommend using the [newer API](./query-cancellation.md) (introduced with v3.30.0) for query cancellation, which uses the [`AbortController` API](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) internally and provides you with an [`AbortSignal` instance](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) in your query function to support query cancellation.\n\n### TypeScript\n\nTypes now require using TypeScript v4.1 or greater\n\n### Supported Browsers\n\nAs of v4, React Query is optimized for modern browsers. We have updated our browserslist to produce a more modern, performant and smaller bundle. You can read about the requirements [here](../installation#requirements).\n\n### `setLogger` is removed\n\nIt was possible to change the logger globally by calling `setLogger`. In v4, that function is replaced with an optional field when creating a `QueryClient`.\n\n```tsx\n- import { QueryClient, setLogger } from 'react-query'; // [!code --]\n+ import { QueryClient } from '@tanstack/react-query'; // [!code ++]\n\n- setLogger(customLogger) // [!code --]\n- const queryClient = new QueryClient(); // [!code --]\n+ const queryClient = new QueryClient({ logger: customLogger }) // [!code ++]\n```\n\n### No _default_ manual Garbage Collection server-side\n\nIn v3, React Query would cache query results for a default of 5 minutes, then manually garbage collect that data. This default was applied to server-side React Query as well.\n\nThis lead to high memory consumption and hanging processes waiting for this manual garbage collection to complete. In v4, by default the server-side `cacheTime` is now set to `Infinity` effectively disabling manual garbage collection (the NodeJS process will clear everything once a request is complete).\n\nThis change only impacts users of server-side React Query, such as with Next.js. If you are setting a `cacheTime` manually this will not impact you (although you may want to mirror behavior).\n\n### Logging in production\n\nStarting with v4, react-query will no longer log errors (e.g. failed fetches) to the console in production mode, as this was confusing to many.\nErrors will still show up in development mode.\n\n### ESM Support\n\nReact Query now supports [package.json `\"exports\"`](https://nodejs.org/api/packages.html#exports) and is fully compatible with Node's native resolution for both CommonJS and ESM. We don't expect this to be a breaking change for most users, but this restricts the files you can import into your project to only the entry points we officially support.\n\n### Streamlined NotifyEvents\n\nSubscribing manually to the `QueryCache` has always given you a `QueryCacheNotifyEvent`, but this was not true for the `MutationCache`. We have streamlined the behavior and also adapted event names accordingly.\n\n#### QueryCacheNotifyEvent\n\n```tsx\n- type: 'queryAdded' // [!code --]\n+ type: 'added' // [!code ++]\n- type: 'queryRemoved' // [!code --]\n+ type: 'removed' // [!code ++]\n- type: 'queryUpdated' // [!code --]\n+ type: 'updated' // [!code ++]\n```\n\n#### MutationCacheNotifyEvent\n\nThe `MutationCacheNotifyEvent` uses the same types as the `QueryCacheNotifyEvent`.\n\n> Note: This is only relevant if you manually subscribe to the caches via `queryCache.subscribe` or `mutationCache.subscribe`\n\n### Separate hydration exports have been removed\n\nWith version [3.22.0](https://github.com/TanStack/query/releases/tag/v3.22.0), hydration utilities moved into the React Query core. With v3, you could still use the old exports from `react-query/hydration`, but these exports have been removed with v4.\n\n```tsx\n- import { dehydrate, hydrate, useHydrate, Hydrate } from 'react-query/hydration' // [!code --]\n+ import { dehydrate, hydrate, useHydrate, Hydrate } from '@tanstack/react-query' // [!code ++]\n```\n\n### Removed undocumented methods from the `queryClient`, `query` and `mutation`\n\nThe methods `cancelMutations` and `executeMutation` on the `QueryClient` were undocumented and unused internally, so we removed them. Since it was just a wrapper around a method available on the `mutationCache`, you can still use the functionality of `executeMutation`\n\n```tsx\n- executeMutation< // [!code --]\n-   TData = unknown, // [!code --]\n-   TError = unknown, // [!code --]\n-   TVariables = void, // [!code --]\n-   TContext = unknown // [!code --]\n- >( // [!code --]\n-   options: MutationOptions<TData, TError, TVariables, TContext> // [!code --]\n- ): Promise<TData> { // [!code --]\n-   return this.mutationCache.build(this, options).execute() // [!code --]\n- } // [!code --]\n```\n\nAdditionally, `query.setDefaultOptions` was removed because it was also unused. `mutation.cancel` was removed because it didn't actually cancel the outgoing request.\n\n### The `src/react` directory was renamed to `src/reactjs`\n\nPreviously, React Query had a directory named `react` which imported from the `react` module. This could cause problems with some Jest configurations, resulting in errors when running tests like:\n\n```\nTypeError: Cannot read property 'createContext' of undefined\n```\n\nWith the renamed directory this no longer is an issue.\n\nIf you were importing anything from `'react-query/react'` directly in your project (as opposed to just `'react-query'`), then you need to update your imports:\n\n```tsx\n- import { QueryClientProvider } from 'react-query/react'; // [!code --]\n+ import { QueryClientProvider } from '@tanstack/react-query/reactjs'; // [!code ++]\n```\n\n## New Features 🚀\n\nv4 comes with an awesome set of new features:\n\n### Support for React 18\n\nReact 18 was released earlier this year, and v4 now has first class support for it and the new concurrent features it brings.\n\n### Proper offline support\n\nIn v3, React Query has always fired off queries and mutations, but then taken the assumption that if you want to retry it, you need to be connected to the internet. This has led to several confusing situations:\n\n- You are offline and mount a query - it goes to loading state, the request fails, and it stays in loading state until you go online again, even though it is not really fetching.\n- Similarly, if you are offline and have retries turned off, your query will just fire and fail, and the query goes to error state.\n- You are offline and want to fire off a query that doesn't necessarily need network connection (because you _can_ use React Query for something other than data fetching), but it fails for some other reason. That query will now be paused until you go online again.\n- Window focus refetching didn't do anything at all if you were offline.\n\nWith v4, React Query introduces a new `networkMode` to tackle all these issues. Please read the dedicated page about the new [Network mode](./network-mode) for more information.\n\n### Tracked Queries per default\n\nReact Query defaults to \"tracking\" query properties, which should give you a nice boost in render optimization. The feature has existed since [v3.6.0](https://github.com/TanStack/query/releases/tag/v3.6.0) and has now become the default behavior with v4.\n\n### Bailing out of updates with setQueryData\n\nWhen using the [functional updater form of setQueryData](../../../reference/QueryClient.md#queryclientsetquerydata), you can now bail out of the update by returning `undefined`. This is helpful if `undefined` is given to you as `previousValue`, which means that currently, no cached entry exists and you don't want to / cannot create one, like in the example of toggling a todo:\n\n```tsx\nqueryClient.setQueryData(['todo', id], (previousTodo) =>\n  previousTodo ? { ...previousTodo, done: true } : undefined,\n)\n```\n\n### Mutation Cache Garbage Collection\n\nMutations can now also be garbage collected automatically, just like queries. The default `cacheTime` for mutations is also set to 5 minutes.\n\n### Custom Contexts for Multiple Providers\n\nCustom contexts can now be specified to pair hooks with their matching `Provider`. This is critical when there may be multiple React Query `Provider` instances in the component tree, and you need to ensure your hook uses the correct `Provider` instance.\n\nAn example:\n\n1. Create a data package.\n\n```tsx\n// Our first data package: @my-scope/container-data\n\nconst context = React.createContext<QueryClient | undefined>(undefined)\nconst queryClient = new QueryClient()\n\nexport const useUser = () => {\n  return useQuery(USER_KEY, USER_FETCHER, {\n    context,\n  })\n}\n\nexport const ContainerDataProvider = ({\n  children,\n}: {\n  children: React.ReactNode\n}) => {\n  return (\n    <QueryClientProvider client={queryClient} context={context}>\n      {children}\n    </QueryClientProvider>\n  )\n}\n```\n\n2. Create a second data package.\n\n```tsx\n// Our second data package: @my-scope/my-component-data\n\nconst context = React.createContext<QueryClient | undefined>(undefined)\nconst queryClient = new QueryClient()\n\nexport const useItems = () => {\n  return useQuery(ITEMS_KEY, ITEMS_FETCHER, {\n    context,\n  })\n}\n\nexport const MyComponentDataProvider = ({\n  children,\n}: {\n  children: React.ReactNode\n}) => {\n  return (\n    <QueryClientProvider client={queryClient} context={context}>\n      {children}\n    </QueryClientProvider>\n  )\n}\n```\n\n3. Use these two data packages in your application.\n\n```tsx\n// Our application\n\nimport { ContainerDataProvider, useUser } from \"@my-scope/container-data\";\nimport { AppDataProvider } from \"@my-scope/app-data\";\nimport { MyComponentDataProvider, useItems } from \"@my-scope/my-component-data\";\n\n<ContainerDataProvider> // <-- Provides container data (like \"user\") using its own React Query provider\n  ...\n  <AppDataProvider> // <-- Provides app data using its own React Query provider (unused in this example)\n    ...\n      <MyComponentDataProvider> // <-- Provides component data (like \"items\") using its own React Query provider\n        <MyComponent />\n      </MyComponentDataProvider>\n    ...\n  </AppDataProvider>\n  ...\n</ContainerDataProvider>\n\n// Example of hooks provided by the \"DataProvider\" components above:\nconst MyComponent = () => {\n  const user = useUser() // <-- Uses the context specified in ContainerDataProvider.\n  const items = useItems() // <-- Uses the context specified in MyComponentDataProvider\n  ...\n}\n```\n"
  },
  {
    "path": "docs/framework/react/guides/migrating-to-v5.md",
    "content": "---\nid: migrating-to-tanstack-query-5\ntitle: Migrating to TanStack Query v5\n---\n\n## Breaking Changes\n\nv5 is a major version, so there are some breaking changes to be aware of:\n\n### Supports a single signature, one object\n\nuseQuery and friends used to have many overloads in TypeScript: different ways how the function could be invoked. Not only was this tough to maintain, type wise, it also required a runtime check to see which types the first and the second parameter were, to correctly create options.\n\nnow we only support the object format.\n\n```tsx\nuseQuery(key, fn, options) // [!code --]\nuseQuery({ queryKey, queryFn, ...options }) // [!code ++]\nuseInfiniteQuery(key, fn, options) // [!code --]\nuseInfiniteQuery({ queryKey, queryFn, ...options }) // [!code ++]\nuseMutation(fn, options) // [!code --]\nuseMutation({ mutationFn, ...options }) // [!code ++]\nuseIsFetching(key, filters) // [!code --]\nuseIsFetching({ queryKey, ...filters }) // [!code ++]\nuseIsMutating(key, filters) // [!code --]\nuseIsMutating({ mutationKey, ...filters }) // [!code ++]\n```\n\n```tsx\nqueryClient.isFetching(key, filters) // [!code --]\nqueryClient.isFetching({ queryKey, ...filters }) // [!code ++]\nqueryClient.ensureQueryData(key, filters) // [!code --]\nqueryClient.ensureQueryData({ queryKey, ...filters }) // [!code ++]\nqueryClient.getQueriesData(key, filters) // [!code --]\nqueryClient.getQueriesData({ queryKey, ...filters }) // [!code ++]\nqueryClient.setQueriesData(key, updater, filters, options) // [!code --]\nqueryClient.setQueriesData({ queryKey, ...filters }, updater, options) // [!code ++]\nqueryClient.removeQueries(key, filters) // [!code --]\nqueryClient.removeQueries({ queryKey, ...filters }) // [!code ++]\nqueryClient.resetQueries(key, filters, options) // [!code --]\nqueryClient.resetQueries({ queryKey, ...filters }, options) // [!code ++]\nqueryClient.cancelQueries(key, filters, options) // [!code --]\nqueryClient.cancelQueries({ queryKey, ...filters }, options) // [!code ++]\nqueryClient.invalidateQueries(key, filters, options) // [!code --]\nqueryClient.invalidateQueries({ queryKey, ...filters }, options) // [!code ++]\nqueryClient.refetchQueries(key, filters, options) // [!code --]\nqueryClient.refetchQueries({ queryKey, ...filters }, options) // [!code ++]\nqueryClient.fetchQuery(key, fn, options) // [!code --]\nqueryClient.fetchQuery({ queryKey, queryFn, ...options }) // [!code ++]\nqueryClient.prefetchQuery(key, fn, options) // [!code --]\nqueryClient.prefetchQuery({ queryKey, queryFn, ...options }) // [!code ++]\nqueryClient.fetchInfiniteQuery(key, fn, options) // [!code --]\nqueryClient.fetchInfiniteQuery({ queryKey, queryFn, ...options }) // [!code ++]\nqueryClient.prefetchInfiniteQuery(key, fn, options) // [!code --]\nqueryClient.prefetchInfiniteQuery({ queryKey, queryFn, ...options }) // [!code ++]\n```\n\n```tsx\nqueryCache.find(key, filters) // [!code --]\nqueryCache.find({ queryKey, ...filters }) // [!code ++]\nqueryCache.findAll(key, filters) // [!code --]\nqueryCache.findAll({ queryKey, ...filters }) // [!code ++]\n```\n\n### `queryClient.getQueryData` now accepts queryKey only as an Argument\n\n`queryClient.getQueryData` argument is changed to accept only a `queryKey`\n\n```tsx\nqueryClient.getQueryData(queryKey, filters) // [!code --]\nqueryClient.getQueryData(queryKey) // [!code ++]\n```\n\n### `queryClient.getQueryState` now accepts queryKey only as an Argument\n\n`queryClient.getQueryState` argument is changed to accept only a `queryKey`\n\n```tsx\nqueryClient.getQueryState(queryKey, filters) // [!code --]\nqueryClient.getQueryState(queryKey) // [!code ++]\n```\n\n#### Codemod\n\nTo make the remove overloads migration easier, v5 comes with a codemod.\n\n> The codemod is a best efforts attempt to help you migrate the breaking change. Please review the generated code thoroughly! Also, there are edge cases that cannot be found by the code mod, so please keep an eye on the log output.\n\nIf you want to run it against `.js` or `.jsx` files, please use the command below:\n\n```\nnpx jscodeshift@latest ./path/to/src/ \\\n  --extensions=js,jsx \\\n  --transform=./node_modules/@tanstack/react-query/build/codemods/src/v5/remove-overloads/remove-overloads.cjs\n```\n\nIf you want to run it against `.ts` or `.tsx` files, please use the command below:\n\n```\nnpx jscodeshift@latest ./path/to/src/ \\\n  --extensions=ts,tsx \\\n  --parser=tsx \\\n  --transform=./node_modules/@tanstack/react-query/build/codemods/src/v5/remove-overloads/remove-overloads.cjs\n```\n\nPlease note in the case of `TypeScript` you need to use `tsx` as the parser; otherwise, the codemod won't be applied properly!\n\n**Note:** Applying the codemod might break your code formatting, so please don't forget to run `prettier` and/or `eslint` after you've applied the codemod!\n\nA few notes about how codemod works:\n\n- Generally, we're looking for the lucky case, when the first parameter is an object expression and contains the \"queryKey\" or \"mutationKey\" property (depending on which hook/method call is being transformed). If this is the case, your code already matches the new signature, so the codemod won't touch it. 🎉\n- If the condition above is not fulfilled, then the codemod will check whether the first parameter is an array expression or an identifier that references an array expression. If this is the case, the codemod will put it into an object expression, then it will be the first parameter.\n- If object parameters can be inferred, the codemod will attempt to copy the already existing properties to the newly created one.\n- If the codemod cannot infer the usage, then it will leave a message on the console. The message contains the file name and the line number of the usage. In this case, you need to do the migration manually.\n- If the transformation results in an error, you will also see a message on the console. This message will notify you something unexpected happened, please do the migration manually.\n\n### Callbacks on useQuery (and QueryObserver) have been removed\n\n`onSuccess`, `onError` and `onSettled` have been removed from Queries. They haven't been touched for Mutations. Please see [this RFC](https://github.com/TanStack/query/discussions/5279) for motivations behind this change and what to do instead.\n\n### The `refetchInterval` callback function only gets `query` passed\n\nThis streamlines how callbacks are invoked (the `refetchOnWindowFocus`, `refetchOnMount` and `refetchOnReconnect` callbacks all only get the query passed as well), and it fixes some typing issues when callbacks get data transformed by `select`.\n\n```tsx\n- refetchInterval: number | false | ((data: TData | undefined, query: Query) => number | false | undefined) // [!code --]\n+ refetchInterval: number | false | ((query: Query) => number | false | undefined) // [!code ++]\n```\n\nYou can still access data with `query.state.data`, however, it will not be data that has been transformed by `select`. If you need to access the transformed data, you can call the transformation again on `query.state.data`.\n\n### The `remove` method has been removed from useQuery\n\nPreviously, remove method used to remove the query from the queryCache without informing observers about it. It was best used to remove data imperatively that is no longer needed, e.g. when logging a user out.\n\nBut It doesn't make much sense to do this while a query is still active, because it will just trigger a hard loading state with the next re-render.\n\nif you still need to remove a query, you can use `queryClient.removeQueries({queryKey: key})`\n\n```tsx\nconst queryClient = useQueryClient()\nconst query = useQuery({ queryKey, queryFn })\n\nquery.remove() // [!code --]\nqueryClient.removeQueries({ queryKey }) // [!code ++]\n```\n\n### The minimum required TypeScript version is now 4.7\n\nMainly because an important fix was shipped around type inference. Please see this [TypeScript issue](https://github.com/microsoft/TypeScript/issues/43371) for more information.\n\n### The `isDataEqual` option has been removed from useQuery\n\nPreviously, This function was used to indicate whether to use previous `data` (`true`) or new data (`false`) as a resolved data for the query.\n\nYou can achieve the same functionality by passing a function to `structuralSharing` instead:\n\n```tsx\nimport { replaceEqualDeep } from '@tanstack/react-query'\n\n- isDataEqual: (oldData, newData) => customCheck(oldData, newData) // [!code --]\n+ structuralSharing: (oldData, newData) => customCheck(oldData, newData) ? oldData : replaceEqualDeep(oldData, newData) // [!code ++]\n```\n\n### The deprecated custom logger has been removed\n\nCustom loggers were already deprecated in 4 and have been removed in this version. Logging only had an effect in development mode, where passing a custom logger is not necessary.\n\n### Supported Browsers\n\nWe have updated our browserslist to produce a more modern, performant and smaller bundle. You can read about the requirements [here](../installation#requirements).\n\n### Private class fields and methods\n\nTanStack Query has always had private fields and methods on classes, but they weren't really private - they were just private in `TypeScript`. We now use [ECMAScript Private class features](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_class_fields), which means those fields are now truly private and can't be accessed from the outside at runtime.\n\n### Rename `cacheTime` to `gcTime`\n\nAlmost everyone gets `cacheTime` wrong. It sounds like \"the amount of time that data is cached for\", but that is not correct.\n\n`cacheTime` does nothing as long as a query is still in use. It only kicks in as soon as the query becomes unused. After the time has passed, data will be \"garbage collected\" to avoid the cache from growing.\n\n`gc` is referring to \"garbage collect\" time. It's a bit more technical, but also a quite [well known abbreviation](<https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)>) in computer science.\n\n```tsx\nconst MINUTE = 1000 * 60;\n\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n-      cacheTime: 10 * MINUTE, // [!code --]\n+      gcTime: 10 * MINUTE, // [!code ++]\n    },\n  },\n})\n```\n\n### The `useErrorBoundary` option has been renamed to `throwOnError`\n\nTo make the `useErrorBoundary` option more framework-agnostic and avoid confusion with the established React function prefix \"`use`\" for hooks and the \"ErrorBoundary\" component name, it has been renamed to `throwOnError` to more accurately reflect its functionality.\n\n### TypeScript: `Error` is now the default type for errors instead of `unknown`\n\nEven though in JavaScript, you can `throw` anything (which makes `unknown` the most correct type), almost always, `Errors` (or subclasses of `Error`) are thrown. This change makes it easier to work with the `error` field in TypeScript for most cases.\n\nIf you want to throw something that isn't an Error, you'll now have to set the generic for yourself:\n\n```ts\nuseQuery<number, string>({\n  queryKey: ['some-query'],\n  queryFn: async () => {\n    if (Math.random() > 0.5) {\n      throw 'some error'\n    }\n    return 42\n  },\n})\n```\n\nFor a way to set a different kind of Error globally, see [the TypeScript Guide](../typescript.md#registering-a-global-error).\n\n### eslint `prefer-query-object-syntax` rule is removed\n\nSince the only supported syntax now is the object syntax, this rule is no longer needed\n\n### Removed `keepPreviousData` in favor of `placeholderData` identity function\n\nWe have removed the `keepPreviousData` option and `isPreviousData` flag as they were doing mostly the same thing as `placeholderData` and `isPlaceholderData` flag.\n\nTo achieve the same functionality as `keepPreviousData`, we have added previous query `data` as an argument to `placeholderData` which accepts an identity function. Therefore you just need to provide an identity function to `placeholderData` or use the included `keepPreviousData` function from TanStack Query.\n\n> A note here is that `useQueries` would not receive `previousData` in the `placeholderData` function as argument. This is due to a dynamic nature of queries passed in the array, which may lead to a different shape of result from placeholder and queryFn.\n\n```tsx\nimport {\n   useQuery,\n+  keepPreviousData // [!code ++]\n} from \"@tanstack/react-query\";\n\nconst {\n   data,\n-  isPreviousData, // [!code --]\n+  isPlaceholderData, // [!code ++]\n} = useQuery({\n  queryKey,\n  queryFn,\n- keepPreviousData: true, // [!code --]\n+ placeholderData: keepPreviousData // [!code ++]\n});\n```\n\nAn identity function, in the context of TanStack Query, refers to a function that always returns its provided argument (i.e. data) unchanged.\n\n```ts\nuseQuery({\n  queryKey,\n  queryFn,\n  placeholderData: (previousData, previousQuery) => previousData, // identity function with the same behaviour as `keepPreviousData`\n})\n```\n\nThere are some caveats to this change however, which you must be aware of:\n\n- `placeholderData` will always put you into `success` state, while `keepPreviousData` gave you the status of the previous query. That status could be `error` if we have data fetched successfully and then got a background refetch error. However, the error itself was not shared, so we decided to stick with behavior of `placeholderData`.\n- `keepPreviousData` gave you the `dataUpdatedAt` timestamp of the previous data, while with `placeholderData`, `dataUpdatedAt` will stay at `0`. This might be annoying if you want to show that timestamp continuously on screen. However you might get around it with `useEffect`.\n\n  ```ts\n  const [updatedAt, setUpdatedAt] = useState(0)\n\n  const { data, dataUpdatedAt } = useQuery({\n    queryKey: ['projects', page],\n    queryFn: () => fetchProjects(page),\n  })\n\n  useEffect(() => {\n    if (dataUpdatedAt > updatedAt) {\n      setUpdatedAt(dataUpdatedAt)\n    }\n  }, [dataUpdatedAt])\n  ```\n\n### Window focus refetching no longer listens to the `focus` event\n\nThe `visibilitychange` event is used exclusively now. This is possible because we only support browsers that support the `visibilitychange` event. This fixes a bunch of issues [as listed here](https://github.com/TanStack/query/pull/4805).\n\n### Network status no longer relies on the `navigator.onLine` property\n\n`navigator.onLine` doesn't work well in Chromium based browsers. There are [a lot of issues](https://bugs.chromium.org/p/chromium/issues/list?q=navigator.online) around false negatives, which lead to Queries being wrongfully marked as `offline`.\n\nTo circumvent this, we now always start with `online: true` and only listen to `online` and `offline` events to update the status.\n\nThis should reduce the likelihood of false negatives, however, it might mean false positives for offline apps that load via serviceWorkers, which can work even without an internet connection.\n\n### Removed custom `context` prop in favor of custom `queryClient` instance\n\nIn v4, we introduced the possibility to pass a custom `context` to all react-query hooks. This allowed for proper isolation when using MicroFrontends.\n\nHowever, `context` is a react-only feature. All that `context` does is give us access to the `queryClient`. We could achieve the same isolation by allowing to pass in a custom `queryClient` directly.\nThis in turn will enable other frameworks to have the same functionality in a framework-agnostic way.\n\n```tsx\nimport { queryClient } from './my-client'\n\nconst { data } = useQuery(\n  {\n    queryKey: ['users', id],\n    queryFn: () => fetch(...),\n-   context: customContext // [!code --]\n  },\n+  queryClient, // [!code ++]\n)\n```\n\n### Removed `refetchPage` in favor of `maxPages`\n\nIn v4, we introduced the possibility to define the pages to refetch for infinite queries with the `refetchPage` function.\n\nHowever, refetching all pages might lead to UI inconsistencies. Also, this option is available on e.g. `queryClient.refetchQueries`, but it only does something for infinite queries, not \"normal\" queries.\n\nThe v5 includes a new `maxPages` option for infinite queries to limit the number of pages to store in the query data and to refetch. This new feature handles the use cases initially identified for the `refetchPage` page feature without the related issues.\n\n### New `dehydrate` API\n\nThe options you can pass to `dehydrate` have been simplified. Queries and Mutations are always dehydrated (according to the default function implementation). To change this behaviour, instead of using the removed boolean options `dehydrateMutations` and `dehydrateQueries` you can implement the function equivalents `shouldDehydrateQuery` or `shouldDehydrateMutation` instead. To get the old behaviour of not hydrating queries/mutations at all, pass in `() => false`.\n\n```tsx\n- dehydrateMutations?: boolean // [!code --]\n- dehydrateQueries?: boolean // [!code --]\n```\n\n### Infinite queries now need a `initialPageParam`\n\nPreviously, we've passed `undefined` to the `queryFn` as `pageParam`, and you could assign a default value to the `pageParam` parameter in the `queryFn` function signature. This had the drawback of storing `undefined` in the `queryCache`, which is not serializable.\n\nInstead, you now have to pass an explicit `initialPageParam` to the infinite query options. This will be used as the `pageParam` for the first page:\n\n```tsx\nuseInfiniteQuery({\n   queryKey,\n-  queryFn: ({ pageParam = 0 }) => fetchSomething(pageParam), // [!code --]\n+  queryFn: ({ pageParam }) => fetchSomething(pageParam), // [!code ++]\n+  initialPageParam: 0, // [!code ++]\n   getNextPageParam: (lastPage) => lastPage.next,\n})\n```\n\n### Manual mode for infinite queries has been removed\n\nPreviously, we've allowed to overwrite the `pageParams` that would be returned from `getNextPageParam` or `getPreviousPageParam` by passing a `pageParam` value directly to `fetchNextPage` or `fetchPreviousPage`. This feature didn't work at all with refetches and wasn't widely known or used. This also means that `getNextPageParam` is now required for infinite queries.\n\n### Returning `null` from `getNextPageParam` or `getPreviousPageParam` now indicates that there is no further page available\n\nIn v4, you needed to explicitly return `undefined` to indicate that there is no further page available. We've widened this check to include `null`.\n\n### No retries on the server\n\nOn the server, `retry` now defaults to `0` instead of `3`. For prefetching, we have always defaulted to `0` retries, but since queries that have `suspense` enabled can now execute directly on the server as well (since React18), we have to make sure that we don't retry on the server at all.\n\n### `status: loading` has been changed to `status: pending` and `isLoading` has been changed to `isPending` and `isInitialLoading` has now been renamed to `isLoading`\n\nThe `loading` status has been renamed to `pending`, and similarly the derived `isLoading` flag has been renamed to `isPending`.\n\nFor mutations as well the `status` has been changed from `loading` to `pending` and the `isLoading` flag has been changed to `isPending`.\n\nLastly, a new derived `isLoading` flag has been added to the queries that is implemented as `isPending && isFetching`. This means that `isLoading` and `isInitialLoading` have the same thing, but `isInitialLoading` is deprecated now and will be removed in the next major version.\n\nTo understand the reasoning behind this change checkout the [v5 roadmap discussion](https://github.com/TanStack/query/discussions/4252).\n\n### `hashQueryKey` has been renamed to `hashKey`\n\nbecause it also hashes mutation keys and can be used inside the `predicate` functions of `useIsMutating` and `useMutationState`, which gets mutations passed.\n\n[//]: # 'FrameworkSpecificBreakingChanges'\n\n### The minimum required React version is now 18.0\n\nReact Query v5 requires React 18.0 or later. This is because we are using the new `useSyncExternalStore` hook, which is only available in React 18.0 and later. Previously, we have been using the shim provided by React.\n\n### The `contextSharing` prop has been removed from QueryClientProvider\n\nYou could previously use the `contextSharing` property to share the first (and at least one) instance of the query client context across the window. This ensured that if TanStack Query was used across different bundles or microfrontends then they will all use the same instance of the context, regardless of module scoping.\n\nWith the removal of the custom context prop in v5, refer to the section on [Removed custom context prop in favor of custom queryClient instance](#removed-custom-context-prop-in-favor-of-custom-queryclient-instance). If you wish to share the same query client across multiple packages of an application, you can directly pass a shared custom `queryClient` instance.\n\n### No longer using `unstable_batchedUpdates` as the batching function in React and React Native\n\nSince the function `unstable_batchedUpdates` is noop in React 18, it will no longer be automatically set as the batching function in `react-query`.\n\nIf your framework supports a custom batching function, you can let TanStack Query know about it by calling `notifyManager.setBatchNotifyFunction`.\n\nFor example, this is how the batch function is set in `solid-query`:\n\n```ts\nimport { notifyManager } from '@tanstack/query-core'\nimport { batch } from 'solid-js'\n\nnotifyManager.setBatchNotifyFunction(batch)\n```\n\n### Hydration API changes\n\nTo better support concurrent features and transitions we've made some changes to the hydration APIs. The `Hydrate` component has been renamed to `HydrationBoundary` and the `useHydrate` hook has been removed.\n\nThe `HydrationBoundary` no longer hydrates mutations, only queries. To hydrate mutations, use the low level `hydrate` API or the `persistQueryClient` plugin.\n\nFinally, as a technical detail, the timing for when queries are hydrated have changed slightly. New queries are still hydrated in the render phase so that SSR works as usual, but any queries that already exist in the cache are now hydrated in an effect instead (as long as their data is fresher than what is in the cache). If you are hydrating just once at the start of your application as is common, this wont affect you, but if you are using Server Components and pass down fresh data for hydration on a page navigation, you might notice a flash of the old data before the page immediately rerenders.\n\nThis last change is technically a breaking one, and was made so we don't prematurely update content on the _existing_ page before a page transition has been fully committed. No action is required on your part.\n\n```tsx\n- import { Hydrate } from '@tanstack/react-query' // [!code --]\n+ import { HydrationBoundary } from '@tanstack/react-query' // [!code ++]\n\n\n- <Hydrate state={dehydratedState}> // [!code --]\n+ <HydrationBoundary state={dehydratedState}> // [!code ++]\n  <App />\n- </Hydrate> // [!code --]\n+ </HydrationBoundary> // [!code ++]\n```\n\n### Query defaults changes\n\n`queryClient.getQueryDefaults` will now merge together all matching registrations instead of returning only the first matching registration.\n\nAs a result, calls to `queryClient.setQueryDefaults` should now be ordered with _increasing_ specificity.\nThat is, registrations should be made from the **most generic key** to the **least generic one**.\n\nFor example:\n\n```ts\n+ queryClient.setQueryDefaults(['todo'], {   // [!code ++]\n+   retry: false,  // [!code ++]\n+   staleTime: 60_000,  // [!code ++]\n+ })  // [!code ++]\nqueryClient.setQueryDefaults(['todo', 'detail'], {\n+   retry: true,  // [!code --]\n  retryDelay: 1_000,\n  staleTime: 10_000,\n})\n- queryClient.setQueryDefaults(['todo'], { // [!code --]\n-   retry: false, // [!code --]\n-   staleTime: 60_000, // [!code --]\n- }) // [!code --]\n```\n\nNote that in this specific example, `retry: true` was added to the `['todo', 'detail']` registration to counteract it now inheriting `retry: false` from the more general registration. The specific changes needed to maintain exact behavior will vary depending on your defaults.\n\n[//]: # 'FrameworkSpecificBreakingChanges'\n\n## New Features 🚀\n\nv5 also comes with new features:\n\n### Simplified optimistic updates\n\nWe have a new, simplified way to perform optimistic updates by leveraging the returned `variables` from `useMutation`:\n\n```tsx\nconst queryInfo = useTodos()\nconst addTodoMutation = useMutation({\n  mutationFn: (newTodo: string) => axios.post('/api/data', { text: newTodo }),\n  onSettled: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),\n})\n\nif (queryInfo.data) {\n  return (\n    <ul>\n      {queryInfo.data.items.map((todo) => (\n        <li key={todo.id}>{todo.text}</li>\n      ))}\n      {addTodoMutation.isPending && (\n        <li key={String(addTodoMutation.submittedAt)} style={{ opacity: 0.5 }}>\n          {addTodoMutation.variables}\n        </li>\n      )}\n    </ul>\n  )\n}\n```\n\nHere, we are only changing how the UI looks when the mutation is running instead of writing data directly to the cache. This works best if we only have one place where we need to show the optimistic update. For more details, have a look at the [optimistic updates documentation](./optimistic-updates.md).\n\n### Limited, Infinite Queries with new maxPages option\n\nInfinite queries are great when infinite scroll or pagination are needed.\nHowever, the more pages you fetch, the more memory you consume, and this also slows down the query refetching process as all the pages are sequentially refetched.\n\nVersion 5 has a new `maxPages` option for infinite queries, which allows developers to limit the number of pages that are stored in the query data and subsequently refetched.\nYou can adjust the `maxPages` value according to the UX and refetching performance you want to deliver.\n\nNote that the infinite list must be bi-directional, which requires both `getNextPageParam` and `getPreviousPageParam` to be defined.\n\n### Infinite Queries can prefetch multiple pages\n\nInfinite Queries can be prefetched like regular Queries. Per default, only the first page of the Query will be prefetched and will be stored under the given QueryKey. If you want to prefetch more than one page, you can use the `pages` option. Read the [prefetching guide](./prefetching.md) for more information.\n\n### New `combine` option for `useQueries`\n\nSee the [useQueries docs](../reference/useQueries.md#combine) for more details.\n\n### Experimental `fine grained storage persister`\n\nSee the [experimental_createPersister docs](../plugins/createPersister.md) for more details.\n\n[//]: # 'FrameworkSpecificNewFeatures'\n\n### Typesafe way to create Query Options\n\nSee the [TypeScript docs](../typescript.md#typing-query-options) for more details.\n\n### new hooks for suspense\n\nWith v5, suspense for data fetching finally becomes \"stable\". We've added dedicated `useSuspenseQuery`, `useSuspenseInfiniteQuery` and `useSuspenseQueries` hooks. With these hooks, `data` will never be potentially `undefined` on type level:\n\n```js\nconst { data: post } = useSuspenseQuery({\n  // ^? const post: Post\n  queryKey: ['post', postId],\n  queryFn: () => fetchPost(postId),\n})\n```\n\nThe experimental `suspense: boolean` flag on the query hooks has been removed.\n\nYou can read more about them in the [suspense docs](./suspense.md).\n\n[//]: # 'FrameworkSpecificNewFeatures'\n"
  },
  {
    "path": "docs/framework/react/guides/mutations.md",
    "content": "---\nid: mutations\ntitle: Mutations\n---\n\nUnlike queries, mutations are typically used to create/update/delete data or perform server side-effects. For this purpose, TanStack Query exports a `useMutation` hook.\n\nHere's an example of a mutation that adds a new todo to the server:\n\n[//]: # 'Example'\n\n```tsx\nfunction App() {\n  const mutation = useMutation({\n    mutationFn: (newTodo) => {\n      return axios.post('/todos', newTodo)\n    },\n  })\n\n  return (\n    <div>\n      {mutation.isPending ? (\n        'Adding todo...'\n      ) : (\n        <>\n          {mutation.isError ? (\n            <div>An error occurred: {mutation.error.message}</div>\n          ) : null}\n\n          {mutation.isSuccess ? <div>Todo added!</div> : null}\n\n          <button\n            onClick={() => {\n              mutation.mutate({ id: new Date(), title: 'Do Laundry' })\n            }}\n          >\n            Create Todo\n          </button>\n        </>\n      )}\n    </div>\n  )\n}\n```\n\n[//]: # 'Example'\n\nA mutation can only be in one of the following states at any given moment:\n\n- `isIdle` or `status === 'idle'` - The mutation is currently idle or in a fresh/reset state\n- `isPending` or `status === 'pending'` - The mutation is currently running\n- `isError` or `status === 'error'` - The mutation encountered an error\n- `isSuccess` or `status === 'success'` - The mutation was successful and mutation data is available\n\nBeyond those primary states, more information is available depending on the state of the mutation:\n\n- `error` - If the mutation is in an `error` state, the error is available via the `error` property.\n- `data` - If the mutation is in a `success` state, the data is available via the `data` property.\n\nIn the example above, you also saw that you can pass variables to your mutations function by calling the `mutate` function with a **single variable or object**.\n\nEven with just variables, mutations aren't all that special, but when used with the `onSuccess` option, the [Query Client's `invalidateQueries` method](../../../reference/QueryClient.md#queryclientinvalidatequeries) and the [Query Client's `setQueryData` method](../../../reference/QueryClient.md#queryclientsetquerydata), mutations become a very powerful tool.\n\n[//]: # 'Info1'\n\n> IMPORTANT: The `mutate` function is an asynchronous function, which means you cannot use it directly in an event callback in **React 16 and earlier**. If you need to access the event in `onSubmit` you need to wrap `mutate` in another function. This is due to [React event pooling](https://reactjs.org/docs/legacy-event-pooling.html).\n\n[//]: # 'Info1'\n[//]: # 'Example2'\n\n```tsx\n// This will not work in React 16 and earlier\nconst CreateTodo = () => {\n  const mutation = useMutation({\n    mutationFn: (event) => {\n      event.preventDefault()\n      return fetch('/api', new FormData(event.target))\n    },\n  })\n\n  return <form onSubmit={mutation.mutate}>...</form>\n}\n\n// This will work\nconst CreateTodo = () => {\n  const mutation = useMutation({\n    mutationFn: (formData) => {\n      return fetch('/api', formData)\n    },\n  })\n  const onSubmit = (event) => {\n    event.preventDefault()\n    mutation.mutate(new FormData(event.target))\n  }\n\n  return <form onSubmit={onSubmit}>...</form>\n}\n```\n\n[//]: # 'Example2'\n\n## Resetting Mutation State\n\nIt's sometimes the case that you need to clear the `error` or `data` of a mutation request. To do this, you can use the `reset` function to handle this:\n\n[//]: # 'Example3'\n\n```tsx\nconst CreateTodo = () => {\n  const [title, setTitle] = useState('')\n  const mutation = useMutation({ mutationFn: createTodo })\n\n  const onCreateTodo = (e) => {\n    e.preventDefault()\n    mutation.mutate({ title })\n  }\n\n  return (\n    <form onSubmit={onCreateTodo}>\n      {mutation.error && (\n        <h5 onClick={() => mutation.reset()}>{mutation.error}</h5>\n      )}\n      <input\n        type=\"text\"\n        value={title}\n        onChange={(e) => setTitle(e.target.value)}\n      />\n      <br />\n      <button type=\"submit\">Create Todo</button>\n    </form>\n  )\n}\n```\n\n[//]: # 'Example3'\n\n## Mutation Side Effects\n\n`useMutation` comes with some helper options that allow quick and easy side-effects at any stage during the mutation lifecycle. These come in handy for both [invalidating and refetching queries after mutations](./invalidations-from-mutations.md) and even [optimistic updates](./optimistic-updates.md)\n\n[//]: # 'Example4'\n\n```tsx\nuseMutation({\n  mutationFn: addTodo,\n  onMutate: (variables, context) => {\n    // A mutation is about to happen!\n\n    // Optionally return a result containing data to use when for example rolling back\n    return { id: 1 }\n  },\n  onError: (error, variables, onMutateResult, context) => {\n    // An error happened!\n    console.log(`rolling back optimistic update with id ${onMutateResult.id}`)\n  },\n  onSuccess: (data, variables, onMutateResult, context) => {\n    // Boom baby!\n  },\n  onSettled: (data, error, variables, onMutateResult, context) => {\n    // Error or success... doesn't matter!\n  },\n})\n```\n\n[//]: # 'Example4'\n\nWhen returning a promise in any of the callback functions it will first be awaited before the next callback is called:\n\n[//]: # 'Example5'\n\n```tsx\nuseMutation({\n  mutationFn: addTodo,\n  onSuccess: async () => {\n    console.log(\"I'm first!\")\n  },\n  onSettled: async () => {\n    console.log(\"I'm second!\")\n  },\n})\n```\n\n[//]: # 'Example5'\n\nYou might find that you want to **trigger additional callbacks** beyond the ones defined on `useMutation` when calling `mutate`. This can be used to trigger component-specific side effects. To do that, you can provide any of the same callback options to the `mutate` function after your mutation variable. Supported options include: `onSuccess`, `onError` and `onSettled`. Please keep in mind that those additional callbacks won't run if your component unmounts _before_ the mutation finishes.\n\n[//]: # 'Example6'\n\n```tsx\nuseMutation({\n  mutationFn: addTodo,\n  onSuccess: (data, variables, onMutateResult, context) => {\n    // I will fire first\n  },\n  onError: (error, variables, onMutateResult, context) => {\n    // I will fire first\n  },\n  onSettled: (data, error, variables, onMutateResult, context) => {\n    // I will fire first\n  },\n})\n\nmutate(todo, {\n  onSuccess: (data, variables, onMutateResult, context) => {\n    // I will fire second!\n  },\n  onError: (error, variables, onMutateResult, context) => {\n    // I will fire second!\n  },\n  onSettled: (data, error, variables, onMutateResult, context) => {\n    // I will fire second!\n  },\n})\n```\n\n[//]: # 'Example6'\n\n### Consecutive mutations\n\nThere is a slight difference in handling `onSuccess`, `onError` and `onSettled` callbacks when it comes to consecutive mutations. When passed to the `mutate` function, they will be fired up only _once_ and only if the component is still mounted. This is due to the fact that mutation observer is removed and resubscribed every time when the `mutate` function is called. On the contrary, `useMutation` handlers execute for each `mutate` call.\n\n> Be aware that most likely, `mutationFn` passed to `useMutation` is asynchronous. In that case, the order in which mutations are fulfilled may differ from the order of `mutate` function calls.\n\n[//]: # 'Example7'\n\n```tsx\nuseMutation({\n  mutationFn: addTodo,\n  onSuccess: (data, variables, onMutateResult, context) => {\n    // Will be called 3 times\n  },\n})\n\nconst todos = ['Todo 1', 'Todo 2', 'Todo 3']\ntodos.forEach((todo) => {\n  mutate(todo, {\n    onSuccess: (data, variables, onMutateResult, context) => {\n      // Will execute only once, for the last mutation (Todo 3),\n      // regardless which mutation resolves first\n    },\n  })\n})\n```\n\n[//]: # 'Example7'\n\n## Promises\n\nUse `mutateAsync` instead of `mutate` to get a promise which will resolve on success or throw on an error. This can for example be used to compose side effects.\n\n[//]: # 'Example8'\n\n```tsx\nconst mutation = useMutation({ mutationFn: addTodo })\n\ntry {\n  const todo = await mutation.mutateAsync(todo)\n  console.log(todo)\n} catch (error) {\n  console.error(error)\n} finally {\n  console.log('done')\n}\n```\n\n[//]: # 'Example8'\n\n## Retry\n\nBy default, TanStack Query will not retry a mutation on error, but it is possible with the `retry` option:\n\n[//]: # 'Example9'\n\n```tsx\nconst mutation = useMutation({\n  mutationFn: addTodo,\n  retry: 3,\n})\n```\n\n[//]: # 'Example9'\n\nIf mutations fail because the device is offline, they will be retried in the same order when the device reconnects.\n\n## Persist mutations\n\nMutations can be persisted to storage if needed and resumed at a later point. This can be done with the hydration functions:\n\n[//]: # 'Example10'\n\n```tsx\nconst queryClient = new QueryClient()\n\n// Define the \"addTodo\" mutation\nqueryClient.setMutationDefaults(['addTodo'], {\n  mutationFn: addTodo,\n  onMutate: async (variables, context) => {\n    // Cancel current queries for the todos list\n    await context.client.cancelQueries({ queryKey: ['todos'] })\n\n    // Create optimistic todo\n    const optimisticTodo = { id: uuid(), title: variables.title }\n\n    // Add optimistic todo to todos list\n    context.client.setQueryData(['todos'], (old) => [...old, optimisticTodo])\n\n    // Return a result with the optimistic todo\n    return { optimisticTodo }\n  },\n  onSuccess: (result, variables, onMutateResult, context) => {\n    // Replace optimistic todo in the todos list with the result\n    context.client.setQueryData(['todos'], (old) =>\n      old.map((todo) =>\n        todo.id === onMutateResult.optimisticTodo.id ? result : todo,\n      ),\n    )\n  },\n  onError: (error, variables, onMutateResult, context) => {\n    // Remove optimistic todo from the todos list\n    context.client.setQueryData(['todos'], (old) =>\n      old.filter((todo) => todo.id !== onMutateResult.optimisticTodo.id),\n    )\n  },\n  retry: 3,\n})\n\n// Start mutation in some component:\nconst mutation = useMutation({ mutationKey: ['addTodo'] })\nmutation.mutate({ title: 'title' })\n\n// If the mutation has been paused because the device is for example offline,\n// Then the paused mutation can be dehydrated when the application quits:\nconst state = dehydrate(queryClient)\n\n// The mutation can then be hydrated again when the application is started:\nhydrate(queryClient, state)\n\n// Resume the paused mutations:\nqueryClient.resumePausedMutations()\n```\n\n[//]: # 'Example10'\n[//]: # 'PersistOfflineIntro'\n\n### Persisting Offline mutations\n\nIf you persist offline mutations with the [persistQueryClient plugin](../plugins/persistQueryClient.md), mutations cannot be resumed when the page is reloaded unless you provide a default mutation function.\n\n[//]: # 'PersistOfflineIntro'\n\nThis is a technical limitation. When persisting to an external storage, only the state of mutations is persisted, as functions cannot be serialized. After hydration, the component that triggers the mutation might not be mounted, so calling `resumePausedMutations` might yield an error: `No mutationFn found`.\n\n[//]: # 'Example11'\n\n```tsx\nconst persister = createSyncStoragePersister({\n  storage: window.localStorage,\n})\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      gcTime: 1000 * 60 * 60 * 24, // 24 hours\n    },\n  },\n})\n\n// we need a default mutation function so that paused mutations can resume after a page reload\nqueryClient.setMutationDefaults(['todos'], {\n  mutationFn: ({ id, data }) => {\n    return api.updateTodo(id, data)\n  },\n})\n\nexport default function App() {\n  return (\n    <PersistQueryClientProvider\n      client={queryClient}\n      persistOptions={{ persister }}\n      onSuccess={() => {\n        // resume mutations after initial restore from localStorage was successful\n        queryClient.resumePausedMutations()\n      }}\n    >\n      <RestOfTheApp />\n    </PersistQueryClientProvider>\n  )\n}\n```\n\n[//]: # 'Example11'\n[//]: # 'OfflineExampleLink'\n\nWe also have an extensive [offline example](../examples/offline) that covers both queries and mutations.\n\n[//]: # 'OfflineExampleLink'\n\n## Mutation Scopes\n\nPer default, all mutations run in parallel - even if you invoke `.mutate()` of the same mutation multiple times. Mutations can be given a `scope` with an `id` to avoid that. All mutations with the same `scope.id` will run in serial, which means when they are triggered, they will start in `isPaused: true` state if there is already a mutation for that scope in progress. They will be put into a queue and will automatically resume once their time in the queue has come.\n\n[//]: # 'ExampleScopes'\n\n```tsx\nconst mutation = useMutation({\n  mutationFn: addTodo,\n  scope: {\n    id: 'todo',\n  },\n})\n```\n\n[//]: # 'ExampleScopes'\n[//]: # 'Materials'\n\n## Further reading\n\nFor more information about mutations, have a look at [TkDodo's article on Mastering Mutations in React Query](https://tkdodo.eu/blog/mastering-mutations-in-react-query).\n\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/react/guides/network-mode.md",
    "content": "---\nid: network-mode\ntitle: Network Mode\n---\n\nTanStack Query provides three different network modes to distinguish how [Queries](./queries.md) and [Mutations](./mutations.md) should behave if you have no network connection. This mode can be set for each Query / Mutation individually, or globally via the query / mutation defaults.\n\nSince TanStack Query is most often used for data fetching in combination with data fetching libraries, the default network mode is [online](#network-mode-online).\n\n## Network Mode: online\n\nIn this mode, Queries and Mutations will not fire unless you have network connection. This is the default mode. If a fetch is initiated for a query, it will always stay in the `state` (`pending`, `error`, `success`) it is in if the fetch cannot be made because there is no network connection. However, a [fetchStatus](./queries.md#fetchstatus) is exposed additionally. This can be either:\n\n- `fetching`: The `queryFn` is really executing - a request is in-flight.\n- `paused`: The query is not executing - it is `paused` until you have connection again\n- `idle`: The query is not fetching and not paused\n\nThe flags `isFetching` and `isPaused` are derived from this state and exposed for convenience.\n\n> Keep in mind that it might not be enough to check for `pending` state to show a loading spinner. Queries can be in `state: 'pending'`, but `fetchStatus: 'paused'` if they are mounting for the first time, and you have no network connection.\n\nIf a query runs because you are online, but you go offline while the fetch is still happening, TanStack Query will also pause the retry mechanism. Paused queries will then continue to run once you re-gain network connection. This is independent of `refetchOnReconnect` (which also defaults to `true` in this mode), because it is not a `refetch`, but rather a `continue`. If the query has been [cancelled](./query-cancellation.md) in the meantime, it will not continue.\n\n## Network Mode: always\n\nIn this mode, TanStack Query will always fetch and ignore the online / offline state. This is likely the mode you want to choose if you use TanStack Query in an environment where you don't need an active network connection for your Queries to work - e.g. if you just read from `AsyncStorage`, or if you just want to return `Promise.resolve(5)` from your `queryFn`.\n\n- Queries will never be `paused` because you have no network connection.\n- Retries will also not pause - your Query will go to `error` state if it fails.\n- `refetchOnReconnect` defaults to `false` in this mode, because reconnecting to the network is not a good indicator anymore that stale queries should be refetched. You can still turn it on if you want.\n\n## Network Mode: offlineFirst\n\nThis mode is the middle ground between the first two options, where TanStack Query will run the `queryFn` once, but then pause retries. This is very handy if you have a serviceWorker that intercepts a request for caching like in an [offline-first PWA](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Offline_Service_workers), or if you use HTTP caching via the [Cache-Control header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching#the_cache-control_header).\n\nIn those situations, the first fetch might succeed because it comes from an offline storage / cache. However, if there is a cache miss, the network request will go out and fail, in which case this mode behaves like an `online` query - pausing retries.\n\n## Devtools\n\nThe [TanStack Query Devtools](../devtools.md) will show Queries in a `paused` state if they would be fetching, but there is no network connection. There is also a toggle button to _Mock offline behavior_. Please note that this button will _not_ actually mess with your network connection (you can do that in the browser devtools), but it will set the [OnlineManager](../../../reference/onlineManager.md) in an offline state.\n\n## Signature\n\n- `networkMode: 'online' | 'always' | 'offlineFirst'`\n  - optional\n  - defaults to `'online'`\n"
  },
  {
    "path": "docs/framework/react/guides/optimistic-updates.md",
    "content": "---\nid: optimistic-updates\ntitle: Optimistic Updates\n---\n\nReact Query provides two ways to optimistically update your UI before a mutation has completed. You can either use the `onMutate` option to update your cache directly, or leverage the returned `variables` to update your UI from the `useMutation` result.\n\n## Via the UI\n\nThis is the simpler variant, as it doesn't interact with the cache directly.\n\n[//]: # 'ExampleUI1'\n\n```tsx\nconst addTodoMutation = useMutation({\n  mutationFn: (newTodo: string) => axios.post('/api/data', { text: newTodo }),\n  // make sure to _return_ the Promise from the query invalidation\n  // so that the mutation stays in `pending` state until the refetch is finished\n  onSettled: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),\n})\n\nconst { isPending, submittedAt, variables, mutate, isError } = addTodoMutation\n```\n\n[//]: # 'ExampleUI1'\n\nyou will then have access to `addTodoMutation.variables`, which contain the added todo. In your UI list, where the query is rendered, you can append another item to the list while the mutation `isPending`:\n\n[//]: # 'ExampleUI2'\n\n```tsx\n<ul>\n  {todoQuery.items.map((todo) => (\n    <li key={todo.id}>{todo.text}</li>\n  ))}\n  {isPending && <li style={{ opacity: 0.5 }}>{variables}</li>}\n</ul>\n```\n\n[//]: # 'ExampleUI2'\n\nWe're rendering a temporary item with a different `opacity` as long as the mutation is pending. Once it completes, the item will automatically no longer be rendered. Given that the refetch succeeded, we should see the item as a \"normal item\" in our list.\n\nIf the mutation errors, the item will also disappear. But we could continue to show it, if we want, by checking for the `isError` state of the mutation. `variables` are _not_ cleared when the mutation errors, so we can still access them, maybe even show a retry button:\n\n[//]: # 'ExampleUI3'\n\n```tsx\n{\n  isError && (\n    <li style={{ color: 'red' }}>\n      {variables}\n      <button onClick={() => mutate(variables)}>Retry</button>\n    </li>\n  )\n}\n```\n\n[//]: # 'ExampleUI3'\n\n### If the mutation and the query don't live in the same component\n\nThis approach works very well if the mutation and the query live in the same component. However, you also get access to all mutations in other components via the dedicated `useMutationState` hook. It is best combined with a `mutationKey`:\n\n[//]: # 'ExampleUI4'\n\n```tsx\n// somewhere in your app\nconst { mutate } = useMutation({\n  mutationFn: (newTodo: string) => axios.post('/api/data', { text: newTodo }),\n  onSettled: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),\n  mutationKey: ['addTodo'],\n})\n\n// access variables somewhere else\nconst variables = useMutationState<string>({\n  filters: { mutationKey: ['addTodo'], status: 'pending' },\n  select: (mutation) => mutation.state.variables,\n})\n```\n\n[//]: # 'ExampleUI4'\n\n`variables` will be an `Array`, because there might be multiple mutations running at the same time. If we need a unique key for the items, we can also select `mutation.state.submittedAt`. This will even make displaying concurrent optimistic updates a breeze.\n\n## Via the cache\n\nWhen you optimistically update your state before performing a mutation, there is a chance that the mutation will fail. In most of these failure cases, you can just trigger a refetch for your optimistic queries to revert them to their true server state. In some circumstances though, refetching may not work correctly and the mutation error could represent some type of server issue that won't make it possible to refetch. In this event, you can instead choose to roll back your update.\n\nTo do this, `useMutation`'s `onMutate` handler option allows you to return a value that will later be passed to both `onError` and `onSettled` handlers as the last argument. In most cases, it is most useful to pass a rollback function.\n\n### Updating a list of todos when adding a new todo\n\n[//]: # 'Example'\n\n```tsx\nconst queryClient = useQueryClient()\n\nuseMutation({\n  mutationFn: updateTodo,\n  // When mutate is called:\n  onMutate: async (newTodo, context) => {\n    // Cancel any outgoing refetches\n    // (so they don't overwrite our optimistic update)\n    await context.client.cancelQueries({ queryKey: ['todos'] })\n\n    // Snapshot the previous value\n    const previousTodos = context.client.getQueryData(['todos'])\n\n    // Optimistically update to the new value\n    context.client.setQueryData(['todos'], (old) => [...old, newTodo])\n\n    // Return a result with the snapshotted value\n    return { previousTodos }\n  },\n  // If the mutation fails,\n  // use the result returned from onMutate to roll back\n  onError: (err, newTodo, onMutateResult, context) => {\n    context.client.setQueryData(['todos'], onMutateResult.previousTodos)\n  },\n  // Always refetch after error or success:\n  onSettled: (data, error, variables, onMutateResult, context) =>\n    context.client.invalidateQueries({ queryKey: ['todos'] }),\n})\n```\n\n[//]: # 'Example'\n\n### Updating a single todo\n\n[//]: # 'Example2'\n\n```tsx\nuseMutation({\n  mutationFn: updateTodo,\n  // When mutate is called:\n  onMutate: async (newTodo, context) => {\n    // Cancel any outgoing refetches\n    // (so they don't overwrite our optimistic update)\n    await context.client.cancelQueries({ queryKey: ['todos', newTodo.id] })\n\n    // Snapshot the previous value\n    const previousTodo = context.client.getQueryData(['todos', newTodo.id])\n\n    // Optimistically update to the new value\n    context.client.setQueryData(['todos', newTodo.id], newTodo)\n\n    // Return a result with the previous and new todo\n    return { previousTodo, newTodo }\n  },\n  // If the mutation fails, use the result we returned above\n  onError: (err, newTodo, onMutateResult, context) => {\n    context.client.setQueryData(\n      ['todos', onMutateResult.newTodo.id],\n      onMutateResult.previousTodo,\n    )\n  },\n  // Always refetch after error or success:\n  onSettled: (newTodo, error, variables, onMutateResult, context) =>\n    context.client.invalidateQueries({ queryKey: ['todos', newTodo.id] }),\n})\n```\n\n[//]: # 'Example2'\n\nYou can also use the `onSettled` function in place of the separate `onError` and `onSuccess` handlers if you wish:\n\n[//]: # 'Example3'\n\n```tsx\nuseMutation({\n  mutationFn: updateTodo,\n  // ...\n  onSettled: async (newTodo, error, variables, onMutateResult, context) => {\n    if (error) {\n      // do something\n    }\n  },\n})\n```\n\n[//]: # 'Example3'\n\n## When to use what\n\nIf you only have one place where the optimistic result should be shown, using `variables` and updating the UI directly is the approach that requires less code and is generally easier to reason about. For example, you don't need to handle rollbacks at all.\n\nHowever, if you have multiple places on the screen that would require to know about the update, manipulating the cache directly will take care of this for you automatically.\n\n[//]: # 'Materials'\n\n## Further reading\n\nHave a look at the guide by TkDodo on [Concurrent Optimistic Updates](https://tkdodo.eu/blog/concurrent-optimistic-updates-in-react-query).\n\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/react/guides/paginated-queries.md",
    "content": "---\nid: paginated-queries\ntitle: Paginated / Lagged Queries\n---\n\nRendering paginated data is a very common UI pattern and in TanStack Query, it \"just works\" by including the page information in the query key:\n\n[//]: # 'Example'\n\n```tsx\nconst result = useQuery({\n  queryKey: ['projects', page],\n  queryFn: () => fetchProjects(page),\n})\n```\n\n[//]: # 'Example'\n\nHowever, if you run this simple example, you might notice something strange:\n\n**The UI jumps in and out of the `success` and `pending` states because each new page is treated like a brand new query.**\n\nThis experience is not optimal and unfortunately is how many tools today insist on working. But not TanStack Query! As you may have guessed, TanStack Query comes with an awesome feature called `placeholderData` that allows us to get around this.\n\n## Better Paginated Queries with `placeholderData`\n\nConsider the following example where we would ideally want to increment a pageIndex (or cursor) for a query. If we were to use `useQuery`, **it would still technically work fine**, but the UI would jump in and out of the `success` and `pending` states as different queries are created and destroyed for each page or cursor. By setting `placeholderData` to `(previousData) => previousData` or `keepPreviousData` function exported from TanStack Query, we get a few new things:\n\n- **The data from the last successful fetch is available while new data is being requested, even though the query key has changed**.\n- When the new data arrives, the previous `data` is seamlessly swapped to show the new data.\n- `isPlaceholderData` is made available to know what data the query is currently providing you\n\n[//]: # 'Example2'\n\n```tsx\nimport { keepPreviousData, useQuery } from '@tanstack/react-query'\nimport React from 'react'\n\nfunction Todos() {\n  const [page, setPage] = React.useState(0)\n\n  const fetchProjects = (page = 0) =>\n    fetch('/api/projects?page=' + page).then((res) => res.json())\n\n  const { isPending, isError, error, data, isFetching, isPlaceholderData } =\n    useQuery({\n      queryKey: ['projects', page],\n      queryFn: () => fetchProjects(page),\n      placeholderData: keepPreviousData,\n    })\n\n  return (\n    <div>\n      {isPending ? (\n        <div>Loading...</div>\n      ) : isError ? (\n        <div>Error: {error.message}</div>\n      ) : (\n        <div>\n          {data.projects.map((project) => (\n            <p key={project.id}>{project.name}</p>\n          ))}\n        </div>\n      )}\n      <span>Current Page: {page + 1}</span>\n      <button\n        onClick={() => setPage((old) => Math.max(old - 1, 0))}\n        disabled={page === 0}\n      >\n        Previous Page\n      </button>\n      <button\n        onClick={() => {\n          if (!isPlaceholderData && data.hasMore) {\n            setPage((old) => old + 1)\n          }\n        }}\n        // Disable the Next Page button until we know a next page is available\n        disabled={isPlaceholderData || !data?.hasMore}\n      >\n        Next Page\n      </button>\n      {isFetching ? <span> Loading...</span> : null}\n    </div>\n  )\n}\n```\n\n[//]: # 'Example2'\n\n## Lagging Infinite Query results with `placeholderData`\n\nWhile not as common, the `placeholderData` option also works flawlessly with the `useInfiniteQuery` hook, so you can seamlessly allow your users to continue to see cached data while infinite query keys change over time.\n"
  },
  {
    "path": "docs/framework/react/guides/parallel-queries.md",
    "content": "---\nid: parallel-queries\ntitle: Parallel Queries\n---\n\n\"Parallel\" queries are queries that are executed in parallel, or at the same time so as to maximize fetching concurrency.\n\n## Manual Parallel Queries\n\nWhen the number of parallel queries does not change, there is **no extra effort** to use parallel queries. Just use any number of TanStack Query's `useQuery` and `useInfiniteQuery` hooks side-by-side!\n\n[//]: # 'Example'\n\n```tsx\nfunction App () {\n  // The following queries will execute in parallel\n  const usersQuery = useQuery({ queryKey: ['users'], queryFn: fetchUsers })\n  const teamsQuery = useQuery({ queryKey: ['teams'], queryFn: fetchTeams })\n  const projectsQuery = useQuery({ queryKey: ['projects'], queryFn: fetchProjects })\n  ...\n}\n```\n\n[//]: # 'Example'\n[//]: # 'Info'\n\n> When using React Query in suspense mode, this pattern of parallelism does not work, since the first query would throw a promise internally and would suspend the component before the other queries run. To get around this, you'll either need to use the `useSuspenseQueries` hook (which is suggested) or orchestrate your own parallelism with separate components for each `useSuspenseQuery` instance.\n\n[//]: # 'Info'\n\n## Dynamic Parallel Queries with `useQueries`\n\n[//]: # 'DynamicParallelIntro'\n\nIf the number of queries you need to execute is changing from render to render, you cannot use manual querying since that would violate the rules of hooks. Instead, TanStack Query provides a `useQueries` hook, which you can use to dynamically execute as many queries in parallel as you'd like.\n\n[//]: # 'DynamicParallelIntro'\n[//]: # 'DynamicParallelDescription'\n\n`useQueries` accepts an **options object** with a **queries key** whose value is an **array of query objects**. It returns an **array of query results**:\n\n[//]: # 'DynamicParallelDescription'\n[//]: # 'Example2'\n\n```tsx\nfunction App({ users }) {\n  const userQueries = useQueries({\n    queries: users.map((user) => {\n      return {\n        queryKey: ['user', user.id],\n        queryFn: () => fetchUserById(user.id),\n      }\n    }),\n  })\n}\n```\n\n[//]: # 'Example2'\n"
  },
  {
    "path": "docs/framework/react/guides/placeholder-query-data.md",
    "content": "---\nid: placeholder-query-data\ntitle: Placeholder Query Data\n---\n\n## What is placeholder data?\n\nPlaceholder data allows a query to behave as if it already has data, similar to the `initialData` option, but **the data is not persisted to the cache**. This comes in handy for situations where you have enough partial (or fake) data to render the query successfully while the actual data is fetched in the background.\n\n> Example: An individual blog post query could pull \"preview\" data from a parent list of blog posts that only include title and a small snippet of the post body. You would not want to persist this partial data to the query result of the individual query, but it is useful for showing the content layout as quickly as possible while the actual query finishes to fetch the entire object.\n\nThere are a few ways to supply placeholder data for a query to the cache before you need it:\n\n- Declaratively:\n  - Provide `placeholderData` to a query to prepopulate its cache if empty\n- Imperatively:\n  - [Prefetch or fetch the data using `queryClient` and the `placeholderData` option](./prefetching.md)\n\nWhen we use `placeholderData`, our Query will not be in a `pending` state - it will start out as being in `success` state, because we have `data` to display - even if that data is just \"placeholder\" data. To distinguish it from \"real\" data, we will also have the `isPlaceholderData` flag set to `true` on the Query result.\n\n## Placeholder Data as a Value\n\n[//]: # 'ExampleValue'\n\n```tsx\nfunction Todos() {\n  const result = useQuery({\n    queryKey: ['todos'],\n    queryFn: () => fetch('/todos'),\n    placeholderData: placeholderTodos,\n  })\n}\n```\n\n[//]: # 'ExampleValue'\n[//]: # 'Memoization'\n\n### Placeholder Data Memoization\n\nIf the process for accessing a query's placeholder data is intensive or just not something you want to perform on every render, you can memoize the value:\n\n```tsx\nfunction Todos() {\n  const placeholderData = useMemo(() => generateFakeTodos(), [])\n  const result = useQuery({\n    queryKey: ['todos'],\n    queryFn: () => fetch('/todos'),\n    placeholderData,\n  })\n}\n```\n\n[//]: # 'Memoization'\n\n## Placeholder Data as a Function\n\n`placeholderData` can also be a function, where you can get access to the data and Query meta information of a \"previous\" successful Query. This is useful for situations where you want to use the data from one query as the placeholder data for another query. When the QueryKey changes, e.g. from `['todos', 1]` to `['todos', 2]`, we can keep displaying \"old\" data instead of having to show a loading spinner while data is _transitioning_ from one Query to the next. For more information, see [Paginated Queries](./paginated-queries.md).\n\n[//]: # 'ExampleFunction'\n\n```tsx\nconst result = useQuery({\n  queryKey: ['todos', id],\n  queryFn: () => fetch(`/todos/${id}`),\n  placeholderData: (previousData, previousQuery) => previousData,\n})\n```\n\n[//]: # 'ExampleFunction'\n\n### Placeholder Data from Cache\n\nIn some circumstances, you may be able to provide the placeholder data for a query from the cached result of another. A good example of this would be searching the cached data from a blog post list query for a preview version of the post, then using that as the placeholder data for your individual post query:\n\n[//]: # 'ExampleCache'\n\n```tsx\nfunction BlogPost({ blogPostId }) {\n  const queryClient = useQueryClient()\n  const result = useQuery({\n    queryKey: ['blogPost', blogPostId],\n    queryFn: () => fetch(`/blogPosts/${blogPostId}`),\n    placeholderData: () => {\n      // Use the smaller/preview version of the blogPost from the 'blogPosts'\n      // query as the placeholder data for this blogPost query\n      return queryClient\n        .getQueryData(['blogPosts'])\n        ?.find((d) => d.id === blogPostId)\n    },\n  })\n}\n```\n\n[//]: # 'ExampleCache'\n[//]: # 'Materials'\n\n## Further reading\n\nFor a comparison between `Placeholder Data` and `Initial Data`, see the [article by TkDodo](https://tkdodo.eu/blog/placeholder-and-initial-data-in-react-query).\n\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/react/guides/prefetching.md",
    "content": "---\nid: prefetching\ntitle: Prefetching & Router Integration\n---\n\nWhen you know or suspect that a certain piece of data will be needed, you can use prefetching to populate the cache with that data ahead of time, leading to a faster experience.\n\nThere are a few different prefetching patterns:\n\n1. In event handlers\n2. In components\n3. Via router integration\n4. During Server Rendering (another form of router integration)\n\nIn this guide, we'll take a look at the first three, while the fourth will be covered in depth in the [Server Rendering & Hydration guide](./ssr.md) and the [Advanced Server Rendering guide](./advanced-ssr.md).\n\nOne specific use of prefetching is to avoid Request Waterfalls, for an in-depth background and explanation of those, see the [Performance & Request Waterfalls guide](./request-waterfalls.md).\n\n## prefetchQuery & prefetchInfiniteQuery\n\nBefore jumping into the different specific prefetch patterns, let's look at the `prefetchQuery` and `prefetchInfiniteQuery` functions. First a few basics:\n\n- Out of the box, these functions use the default `staleTime` configured for the `queryClient` to determine whether existing data in the cache is fresh or needs to be fetched again\n- You can also pass a specific `staleTime` like this: `prefetchQuery({ queryKey: ['todos'], queryFn: fn, staleTime: 5000 })`\n  - This `staleTime` is only used for the prefetch, you still need to set it for any `useQuery` call as well\n  - If you want to ignore `staleTime` and instead always return data if it's available in the cache, you can use the `ensureQueryData` function.\n  - Tip: If you are prefetching on the server, set a default `staleTime` higher than `0` for that `queryClient` to avoid having to pass in a specific `staleTime` to each prefetch call\n- If no instances of `useQuery` appear for a prefetched query, it will be deleted and garbage collected after the time specified in `gcTime`\n- These functions return `Promise<void>` and thus never return query data. If that's something you need, use `fetchQuery`/`fetchInfiniteQuery` instead.\n- The prefetch functions never throw errors because they usually try to fetch again in a `useQuery` which is a nice graceful fallback. If you need to catch errors, use `fetchQuery`/`fetchInfiniteQuery` instead.\n\nThis is how you use `prefetchQuery`:\n\n[//]: # 'ExamplePrefetchQuery'\n\n```tsx\nconst prefetchTodos = async () => {\n  // The results of this query will be cached like a normal query\n  await queryClient.prefetchQuery({\n    queryKey: ['todos'],\n    queryFn: fetchTodos,\n  })\n}\n```\n\n[//]: # 'ExamplePrefetchQuery'\n\nInfinite Queries can be prefetched like regular Queries. Per default, only the first page of the Query will be prefetched and will be stored under the given QueryKey. If you want to prefetch more than one page, you can use the `pages` option, in which case you also have to provide a `getNextPageParam` function:\n\n[//]: # 'ExamplePrefetchInfiniteQuery'\n\n```tsx\nconst prefetchProjects = async () => {\n  // The results of this query will be cached like a normal query\n  await queryClient.prefetchInfiniteQuery({\n    queryKey: ['projects'],\n    queryFn: fetchProjects,\n    initialPageParam: 0,\n    getNextPageParam: (lastPage, pages) => lastPage.nextCursor,\n    pages: 3, // prefetch the first 3 pages\n  })\n}\n```\n\n[//]: # 'ExamplePrefetchInfiniteQuery'\n\nNext, let's look at how you can use these and other ways to prefetch in different situations.\n\n## Prefetch in event handlers\n\nA straightforward form of prefetching is doing it when the user interacts with something. In this example we'll use `queryClient.prefetchQuery` to start a prefetch on `onMouseEnter` or `onFocus`.\n\n[//]: # 'ExampleEventHandler'\n\n```tsx\nfunction ShowDetailsButton() {\n  const queryClient = useQueryClient()\n\n  const prefetch = () => {\n    queryClient.prefetchQuery({\n      queryKey: ['details'],\n      queryFn: getDetailsData,\n      // Prefetch only fires when data is older than the staleTime,\n      // so in a case like this you definitely want to set one\n      staleTime: 60000,\n    })\n  }\n\n  return (\n    <button onMouseEnter={prefetch} onFocus={prefetch} onClick={...}>\n      Show Details\n    </button>\n  )\n}\n```\n\n[//]: # 'ExampleEventHandler'\n\n## Prefetch in components\n\nPrefetching during the component lifecycle is useful when we know some child or descendant will need a particular piece of data, but we can't render that until some other query has finished loading. Let's borrow an example from the Request Waterfall guide to explain:\n\n[//]: # 'ExampleComponent'\n\n```tsx\nfunction Article({ id }) {\n  const { data: articleData, isPending } = useQuery({\n    queryKey: ['article', id],\n    queryFn: getArticleById,\n  })\n\n  if (isPending) {\n    return 'Loading article...'\n  }\n\n  return (\n    <>\n      <ArticleHeader articleData={articleData} />\n      <ArticleBody articleData={articleData} />\n      <Comments id={id} />\n    </>\n  )\n}\n\nfunction Comments({ id }) {\n  const { data, isPending } = useQuery({\n    queryKey: ['article-comments', id],\n    queryFn: getArticleCommentsById,\n  })\n\n  ...\n}\n```\n\n[//]: # 'ExampleComponent'\n\nThis results in a request waterfall looking like this:\n\n```\n1. |> getArticleById()\n2.   |> getArticleCommentsById()\n```\n\nAs mentioned in that guide, one way to flatten this waterfall and improve performance is to hoist the `getArticleCommentsById` query to the parent and pass down the result as a prop, but what if this is not feasible or desirable, for example when the components are unrelated and have multiple levels between them?\n\nIn that case, we can instead prefetch the query in the parent. The simplest way to do this is to use a query but ignore the result:\n\n[//]: # 'ExampleParentComponent'\n\n```tsx\nfunction Article({ id }) {\n  const { data: articleData, isPending } = useQuery({\n    queryKey: ['article', id],\n    queryFn: getArticleById,\n  })\n\n  // Prefetch\n  useQuery({\n    queryKey: ['article-comments', id],\n    queryFn: getArticleCommentsById,\n    // Optional optimization to avoid rerenders when this query changes:\n    notifyOnChangeProps: [],\n  })\n\n  if (isPending) {\n    return 'Loading article...'\n  }\n\n  return (\n    <>\n      <ArticleHeader articleData={articleData} />\n      <ArticleBody articleData={articleData} />\n      <Comments id={id} />\n    </>\n  )\n}\n\nfunction Comments({ id }) {\n  const { data, isPending } = useQuery({\n    queryKey: ['article-comments', id],\n    queryFn: getArticleCommentsById,\n  })\n\n  ...\n}\n```\n\n[//]: # 'ExampleParentComponent'\n\nThis starts fetching `'article-comments'` immediately and flattens the waterfall:\n\n```\n1. |> getArticleById()\n1. |> getArticleCommentsById()\n```\n\n[//]: # 'Suspense'\n\nIf you want to prefetch together with Suspense, you will have to do things a bit differently. You can't use `useSuspenseQueries` to prefetch, since the prefetch would block the component from rendering. You also can not use `useQuery` for the prefetch, because that wouldn't start the prefetch until after suspenseful query had resolved. For this scenario, you can use the [`usePrefetchQuery`](../reference/usePrefetchQuery.md) or the [`usePrefetchInfiniteQuery`](../reference/usePrefetchInfiniteQuery.md) hooks available in the library.\n\nYou can now use `useSuspenseQuery` in the component that actually needs the data. You _might_ want to wrap this later component in its own `<Suspense>` boundary so the \"secondary\" query we are prefetching does not block rendering of the \"primary\" data.\n\n```tsx\nfunction ArticleLayout({ id }) {\n  usePrefetchQuery({\n    queryKey: ['article-comments', id],\n    queryFn: getArticleCommentsById,\n  })\n\n  return (\n    <Suspense fallback=\"Loading article\">\n      <Article id={id} />\n    </Suspense>\n  )\n}\n\nfunction Article({ id }) {\n  const { data: articleData, isPending } = useSuspenseQuery({\n    queryKey: ['article', id],\n    queryFn: getArticleById,\n  })\n\n  ...\n}\n```\n\nAnother way is to prefetch inside of the query function. This makes sense if you know that every time an article is fetched it's very likely comments will also be needed. For this, we'll use `queryClient.prefetchQuery`:\n\n```tsx\nconst queryClient = useQueryClient()\nconst { data: articleData, isPending } = useQuery({\n  queryKey: ['article', id],\n  queryFn: (...args) => {\n    queryClient.prefetchQuery({\n      queryKey: ['article-comments', id],\n      queryFn: getArticleCommentsById,\n    })\n\n    return getArticleById(...args)\n  },\n})\n```\n\nPrefetching in an effect also works, but note that if you are using `useSuspenseQuery` in the same component, this effect wont run until _after_ the query finishes which might not be what you want.\n\n```tsx\nconst queryClient = useQueryClient()\n\nuseEffect(() => {\n  queryClient.prefetchQuery({\n    queryKey: ['article-comments', id],\n    queryFn: getArticleCommentsById,\n  })\n}, [queryClient, id])\n```\n\nTo recap, if you want to prefetch a query during the component lifecycle, there are a few different ways to do it, pick the one that suits your situation best:\n\n- Prefetch before a suspense boundary using `usePrefetchQuery` or `usePrefetchInfiniteQuery` hooks\n- Use `useQuery` or `useSuspenseQueries` and ignore the result\n- Prefetch inside the query function\n- Prefetch in an effect\n\nLet's look at a slightly more advanced case next.\n\n[//]: # 'Suspense'\n\n### Dependent Queries & Code Splitting\n\nSometimes we want to prefetch conditionally, based on the result of another fetch. Consider this example borrowed from the [Performance & Request Waterfalls guide](./request-waterfalls.md):\n\n[//]: # 'ExampleConditionally1'\n\n```tsx\n// This lazy loads the GraphFeedItem component, meaning\n// it wont start loading until something renders it\nconst GraphFeedItem = React.lazy(() => import('./GraphFeedItem'))\n\nfunction Feed() {\n  const { data, isPending } = useQuery({\n    queryKey: ['feed'],\n    queryFn: getFeed,\n  })\n\n  if (isPending) {\n    return 'Loading feed...'\n  }\n\n  return (\n    <>\n      {data.map((feedItem) => {\n        if (feedItem.type === 'GRAPH') {\n          return <GraphFeedItem key={feedItem.id} feedItem={feedItem} />\n        }\n\n        return <StandardFeedItem key={feedItem.id} feedItem={feedItem} />\n      })}\n    </>\n  )\n}\n\n// GraphFeedItem.tsx\nfunction GraphFeedItem({ feedItem }) {\n  const { data, isPending } = useQuery({\n    queryKey: ['graph', feedItem.id],\n    queryFn: getGraphDataById,\n  })\n\n  ...\n}\n```\n\n[//]: # 'ExampleConditionally1'\n\nAs noted over in that guide, this example leads to the following double request waterfall:\n\n```\n1. |> getFeed()\n2.   |> JS for <GraphFeedItem>\n3.     |> getGraphDataById()\n```\n\nIf we can not restructure our API so `getFeed()` also returns the `getGraphDataById()` data when necessary, there is no way to get rid of the `getFeed->getGraphDataById` waterfall, but by leveraging conditional prefetching, we can at least load the code and data in parallel. Just like described above, there are multiple ways to do this, but for this example, we'll do it in the query function:\n\n[//]: # 'ExampleConditionally2'\n\n```tsx\nfunction Feed() {\n  const queryClient = useQueryClient()\n  const { data, isPending } = useQuery({\n    queryKey: ['feed'],\n    queryFn: async (...args) => {\n      const feed = await getFeed(...args)\n\n      for (const feedItem of feed) {\n        if (feedItem.type === 'GRAPH') {\n          queryClient.prefetchQuery({\n            queryKey: ['graph', feedItem.id],\n            queryFn: getGraphDataById,\n          })\n        }\n      }\n\n      return feed\n    }\n  })\n\n  ...\n}\n```\n\n[//]: # 'ExampleConditionally2'\n\nThis would load the code and data in parallel:\n\n```\n1. |> getFeed()\n2.   |> JS for <GraphFeedItem>\n2.   |> getGraphDataById()\n```\n\nThere is a tradeoff however, in that the code for `getGraphDataById` is now included in the parent bundle instead of in `JS for <GraphFeedItem>` so you'll need to determine what's the best performance tradeoff on a case by case basis. If `GraphFeedItem` are likely, it's probably worth to include the code in the parent. If they are exceedingly rare, it's probably not.\n\n[//]: # 'Router'\n\n## Router Integration\n\nBecause data fetching in the component tree itself can easily lead to request waterfalls and the different fixes for that can be cumbersome as they accumulate throughout the application, an attractive way to do prefetching is integrating it at the router level.\n\nIn this approach, you explicitly declare for each _route_ what data is going to be needed for that component tree, ahead of time. Because Server Rendering has traditionally needed all data to be loaded before rendering starts, this has been the dominating approach for SSR'd apps for a long time. This is still a common approach and you can read more about it in the [Server Rendering & Hydration guide](./ssr.md).\n\nFor now, let's focus on the client side case and look at an example of how you can make this work with [TanStack Router](https://tanstack.com/router). These examples leave out a lot of setup and boilerplate to stay concise, you can check out a [full React Query example](https://tanstack.com/router/latest/docs/framework/react/examples/basic-react-query-file-based) over in the [TanStack Router docs](https://tanstack.com/router/latest/docs).\n\nWhen integrating at the router level, you can choose to either _block_ rendering of that route until all data is present, or you can start a prefetch but not await the result. That way, you can start rendering the route as soon as possible. You can also mix these two approaches and await some critical data, but start rendering before all the secondary data has finished loading. In this example, we'll configure an `/article` route to not render until the article data has finished loading, as well as start prefetching comments as soon as possible, but not block rendering the route if comments haven't finished loading yet.\n\n```tsx\nconst queryClient = new QueryClient()\nconst routerContext = new RouterContext()\nconst rootRoute = routerContext.createRootRoute({\n  component: () => { ... }\n})\n\nconst articleRoute = new Route({\n  getParentRoute: () => rootRoute,\n  path: 'article',\n  beforeLoad: () => {\n    return {\n      articleQueryOptions: { queryKey: ['article'], queryFn: fetchArticle },\n      commentsQueryOptions: { queryKey: ['comments'], queryFn: fetchComments },\n    }\n  },\n  loader: async ({\n    context: { queryClient },\n    routeContext: { articleQueryOptions, commentsQueryOptions },\n  }) => {\n    // Fetch comments asap, but don't block\n    queryClient.prefetchQuery(commentsQueryOptions)\n\n    // Don't render the route at all until article has been fetched\n    await queryClient.prefetchQuery(articleQueryOptions)\n  },\n  component: ({ useRouteContext }) => {\n    const { articleQueryOptions, commentsQueryOptions } = useRouteContext()\n    const articleQuery = useQuery(articleQueryOptions)\n    const commentsQuery = useQuery(commentsQueryOptions)\n\n    return (\n      ...\n    )\n  },\n  errorComponent: () => 'Oh crap!',\n})\n```\n\nIntegration with other routers is also possible, see the [react-router](../examples/react-router) for another demonstration.\n\n[//]: # 'Router'\n\n## Manually Priming a Query\n\nIf you already have the data for your query synchronously available, you don't need to prefetch it. You can just use the [Query Client's `setQueryData` method](../../../reference/QueryClient.md#queryclientsetquerydata) to directly add or update a query's cached result by key.\n\n[//]: # 'ExampleManualPriming'\n\n```tsx\nqueryClient.setQueryData(['todos'], todos)\n```\n\n[//]: # 'ExampleManualPriming'\n[//]: # 'Materials'\n\n## Further reading\n\nFor a deep-dive on how to get data into your Query Cache before you fetch, see the [article Seeding the Query Cache by TkDodo](https://tkdodo.eu/blog/seeding-the-query-cache).\n\nIntegrating with Server Side routers and frameworks is very similar to what we just saw, with the addition that the data has to be passed from the server to the client to be hydrated into the cache there. To learn how, continue on to the [Server Rendering & Hydration guide](./ssr.md).\n\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/react/guides/queries.md",
    "content": "---\nid: queries\ntitle: Queries\n---\n\n## Query Basics\n\nA query is a declarative dependency on an asynchronous source of data that is tied to a **unique key**. A query can be used with any Promise based method (including GET and POST methods) to fetch data from a server. If your method modifies data on the server, we recommend using [Mutations](./mutations.md) instead.\n\n[//]: # 'SubscribeDescription'\n\nTo subscribe to a query in your components or custom hooks, call the `useQuery` hook with at least:\n\n[//]: # 'SubscribeDescription'\n\n- A **unique key for the query**\n- A function that returns a promise that:\n  - Resolves the data, or\n  - Throws an error\n\n[//]: # 'Example'\n\n```tsx\nimport { useQuery } from '@tanstack/react-query'\n\nfunction App() {\n  const info = useQuery({ queryKey: ['todos'], queryFn: fetchTodoList })\n}\n```\n\n[//]: # 'Example'\n\nThe **unique key** you provide is used internally for refetching, caching, and sharing your queries throughout your application.\n\nThe query result returned by `useQuery` contains all of the information about the query that you'll need for templating and any other usage of the data:\n\n[//]: # 'Example2'\n\n```tsx\nconst result = useQuery({ queryKey: ['todos'], queryFn: fetchTodoList })\n```\n\n[//]: # 'Example2'\n\nThe `result` object contains a few very important states you'll need to be aware of to be productive. A query can only be in one of the following states at any given moment:\n\n- `isPending` or `status === 'pending'` - The query has no data yet\n- `isError` or `status === 'error'` - The query encountered an error\n- `isSuccess` or `status === 'success'` - The query was successful and data is available\n\nBeyond those primary states, more information is available depending on the state of the query:\n\n- `error` - If the query is in an `isError` state, the error is available via the `error` property.\n- `data` - If the query is in an `isSuccess` state, the data is available via the `data` property.\n- `isFetching` - In any state, if the query is fetching at any time (including background refetching) `isFetching` will be `true`.\n\nFor **most** queries, it's usually sufficient to check for the `isPending` state, then the `isError` state, then finally, assume that the data is available and render the successful state:\n\n[//]: # 'Example3'\n\n```tsx\nfunction Todos() {\n  const { isPending, isError, data, error } = useQuery({\n    queryKey: ['todos'],\n    queryFn: fetchTodoList,\n  })\n\n  if (isPending) {\n    return <span>Loading...</span>\n  }\n\n  if (isError) {\n    return <span>Error: {error.message}</span>\n  }\n\n  // We can assume by this point that `isSuccess === true`\n  return (\n    <ul>\n      {data.map((todo) => (\n        <li key={todo.id}>{todo.title}</li>\n      ))}\n    </ul>\n  )\n}\n```\n\n[//]: # 'Example3'\n\nIf booleans aren't your thing, you can always use the `status` state as well:\n\n[//]: # 'Example4'\n\n```tsx\nfunction Todos() {\n  const { status, data, error } = useQuery({\n    queryKey: ['todos'],\n    queryFn: fetchTodoList,\n  })\n\n  if (status === 'pending') {\n    return <span>Loading...</span>\n  }\n\n  if (status === 'error') {\n    return <span>Error: {error.message}</span>\n  }\n\n  // also status === 'success', but \"else\" logic works, too\n  return (\n    <ul>\n      {data.map((todo) => (\n        <li key={todo.id}>{todo.title}</li>\n      ))}\n    </ul>\n  )\n}\n```\n\n[//]: # 'Example4'\n\nTypeScript will also narrow the type of `data` correctly if you've checked for `pending` and `error` before accessing it.\n\n### FetchStatus\n\nIn addition to the `status` field, you will also get an additional `fetchStatus` property with the following options:\n\n- `fetchStatus === 'fetching'` - The query is currently fetching.\n- `fetchStatus === 'paused'` - The query wanted to fetch, but it is paused. Read more about this in the [Network Mode](./network-mode.md) guide.\n- `fetchStatus === 'idle'` - The query is not doing anything at the moment.\n\n### Why two different states?\n\nBackground refetches and stale-while-revalidate logic make all combinations for `status` and `fetchStatus` possible. For example:\n\n- a query in `success` status will usually be in `idle` fetchStatus, but it could also be in `fetching` if a background refetch is happening.\n- a query that mounts and has no data will usually be in `pending` status and `fetching` fetchStatus, but it could also be `paused` if there is no network connection.\n\nSo keep in mind that a query can be in `pending` state without actually fetching data. As a rule of thumb:\n\n- The `status` gives information about the `data`: Do we have any or not?\n- The `fetchStatus` gives information about the `queryFn`: Is it running or not?\n\n[//]: # 'Materials'\n\n## Further Reading\n\nFor an alternative way of performing status checks, have a look at [this article by TkDodo](https://tkdodo.eu/blog/status-checks-in-react-query).\n\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/react/guides/query-cancellation.md",
    "content": "---\nid: query-cancellation\ntitle: Query Cancellation\n---\n\nTanStack Query provides each query function with an [`AbortSignal` instance](https://developer.mozilla.org/docs/Web/API/AbortSignal). When a query becomes out-of-date or inactive, this `signal` will become aborted. This means that all queries are cancellable, and you can respond to the cancellation inside your query function if desired. The best part about this is that it allows you to continue to use normal async/await syntax while getting all the benefits of automatic cancellation.\n\nThe `AbortController` API is available in [most runtime environments](https://developer.mozilla.org/docs/Web/API/AbortController#browser_compatibility), but if your runtime environment does not support it, you will need to provide a polyfill. There are [several available](https://www.npmjs.com/search?q=abortcontroller%20polyfill).\n\n## Default behavior\n\nBy default, queries that unmount or become unused before their promises are resolved are _not_ cancelled. This means that after the promise has resolved, the resulting data will be available in the cache. This is helpful if you've started receiving a query, but then unmount the component before it finishes. If you mount the component again and the query has not been garbage collected yet, data will be available.\n\nHowever, if you consume the `AbortSignal`, the Promise will be cancelled (e.g. aborting the fetch) and therefore, also the Query must be cancelled. Cancelling the query will result in its state being _reverted_ to its previous state.\n\n## Using `fetch`\n\n[//]: # 'Example'\n\n```tsx\nconst query = useQuery({\n  queryKey: ['todos'],\n  queryFn: async ({ signal }) => {\n    const todosResponse = await fetch('/todos', {\n      // Pass the signal to one fetch\n      signal,\n    })\n    const todos = await todosResponse.json()\n\n    const todoDetails = todos.map(async ({ details }) => {\n      const response = await fetch(details, {\n        // Or pass it to several\n        signal,\n      })\n      return response.json()\n    })\n\n    return Promise.all(todoDetails)\n  },\n})\n```\n\n[//]: # 'Example'\n\n## Using `axios` [v0.22.0+](https://github.com/axios/axios/releases/tag/v0.22.0)\n\n[//]: # 'Example2'\n\n```tsx\nimport axios from 'axios'\n\nconst query = useQuery({\n  queryKey: ['todos'],\n  queryFn: ({ signal }) =>\n    axios.get('/todos', {\n      // Pass the signal to `axios`\n      signal,\n    }),\n})\n```\n\n[//]: # 'Example2'\n\n### Using `axios` with version lower than v0.22.0\n\n[//]: # 'Example3'\n\n```tsx\nimport axios from 'axios'\n\nconst query = useQuery({\n  queryKey: ['todos'],\n  queryFn: ({ signal }) => {\n    // Create a new CancelToken source for this request\n    const CancelToken = axios.CancelToken\n    const source = CancelToken.source()\n\n    const promise = axios.get('/todos', {\n      // Pass the source token to your request\n      cancelToken: source.token,\n    })\n\n    // Cancel the request if TanStack Query signals to abort\n    signal?.addEventListener('abort', () => {\n      source.cancel('Query was cancelled by TanStack Query')\n    })\n\n    return promise\n  },\n})\n```\n\n[//]: # 'Example3'\n\n## Using `XMLHttpRequest`\n\n[//]: # 'Example4'\n\n```tsx\nconst query = useQuery({\n  queryKey: ['todos'],\n  queryFn: ({ signal }) => {\n    return new Promise((resolve, reject) => {\n      var oReq = new XMLHttpRequest()\n      oReq.addEventListener('load', () => {\n        resolve(JSON.parse(oReq.responseText))\n      })\n      signal?.addEventListener('abort', () => {\n        oReq.abort()\n        reject()\n      })\n      oReq.open('GET', '/todos')\n      oReq.send()\n    })\n  },\n})\n```\n\n[//]: # 'Example4'\n\n## Using `graphql-request`\n\nAn `AbortSignal` can be set in the client `request` method.\n\n[//]: # 'Example5'\n\n```tsx\nconst client = new GraphQLClient(endpoint)\n\nconst query = useQuery({\n  queryKey: ['todos'],\n  queryFn: ({ signal }) => {\n    client.request({ document: query, signal })\n  },\n})\n```\n\n[//]: # 'Example5'\n\n## Using `graphql-request` with version lower than v4.0.0\n\nAn `AbortSignal` can be set in the `GraphQLClient` constructor.\n\n[//]: # 'Example6'\n\n```tsx\nconst query = useQuery({\n  queryKey: ['todos'],\n  queryFn: ({ signal }) => {\n    const client = new GraphQLClient(endpoint, {\n      signal,\n    })\n    return client.request(query, variables)\n  },\n})\n```\n\n[//]: # 'Example6'\n\n## Manual Cancellation\n\nYou might want to cancel a query manually. For example, if the request takes a long time to finish, you can allow the user to click a cancel button to stop the request. To do this, you just need to call `queryClient.cancelQueries({ queryKey })`, which will cancel the query and revert it back to its previous state. If you have consumed the `signal` passed to the query function, TanStack Query will additionally also cancel the Promise.\n\n[//]: # 'Example7'\n\n```tsx\nconst query = useQuery({\n  queryKey: ['todos'],\n  queryFn: async ({ signal }) => {\n    const resp = await fetch('/todos', { signal })\n    return resp.json()\n  },\n})\n\nconst queryClient = useQueryClient()\n\nreturn (\n  <button\n    onClick={(e) => {\n      e.preventDefault()\n      queryClient.cancelQueries({ queryKey: ['todos'] })\n    }}\n  >\n    Cancel\n  </button>\n)\n```\n\n[//]: # 'Example7'\n\n## `Cancel Options`\n\nCancel options are used to control the behavior of query cancellation operations.\n\n```tsx\n// Cancel specific queries silently\nawait queryClient.cancelQueries({ queryKey: ['posts'] }, { silent: true })\n```\n\nA cancel options object supports the following properties:\n\n- `silent?: boolean`\n  - When set to `true`, suppresses propagation of `CancelledError` to observers (e.g., `onError` callbacks) and related notifications, and returns the retry promise instead of rejecting.\n  - Defaults to `false`\n- `revert?: boolean`\n  - When set to `true`, restores the query’s state (data and status) from immediately before the in-flight fetch, sets `fetchStatus` back to `idle`, and only throws if there was no prior data.\n  - Defaults to `true`\n\n## Limitations\n\n[//]: # 'Limitations'\n\nCancellation does not work when working with `Suspense` hooks: `useSuspenseQuery`, `useSuspenseQueries` and `useSuspenseInfiniteQuery`.\n\n[//]: # 'Limitations'\n"
  },
  {
    "path": "docs/framework/react/guides/query-functions.md",
    "content": "---\nid: query-functions\ntitle: Query Functions\n---\n\nA query function can be literally any function that **returns a promise**. The promise that is returned should either **resolve the data** or **throw an error**.\n\nAll of the following are valid query function configurations:\n\n[//]: # 'Example'\n\n```tsx\nuseQuery({ queryKey: ['todos'], queryFn: fetchAllTodos })\nuseQuery({ queryKey: ['todos', todoId], queryFn: () => fetchTodoById(todoId) })\nuseQuery({\n  queryKey: ['todos', todoId],\n  queryFn: async () => {\n    const data = await fetchTodoById(todoId)\n    return data\n  },\n})\nuseQuery({\n  queryKey: ['todos', todoId],\n  queryFn: ({ queryKey }) => fetchTodoById(queryKey[1]),\n})\n```\n\n[//]: # 'Example'\n\n## Handling and Throwing Errors\n\nFor TanStack Query to determine a query has errored, the query function **must throw** or return a **rejected Promise**. Any error that is thrown in the query function will be persisted on the `error` state of the query.\n\n[//]: # 'Example2'\n\n```tsx\nconst { error } = useQuery({\n  queryKey: ['todos', todoId],\n  queryFn: async () => {\n    if (somethingGoesWrong) {\n      throw new Error('Oh no!')\n    }\n    if (somethingElseGoesWrong) {\n      return Promise.reject(new Error('Oh no!'))\n    }\n\n    return data\n  },\n})\n```\n\n[//]: # 'Example2'\n\n## Usage with `fetch` and other clients that do not throw by default\n\nWhile most utilities like `axios` or `graphql-request` automatically throw errors for unsuccessful HTTP calls, some utilities like `fetch` do not throw errors by default. If that's the case, you'll need to throw them on your own. Here is a simple way to do that with the popular `fetch` API:\n\n[//]: # 'Example3'\n\n```tsx\nuseQuery({\n  queryKey: ['todos', todoId],\n  queryFn: async () => {\n    const response = await fetch('/todos/' + todoId)\n    if (!response.ok) {\n      throw new Error('Network response was not ok')\n    }\n    return response.json()\n  },\n})\n```\n\n[//]: # 'Example3'\n\n## Query Function Variables\n\nQuery keys are not just for uniquely identifying the data you are fetching, but are also conveniently passed into your query function as part of the QueryFunctionContext. While not always necessary, this makes it possible to extract your query functions if needed:\n\n[//]: # 'Example4'\n\n```tsx\nfunction Todos({ status, page }) {\n  const result = useQuery({\n    queryKey: ['todos', { status, page }],\n    queryFn: fetchTodoList,\n  })\n}\n\n// Access the key, status and page variables in your query function!\nfunction fetchTodoList({ queryKey }) {\n  const [_key, { status, page }] = queryKey\n  return new Promise()\n}\n```\n\n[//]: # 'Example4'\n\n### QueryFunctionContext\n\nThe `QueryFunctionContext` is the object passed to each query function. It consists of:\n\n- `queryKey: QueryKey`: [Query Keys](./query-keys.md)\n- `client: QueryClient`: [QueryClient](../../../reference/QueryClient.md)\n- `signal?: AbortSignal`\n  - [AbortSignal](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) instance provided by TanStack Query\n  - Can be used for [Query Cancellation](./query-cancellation.md)\n- `meta: Record<string, unknown> | undefined`\n  - an optional field you can fill with additional information about your query\n\nAdditionally, [Infinite Queries](./infinite-queries.md) get the following options passed:\n\n- `pageParam: TPageParam`\n  - the page parameter used to fetch the current page\n- `direction: 'forward' | 'backward'`\n  - **deprecated**\n  - the direction of the current page fetch\n  - To get access to the direction of the current page fetch, please add a direction to `pageParam` from `getNextPageParam` and `getPreviousPageParam`.\n"
  },
  {
    "path": "docs/framework/react/guides/query-invalidation.md",
    "content": "---\nid: query-invalidation\ntitle: Query Invalidation\n---\n\nWaiting for queries to become stale before they are fetched again doesn't always work, especially when you know for a fact that a query's data is out of date because of something the user has done. For that purpose, the `QueryClient` has an `invalidateQueries` method that lets you intelligently mark queries as stale and potentially refetch them too!\n\n[//]: # 'Example'\n\n```tsx\n// Invalidate every query in the cache\nqueryClient.invalidateQueries()\n// Invalidate every query with a key that starts with `todos`\nqueryClient.invalidateQueries({ queryKey: ['todos'] })\n```\n\n[//]: # 'Example'\n\n> Note: Where other libraries that use normalized caches would attempt to update local queries with the new data either imperatively or via schema inference, TanStack Query gives you the tools to avoid the manual labor that comes with maintaining normalized caches and instead prescribes **targeted invalidation, background-refetching and ultimately atomic updates**.\n\nWhen a query is invalidated with `invalidateQueries`, two things happen:\n\n- It is marked as stale. This stale state overrides any `staleTime` configurations being used in `useQuery` or related hooks\n- If the query is currently being rendered via `useQuery` or related hooks, it will also be refetched in the background\n\n## Query Matching with `invalidateQueries`\n\nWhen using APIs like `invalidateQueries` and `removeQueries` (and others that support partial query matching), you can match multiple queries by their prefix, or get really specific and match an exact query. For information on the types of filters you can use, please see [Query Filters](./filters.md#query-filters).\n\nIn this example, we can use the `todos` prefix to invalidate any queries that start with `todos` in their query key:\n\n[//]: # 'Example2'\n\n```tsx\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\n\n// Get QueryClient from the context\nconst queryClient = useQueryClient()\n\nqueryClient.invalidateQueries({ queryKey: ['todos'] })\n\n// Both queries below will be invalidated\nconst todoListQuery = useQuery({\n  queryKey: ['todos'],\n  queryFn: fetchTodoList,\n})\nconst todoListQuery = useQuery({\n  queryKey: ['todos', { page: 1 }],\n  queryFn: fetchTodoList,\n})\n```\n\n[//]: # 'Example2'\n\nYou can even invalidate queries with specific variables by passing a more specific query key to the `invalidateQueries` method:\n\n[//]: # 'Example3'\n\n```tsx\nqueryClient.invalidateQueries({\n  queryKey: ['todos', { type: 'done' }],\n})\n\n// The query below will be invalidated\nconst todoListQuery = useQuery({\n  queryKey: ['todos', { type: 'done' }],\n  queryFn: fetchTodoList,\n})\n\n// However, the following query below will NOT be invalidated\nconst todoListQuery = useQuery({\n  queryKey: ['todos'],\n  queryFn: fetchTodoList,\n})\n```\n\n[//]: # 'Example3'\n\nThe `invalidateQueries` API is very flexible, so even if you want to **only** invalidate `todos` queries that don't have any more variables or subkeys, you can pass an `exact: true` option to the `invalidateQueries` method:\n\n[//]: # 'Example4'\n\n```tsx\nqueryClient.invalidateQueries({\n  queryKey: ['todos'],\n  exact: true,\n})\n\n// The query below will be invalidated\nconst todoListQuery = useQuery({\n  queryKey: ['todos'],\n  queryFn: fetchTodoList,\n})\n\n// However, the following query below will NOT be invalidated\nconst todoListQuery = useQuery({\n  queryKey: ['todos', { type: 'done' }],\n  queryFn: fetchTodoList,\n})\n```\n\n[//]: # 'Example4'\n\nIf you find yourself wanting **even more** granularity, you can pass a predicate function to the `invalidateQueries` method. This function will receive each `Query` instance from the query cache and allow you to return `true` or `false` for whether you want to invalidate that query:\n\n[//]: # 'Example5'\n\n```tsx\nqueryClient.invalidateQueries({\n  predicate: (query) =>\n    query.queryKey[0] === 'todos' && query.queryKey[1]?.version >= 10,\n})\n\n// The query below will be invalidated\nconst todoListQuery = useQuery({\n  queryKey: ['todos', { version: 20 }],\n  queryFn: fetchTodoList,\n})\n\n// The query below will be invalidated\nconst todoListQuery = useQuery({\n  queryKey: ['todos', { version: 10 }],\n  queryFn: fetchTodoList,\n})\n\n// However, the following query below will NOT be invalidated\nconst todoListQuery = useQuery({\n  queryKey: ['todos', { version: 5 }],\n  queryFn: fetchTodoList,\n})\n```\n\n[//]: # 'Example5'\n"
  },
  {
    "path": "docs/framework/react/guides/query-keys.md",
    "content": "---\nid: query-keys\ntitle: Query Keys\n---\n\nAt its core, TanStack Query manages query caching for you based on query keys. Query keys have to be an Array at the top level, and can be as simple as an Array with a single string, or as complex as an array of many strings and nested objects. As long as the query key is serializable using `JSON.stringify`, and **unique to the query's data**, you can use it!\n\n## Simple Query Keys\n\nThe simplest form of a key is an array with constants values. This format is useful for:\n\n- Generic List/Index resources\n- Non-hierarchical resources\n\n[//]: # 'Example'\n\n```tsx\n// A list of todos\nuseQuery({ queryKey: ['todos'], ... })\n\n// Something else, whatever!\nuseQuery({ queryKey: ['something', 'special'], ... })\n```\n\n[//]: # 'Example'\n\n## Array Keys with variables\n\nWhen a query needs more information to uniquely describe its data, you can use an array with a string and any number of serializable objects to describe it. This is useful for:\n\n- Hierarchical or nested resources\n  - It's common to pass an ID, index, or other primitive to uniquely identify the item\n- Queries with additional parameters\n  - It's common to pass an object of additional options\n\n[//]: # 'Example2'\n\n```tsx\n// An individual todo\nuseQuery({ queryKey: ['todo', 5], ... })\n\n// An individual todo in a \"preview\" format\nuseQuery({ queryKey: ['todo', 5, { preview: true }], ...})\n\n// A list of todos that are \"done\"\nuseQuery({ queryKey: ['todos', { type: 'done' }], ... })\n```\n\n[//]: # 'Example2'\n\n## Query Keys are hashed deterministically!\n\nThis means that no matter the order of keys in objects, all of the following queries are considered equal:\n\n[//]: # 'Example3'\n\n```tsx\nuseQuery({ queryKey: ['todos', { status, page }], ... })\nuseQuery({ queryKey: ['todos', { page, status }], ...})\nuseQuery({ queryKey: ['todos', { page, status, other: undefined }], ... })\n```\n\n[//]: # 'Example3'\n\nThe following query keys, however, are not equal. Array item order matters!\n\n[//]: # 'Example4'\n\n```tsx\nuseQuery({ queryKey: ['todos', status, page], ... })\nuseQuery({ queryKey: ['todos', page, status], ...})\nuseQuery({ queryKey: ['todos', undefined, page, status], ...})\n```\n\n[//]: # 'Example4'\n\n## If your query function depends on a variable, include it in your query key\n\nSince query keys uniquely describe the data they are fetching, they should include any variables you use in your query function that **change**. For example:\n\n[//]: # 'Example5'\n\n```tsx\nfunction Todos({ todoId }) {\n  const result = useQuery({\n    queryKey: ['todos', todoId],\n    queryFn: () => fetchTodoById(todoId),\n  })\n}\n```\n\n[//]: # 'Example5'\n\nNote that query keys act as dependencies for your query functions. Adding dependent variables to your query key will ensure that queries are cached independently, and that any time a variable changes, _queries will be refetched automatically_ (depending on your `staleTime` settings). See the [exhaustive-deps](../../../eslint/exhaustive-deps.md) section for more information and examples.\n\n[//]: # 'Materials'\n\n## Further reading\n\nFor tips on organizing Query Keys in larger applications, have a look at [Effective React Query Keys](https://tkdodo.eu/blog/effective-react-query-keys) and check the [Query Key Factory Package](https://github.com/lukemorales/query-key-factory) from\nthe [Community Resources](../../../community-resources).\n\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/react/guides/query-options.md",
    "content": "---\nid: query-options\ntitle: Query Options\n---\n\nOne of the best ways to share `queryKey` and `queryFn` between multiple places, yet keep them co-located to one another, is to use the `queryOptions` helper. At runtime, this helper just returns whatever you pass into it, but it has a lot of advantages when using it [with TypeScript](../typescript.md#typing-query-options). You can define all possible options for a query in one place, and you'll also get type inference and type safety for all of them.\n\n[//]: # 'Example1'\n\n```ts\nimport { queryOptions } from '@tanstack/react-query'\n\nfunction groupOptions(id: number) {\n  return queryOptions({\n    queryKey: ['groups', id],\n    queryFn: () => fetchGroups(id),\n    staleTime: 5 * 1000,\n  })\n}\n\n// usage:\n\nuseQuery(groupOptions(1))\nuseSuspenseQuery(groupOptions(5))\nuseQueries({\n  queries: [groupOptions(1), groupOptions(2)],\n})\nqueryClient.prefetchQuery(groupOptions(23))\nqueryClient.setQueryData(groupOptions(42).queryKey, newGroups)\n```\n\n[//]: # 'Example1'\n\nFor Infinite Queries, a separate [`infiniteQueryOptions`](../reference/infiniteQueryOptions.md) helper is available.\n\n[//]: # 'SelectDescription'\n\nYou can still override some options at the component level. A very common and useful pattern is to create per-component [`select`](./render-optimizations.md#select) functions:\n\n[//]: # 'SelectDescription'\n[//]: # 'Example2'\n\n```ts\n// Type inference still works, so query.data will be the return type of select instead of queryFn\n\nconst query = useQuery({\n  ...groupOptions(1),\n  select: (data) => data.groupName,\n})\n```\n\n[//]: # 'Example2'\n"
  },
  {
    "path": "docs/framework/react/guides/query-retries.md",
    "content": "---\nid: query-retries\ntitle: Query Retries\n---\n\nWhen a `useQuery` query fails (the query function throws an error), TanStack Query will automatically retry the query if that query's request has not reached the max number of consecutive retries (defaults to `3`) or a function is provided to determine if a retry is allowed.\n\nYou can configure retries both on a global level and an individual query level.\n\n- Setting `retry = false` will disable retries.\n- Setting `retry = 6` will retry failing requests 6 times before showing the final error thrown by the function.\n- Setting `retry = true` will infinitely retry failing requests.\n- Setting `retry = (failureCount, error) => ...` allows for custom logic based on why the request failed. Note that `failureCount` starts at `0` for the first retry attempt.\n\n[//]: # 'Info'\n\n> On the server, retries default to `0` to make server rendering as fast as possible.\n\n[//]: # 'Info'\n[//]: # 'Example'\n\n```tsx\nimport { useQuery } from '@tanstack/react-query'\n\n// Make a specific query retry a certain number of times\nconst result = useQuery({\n  queryKey: ['todos', 1],\n  queryFn: fetchTodoListPage,\n  retry: 10, // Will retry failed requests 10 times before displaying an error\n})\n```\n\n[//]: # 'Example'\n\n> Info: Contents of the `error` property will be part of `failureReason` response property of `useQuery` until the last retry attempt. So in above example any error contents will be part of `failureReason` property for first 9 retry attempts (Overall 10 attempts) and finally they will be part of `error` after last attempt if error persists after all retry attempts.\n\n## Retry Delay\n\nBy default, retries in TanStack Query do not happen immediately after a request fails. As is standard, a back-off delay is gradually applied to each retry attempt.\n\nThe default `retryDelay` is set to double (starting at `1000`ms) with each attempt, but not exceed 30 seconds:\n\n[//]: # 'Example2'\n\n```tsx\n// Configure for all queries\nimport {\n  QueryCache,\n  QueryClient,\n  QueryClientProvider,\n} from '@tanstack/react-query'\n\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000),\n    },\n  },\n})\n\nfunction App() {\n  return <QueryClientProvider client={queryClient}>...</QueryClientProvider>\n}\n```\n\n[//]: # 'Example2'\n\nThough it is not recommended, you can obviously override the `retryDelay` function/integer in both the Provider and individual query options. If set to an integer instead of a function the delay will always be the same amount of time:\n\n[//]: # 'Example3'\n\n```tsx\nconst result = useQuery({\n  queryKey: ['todos'],\n  queryFn: fetchTodoList,\n  retryDelay: 1000, // Will always wait 1000ms to retry, regardless of how many retries\n})\n```\n\n[//]: # 'Example3'\n\n## Background Retry Behavior\n\nWhen using `refetchInterval` with `refetchIntervalInBackground: true`, retries will pause when the browser tab is inactive. This happens because retries respect the same focus behavior as regular refetches.\n\nIf you need continuous retries in the background, consider disabling retries and implementing a custom refetch strategy:\n\n[//]: # 'Example4'\n\n```tsx\nconst result = useQuery({\n  queryKey: ['todos'],\n  queryFn: fetchTodos,\n  refetchInterval: (query) => {\n    // Refetch more frequently when in error state\n    return query.state.status === 'error' ? 5000 : 30000\n  },\n  refetchIntervalInBackground: true,\n  retry: false, // Disable built-in retries\n})\n```\n\n[//]: # 'Example4'\n\nThis approach lets you control retry timing manually while keeping refetches active in the background.\n"
  },
  {
    "path": "docs/framework/react/guides/render-optimizations.md",
    "content": "---\nid: render-optimizations\ntitle: Render Optimizations\n---\n\nReact Query applies a couple of optimizations automatically to ensure that your components only re-render when they actually need to. This is done by the following means:\n\n## structural sharing\n\nReact Query uses a technique called \"structural sharing\" to ensure that as many references as possible will be kept intact between re-renders. If data is fetched over the network, usually, you'll get a completely new reference by json parsing the response. However, React Query will keep the original reference if _nothing_ changed in the data. If a subset changed, React Query will keep the unchanged parts and only replace the changed parts.\n\n> Note: This optimization only works if the `queryFn` returns JSON compatible data. You can turn it off by setting `structuralSharing: false` globally or on a per-query basis, or you can implement your own structural sharing by passing a function to it.\n\n### referential identity\n\nThe top level object returned from `useQuery`, `useInfiniteQuery`, `useMutation` and the Array returned from `useQueries` is **not referentially stable**. It will be a new reference on every render. However, the `data` properties returned from these hooks will be as stable as possible.\n\n## tracked properties\n\nReact Query will only trigger a re-render if one of the properties returned from `useQuery` is actually \"used\". This is done by using [Proxy object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy). This avoids a lot of unnecessary re-renders, e.g. because properties like `isFetching` or `isStale` might change often, but are not used in the component.\n\nYou can customize this feature by setting `notifyOnChangeProps` manually globally or on a per-query basis. If you want to turn that feature off, you can set `notifyOnChangeProps: 'all'`.\n\n> Note: The get trap of a proxy is invoked by accessing a property, either via destructuring or by accessing it directly. If you use object rest destructuring, you will disable this optimization. We have a [lint rule](../../../eslint/no-rest-destructuring.md) to guard against this pitfall.\n\n## select\n\nYou can use the `select` option to select a subset of the data that your component should subscribe to. This is useful for highly optimized data transformations or to avoid unnecessary re-renders.\n\n```js\nexport const useTodos = (select) => {\n  return useQuery({\n    queryKey: ['todos'],\n    queryFn: fetchTodos,\n    select,\n  })\n}\n\nexport const useTodoCount = () => {\n  return useTodos((data) => data.length)\n}\n```\n\nA component using the `useTodoCount` custom hook will only re-render if the length of the todos changes. It will **not** re-render if e.g. the name of a todo changed.\n\n> Note: `select` operates on successfully cached data and is not the appropriate place to throw errors. The source of truth for errors is the `queryFn`, and a `select` function that returns an error results in `data` being `undefined` and `isSuccess` being `true`. We recommend handling errors in the `queryFn` if you wish to have a query fail on incorrect data, or outside of the query hook if you have a error case not related to caching.\n\n### memoization\n\nThe `select` function will only re-run if:\n\n- the `select` function itself changed referentially\n- `data` changed\n\nThis means that an inlined `select` function, as shown above, will run on every render. To avoid this, you can wrap the `select` function in `useCallback`, or extract it to a stable function reference if it doesn't have any dependencies:\n\n```js\n// wrapped in useCallback\nexport const useTodoCount = () => {\n  return useTodos(useCallback((data) => data.length, []))\n}\n```\n\n```js\n// extracted to a stable function reference\nconst selectTodoCount = (data) => data.length\n\nexport const useTodoCount = () => {\n  return useTodos(selectTodoCount)\n}\n```\n\n## Further Reading\n\nFor an in-depth guide about these topics, read [React Query Render Optimizations](https://tkdodo.eu/blog/react-query-render-optimizations) from\nthe TkDodo. To learn how to best optimize the `select` option, read [React Query Selectors, Supercharged](https://tkdodo.eu/blog/react-query-selectors-supercharged)\n"
  },
  {
    "path": "docs/framework/react/guides/request-waterfalls.md",
    "content": "---\nid: request-waterfalls\ntitle: Performance & Request Waterfalls\n---\n\nApplication performance is a broad and complex area and while React Query can't make your APIs faster, there are still things to be mindful about in how you use React Query to ensure the best performance.\n\nThe biggest performance footgun when using React Query, or indeed any data fetching library that lets you fetch data inside of components, is request waterfalls. The rest of this page will explain what they are, how you can spot them and how you can restructure your application or APIs to avoid them.\n\nThe [Prefetching & Router Integration guide](./prefetching.md) builds on this and teaches you how to prefetch data ahead of time when it's not possible or feasible to restructure your application or APIs.\n\nThe [Server Rendering & Hydration guide](./ssr.md) teaches you how to prefetch data on the server and pass that data down to the client so you don't have to fetch it again.\n\n[//]: # 'AdvancedSSRLink'\n\nThe [Advanced Server Rendering guide](./advanced-ssr.md) further teaches you how to apply these patterns to Server Components and Streaming Server Rendering.\n\n[//]: # 'AdvancedSSRLink'\n\n## What is a Request Waterfall?\n\nA request waterfall is what happens when a request for a resource (code, css, images, data) does not start until _after_ another request for a resource has finished.\n\nConsider a web page. Before you can load things like the CSS, JS etc, the browser first needs to load the markup. This is a request waterfall.\n\n```\n1. |-> Markup\n2.   |-> CSS\n2.   |-> JS\n2.   |-> Image\n```\n\nIf you fetch your CSS inside a JS file, you now have a double waterfall:\n\n```\n1. |-> Markup\n2.   |-> JS\n3.     |-> CSS\n```\n\nIf that CSS uses a background image, it's a triple waterfall:\n\n```\n1. |-> Markup\n2.   |-> JS\n3.     |-> CSS\n4.       |-> Image\n```\n\nThe best way to spot and analyze your request waterfalls is usually by opening your browsers devtools \"Network\" tab.\n\nEach waterfall represents at least one roundtrip to the server, unless the resource is locally cached (in practice, some of these waterfalls might represent more than one roundtrip because the browser needs to establish a connection which requires some back and forth, but let's ignore that here). Because of this, the negative effects of request waterfalls are highly dependent on the users latency. Consider the example of the triple waterfall, which actually represents 4 server roundtrips. With 250ms latency, which is not uncommon on 3g networks or in bad network conditions, we end up with a total time of 4\\*250=1000ms **only counting latency**. If we were able to flatten that to the first example with only 2 roundtrips, we get 500ms instead, possibly loading that background image in half the time!\n\n## Request Waterfalls & React Query\n\nNow let's consider React Query. We'll focus on the case without Server Rendering first. Before we can even start making a query, we need to load the JS, so before we can show that data on the screen, we have a double waterfall:\n\n```\n1. |-> Markup\n2.   |-> JS\n3.     |-> Query\n```\n\nWith this as a basis, let's look at a few different patterns that can lead to Request Waterfalls in React Query, and how to avoid them.\n\n- Single Component Waterfalls / Serial Queries\n- Nested Component Waterfalls\n- Code Splitting\n\n### Single Component Waterfalls / Serial Queries\n\nWhen a single component first fetches one query, and then another, that's a request waterfall. This can happen when the second query is a [Dependent Query](./dependent-queries.md), that is, it depends on data from the first query when fetching:\n\n[//]: # 'DependentExample'\n\n```tsx\n// Get the user\nconst { data: user } = useQuery({\n  queryKey: ['user', email],\n  queryFn: getUserByEmail,\n})\n\nconst userId = user?.id\n\n// Then get the user's projects\nconst {\n  status,\n  fetchStatus,\n  data: projects,\n} = useQuery({\n  queryKey: ['projects', userId],\n  queryFn: getProjectsByUser,\n  // The query will not execute until the userId exists\n  enabled: !!userId,\n})\n```\n\n[//]: # 'DependentExample'\n\nWhile not always feasible, for optimal performance it's better to restructure your API so you can fetch both of these in a single query. In the example above, instead of first fetching `getUserByEmail` to be able to `getProjectsByUser`, introducing a new `getProjectsByUserEmail` query would flatten the waterfall.\n\n[//]: # 'ServerComponentsNote1'\n\n> Another way to mitigate dependent queries without restructuring your API is to move the waterfall to the server where latency is lower. This is the idea behind Server Components which are covered in the [Advanced Server Rendering guide](./advanced-ssr.md).\n\n[//]: # 'ServerComponentsNote1'\n[//]: # 'SuspenseSerial'\n\nAnother example of serial queries is when you use React Query with Suspense:\n\n```tsx\nfunction App () {\n  // The following queries will execute in serial, causing separate roundtrips to the server:\n  const usersQuery = useSuspenseQuery({ queryKey: ['users'], queryFn: fetchUsers })\n  const teamsQuery = useSuspenseQuery({ queryKey: ['teams'], queryFn: fetchTeams })\n  const projectsQuery = useSuspenseQuery({ queryKey: ['projects'], queryFn: fetchProjects })\n\n  // Note that since the queries above suspend rendering, no data\n  // gets rendered until all of the queries finished\n  ...\n}\n```\n\nNote that with regular `useQuery` these would happen in parallel.\n\nLuckily, this is easy to fix, by always using the hook `useSuspenseQueries` when you have multiple suspenseful queries in a component.\n\n```tsx\nconst [usersQuery, teamsQuery, projectsQuery] = useSuspenseQueries({\n  queries: [\n    { queryKey: ['users'], queryFn: fetchUsers },\n    { queryKey: ['teams'], queryFn: fetchTeams },\n    { queryKey: ['projects'], queryFn: fetchProjects },\n  ],\n})\n```\n\n[//]: # 'SuspenseSerial'\n\n### Nested Component Waterfalls\n\n[//]: # 'NestedIntro'\n\nNested Component Waterfalls is when both a parent and a child component contains queries, and the parent does not render the child until its query is done. This can happen both with `useQuery` and `useSuspenseQuery`.\n\n[//]: # 'NestedIntro'\n\nIf the child renders conditionally based on the data in the parent, or if the child relies on some part of the result being passed down as a prop from the parent to make its query, we have a _dependent_ nested component waterfall.\n\nLet's first look at an example where the child is **not** dependent on the parent.\n\n[//]: # 'NestedExample'\n\n```tsx\nfunction Article({ id }) {\n  const { data: articleData, isPending } = useQuery({\n    queryKey: ['article', id],\n    queryFn: getArticleById,\n  })\n\n  if (isPending) {\n    return 'Loading article...'\n  }\n\n  return (\n    <>\n      <ArticleHeader articleData={articleData} />\n      <ArticleBody articleData={articleData} />\n      <Comments id={id} />\n    </>\n  )\n\n}\n\nfunction Comments({ id }) {\n  const { data, isPending } = useQuery({\n    queryKey: ['article-comments', id],\n    queryFn: getArticleCommentsById,\n  })\n\n  ...\n}\n```\n\n[//]: # 'NestedExample'\n\nNote that while `<Comments>` takes a prop `id` from the parent, that id is already available when the `<Article>` renders so there is no reason we could not fetch the comments at the same time as the article. In real world applications, the child might be nested far below the parent and these kinds of waterfalls are often trickier to spot and fix, but for our example, one way to flatten the waterfall would be to hoist the comments query to the parent instead:\n\n[//]: # 'NestedHoistedExample'\n\n```tsx\nfunction Article({ id }) {\n  const { data: articleData, isPending: articlePending } = useQuery({\n    queryKey: ['article', id],\n    queryFn: getArticleById,\n  })\n\n  const { data: commentsData, isPending: commentsPending } = useQuery({\n    queryKey: ['article-comments', id],\n    queryFn: getArticleCommentsById,\n  })\n\n  if (articlePending) {\n    return 'Loading article...'\n  }\n\n  return (\n    <>\n      <ArticleHeader articleData={articleData} />\n      <ArticleBody articleData={articleData} />\n      {commentsPending ? (\n        'Loading comments...'\n      ) : (\n        <Comments commentsData={commentsData} />\n      )}\n    </>\n  )\n}\n```\n\n[//]: # 'NestedHoistedExample'\n[//]: # 'NestedHoistedOutro'\n\nThe two queries will now fetch in parallel. Note that if you are using suspense, you'd want to combine these two queries into a single `useSuspenseQueries` instead.\n\n[//]: # 'NestedHoistedOutro'\n\nAnother way to flatten this waterfall would be to prefetch the comments in the `<Article>` component, or prefetch both of these queries at the router level on page load or page navigation, read more about this in the [Prefetching & Router Integration guide](./prefetching.md).\n\nNext, let's look at a _Dependent Nested Component Waterfall_.\n\n[//]: # 'DependentNestedExample'\n\n```tsx\nfunction Feed() {\n  const { data, isPending } = useQuery({\n    queryKey: ['feed'],\n    queryFn: getFeed,\n  })\n\n  if (isPending) {\n    return 'Loading feed...'\n  }\n\n  return (\n    <>\n      {data.map((feedItem) => {\n        if (feedItem.type === 'GRAPH') {\n          return <GraphFeedItem key={feedItem.id} feedItem={feedItem} />\n        }\n\n        return <StandardFeedItem key={feedItem.id} feedItem={feedItem} />\n      })}\n    </>\n  )\n}\n\nfunction GraphFeedItem({ feedItem }) {\n  const { data, isPending } = useQuery({\n    queryKey: ['graph', feedItem.id],\n    queryFn: getGraphDataById,\n  })\n\n  ...\n}\n```\n\n[//]: # 'DependentNestedExample'\n\nThe second query `getGraphDataById` is dependent on its parent in two different ways. First of all, it doesn't ever happen unless the `feedItem` is a graph, and second, it needs an `id` from the parent.\n\n```\n1. |> getFeed()\n2.   |> getGraphDataById()\n```\n\n[//]: # 'ServerComponentsNote2'\n\nIn this example, we can't trivially flatten the waterfall by just hoisting the query to the parent, or even adding prefetching. Just like the dependent query example at the beginning of this guide, one option is to refactor our API to include the graph data in the `getFeed` query. Another more advanced solution is to leverage Server Components to move the waterfall to the server where latency is lower (read more about this in the [Advanced Server Rendering guide](./advanced-ssr.md)) but note that this can be a very big architectural change.\n\n[//]: # 'ServerComponentsNote2'\n\nYou can have good performance even with a few query waterfalls here and there, just know they are a common performance concern and be mindful about them. An especially insidious version is when Code Splitting is involved, let's take a look at this next.\n\n### Code Splitting\n\nSplitting an applications JS-code into smaller chunks and only loading the necessary parts is usually a critical step in achieving good performance. It does have a downside however, in that it often introduces request waterfalls. When that code split code also has a query inside it, this problem is worsened further.\n\nConsider this a slightly modified version of the Feed example.\n\n[//]: # 'LazyExample'\n\n```tsx\n// This lazy loads the GraphFeedItem component, meaning\n// it wont start loading until something renders it\nconst GraphFeedItem = React.lazy(() => import('./GraphFeedItem'))\n\nfunction Feed() {\n  const { data, isPending } = useQuery({\n    queryKey: ['feed'],\n    queryFn: getFeed,\n  })\n\n  if (isPending) {\n    return 'Loading feed...'\n  }\n\n  return (\n    <>\n      {data.map((feedItem) => {\n        if (feedItem.type === 'GRAPH') {\n          return <GraphFeedItem key={feedItem.id} feedItem={feedItem} />\n        }\n\n        return <StandardFeedItem key={feedItem.id} feedItem={feedItem} />\n      })}\n    </>\n  )\n}\n\n// GraphFeedItem.tsx\nfunction GraphFeedItem({ feedItem }) {\n  const { data, isPending } = useQuery({\n    queryKey: ['graph', feedItem.id],\n    queryFn: getGraphDataById,\n  })\n\n  ...\n}\n```\n\n[//]: # 'LazyExample'\n\nThis example has a double waterfall, looking like this:\n\n```\n1. |> getFeed()\n2.   |> JS for <GraphFeedItem>\n3.     |> getGraphDataById()\n```\n\nBut that's just looking at the code from the example, if we consider what the first page load of this page looks like, we actually have to complete 5 round trips to the server before we can render the graph!\n\n```\n1. |> Markup\n2.   |> JS for <Feed>\n3.     |> getFeed()\n4.       |> JS for <GraphFeedItem>\n5.         |> getGraphDataById()\n```\n\nNote that this looks a bit different when server rendering, we will explore that further in the [Server Rendering & Hydration guide](./ssr.md). Also note that it's not uncommon for the route that contains `<Feed>` to also be code split, which could add yet another hop.\n\nIn the code split case, it might actually help to hoist the `getGraphDataById` query to the `<Feed>` component and make it conditional, or add a conditional prefetch. That query could then be fetched in parallel with the code, turning the example part into this:\n\n```\n1. |> getFeed()\n2.   |> getGraphDataById()\n2.   |> JS for <GraphFeedItem>\n```\n\nThis is very much a tradeoff however. You are now including the data fetching code for `getGraphDataById` in the same bundle as `<Feed>`, so evaluate what is best for your case. Read more about how to do this in the [Prefetching & Router Integration guide](./prefetching.md).\n\n[//]: # 'ServerComponentsNote3'\n\n> The tradeoff between:\n>\n> - Include all data fetching code in the main bundle, even if we seldom use it\n> - Put the data fetching code in the code split bundle, but with a request waterfall\n>\n> is not great and has been one of the motivations for Server Components. With Server Components, it's possible to avoid both, read more about how this applies to React Query in the [Advanced Server Rendering guide](./advanced-ssr.md).\n\n[//]: # 'ServerComponentsNote3'\n\n## Summary and takeaways\n\nRequest Waterfalls are a very common and complex performance concern with many tradeoffs. There are many ways to accidentally introduce them into your application:\n\n- Adding a query to a child, not realizing a parent already has a query\n- Adding a query to a parent, not realizing a child already has a query\n- Moving a component with descendants that has a query to a new parent with an ancestor that has a query\n- Etc..\n\nBecause of this accidental complexity, it pays off to be mindful of waterfalls and regularly examine your application looking for them (a good way is to examine the Network tab every now and then!). You don't necessarily have to flatten them all to have good performance, but keep an eye out for the high impact ones.\n\nIn the next guide, we'll look at more ways to flatten waterfalls, by leveraging [Prefetching & Router Integration](./prefetching.md).\n"
  },
  {
    "path": "docs/framework/react/guides/scroll-restoration.md",
    "content": "---\nid: scroll-restoration\ntitle: Scroll Restoration\n---\n\nTraditionally, when you navigate to a previously visited page on a web browser, you would find that the page would be scrolled to the exact position where you were before you navigated away from that page. This is called **scroll restoration** and has been in a bit of a regression since web applications have started moving towards client side data fetching. With TanStack Query however, that's no longer the case.\n\nTanStack Query doesn’t implement scroll restoration by itself, but it removes one of the biggest causes of broken restoration in SPA’s: refetch-induced UI resets. By keeping previously fetched data in cache (and optionally using `placeholderData`), navigation back to a page can render instantly with stable layout, making scroll restoration reliable when handled by the router (e.g. React Router’s ScrollRestoration, TanStack Router’s scroll restoration, or a small custom history-based solution).\n\nOut of the box, \"scroll restoration\" for all queries (including paginated and infinite queries) Just Works™️ in TanStack Query. The reason for this is that query results are cached and able to be retrieved synchronously when a query is rendered. As long as your queries are being cached long enough (the default time is 5 minutes) and have not been garbage collected, scroll restoration will work out of the box all the time.\n"
  },
  {
    "path": "docs/framework/react/guides/ssr.md",
    "content": "---\nid: ssr\ntitle: Server Rendering & Hydration\n---\n\nIn this guide you'll learn how to use React Query with server rendering.\n\nSee the guide on [Prefetching & Router Integration](./prefetching.md) for some background. You might also want to check out the [Performance & Request Waterfalls guide](./request-waterfalls.md) before that.\n\nFor deeper examples on hydration + prefetching (including code splitting), see the [Dependent Queries & Code Splitting](./prefetching.md#dependent-queries-code-splitting) section.\n\nFor advanced server rendering patterns, such as streaming, Server Components and the new Next.js app router, see the [Advanced Server Rendering guide](./advanced-ssr.md).\n\nIf you just want to see some code, you can skip ahead to the [Full Next.js pages router example](#full-nextjs-pages-router-example) or the [Full Remix example](#full-remix-example) below.\n\n## Server Rendering & React Query\n\nSo what is server rendering anyway? The rest of this guide will assume you are familiar with the concept, but let's spend some time to look at how it relates to React Query. Server rendering is the act of generating the initial html on the server, so that the user has some content to look at as soon as the page loads. This can happen on demand when a page is requested (SSR). It can also happen ahead of time either because a previous request was cached, or at build time (SSG).\n\nIf you've read the [Performance & Request Waterfalls guide](./request-waterfalls.md), you might remember this:\n\n```\n1. |-> Markup (without content)\n2.   |-> JS\n3.     |-> Query\n```\n\nWith a client rendered application, these are the minimum 3 server roundtrips you will need to make before getting any content on the screen for the user. One way of viewing server rendering is that it turns the above into this:\n\n```\n1. |-> Markup (with content AND initial data)\n2.   |-> JS\n```\n\nAs soon as **1.** is complete, the user can see the content and when **2.** finishes, the page is interactive and clickable. Because the markup also contains the initial data we need, step **3.** does not need to run on the client at all, at least until you want to revalidate the data for some reason.\n\nThis is all from the clients perspective. On the server, we need to **prefetch** that data before we generate/render the markup, we need to **dehydrate** that data into a serializable format we can embed in the markup, and on the client we need to **hydrate** that data into a React Query cache so we can avoid doing a new fetch on the client.\n\nRead on to learn how to implement these three steps with React Query.\n\n## A quick note on Suspense\n\nThis guide uses the regular `useQuery` API. While we don't necessarily recommend it, it is possible to replace this with `useSuspenseQuery` instead **as long as you always prefetch all your queries**. The upside is that you get to use `<Suspense>` for loading states on the client.\n\nIf you do forget to prefetch a query when you are using `useSuspenseQuery`, the consequences will depend on the framework you are using. In some cases, the data will Suspend and get fetched on the server but never be hydrated to the client, where it will fetch again. In these cases you will get a markup hydration mismatch, because the server and the client tried to render different things.\n\n## Initial setup\n\nThe first steps of using React Query is always to create a `queryClient` and wrap the application in a `<QueryClientProvider>`. When doing server rendering, it's important to create the `queryClient` instance **inside of your app**, in React state (an instance ref works fine too). **This ensures that data is not shared between different users and requests**, while still only creating the `queryClient` once per component lifecycle.\n\nNext.js pages router:\n\n```tsx\n// _app.tsx\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\n\n// NEVER DO THIS:\n// const queryClient = new QueryClient()\n//\n// Creating the queryClient at the file root level makes the cache shared\n// between all requests and means _all_ data gets passed to _all_ users.\n// Besides being bad for performance, this also leaks any sensitive data.\n\nexport default function MyApp({ Component, pageProps }) {\n  // Instead do this, which ensures each request has its own cache:\n  const [queryClient] = React.useState(\n    () =>\n      new QueryClient({\n        defaultOptions: {\n          queries: {\n            // With SSR, we usually want to set some default staleTime\n            // above 0 to avoid refetching immediately on the client\n            staleTime: 60 * 1000,\n          },\n        },\n      }),\n  )\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      <Component {...pageProps} />\n    </QueryClientProvider>\n  )\n}\n```\n\nRemix:\n\n```tsx\n// app/root.tsx\nimport { Outlet } from '@remix-run/react'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\n\nexport default function MyApp() {\n  const [queryClient] = React.useState(\n    () =>\n      new QueryClient({\n        defaultOptions: {\n          queries: {\n            // With SSR, we usually want to set some default staleTime\n            // above 0 to avoid refetching immediately on the client\n            staleTime: 60 * 1000,\n          },\n        },\n      }),\n  )\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      <Outlet />\n    </QueryClientProvider>\n  )\n}\n```\n\n## Get started fast with `initialData`\n\nThe quickest way to get started is to not involve React Query at all when it comes to prefetching and not use the `dehydrate`/`hydrate` APIs. What you do instead is passing the raw data in as the `initialData` option to `useQuery`. Let's look at an example using Next.js pages router, using `getServerSideProps`.\n\n```tsx\nexport async function getServerSideProps() {\n  const posts = await getPosts()\n  return { props: { posts } }\n}\n\nfunction Posts(props) {\n  const { data } = useQuery({\n    queryKey: ['posts'],\n    queryFn: getPosts,\n    initialData: props.posts,\n  })\n\n  // ...\n}\n```\n\nThis also works with `getStaticProps` or even the older `getInitialProps` and the same pattern can be applied in any other framework that has equivalent functions. This is what the same example looks like with Remix:\n\n```tsx\nexport async function loader() {\n  const posts = await getPosts()\n  return json({ posts })\n}\n\nfunction Posts() {\n  const { posts } = useLoaderData<typeof loader>()\n\n  const { data } = useQuery({\n    queryKey: ['posts'],\n    queryFn: getPosts,\n    initialData: posts,\n  })\n\n  // ...\n}\n```\n\nThe setup is minimal and this can be a quick solution for some cases, but there are a **few tradeoffs to consider** when compared to the full approach:\n\n- If you are calling `useQuery` in a component deeper down in the tree you need to pass the `initialData` down to that point\n- If you are calling `useQuery` with the same query in multiple locations, passing `initialData` to only one of them can be brittle and break when your app changes since. If you remove or move the component that has the `useQuery` with `initialData`, the more deeply nested `useQuery` might no longer have any data. Passing `initialData` to **all** queries that needs it can also be cumbersome.\n- There is no way to know at what time the query was fetched on the server, so `dataUpdatedAt` and determining if the query needs refetching is based on when the page loaded instead\n- If there is already data in the cache for a query, `initialData` will never overwrite this data, **even if the new data is fresher than the old one**.\n  - To understand why this is especially bad, consider the `getServerSideProps` example above. If you navigate back and forth to a page several times, `getServerSideProps` would get called each time and fetch new data, but because we are using the `initialData` option, the client cache and data would never be updated.\n\nSetting up the full hydration solution is straightforward and does not have these drawbacks, this will be the focus for the rest of the documentation.\n\n## Using the Hydration APIs\n\nWith just a little more setup, you can use a `queryClient` to prefetch queries during a preload phase, pass a serialized version of that `queryClient` to the rendering part of the app and reuse it there. This avoids the drawbacks above. Feel free to skip ahead for full Next.js pages router and Remix examples, but at a general level these are the extra steps:\n\n- In the framework loader function, create a `const queryClient = new QueryClient(options)`\n- In the loader function, do `await queryClient.prefetchQuery(...)` for each query you want to prefetch\n  - You want to use `await Promise.all(...)` to fetch the queries in parallel when possible\n  - It's fine to have queries that aren't prefetched. These wont be server rendered, instead they will be fetched on the client after the application is interactive. This can be great for content that are shown only after user interaction, or is far down on the page to avoid blocking more critical content.\n- From the loader, return `dehydrate(queryClient)`, note that the exact syntax to return this differs between frameworks\n- Wrap your tree with `<HydrationBoundary state={dehydratedState}>` where `dehydratedState` comes from the framework loader. How you get `dehydratedState` also differs between frameworks.\n  - This can be done for each route, or at the top of the application to avoid boilerplate, see examples\n\n> An interesting detail is that there are actually _three_ `queryClient`s involved. The framework loaders are a form of \"preloading\" phase that happens before rendering, and this phase has its own `queryClient` that does the prefetching. The dehydrated result of this phase gets passed to **both** the server rendering process **and** the client rendering process which each has its own `queryClient`. This ensures they both start with the same data so they can return the same markup.\n\n> Server Components are another form of \"preloading\" phase, that can also \"preload\" (pre-render) parts of a React component tree. Read more in the [Advanced Server Rendering guide](./advanced-ssr.md).\n\n### Full Next.js pages router example\n\n> For app router documentation, see the [Advanced Server Rendering guide](./advanced-ssr.md).\n\nInitial setup:\n\n```tsx\n// _app.tsx\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\n\nexport default function MyApp({ Component, pageProps }) {\n  const [queryClient] = React.useState(\n    () =>\n      new QueryClient({\n        defaultOptions: {\n          queries: {\n            // With SSR, we usually want to set some default staleTime\n            // above 0 to avoid refetching immediately on the client\n            staleTime: 60 * 1000,\n          },\n        },\n      }),\n  )\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      <Component {...pageProps} />\n    </QueryClientProvider>\n  )\n}\n```\n\nIn each route:\n\n```tsx\n// pages/posts.tsx\nimport {\n  dehydrate,\n  HydrationBoundary,\n  QueryClient,\n  useQuery,\n} from '@tanstack/react-query'\n\n// This could also be getServerSideProps\nexport async function getStaticProps() {\n  const queryClient = new QueryClient()\n\n  await queryClient.prefetchQuery({\n    queryKey: ['posts'],\n    queryFn: getPosts,\n  })\n\n  return {\n    props: {\n      dehydratedState: dehydrate(queryClient),\n    },\n  }\n}\n\nfunction Posts() {\n  // This useQuery could just as well happen in some deeper child to\n  // the <PostsRoute>, data will be available immediately either way\n  const { data } = useQuery({ queryKey: ['posts'], queryFn: getPosts })\n\n  // This query was not prefetched on the server and will not start\n  // fetching until on the client, both patterns are fine to mix\n  const { data: commentsData } = useQuery({\n    queryKey: ['posts-comments'],\n    queryFn: getComments,\n  })\n\n  // ...\n}\n\nexport default function PostsRoute({ dehydratedState }) {\n  return (\n    <HydrationBoundary state={dehydratedState}>\n      <Posts />\n    </HydrationBoundary>\n  )\n}\n```\n\n### Full Remix example\n\nInitial setup:\n\n```tsx\n// app/root.tsx\nimport { Outlet } from '@remix-run/react'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\n\nexport default function MyApp() {\n  const [queryClient] = React.useState(\n    () =>\n      new QueryClient({\n        defaultOptions: {\n          queries: {\n            // With SSR, we usually want to set some default staleTime\n            // above 0 to avoid refetching immediately on the client\n            staleTime: 60 * 1000,\n          },\n        },\n      }),\n  )\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      <Outlet />\n    </QueryClientProvider>\n  )\n}\n```\n\nIn each route, note that it's fine to do this in nested routes too:\n\n```tsx\n// app/routes/posts.tsx\nimport { json } from '@remix-run/node'\nimport {\n  dehydrate,\n  HydrationBoundary,\n  QueryClient,\n  useQuery,\n} from '@tanstack/react-query'\n\nexport async function loader() {\n  const queryClient = new QueryClient()\n\n  await queryClient.prefetchQuery({\n    queryKey: ['posts'],\n    queryFn: getPosts,\n  })\n\n  return json({ dehydratedState: dehydrate(queryClient) })\n}\n\nfunction Posts() {\n  // This useQuery could just as well happen in some deeper child to\n  // the <PostsRoute>, data will be available immediately either way\n  const { data } = useQuery({ queryKey: ['posts'], queryFn: getPosts })\n\n  // This query was not prefetched on the server and will not start\n  // fetching until on the client, both patterns are fine to mix\n  const { data: commentsData } = useQuery({\n    queryKey: ['posts-comments'],\n    queryFn: getComments,\n  })\n\n  // ...\n}\n\nexport default function PostsRoute() {\n  const { dehydratedState } = useLoaderData<typeof loader>()\n  return (\n    <HydrationBoundary state={dehydratedState}>\n      <Posts />\n    </HydrationBoundary>\n  )\n}\n```\n\n## Optional - Remove boilerplate\n\nHaving this part in every route might seem like a lot of boilerplate:\n\n```tsx\nexport default function PostsRoute({ dehydratedState }) {\n  return (\n    <HydrationBoundary state={dehydratedState}>\n      <Posts />\n    </HydrationBoundary>\n  )\n}\n```\n\nWhile there is nothing wrong with this approach, if you want to get rid of this boilerplate, here's how you can modify your setup in Next.js:\n\n```tsx\n// _app.tsx\nimport {\n  HydrationBoundary,\n  QueryClient,\n  QueryClientProvider,\n} from '@tanstack/react-query'\n\nexport default function MyApp({ Component, pageProps }) {\n  const [queryClient] = React.useState(() => new QueryClient())\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      <HydrationBoundary state={pageProps.dehydratedState}>\n        <Component {...pageProps} />\n      </HydrationBoundary>\n    </QueryClientProvider>\n  )\n}\n\n// pages/posts.tsx\n// Remove PostsRoute with the HydrationBoundary and instead export Posts directly:\nexport default function Posts() { ... }\n```\n\nWith Remix, this is a little bit more involved, we recommend checking out the [use-dehydrated-state](https://github.com/maplegrove-io/use-dehydrated-state) package.\n\n## Prefetching dependent queries\n\nOver in the Prefetching guide we learned how to [prefetch dependent queries](./prefetching.md#dependent-queries-code-splitting), but how do we do this in framework loaders? Consider the following code, taken from the [Dependent Queries guide](./dependent-queries.md):\n\n```tsx\n// Get the user\nconst { data: user } = useQuery({\n  queryKey: ['user', email],\n  queryFn: getUserByEmail,\n})\n\nconst userId = user?.id\n\n// Then get the user's projects\nconst {\n  status,\n  fetchStatus,\n  data: projects,\n} = useQuery({\n  queryKey: ['projects', userId],\n  queryFn: getProjectsByUser,\n  // The query will not execute until the userId exists\n  enabled: !!userId,\n})\n```\n\nHow would we prefetch this so it can be server rendered? Here's an example:\n\n```tsx\n// For Remix, rename this to loader instead\nexport async function getServerSideProps() {\n  const queryClient = new QueryClient()\n\n  const user = await queryClient.fetchQuery({\n    queryKey: ['user', email],\n    queryFn: getUserByEmail,\n  })\n\n  if (user?.userId) {\n    await queryClient.prefetchQuery({\n      queryKey: ['projects', userId],\n      queryFn: getProjectsByUser,\n    })\n  }\n\n  // For Remix:\n  // return json({ dehydratedState: dehydrate(queryClient) })\n  return { props: { dehydratedState: dehydrate(queryClient) } }\n}\n```\n\nThis can get more complex of course, but since these loader functions are just JavaScript, you can use the full power of the language to build your logic. Make sure you prefetch all queries that you want to be server rendered.\n\n## Error handling\n\nReact Query defaults to a graceful degradation strategy. This means:\n\n- `queryClient.prefetchQuery(...)` never throws errors\n- `dehydrate(...)` only includes successful queries, not failed ones\n\nThis will lead to any failed queries being retried on the client and that the server rendered output will include loading states instead of the full content.\n\nWhile a good default, sometimes this is not what you want. When critical content is missing, you might want to respond with a 404 or 500 status code depending on the situation. For these cases, use `queryClient.fetchQuery(...)` instead, which will throw errors when it fails, letting you handle things in a suitable way.\n\n```tsx\nlet result\n\ntry {\n  result = await queryClient.fetchQuery(...)\n} catch (error) {\n  // Handle the error, refer to your framework documentation\n}\n\n// You might also want to check and handle any invalid `result` here\n```\n\nIf you for some reason want to include failed queries in the dehydrated state to avoid retries, you can use the option `shouldDehydrateQuery` to override the default function and implement your own logic:\n\n```tsx\ndehydrate(queryClient, {\n  shouldDehydrateQuery: (query) => {\n    // This will include all queries, including failed ones,\n    // but you can also implement your own logic by inspecting `query`\n    return true\n  },\n})\n```\n\n## Serialization\n\nWhen doing `return { props: { dehydratedState: dehydrate(queryClient) } }` in Next.js, or `return json({ dehydratedState: dehydrate(queryClient) })` in Remix, what happens is that the `dehydratedState` representation of the `queryClient` is serialized by the framework so it can be embedded into the markup and transported to the client.\n\nBy default, these frameworks only support returning things that are safely serializable/parsable, and therefore do not support `undefined`, `Error`, `Date`, `Map`, `Set`, `BigInt`, `Infinity`, `NaN`, `-0`, regular expressions etc. This also means that you can not return any of these things from your queries. If returning these values is something you want, check out [superjson](https://github.com/blitz-js/superjson) or similar packages.\n\nIf you are using a custom SSR setup, you need to take care of this step yourself. Your first instinct might be to use `JSON.stringify(dehydratedState)`, but because this doesn't escape things like `<script>alert('Oh no..')</script>` by default, this can easily lead to **XSS-vulnerabilities** in your application. [superjson](https://github.com/blitz-js/superjson) also **does not** escape values and is unsafe to use by itself in a custom SSR setup (unless you add an extra step for escaping the output). Instead we recommend using a library like [Serialize JavaScript](https://github.com/yahoo/serialize-javascript) or [devalue](https://github.com/Rich-Harris/devalue) which are both safe against XSS injections out of the box.\n\n## A note about request waterfalls\n\nIn the [Performance & Request Waterfalls guide](./request-waterfalls.md) we mentioned we would revisit how server rendering changes one of the more complex nested waterfalls. Check back for the [specific code example](./request-waterfalls#code-splitting), but as a refresher, we have a code split `<GraphFeedItem>` component inside a `<Feed>` component. This only renders if the feed contains a graph item and both of these components fetches their own data. With client rendering, this leads to the following request waterfall:\n\n```\n1. |> Markup (without content)\n2.   |> JS for <Feed>\n3.     |> getFeed()\n4.       |> JS for <GraphFeedItem>\n5.         |> getGraphDataById()\n```\n\nThe nice thing about server rendering is that we can turn the above into:\n\n```\n1. |> Markup (with content AND initial data)\n2.   |> JS for <Feed>\n2.   |> JS for <GraphFeedItem>\n```\n\nNote that the queries are no longer fetched on the client, instead their data was included in the markup. The reason we can now load the JS in parallel is that since `<GraphFeedItem>` was rendered on the server we know that we are going to need this JS on the client as well and can insert a script-tag for this chunk in the markup. On the server, we would still have this request waterfall:\n\n```\n1. |> getFeed()\n2.   |> getGraphDataById()\n```\n\nWe simply can not know before we have fetched the feed if we also need to fetch graph data, they are dependent queries. Because this happens on the server where latency is generally both lower and more stable, this often isn't such a big deal.\n\nAmazing, we've mostly flattened our waterfalls! There's a catch though. Let's call this page the `/feed` page, and let's pretend we also have another page like `/posts`. If we type in `www.example.com/feed` directly in the url bar and hit enter, we get all these great server rendering benefits, BUT, if we instead type in `www.example.com/posts` and then **click a link** to `/feed`, we're back to this:\n\n```\n1. |> JS for <Feed>\n2.   |> getFeed()\n3.     |> JS for <GraphFeedItem>\n4.       |> getGraphDataById()\n```\n\nThis is because with SPA's, server rendering only works for the initial page load, not for any subsequent navigation.\n\nModern frameworks often try to solve this by fetching the initial code and data in parallel, so if you were using Next.js or Remix with the prefetching patterns we outlined in this guide, including how to prefetch dependent queries, it would actually look like this instead:\n\n```\n1. |> JS for <Feed>\n1. |> getFeed() + getGraphDataById()\n2.   |> JS for <GraphFeedItem>\n```\n\nThis is much better, but if we want to improve this further we can flatten this to a single roundtrip with Server Components. Learn how in the [Advanced Server Rendering guide](./advanced-ssr.md).\n\n## Tips, Tricks and Caveats\n\n### Staleness is measured from when the query was fetched on the server\n\nA query is considered stale depending on when it was `dataUpdatedAt`. A caveat here is that the server needs to have the correct time for this to work properly, but UTC time is used, so timezones do not factor into this.\n\nBecause `staleTime` defaults to `0`, queries will be refetched in the background on page load by default. You might want to use a higher `staleTime` to avoid this double fetching, especially if you don't cache your markup.\n\nThis refetching of stale queries is a perfect match when caching markup in a CDN! You can set the cache time of the page itself decently high to avoid having to re-render pages on the server, but configure the `staleTime` of the queries lower to make sure data is refetched in the background as soon as a user visits the page. Maybe you want to cache the pages for a week, but refetch the data automatically on page load if it's older than a day?\n\n### High memory consumption on server\n\nIn case you are creating the `QueryClient` for every request, React Query creates the isolated cache for this client, which is preserved in memory for the `gcTime` period. That may lead to high memory consumption on server in case of high number of requests during that period.\n\nOn the server, `gcTime` defaults to `Infinity` which disables manual garbage collection and will automatically clear memory once a request has finished. If you are explicitly setting a non-Infinity `gcTime` then you will be responsible for clearing the cache early.\n\nAvoid setting `gcTime` to `0` as it may result in a hydration error. This occurs because the [Hydration Boundary](../reference/hydration.md#hydrationboundary) places necessary data into the cache for rendering, but if the garbage collector removes the data before the rendering completes, issues may arise. If you require a shorter `gcTime`, we recommend setting it to `2 * 1000` to allow sufficient time for the app to reference the data.\n\nTo clear the cache after it is not needed and to lower memory consumption, you can add a call to [`queryClient.clear()`](../../../reference/QueryClient.md#queryclientclear) after the request is handled and dehydrated state has been sent to the client.\n\nAlternatively, you can set a smaller `gcTime`.\n\n### Caveat for Next.js rewrites\n\nThere's a catch if you're using [Next.js' rewrites feature](https://nextjs.org/docs/app/api-reference/next-config-js/rewrites) together with [Automatic Static Optimization](https://nextjs.org/docs/pages/building-your-application/rendering/automatic-static-optimization) or `getStaticProps`: It will cause a second hydration by React Query. That's because [Next.js needs to ensure that they parse the rewrites](https://nextjs.org/docs/app/api-reference/next-config-js/rewrites#rewrite-parameters) on the client and collect any params after hydration so that they can be provided in `router.query`.\n\nThe result is missing referential equality for all the hydration data, which for example triggers wherever your data is used as props of components or in the dependency array of `useEffect`s/`useMemo`s.\n"
  },
  {
    "path": "docs/framework/react/guides/suspense.md",
    "content": "---\nid: suspense\ntitle: Suspense\n---\n\nReact Query can also be used with React's Suspense for Data Fetching APIs. For this, we have dedicated hooks:\n\n- [useSuspenseQuery](../reference/useSuspenseQuery.md)\n- [useSuspenseInfiniteQuery](../reference/useSuspenseInfiniteQuery.md)\n- [useSuspenseQueries](../reference/useSuspenseQueries.md)\n- Additionally, you can use the `useQuery().promise` and `React.use()` (Experimental)\n\nWhen using suspense mode, `status` states and `error` objects are not needed and are then replaced by usage of the `React.Suspense` component (including the use of the `fallback` prop and React error boundaries for catching errors). Please read the [Resetting Error Boundaries](#resetting-error-boundaries) and look at the [Suspense Example](../examples/suspense) for more information on how to set up suspense mode.\n\nIf you want mutations to propagate errors to the nearest error boundary (similar to queries), you can set the `throwOnError` option to `true` as well.\n\nEnabling suspense mode for a query:\n\n```tsx\nimport { useSuspenseQuery } from '@tanstack/react-query'\n\nconst { data } = useSuspenseQuery({ queryKey, queryFn })\n```\n\nThis works nicely in TypeScript, because `data` is guaranteed to be defined (as errors and loading states are handled by Suspense- and ErrorBoundaries).\n\nOn the flip side, you therefore can't conditionally enable / disable the Query. This generally shouldn't be necessary for dependent Queries because with suspense, all your Queries inside one component are fetched in serial.\n\n`placeholderData` also doesn't exist for this Query. To prevent the UI from being replaced by a fallback during an update, wrap your updates that change the QueryKey into [startTransition](https://react.dev/reference/react/Suspense#preventing-unwanted-fallbacks).\n\n### throwOnError default\n\nNot all errors are thrown to the nearest Error Boundary per default - we're only throwing errors if there is no other data to show. That means if a Query ever successfully got data in the cache, the component will render, even if data is `stale`. Thus, the default for `throwOnError` is:\n\n```\nthrowOnError: (error, query) => typeof query.state.data === 'undefined'\n```\n\nSince you can't change `throwOnError` (because it would allow for `data` to become potentially `undefined`), you have to throw errors manually if you want all errors to be handled by Error Boundaries:\n\n```tsx\nimport { useSuspenseQuery } from '@tanstack/react-query'\n\nconst { data, error, isFetching } = useSuspenseQuery({ queryKey, queryFn })\n\nif (error && !isFetching) {\n  throw error\n}\n\n// continue rendering data\n```\n\n## Resetting Error Boundaries\n\nWhether you are using **suspense** or **throwOnError** in your queries, you will need a way to let queries know that you want to try again when re-rendering after some error occurred.\n\nQuery errors can be reset with the `QueryErrorResetBoundary` component or with the `useQueryErrorResetBoundary` hook.\n\nWhen using the component it will reset any query errors within the boundaries of the component:\n\n```tsx\nimport { QueryErrorResetBoundary } from '@tanstack/react-query'\nimport { ErrorBoundary } from 'react-error-boundary'\n\nconst App = () => (\n  <QueryErrorResetBoundary>\n    {({ reset }) => (\n      <ErrorBoundary\n        onReset={reset}\n        fallbackRender={({ resetErrorBoundary }) => (\n          <div>\n            There was an error!\n            <Button onClick={() => resetErrorBoundary()}>Try again</Button>\n          </div>\n        )}\n      >\n        <Page />\n      </ErrorBoundary>\n    )}\n  </QueryErrorResetBoundary>\n)\n```\n\nWhen using the hook it will reset any query errors within the closest `QueryErrorResetBoundary`. If there is no boundary defined it will reset them globally:\n\n```tsx\nimport { useQueryErrorResetBoundary } from '@tanstack/react-query'\nimport { ErrorBoundary } from 'react-error-boundary'\n\nconst App = () => {\n  const { reset } = useQueryErrorResetBoundary()\n  return (\n    <ErrorBoundary\n      onReset={reset}\n      fallbackRender={({ resetErrorBoundary }) => (\n        <div>\n          There was an error!\n          <Button onClick={() => resetErrorBoundary()}>Try again</Button>\n        </div>\n      )}\n    >\n      <Page />\n    </ErrorBoundary>\n  )\n}\n```\n\n## Fetch-on-render vs Render-as-you-fetch\n\nOut of the box, React Query in `suspense` mode works really well as a **Fetch-on-render** solution with no additional configuration. This means that when your components attempt to mount, they will trigger query fetching and suspend, but only once you have imported them and mounted them. If you want to take it to the next level and implement a **Render-as-you-fetch** model, we recommend implementing [Prefetching](./prefetching.md) on routing callbacks and/or user interactions events to start loading queries before they are mounted and hopefully even before you start importing or mounting their parent components.\n\n## Suspense on the Server with streaming\n\nIf you are using `NextJs`, you can use our **experimental** integration for Suspense on the Server: `@tanstack/react-query-next-experimental`. This package will allow you to fetch data on the server (in a client component) by just calling `useSuspenseQuery` in your component. Results will then be streamed from the server to the client as SuspenseBoundaries resolve.\n\nTo achieve this, wrap your app in the `ReactQueryStreamedHydration` component:\n\n```tsx\n// app/providers.tsx\n'use client'\n\nimport {\n  isServer,\n  QueryClient,\n  QueryClientProvider,\n} from '@tanstack/react-query'\nimport * as React from 'react'\nimport { ReactQueryStreamedHydration } from '@tanstack/react-query-next-experimental'\n\nfunction makeQueryClient() {\n  return new QueryClient({\n    defaultOptions: {\n      queries: {\n        // With SSR, we usually want to set some default staleTime\n        // above 0 to avoid refetching immediately on the client\n        staleTime: 60 * 1000,\n      },\n    },\n  })\n}\n\nlet browserQueryClient: QueryClient | undefined = undefined\n\nfunction getQueryClient() {\n  if (isServer) {\n    // Server: always make a new query client\n    return makeQueryClient()\n  } else {\n    // Browser: make a new query client if we don't already have one\n    // This is very important, so we don't re-make a new client if React\n    // suspends during the initial render. This may not be needed if we\n    // have a suspense boundary BELOW the creation of the query client\n    if (!browserQueryClient) browserQueryClient = makeQueryClient()\n    return browserQueryClient\n  }\n}\n\nexport function Providers(props: { children: React.ReactNode }) {\n  // NOTE: Avoid useState when initializing the query client if you don't\n  //       have a suspense boundary between this and the code that may\n  //       suspend because React will throw away the client on the initial\n  //       render if it suspends and there is no boundary\n  const queryClient = getQueryClient()\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      <ReactQueryStreamedHydration>\n        {props.children}\n      </ReactQueryStreamedHydration>\n    </QueryClientProvider>\n  )\n}\n```\n\nFor more information, check out the [NextJs Suspense Streaming Example](../examples/nextjs-suspense-streaming) and the [Advanced Rendering & Hydration](./advanced-ssr.md) guide.\n\n## Using `useQuery().promise` and `React.use()` (Experimental)\n\n> To enable this feature, you need to set the `experimental_prefetchInRender` option to `true` when creating your `QueryClient`\n\n**Example code:**\n\n```tsx\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      experimental_prefetchInRender: true,\n    },\n  },\n})\n```\n\n**Usage:**\n\n```tsx\nimport React from 'react'\nimport { useQuery } from '@tanstack/react-query'\nimport { fetchTodos, type Todo } from './api'\n\nfunction TodoList({ query }: { query: UseQueryResult<Todo[]> }) {\n  const data = React.use(query.promise)\n\n  return (\n    <ul>\n      {data.map((todo) => (\n        <li key={todo.id}>{todo.title}</li>\n      ))}\n    </ul>\n  )\n}\n\nexport function App() {\n  const query = useQuery({ queryKey: ['todos'], queryFn: fetchTodos })\n\n  return (\n    <>\n      <h1>Todos</h1>\n      <React.Suspense fallback={<div>Loading...</div>}>\n        <TodoList query={query} />\n      </React.Suspense>\n    </>\n  )\n}\n```\n\nFor a more complete example, see [suspense example on GitHub](https://github.com/TanStack/query/tree/main/examples/react/suspense).\n\nFor a Next.js streaming example, see [nextjs-suspense-streaming example on GitHub](https://github.com/TanStack/query/tree/main/examples/react/nextjs-suspense-streaming).\n"
  },
  {
    "path": "docs/framework/react/guides/testing.md",
    "content": "---\nid: testing\ntitle: Testing\n---\n\nReact Query works by means of hooks - either the ones we offer or custom ones that wrap around them.\n\nWith React 17 or earlier, writing unit tests for these custom hooks can be done by means of the [React Hooks Testing Library](https://react-hooks-testing-library.com/) library.\n\nInstall this by running:\n\n```sh\nnpm install @testing-library/react-hooks react-test-renderer --save-dev\n```\n\n(The `react-test-renderer` library is needed as a peer dependency of `@testing-library/react-hooks`, and needs to correspond to the version of React that you are using.)\n\n_Note_: when using React 18 or later, `renderHook` is available directly through the `@testing-library/react` package, and `@testing-library/react-hooks` is no longer required.\n\n## Our First Test\n\nOnce installed, a simple test can be written. Given the following custom hook:\n\n```tsx\nexport function useCustomHook() {\n  return useQuery({ queryKey: ['customHook'], queryFn: () => 'Hello' })\n}\n```\n\nWe can write a test for this as follows:\n\n```tsx\nimport { renderHook, waitFor } from '@testing-library/react'\n\nconst queryClient = new QueryClient()\nconst wrapper = ({ children }) => (\n  <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>\n)\n\nconst { result } = renderHook(() => useCustomHook(), { wrapper })\n\nawait waitFor(() => expect(result.current.isSuccess).toBe(true))\n\nexpect(result.current.data).toEqual('Hello')\n```\n\nNote that we provide a custom wrapper that builds the `QueryClient` and `QueryClientProvider`. This helps to ensure that our test is completely isolated from any other tests.\n\nIt is possible to write this wrapper only once, but if so we need to ensure that the `QueryClient` gets cleared before every test, and that tests don't run in parallel otherwise one test will influence the results of others.\n\n## Turn off retries\n\nThe library defaults to three retries with exponential backoff, which means that your tests are likely to timeout if you want to test an erroneous query. The easiest way to turn retries off is via the QueryClientProvider. Let's extend the above example:\n\n```tsx\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      // ✅ turns retries off\n      retry: false,\n    },\n  },\n})\nconst wrapper = ({ children }) => (\n  <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>\n)\n```\n\nThis will set the defaults for all queries in the component tree to \"no retries\". It is important to know that this will only work if your actual useQuery has no explicit retries set. If you have a query that wants 5 retries, this will still take precedence, because defaults are only taken as a fallback.\n\n## Set gcTime to Infinity with Jest\n\nIf you use Jest, you can set the `gcTime` to `Infinity` to prevent \"Jest did not exit one second after the test run completed\" error message. This is the default behavior on the server, and is only necessary to set if you are explicitly setting a `gcTime`.\n\n## Testing Network Calls\n\nThe primary use for React Query is to cache network requests, so it's important that we can test our code is making the correct network requests in the first place.\n\nThere are plenty of ways that these can be tested, but for this example we are going to use [nock](https://www.npmjs.com/package/nock).\n\nGiven the following custom hook:\n\n```tsx\nfunction useFetchData() {\n  return useQuery({\n    queryKey: ['fetchData'],\n    queryFn: () => request('/api/data'),\n  })\n}\n```\n\nWe can write a test for this as follows:\n\n```tsx\nconst queryClient = new QueryClient()\nconst wrapper = ({ children }) => (\n  <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>\n)\n\nconst expectation = nock('http://example.com').get('/api/data').reply(200, {\n  answer: 42,\n})\n\nconst { result } = renderHook(() => useFetchData(), { wrapper })\n\nawait waitFor(() => expect(result.current.isSuccess).toBe(true))\n\nexpect(result.current.data).toEqual({ answer: 42 })\n```\n\nHere we are making use of `waitFor` and waiting until the query status indicates that the request has succeeded. This way we know that our hook has finished and should have the correct data. _Note_: when using React 18, the semantics of `waitFor` have changed as noted above.\n\n## Testing Load More / Infinite Scroll\n\nFirst we need to mock our API response\n\n```tsx\nfunction generateMockedResponse(page) {\n  return {\n    page: page,\n    items: [...]\n  }\n}\n```\n\nThen, our `nock` configuration needs to differentiate responses based on the page, and we'll be using `uri` to do this.\n`uri`'s value here will be something like `\"/?page=1` or `/?page=2`\n\n```tsx\nconst expectation = nock('http://example.com')\n  .persist()\n  .query(true)\n  .get('/api/data')\n  .reply(200, (uri) => {\n    const url = new URL(`http://example.com${uri}`)\n    const { page } = Object.fromEntries(url.searchParams)\n    return generateMockedResponse(page)\n  })\n```\n\n(Notice the `.persist()`, because we'll be calling from this endpoint multiple times)\n\nNow we can safely run our tests, the trick here is to await for the data assertion to pass:\n\n```tsx\nconst { result } = renderHook(() => useInfiniteQueryCustomHook(), {\n  wrapper,\n})\n\nawait waitFor(() => expect(result.current.isSuccess).toBe(true))\n\nexpect(result.current.data.pages).toStrictEqual(generateMockedResponse(1))\n\nresult.current.fetchNextPage()\n\nawait waitFor(() =>\n  expect(result.current.data.pages).toStrictEqual([\n    ...generateMockedResponse(1),\n    ...generateMockedResponse(2),\n  ]),\n)\n\nexpectation.done()\n```\n\n_Note_: when using React 18, the semantics of `waitFor` have changed as noted above.\n\n## Further reading\n\nFor additional tips and an alternative setup using `mock-service-worker`, have a look at [this article by TkDodo on Testing React Query](https://tkdodo.eu/blog/testing-react-query).\n"
  },
  {
    "path": "docs/framework/react/guides/updates-from-mutation-responses.md",
    "content": "---\nid: updates-from-mutation-responses\ntitle: Updates from Mutation Responses\n---\n\nWhen dealing with mutations that **update** objects on the server, it's common for the new object to be automatically returned in the response of the mutation. Instead of refetching any queries for that item and wasting a network call for data we already have, we can take advantage of the object returned by the mutation function and update the existing query with the new data immediately using the [Query Client's `setQueryData`](../../../reference/QueryClient.md#queryclientsetquerydata) method:\n\n[//]: # 'Example'\n\n```tsx\nconst queryClient = useQueryClient()\n\nconst mutation = useMutation({\n  mutationFn: editTodo,\n  onSuccess: (data) => {\n    queryClient.setQueryData(['todo', { id: 5 }], data)\n  },\n})\n\nmutation.mutate({\n  id: 5,\n  name: 'Do the laundry',\n})\n\n// The query below will be updated with the response from the\n// successful mutation\nconst { status, data, error } = useQuery({\n  queryKey: ['todo', { id: 5 }],\n  queryFn: fetchTodoById,\n})\n```\n\n[//]: # 'Example'\n\nYou might want to tie the `onSuccess` logic into a reusable mutation, for that you can\ncreate a custom hook like this:\n\n[//]: # 'Example2'\n\n```tsx\nconst useMutateTodo = () => {\n  const queryClient = useQueryClient()\n\n  return useMutation({\n    mutationFn: editTodo,\n    // Notice the second argument is the variables object that the `mutate` function receives\n    onSuccess: (data, variables) => {\n      queryClient.setQueryData(['todo', { id: variables.id }], data)\n    },\n  })\n}\n```\n\n[//]: # 'Example2'\n\n## Immutability\n\nUpdates via `setQueryData` must be performed in an _immutable_ way. **DO NOT** attempt to write directly to the cache by mutating data (that you retrieved from the cache) in place. It might work at first but can lead to subtle bugs along the way.\n\n[//]: # 'Example3'\n\n```tsx\nqueryClient.setQueryData(['posts', { id }], (oldData) => {\n  if (oldData) {\n    // ❌ do not try this\n    oldData.title = 'my new post title'\n  }\n  return oldData\n})\n\nqueryClient.setQueryData(\n  ['posts', { id }],\n  // ✅ this is the way\n  (oldData) =>\n    oldData\n      ? {\n          ...oldData,\n          title: 'my new post title',\n        }\n      : oldData,\n)\n```\n\n[//]: # 'Example3'\n"
  },
  {
    "path": "docs/framework/react/guides/window-focus-refetching.md",
    "content": "---\nid: window-focus-refetching\ntitle: Window Focus Refetching\n---\n\nIf a user leaves your application and returns and the query data is stale, **TanStack Query automatically requests fresh data for you in the background**. You can disable this globally or per-query using the `refetchOnWindowFocus` option:\n\n#### Disabling Globally\n\n[//]: # 'Example'\n\n```tsx\n//\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      refetchOnWindowFocus: false, // default: true\n    },\n  },\n})\n\nfunction App() {\n  return <QueryClientProvider client={queryClient}>...</QueryClientProvider>\n}\n```\n\n[//]: # 'Example'\n\n#### Disabling Per-Query\n\n[//]: # 'Example2'\n\n```tsx\nuseQuery({\n  queryKey: ['todos'],\n  queryFn: fetchTodos,\n  refetchOnWindowFocus: false,\n})\n```\n\n[//]: # 'Example2'\n\n## Custom Window Focus Event\n\nIn rare circumstances, you may want to manage your own window focus events that trigger TanStack Query to revalidate. To do this, TanStack Query provides a `focusManager.setEventListener` function that supplies you the callback that should be fired when the window is focused and allows you to set up your own events. When calling `focusManager.setEventListener`, the previously set handler is removed (which in most cases will be the default handler) and your new handler is used instead. For example, this is the default handler:\n\n[//]: # 'Example3'\n\n```tsx\nfocusManager.setEventListener((handleFocus) => {\n  // Listen to visibilitychange\n  if (typeof window !== 'undefined' && window.addEventListener) {\n    const visibilitychangeHandler = () => {\n      handleFocus(document.visibilityState === 'visible')\n    }\n    window.addEventListener('visibilitychange', visibilitychangeHandler, false)\n    return () => {\n      // Be sure to unsubscribe if a new handler is set\n      window.removeEventListener('visibilitychange', visibilitychangeHandler)\n    }\n  }\n})\n```\n\n[//]: # 'Example3'\n[//]: # 'ReactNative'\n\n## Managing Focus in React Native\n\nInstead of event listeners on `window`, React Native provides focus information through the [`AppState` module](https://reactnative.dev/docs/appstate#app-states). You can use the `AppState` \"change\" event to trigger an update when the app state changes to \"active\":\n\n```tsx\nimport { AppState } from 'react-native'\nimport { focusManager } from '@tanstack/react-query'\n\nfunction onAppStateChange(status: AppStateStatus) {\n  if (Platform.OS !== 'web') {\n    focusManager.setFocused(status === 'active')\n  }\n}\n\nuseEffect(() => {\n  const subscription = AppState.addEventListener('change', onAppStateChange)\n\n  return () => subscription.remove()\n}, [])\n```\n\n[//]: # 'ReactNative'\n\n## Managing focus state\n\n[//]: # 'Example4'\n\n```tsx\nimport { focusManager } from '@tanstack/react-query'\n\n// Override the default focus state\nfocusManager.setFocused(true)\n\n// Fallback to the default focus check\nfocusManager.setFocused(undefined)\n```\n\n[//]: # 'Example4'\n"
  },
  {
    "path": "docs/framework/react/installation.md",
    "content": "---\nid: installation\ntitle: Installation\n---\n\nYou can install React Query via [NPM](https://npmjs.com/),\nor a good ol' `<script>` via\n[ESM.sh](https://esm.sh/).\n\n### NPM\n\n```bash\nnpm i @tanstack/react-query\n```\n\nor\n\n```bash\npnpm add @tanstack/react-query\n```\n\nor\n\n```bash\nyarn add @tanstack/react-query\n```\n\nor\n\n```bash\nbun add @tanstack/react-query\n```\n\n[//]: # 'Compatibility'\n\nReact Query is compatible with React v18+ and works with ReactDOM and React Native.\n\n> Wanna give it a spin before you download? Try out the [simple](./examples/simple) or [basic](./examples/basic) examples!\n\n[//]: # 'Compatibility'\n\n### CDN\n\nIf you're not using a module bundler or package manager, you can also use this library via an ESM-compatible CDN such as [ESM.sh](https://esm.sh/). Simply add a `<script type=\"module\">` tag to the bottom of your HTML file:\n\n[//]: # 'CDNExample'\n\n```html\n<script type=\"module\">\n  import React from 'https://esm.sh/react@18.2.0'\n  import ReactDOM from 'https://esm.sh/react-dom@18.2.0'\n  import { QueryClient } from 'https://esm.sh/@tanstack/react-query'\n</script>\n```\n\n> You can find instructions on how to use React without JSX [here](https://react.dev/reference/react/createElement#creating-an-element-without-jsx).\n\n[//]: # 'CDNExample'\n\n### Requirements\n\nReact Query is optimized for modern browsers. It is compatible with the following browsers config\n\n```\nChrome >= 91\nFirefox >= 90\nEdge >= 91\nSafari >= 15\niOS >= 15\nOpera >= 77\n```\n\n> Depending on your environment, you might need to add polyfills. If you want to support older browsers, you need to transpile the library from `node_modules` yourselves.\n\n### Recommendations\n\nIt is recommended to also use our [ESLint Plugin Query](../../eslint/eslint-plugin-query.md) to help you catch bugs and inconsistencies while you code. You can install it via:\n\n```bash\nnpm i -D @tanstack/eslint-plugin-query\n```\n\nor\n\n```bash\npnpm add -D @tanstack/eslint-plugin-query\n```\n\nor\n\n```bash\nyarn add -D @tanstack/eslint-plugin-query\n```\n\nor\n\n```bash\nbun add -D @tanstack/eslint-plugin-query\n```\n"
  },
  {
    "path": "docs/framework/react/overview.md",
    "content": "---\nid: overview\ntitle: Overview\n---\n\nTanStack Query (formerly known as React Query) is often described as the missing data-fetching library for web applications, but in more technical terms, it makes **fetching, caching, synchronizing and updating server state** in your web applications a breeze.\n\n## Motivation\n\nMost core web frameworks **do not** come with an opinionated way of fetching or updating data in a holistic way. Because of this developers end up building either meta-frameworks which encapsulate strict opinions about data-fetching, or they invent their own ways of fetching data. This usually means cobbling together component-based state and side-effects, or using more general purpose state management libraries to store and provide asynchronous data throughout their apps.\n\nWhile most traditional state management libraries are great for working with client state, they are **not so great at working with async or server state**. This is because **server state is totally different**. For starters, server state:\n\n- Is persisted remotely in a location you may not control or own\n- Requires asynchronous APIs for fetching and updating\n- Implies shared ownership and can be changed by other people without your knowledge\n- Can potentially become \"out of date\" in your applications if you're not careful\n\nOnce you grasp the nature of server state in your application, **even more challenges will arise** as you go, for example:\n\n- Caching... (possibly the hardest thing to do in programming)\n- Deduping multiple requests for the same data into a single request\n- Updating \"out of date\" data in the background\n- Knowing when data is \"out of date\"\n- Reflecting updates to data as quickly as possible\n- Performance optimizations like pagination and lazy loading data\n- Managing memory and garbage collection of server state\n- Memoizing query results with structural sharing\n\nIf you're not overwhelmed by that list, then that must mean that you've probably solved all of your server state problems already and deserve an award. However, if you are like a vast majority of people, you either have yet to tackle all or most of these challenges and we're only scratching the surface!\n\nTanStack Query is hands down one of the _best_ libraries for managing server state. It works amazingly well **out-of-the-box, with zero-config, and can be customized** to your liking as your application grows.\n\nTanStack Query allows you to defeat and overcome the tricky challenges and hurdles of _server state_ and control your app data before it starts to control you.\n\nOn a more technical note, TanStack Query will likely:\n\n- Help you remove **many** lines of complicated and misunderstood code from your application and replace with just a handful of lines of TanStack Query logic\n- Make your application more maintainable and easier to build new features without worrying about wiring up new server state data sources\n- Have a direct impact on your end-users by making your application feel faster and more responsive than ever before\n- Potentially help you save on bandwidth and increase memory performance\n\n[//]: # 'Example'\n\n## Enough talk, show me some code already!\n\nIn the example below, you can see TanStack Query in its most basic and simple form being used to fetch the GitHub stats for the TanStack Query GitHub project itself:\n\n[Open in StackBlitz](https://stackblitz.com/github/TanStack/query/tree/main/examples/react/simple)\n\n```tsx\nimport {\n  QueryClient,\n  QueryClientProvider,\n  useQuery,\n} from '@tanstack/react-query'\n\nconst queryClient = new QueryClient()\n\nexport default function App() {\n  return (\n    <QueryClientProvider client={queryClient}>\n      <Example />\n    </QueryClientProvider>\n  )\n}\n\nfunction Example() {\n  const { isPending, error, data } = useQuery({\n    queryKey: ['repoData'],\n    queryFn: () =>\n      fetch('https://api.github.com/repos/TanStack/query').then((res) =>\n        res.json(),\n      ),\n  })\n\n  if (isPending) return 'Loading...'\n\n  if (error) return 'An error has occurred: ' + error.message\n\n  return (\n    <div>\n      <h1>{data.name}</h1>\n      <p>{data.description}</p>\n      <strong>👀 {data.subscribers_count}</strong>{' '}\n      <strong>✨ {data.stargazers_count}</strong>{' '}\n      <strong>🍴 {data.forks_count}</strong>\n    </div>\n  )\n}\n```\n\n[//]: # 'Example'\n[//]: # 'Materials'\n\n## You talked me into it, so what now?\n\n- Consider taking the official [TanStack Query Course](https://query.gg?s=tanstack) (or buying it for your whole team!)\n- Learn TanStack Query at your own pace with our amazingly thorough [Walkthrough Guide](./installation.md) and [API Reference](./reference/useQuery.md)\n- See the Article [Why You Want React Query](https://tkdodo.eu/blog/why-you-want-react-query).\n\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/react/plugins/broadcastQueryClient.md",
    "content": "---\nid: broadcastQueryClient\ntitle: broadcastQueryClient (Experimental)\n---\n\n> VERY IMPORTANT: This utility is currently in an experimental stage. This means that breaking changes will happen in minor AND patch releases. Use at your own risk. If you choose to rely on this in production in an experimental stage, please lock your version to a patch-level version to avoid unexpected breakages.\n\n`broadcastQueryClient` is a utility for broadcasting and syncing the state of your queryClient between browser tabs/windows with the same origin.\n\n## Installation\n\nThis utility comes as a separate package and is available under the `'@tanstack/query-broadcast-client-experimental'` import.\n\n## Usage\n\nImport the `broadcastQueryClient` function, and pass it your `QueryClient` instance, and optionally, set a `broadcastChannel`.\n\n```tsx\nimport { broadcastQueryClient } from '@tanstack/query-broadcast-client-experimental'\n\nconst queryClient = new QueryClient()\n\nbroadcastQueryClient({\n  queryClient,\n  broadcastChannel: 'my-app',\n})\n```\n\n## API\n\n### `broadcastQueryClient`\n\nPass this function a `QueryClient` instance and optionally, a `broadcastChannel`.\n\n```tsx\nbroadcastQueryClient({ queryClient, broadcastChannel })\n```\n\n### `Options`\n\nAn object of options:\n\n```tsx\ninterface BroadcastQueryClientOptions {\n  /** The QueryClient to sync */\n  queryClient: QueryClient\n  /** This is the unique channel name that will be used\n   * to communicate between tabs and windows */\n  broadcastChannel?: string\n  /** Options for the BroadcastChannel API */\n  options?: BroadcastChannelOptions\n}\n```\n\nThe default options are:\n\n```tsx\n{\n  broadcastChannel = 'tanstack-query',\n}\n```\n"
  },
  {
    "path": "docs/framework/react/plugins/createAsyncStoragePersister.md",
    "content": "---\nid: createAsyncStoragePersister\ntitle: createAsyncStoragePersister\n---\n\n## Installation\n\nThis utility comes as a separate package and is available under the `'@tanstack/query-async-storage-persister'` import.\n\n```bash\nnpm install @tanstack/query-async-storage-persister @tanstack/react-query-persist-client\n```\n\nor\n\n```bash\npnpm add @tanstack/query-async-storage-persister @tanstack/react-query-persist-client\n```\n\nor\n\n```bash\nyarn add @tanstack/query-async-storage-persister @tanstack/react-query-persist-client\n```\n\nor\n\n```bash\nbun add @tanstack/query-async-storage-persister @tanstack/react-query-persist-client\n```\n\n## Usage\n\n- Import the `createAsyncStoragePersister` function\n- Create a new asyncStoragePersister\n  - you can pass any `storage` to it that adheres to the `AsyncStorage` interface - the example below uses the async-storage from React Native.\n  - storages that read and write synchronously, like `window.localstorage`, also adhere to the `AsyncStorage` interface and can therefore also be used with `createAsyncStoragePersister`.\n- Wrap your app by using [`PersistQueryClientProvider`](./persistQueryClient.md#persistqueryclientprovider) component.\n\n```tsx\nimport AsyncStorage from '@react-native-async-storage/async-storage'\nimport { QueryClient } from '@tanstack/react-query'\nimport { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'\nimport { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister'\n\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      gcTime: 1000 * 60 * 60 * 24, // 24 hours\n    },\n  },\n})\n\nconst asyncStoragePersister = createAsyncStoragePersister({\n  storage: AsyncStorage,\n})\n\nconst Root = () => (\n  <PersistQueryClientProvider\n    client={queryClient}\n    persistOptions={{ persister: asyncStoragePersister }}\n  >\n    <App />\n  </PersistQueryClientProvider>\n)\n\nexport default Root\n```\n\n## Retries\n\nRetries work the same as for a [SyncStoragePersister](./createSyncStoragePersister.md), except that they can also be asynchronous. You can also use all the predefined retry handlers.\n\n## API\n\n### `createAsyncStoragePersister`\n\nCall this function to create an asyncStoragePersister that you can use later with `persistQueryClient`.\n\n```tsx\ncreateAsyncStoragePersister(options: CreateAsyncStoragePersisterOptions)\n```\n\n### `Options`\n\n```tsx\ninterface CreateAsyncStoragePersisterOptions {\n  /** The storage client used for setting an retrieving items from cache */\n  storage: AsyncStorage | undefined | null\n  /** The key to use when storing the cache to localStorage */\n  key?: string\n  /** To avoid localStorage spamming,\n   * pass a time in ms to throttle saving the cache to disk */\n  throttleTime?: number\n  /** How to serialize the data to storage */\n  serialize?: (client: PersistedClient) => string\n  /** How to deserialize the data from storage */\n  deserialize?: (cachedString: string) => PersistedClient\n  /** How to retry persistence on error **/\n  retry?: AsyncPersistRetryer\n}\n\ninterface AsyncStorage<TStorageValue = string> {\n  getItem: (key: string) => MaybePromise<TStorageValue | undefined | null>\n  setItem: (key: string, value: TStorageValue) => MaybePromise<unknown>\n  removeItem: (key: string) => MaybePromise<void>\n  entries?: () => MaybePromise<Array<[key: string, value: TStorageValue]>>\n}\n```\n\nThe default options are:\n\n```tsx\n{\n  key = `REACT_QUERY_OFFLINE_CACHE`,\n  throttleTime = 1000,\n  serialize = JSON.stringify,\n  deserialize = JSON.parse,\n}\n```\n"
  },
  {
    "path": "docs/framework/react/plugins/createPersister.md",
    "content": "---\nid: createPersister\ntitle: experimental_createQueryPersister\n---\n\n## Installation\n\nThis utility comes as a separate package and is available under the `'@tanstack/query-persist-client-core'` import.\n\n```bash\nnpm install @tanstack/query-persist-client-core\n```\n\nor\n\n```bash\npnpm add @tanstack/query-persist-client-core\n```\n\nor\n\n```bash\nyarn add @tanstack/query-persist-client-core\n```\n\nor\n\n```bash\nbun add @tanstack/query-persist-client-core\n```\n\n> Note: This util is also included in the `@tanstack/react-query-persist-client` package, so you do not need to install it separately if you are using that package.\n\n## Usage\n\n- Import the `experimental_createQueryPersister` function\n- Create a new `experimental_createQueryPersister`\n  - you can pass any `storage` to it that adheres to the `AsyncStorage` interface - the example below uses the async-storage from React Native.\n- Pass that `persister` as an option to your Query. This can be done either by passing it to the `defaultOptions` of the `QueryClient` or to any `useQuery` hook instance.\n  - If you pass this `persister` as `defaultOptions`, all queries will be persisted to the provided `storage`. You can additionally narrow this down by passing `filters`. In contrast to the `persistClient` plugin, this will not persist the whole query client as a single item, but each query separately. As a key, the query hash is used.\n  - If you provide this `persister` to a single `useQuery` hook, only this Query will be persisted.\n- Note: `queryClient.setQueryData()` operations are not persisted, this means that if you perform an optimistic update and refresh the page before the query has been invalidated, your changes to the query data will be lost. See https://github.com/TanStack/query/issues/6310\n\nThis way, you do not need to store whole `QueryClient`, but choose what is worth to be persisted in your application. Each query is lazily restored (when the Query is first used) and persisted (after each run of the `queryFn`), so it does not need to be throttled. `staleTime` is also respected after restoring the Query, so if data is considered `stale`, it will be refetched immediately after restoring. If data is `fresh`, the `queryFn` will not run.\n\nGarbage collecting a Query from memory **does not** affect the persisted data. That means Queries can be kept in memory for a shorter period of time to be more **memory efficient**. If they are used the next time, they will just be restored from the persistent storage again.\n\n```tsx\nimport AsyncStorage from '@react-native-async-storage/async-storage'\nimport { QueryClient } from '@tanstack/react-query'\nimport { experimental_createQueryPersister } from '@tanstack/query-persist-client-core'\n\nconst persister = experimental_createQueryPersister({\n  storage: AsyncStorage,\n  maxAge: 1000 * 60 * 60 * 12, // 12 hours\n})\n\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      gcTime: 1000 * 30, // 30 seconds\n      persister: persister.persisterFn,\n    },\n  },\n})\n```\n\n### Adapted defaults\n\nThe `createPersister` plugin technically wraps the `queryFn`, so it doesn't restore if the `queryFn` doesn't run. In that way, it acts as a caching layer between the Query and the network. Thus, the `networkMode` defaults to `'offlineFirst'` when a persister is used, so that restoring from the persistent storage can also happen even if there is no network connection.\n\n## Additional utilities\n\nInvoking `experimental_createQueryPersister` returns additional utilities in addition to `persisterFn` for easier implementation of userland functionalities.\n\n### `persistQueryByKey(queryKey: QueryKey, queryClient: QueryClient): Promise<void>`\n\nThis function will persist `Query` to storage and key defined when creating persister.  \nThis utility might be used along `setQueryData` to persist optimistic update to storage without waiting for invalidation.\n\n```tsx\nconst persister = experimental_createQueryPersister({\n  storage: AsyncStorage,\n  maxAge: 1000 * 60 * 60 * 12, // 12 hours\n})\n\nconst queryClient = useQueryClient()\n\nuseMutation({\n  mutationFn: updateTodo,\n  onMutate: async (newTodo) => {\n    ...\n    // Optimistically update to the new value\n    queryClient.setQueryData(['todos'], (old) => [...old, newTodo])\n    // And persist it to storage\n    persister.persistQueryByKey(['todos'], queryClient)\n    ...\n  },\n})\n```\n\n### `retrieveQuery<T>(queryHash: string): Promise<T | undefined>`\n\nThis function would attempt to retrieve persisted query by `queryHash`.  \nIf `query` is `expired`, `busted` or `malformed` it would be removed from the storage instead, and `undefined` would be returned.\n\n### `persisterGc(): Promise<void>`\n\nThis function can be used to sporadically clean up stoage from `expired`, `busted` or `malformed` entries.\n\nFor this function to work, your storage must expose `entries` method that would return a `key-value tuple array`.  \nFor example `Object.entries(localStorage)` for `localStorage` or `entries` from `idb-keyval`.\n\n### `restoreQueries(queryClient: QueryClient, filters): Promise<void>`\n\nThis function can be used to restore queries that are currently stored by persister.  \nFor example when your app is starting up in offline mode, or you want all or only specific data from previous session to be immediately available without intermediate `loading` state.\n\nThe filter object supports the following properties:\n\n- `queryKey?: QueryKey`\n  - Set this property to define a query key to match on.\n- `exact?: boolean`\n  - If you don't want to search queries inclusively by query key, you can pass the `exact: true` option to return only the query with the exact query key you have passed.\n\nFor this function to work, your storage must expose `entries` method that would return a `key-value tuple array`.  \nFor example `Object.entries(localStorage)` for `localStorage` or `entries` from `idb-keyval`.\n\n### `removeQueries(filters): Promise<void>`\n\nWhen using `queryClient.removeQueries`, the data remains in the persister and needs to be removed separately.\nThis function can be used to remove queries that are currently stored by persister.\n\nThe filter object supports the following properties:\n\n- `queryKey?: QueryKey`\n  - Set this property to define a query key to match on.\n- `exact?: boolean`\n  - If you don't want to search queries inclusively by query key, you can pass the `exact: true` option to return only the query with the exact query key you have passed.\n\nFor this function to work, your storage must expose `entries` method that would return a `key-value tuple array`.  \nFor example `Object.entries(localStorage)` for `localStorage` or `entries` from `idb-keyval`.\n\n## API\n\n### `experimental_createQueryPersister`\n\n```tsx\nexperimental_createQueryPersister(options: StoragePersisterOptions)\n```\n\n#### `Options`\n\n```tsx\nexport interface StoragePersisterOptions {\n  /** The storage client used for setting and retrieving items from cache.\n   * For SSR pass in `undefined`.\n   */\n  storage: AsyncStorage | Storage | undefined | null\n  /**\n   * How to serialize the data to storage.\n   * @default `JSON.stringify`\n   */\n  serialize?: (persistedQuery: PersistedQuery) => string\n  /**\n   * How to deserialize the data from storage.\n   * @default `JSON.parse`\n   */\n  deserialize?: (cachedString: string) => PersistedQuery\n  /**\n   * A unique string that can be used to forcefully invalidate existing caches,\n   * if they do not share the same buster string\n   */\n  buster?: string\n  /**\n   * The max-allowed age of the cache in milliseconds.\n   * If a persisted cache is found that is older than this\n   * time, it will be discarded\n   * @default 24 hours\n   */\n  maxAge?: number\n  /**\n   * Prefix to be used for storage key.\n   * Storage key is a combination of prefix and query hash in a form of `prefix-queryHash`.\n   */\n  prefix?: string\n  /**\n   * If set to `true`, the query will refetch on successful query restoration if the data is stale.\n   * If set to `false`, the query will not refetch on successful query restoration.\n   * If set to `'always'`, the query will always refetch on successful query restoration.\n   * Defaults to `true`.\n   */\n  refetchOnRestore?: boolean | 'always'\n  /**\n   * Filters to narrow down which Queries should be persisted.\n   */\n  filters?: QueryFilters\n}\n\ninterface AsyncStorage<TStorageValue = string> {\n  getItem: (key: string) => MaybePromise<TStorageValue | undefined | null>\n  setItem: (key: string, value: TStorageValue) => MaybePromise<unknown>\n  removeItem: (key: string) => MaybePromise<void>\n  entries?: () => MaybePromise<Array<[key: string, value: TStorageValue]>>\n}\n```\n\nThe default options are:\n\n```tsx\n{\n  prefix = 'tanstack-query',\n  maxAge = 1000 * 60 * 60 * 24,\n  serialize = JSON.stringify,\n  deserialize = JSON.parse,\n  refetchOnRestore = true,\n}\n```\n"
  },
  {
    "path": "docs/framework/react/plugins/createSyncStoragePersister.md",
    "content": "---\nid: createSyncStoragePersister\ntitle: createSyncStoragePersister\n---\n\n## Deprecated\n\nThis plugin is deprecated and will be removed in the next major version.\nYou can simply use ['@tanstack/query-async-storage-persister'](./createAsyncStoragePersister.md) instead.\n\n## Installation\n\nThis utility comes as a separate package and is available under the `'@tanstack/query-sync-storage-persister'` import.\n\n```bash\nnpm install @tanstack/query-sync-storage-persister @tanstack/react-query-persist-client\n```\n\nor\n\n```bash\npnpm add @tanstack/query-sync-storage-persister @tanstack/react-query-persist-client\n```\n\nor\n\n```bash\nyarn add @tanstack/query-sync-storage-persister @tanstack/react-query-persist-client\n```\n\nor\n\n```bash\nbun add @tanstack/query-sync-storage-persister @tanstack/react-query-persist-client\n```\n\n## Usage\n\n- Import the `createSyncStoragePersister` function\n- Create a new syncStoragePersister\n- Pass it to the [`persistQueryClient`](./persistQueryClient.md) function\n\n```tsx\nimport { persistQueryClient } from '@tanstack/react-query-persist-client'\nimport { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister'\n\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      gcTime: 1000 * 60 * 60 * 24, // 24 hours\n    },\n  },\n})\n\nconst localStoragePersister = createSyncStoragePersister({\n  storage: window.localStorage,\n})\n// const sessionStoragePersister = createSyncStoragePersister({ storage: window.sessionStorage })\n\npersistQueryClient({\n  queryClient,\n  persister: localStoragePersister,\n})\n```\n\n## Retries\n\nPersistence can fail, e.g. if the size exceeds the available space on the storage. Errors can be handled gracefully by providing a `retry` function to the persister.\n\nThe retry function receives the `persistedClient` it tried to save, as well as the `error` and the `errorCount` as input. It is expected to return a _new_ `PersistedClient`, with which it tries to persist again. If _undefined_ is returned, there will be no further attempt to persist.\n\n```tsx\nexport type PersistRetryer = (props: {\n  persistedClient: PersistedClient\n  error: Error\n  errorCount: number\n}) => PersistedClient | undefined\n```\n\n### Predefined strategies\n\nPer default, no retry will occur. You can use one of the predefined strategies to handle retries. They can be imported `from '@tanstack/react-query-persist-client'`:\n\n- `removeOldestQuery`\n  - will return a new `PersistedClient` with the oldest query removed.\n\n```tsx\nconst localStoragePersister = createSyncStoragePersister({\n  storage: window.localStorage,\n  retry: removeOldestQuery,\n})\n```\n\n## API\n\n### `createSyncStoragePersister`\n\nCall this function to create a syncStoragePersister that you can use later with `persistQueryClient`.\n\n```tsx\ncreateSyncStoragePersister(options: CreateSyncStoragePersisterOptions)\n```\n\n### `Options`\n\n```tsx\ninterface CreateSyncStoragePersisterOptions {\n  /** The storage client used for setting an retrieving items from cache (window.localStorage or window.sessionStorage) */\n  storage: Storage | undefined | null\n  /** The key to use when storing the cache */\n  key?: string\n  /** To avoid spamming,\n   * pass a time in ms to throttle saving the cache to disk */\n  throttleTime?: number\n  /** How to serialize the data to storage */\n  serialize?: (client: PersistedClient) => string\n  /** How to deserialize the data from storage */\n  deserialize?: (cachedString: string) => PersistedClient\n  /** How to retry persistence on error **/\n  retry?: PersistRetryer\n}\n```\n\nThe default options are:\n\n```tsx\n{\n  key = `REACT_QUERY_OFFLINE_CACHE`,\n  throttleTime = 1000,\n  serialize = JSON.stringify,\n  deserialize = JSON.parse,\n}\n```\n\n#### `serialize` and `deserialize` options\n\nThere is a limit to the amount of data which can be stored in `localStorage`.\nIf you need to store more data in `localStorage`, you can override the `serialize` and `deserialize` functions to compress and decompress the data using a library like [lz-string](https://github.com/pieroxy/lz-string/).\n\n```tsx\nimport { QueryClient } from '@tanstack/react-query'\nimport { persistQueryClient } from '@tanstack/react-query-persist-client'\nimport { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister'\n\nimport { compress, decompress } from 'lz-string'\n\nconst queryClient = new QueryClient({\n  defaultOptions: { queries: { staleTime: Infinity } },\n})\n\npersistQueryClient({\n  queryClient: queryClient,\n  persister: createSyncStoragePersister({\n    storage: window.localStorage,\n    serialize: (data) => compress(JSON.stringify(data)),\n    deserialize: (data) => JSON.parse(decompress(data)),\n  }),\n  maxAge: Infinity,\n})\n```\n"
  },
  {
    "path": "docs/framework/react/plugins/persistQueryClient.md",
    "content": "---\nid: persistQueryClient\ntitle: persistQueryClient\n---\n\nThis is set of utilities for interacting with \"persisters\" which save your queryClient for later use. Different **persisters** can be used to store your client and cache to many different storage layers.\n\n## Build Persisters\n\n- [createSyncStoragePersister](./createSyncStoragePersister.md)\n- [createAsyncStoragePersister](./createAsyncStoragePersister.md)\n- [create a custom persister](#persisters)\n\n## How It Works\n\n**IMPORTANT** - for persist to work properly, you probably want to pass `QueryClient` a `gcTime` value to override the default during hydration (as shown above).\n\nIf it is not set when creating the `QueryClient` instance, it will default to `300000` (5 minutes) for hydration, and the stored cache will be discarded after 5 minutes of inactivity. This is the default garbage collection behavior.\n\nIt should be set as the same value or higher than persistQueryClient's `maxAge` option. E.g. if `maxAge` is 24 hours (the default) then `gcTime` should be 24 hours or higher. If lower than `maxAge`, garbage collection will kick in and discard the stored cache earlier than expected.\n\nYou can also pass it `Infinity` to disable garbage collection behavior entirely.\n\nDue to a JavaScript limitation, the maximum allowed `gcTime` is about [24 days](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout#maximum_delay_value), although it is possible to work around this limit using [timeoutManager.setTimeoutProvider](../../../reference/timeoutManager.md#timeoutmanagersettimeoutprovider).\n\n```tsx\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      gcTime: 1000 * 60 * 60 * 24, // 24 hours\n    },\n  },\n})\n```\n\n### Cache Busting\n\nSometimes you may make changes to your application or data that immediately invalidate any and all cached data. If and when this happens, you can pass a `buster` string option. If the cache that is found does not also have that buster string, it will be discarded. The following several functions accept this option:\n\n```tsx\npersistQueryClient({ queryClient, persister, buster: buildHash })\npersistQueryClientSave({ queryClient, persister, buster: buildHash })\npersistQueryClientRestore({ queryClient, persister, buster: buildHash })\n```\n\n### Removal\n\nIf data is found to be any of the following:\n\n1. expired (see `maxAge`)\n2. busted (see `buster`)\n3. error (ex: `throws ...`)\n4. empty (ex: `undefined`)\n\nthe persister `removeClient()` is called and the cache is immediately discarded.\n\n## API\n\n### `persistQueryClientSave`\n\n- Your query/mutation are [`dehydrated`](../reference/hydration.md#dehydrate) and stored by the persister you provided.\n- `createSyncStoragePersister` and `createAsyncStoragePersister` throttle this action to happen at most every 1 second to save on potentially expensive writes. Review their documentation to see how to customize their throttle timing.\n\nYou can use this to explicitly persist the cache at the moment(s) you choose.\n\n```tsx\npersistQueryClientSave({\n  queryClient,\n  persister,\n  buster = '',\n  dehydrateOptions = undefined,\n})\n```\n\n### `persistQueryClientSubscribe`\n\nRuns `persistQueryClientSave` whenever the cache changes for your `queryClient`. For example: you might initiate the `subscribe` when a user logs-in and checks \"Remember me\".\n\n- It returns an `unsubscribe` function which you can use to discontinue the monitor; ending the updates to the persisted cache.\n- If you want to erase the persisted cache after the `unsubscribe`, you can send a new `buster` to `persistQueryClientRestore` which will trigger the persister's `removeClient` function and discard the persisted cache.\n\n```tsx\npersistQueryClientSubscribe({\n  queryClient,\n  persister,\n  buster = '',\n  dehydrateOptions = undefined,\n})\n```\n\n### `persistQueryClientRestore`\n\n- Attempts to [`hydrate`](../reference/hydration.md#hydrate) a previously persisted dehydrated query/mutation cache from the persister back into the query cache of the passed query client.\n- If a cache is found that is older than the `maxAge` (which by default is 24 hours), it will be discarded. This timing can be customized as you see fit.\n\nYou can use this to restore the cache at moment(s) you choose.\n\n```tsx\npersistQueryClientRestore({\n  queryClient,\n  persister,\n  maxAge = 1000 * 60 * 60 * 24, // 24 hours\n  buster = '',\n  hydrateOptions = undefined,\n})\n```\n\n### `persistQueryClient`\n\nTakes the following actions:\n\n1. Immediately restores any persisted cache ([see `persistQueryClientRestore`](#persistqueryclientrestore))\n2. Subscribes to the query cache and returns the `unsubscribe` function ([see `persistQueryClientSubscribe`](#persistqueryclientsubscribe)).\n\nThis functionality is preserved from version 3.x.\n\n```tsx\npersistQueryClient({\n  queryClient,\n  persister,\n  maxAge = 1000 * 60 * 60 * 24, // 24 hours\n  buster = '',\n  hydrateOptions = undefined,\n  dehydrateOptions = undefined,\n})\n```\n\n### `Options`\n\nAll options available are as follows:\n\n```tsx\ninterface PersistQueryClientOptions {\n  /** The QueryClient to persist */\n  queryClient: QueryClient\n  /** The Persister interface for storing and restoring the cache\n   * to/from a persisted location */\n  persister: Persister\n  /** The max-allowed age of the cache in milliseconds.\n   * If a persisted cache is found that is older than this\n   * time, it will be **silently** discarded\n   * (defaults to 24 hours) */\n  maxAge?: number\n  /** A unique string that can be used to forcefully\n   * invalidate existing caches if they do not share the same buster string */\n  buster?: string\n  /** The options passed to the hydrate function\n   * Not used on `persistQueryClientSave` or `persistQueryClientSubscribe` */\n  hydrateOptions?: HydrateOptions\n  /** The options passed to the dehydrate function\n   * Not used on `persistQueryClientRestore` */\n  dehydrateOptions?: DehydrateOptions\n}\n```\n\nThere are actually three interfaces available:\n\n- `PersistedQueryClientSaveOptions` is used for `persistQueryClientSave` and `persistQueryClientSubscribe` (doesn't use `hydrateOptions`).\n- `PersistedQueryClientRestoreOptions` is used for `persistQueryClientRestore` (doesn't use `dehydrateOptions`).\n- `PersistQueryClientOptions` is used for `persistQueryClient`\n\n## Usage with React\n\n[persistQueryClient](#persistQueryClient) will try to restore the cache and automatically subscribes to further changes, thus syncing your client to the provided storage.\n\nHowever, restoring is asynchronous, because all persisters are async by nature, which means that if you render your App while you are restoring, you might get into race conditions if a query mounts and fetches at the same time.\n\nFurther, if you subscribe to changes outside of the React component lifecycle, you have no way of unsubscribing:\n\n```tsx\n// 🚨 never unsubscribes from syncing\npersistQueryClient({\n  queryClient,\n  persister: localStoragePersister,\n})\n\n// 🚨 happens at the same time as restoring\nReactDOM.createRoot(rootElement).render(<App />)\n```\n\n### PersistQueryClientProvider\n\nFor this use-case, you can use the `PersistQueryClientProvider`. It will make sure to subscribe / unsubscribe correctly according to the React component lifecycle, and it will also make sure that queries will not start fetching while we are still restoring. Queries will still render though, they will just be put into `fetchingState: 'idle'` until data has been restored. Then, they will refetch unless the restored data is _fresh_ enough, and _initialData_ will also be respected. It can be used _instead of_ the normal [QueryClientProvider](../reference/QueryClientProvider.md):\n\n```tsx\nimport { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'\nimport { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister'\n\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      gcTime: 1000 * 60 * 60 * 24, // 24 hours\n    },\n  },\n})\n\nconst persister = createAsyncStoragePersister({\n  storage: window.localStorage,\n})\n\nReactDOM.createRoot(rootElement).render(\n  <PersistQueryClientProvider\n    client={queryClient}\n    persistOptions={{ persister }}\n  >\n    <App />\n  </PersistQueryClientProvider>,\n)\n```\n\n#### Props\n\n`PersistQueryClientProvider` takes the same props as [QueryClientProvider](../reference/QueryClientProvider.md), and additionally:\n\n- `persistOptions: PersistQueryClientOptions`\n  - all [options](#options) you can pass to [persistQueryClient](#persistqueryclient) minus the QueryClient itself\n- `onSuccess?: () => Promise<unknown> | unknown`\n  - optional\n  - will be called when the initial restore is finished\n  - can be used to [resumePausedMutations](../../../reference/QueryClient.md#queryclientresumepausedmutations)\n  - if a Promise is returned, it will be awaited; restoring is seen as ongoing until then\n- `onError?: () => Promise<unknown> | unknown`\n  - optional\n  - will be called when an error is thrown during restoration\n  - if a Promise is returned, it will be awaited\n\n### useIsRestoring\n\nIf you are using the `PersistQueryClientProvider`, you can also use the `useIsRestoring` hook alongside it to check if a restore is currently in progress. `useQuery` and friends also check this internally to avoid race conditions between the restore and mounting queries.\n\n## Persisters\n\n### Persisters Interface\n\nPersisters have the following interfaces:\n\n```tsx\nexport interface Persister {\n  persistClient(persistClient: PersistedClient): Promisable<void>\n  restoreClient(): Promisable<PersistedClient | undefined>\n  removeClient(): Promisable<void>\n}\n```\n\nPersisted Client entries have the following interface:\n\n```tsx\nexport interface PersistedClient {\n  timestamp: number\n  buster: string\n  clientState: DehydratedState\n}\n```\n\nYou can import these (to build a persister):\n\n```tsx\nimport {\n  PersistedClient,\n  Persister,\n} from '@tanstack/react-query-persist-client'\n```\n\n### Building A Persister\n\nYou can persist however you like. Here is an example of how to build an [Indexed DB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) persister. Compared to `Web Storage API`, Indexed DB is faster, stores more than 5MB, and doesn't require serialization. That means it can readily store Javascript native types, such as `Date` and `File`.\n\n```tsx\nimport { get, set, del } from 'idb-keyval'\nimport {\n  PersistedClient,\n  Persister,\n} from '@tanstack/react-query-persist-client'\n\n/**\n * Creates an Indexed DB persister\n * @see https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API\n */\nexport function createIDBPersister(idbValidKey: IDBValidKey = 'reactQuery') {\n  return {\n    persistClient: async (client: PersistedClient) => {\n      await set(idbValidKey, client)\n    },\n    restoreClient: async () => {\n      return await get<PersistedClient>(idbValidKey)\n    },\n    removeClient: async () => {\n      await del(idbValidKey)\n    },\n  } satisfies Persister\n}\n```\n"
  },
  {
    "path": "docs/framework/react/quick-start.md",
    "content": "---\nid: quick-start\ntitle: Quick Start\n---\n\nThis code snippet very briefly illustrates the 3 core concepts of React Query:\n\n- [Queries](./guides/queries.md)\n- [Mutations](./guides/mutations.md)\n- [Query Invalidation](./guides/query-invalidation.md)\n\n[//]: # 'Example'\n\nIf you're looking for a fully functioning example, please have a look at our [simple StackBlitz example](./examples/simple)\n\n```tsx\nimport {\n  useQuery,\n  useMutation,\n  useQueryClient,\n  QueryClient,\n  QueryClientProvider,\n} from '@tanstack/react-query'\nimport { getTodos, postTodo } from '../my-api'\n\n// Create a client\nconst queryClient = new QueryClient()\n\nfunction App() {\n  return (\n    // Provide the client to your App\n    <QueryClientProvider client={queryClient}>\n      <Todos />\n    </QueryClientProvider>\n  )\n}\n\nfunction Todos() {\n  // Access the client\n  const queryClient = useQueryClient()\n\n  // Queries\n  const query = useQuery({ queryKey: ['todos'], queryFn: getTodos })\n\n  // Mutations\n  const mutation = useMutation({\n    mutationFn: postTodo,\n    onSuccess: () => {\n      // Invalidate and refetch\n      queryClient.invalidateQueries({ queryKey: ['todos'] })\n    },\n  })\n\n  return (\n    <div>\n      <ul>\n        {query.data?.map((todo) => (\n          <li key={todo.id}>{todo.title}</li>\n        ))}\n      </ul>\n\n      <button\n        onClick={() => {\n          mutation.mutate({\n            id: Date.now(),\n            title: 'Do Laundry',\n          })\n        }}\n      >\n        Add Todo\n      </button>\n    </div>\n  )\n}\n\nrender(<App />, document.getElementById('root'))\n```\n\n[//]: # 'Example'\n\nThese three concepts make up most of the core functionality of React Query. The next sections of the documentation will go over each of these core concepts in great detail.\n"
  },
  {
    "path": "docs/framework/react/react-native.md",
    "content": "---\nid: react-native\ntitle: React Native\n---\n\nReact Query is designed to work out of the box with React Native.\n\n## DevTools Support\n\nThere are several options available for React Native DevTools integration:\n\n1. **Native macOS App**: A 3rd party app for debugging React Query in any js-based application:\n   https://github.com/LovesWorking/rn-better-dev-tools\n\n2. **Flipper Plugin**: A 3rd party plugin for Flipper users:\n   https://github.com/bgaleotti/react-query-native-devtools\n\n3. **Reactotron Plugin**: A 3rd party plugin for Reactotron users:\n   https://github.com/hsndmr/reactotron-react-query\n\n## Online status management\n\nReact Query already supports auto refetch on reconnect in web browser.\nTo add this behavior in React Native you have to use React Query `onlineManager` as in the example below:\n\n```tsx\nimport NetInfo from '@react-native-community/netinfo'\nimport { onlineManager } from '@tanstack/react-query'\n\nonlineManager.setEventListener((setOnline) => {\n  return NetInfo.addEventListener((state) => {\n    setOnline(!!state.isConnected)\n  })\n})\n```\n\nor\n\n```tsx\nimport { onlineManager } from '@tanstack/react-query'\nimport * as Network from 'expo-network'\n\nonlineManager.setEventListener((setOnline) => {\n  let initialised = false\n\n  const eventSubscription = Network.addNetworkStateListener((state) => {\n    initialised = true\n    setOnline(!!state.isConnected)\n  })\n\n  Network.getNetworkStateAsync()\n    .then((state) => {\n      if (!initialised) {\n        setOnline(!!state.isConnected)\n      }\n    })\n    .catch(() => {\n      // getNetworkStateAsync can reject on some platforms/SDK versions\n    })\n\n  return eventSubscription.remove\n})\n```\n\n## Refetch on App focus\n\nInstead of event listeners on `window`, React Native provides focus information through the [`AppState` module](https://reactnative.dev/docs/appstate#app-states). You can use the `AppState` \"change\" event to trigger an update when the app state changes to \"active\":\n\n```tsx\nimport { useEffect } from 'react'\nimport { AppState, Platform } from 'react-native'\nimport type { AppStateStatus } from 'react-native'\nimport { focusManager } from '@tanstack/react-query'\n\nfunction onAppStateChange(status: AppStateStatus) {\n  if (Platform.OS !== 'web') {\n    focusManager.setFocused(status === 'active')\n  }\n}\n\nuseEffect(() => {\n  const subscription = AppState.addEventListener('change', onAppStateChange)\n\n  return () => subscription.remove()\n}, [])\n```\n\n## Refresh on Screen focus\n\nIn some situations, you may want to refetch the query when a React Native Screen is focused again.\nThis custom hook will refetch **all active stale queries** when the screen is focused again.\n\n```tsx\nimport React from 'react'\nimport { useFocusEffect } from '@react-navigation/native'\nimport { useQueryClient } from '@tanstack/react-query'\n\nexport function useRefreshOnFocus() {\n  const queryClient = useQueryClient()\n  const firstTimeRef = React.useRef(true)\n\n  useFocusEffect(\n    React.useCallback(() => {\n      if (firstTimeRef.current) {\n        firstTimeRef.current = false\n        return\n      }\n\n      // refetch all stale active queries\n      queryClient.refetchQueries({\n        queryKey: ['posts'],\n        stale: true,\n        type: 'active',\n      })\n    }, [queryClient]),\n  )\n}\n```\n\nIn the above code, the first focus (when the screen is initially mounted) is skipped because `useFocusEffect` calls our callback on mount in addition to screen focus.\n\n## Disable queries on out of focus screens\n\nIf you don’t want certain queries to remain “live” while a screen is out of focus, you can use the subscribed prop on useQuery. This prop lets you control whether a query stays subscribed to updates. Combined with React Navigation’s useIsFocused, it allows you to seamlessly unsubscribe from queries when a screen isn’t in focus:\n\nExample usage:\n\n```tsx\nimport React from 'react'\nimport { useIsFocused } from '@react-navigation/native'\nimport { useQuery } from '@tanstack/react-query'\nimport { Text } from 'react-native'\n\nfunction MyComponent() {\n  const isFocused = useIsFocused()\n\n  const { dataUpdatedAt } = useQuery({\n    queryKey: ['key'],\n    queryFn: () => fetch(...),\n    subscribed: isFocused,\n  })\n\n  return <Text>DataUpdatedAt: {dataUpdatedAt}</Text>\n}\n```\n\nWhen subscribed is false, the query unsubscribes from updates and won’t trigger re-renders or fetch new data for that screen. Once it becomes true again (e.g., when the screen regains focus), the query re-subscribes and stays up to date.\n"
  },
  {
    "path": "docs/framework/react/reference/QueryClientProvider.md",
    "content": "---\nid: QueryClientProvider\ntitle: QueryClientProvider\n---\n\nUse the `QueryClientProvider` component to connect and provide a `QueryClient` to your application:\n\n```tsx\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\n\nconst queryClient = new QueryClient()\n\nfunction App() {\n  return <QueryClientProvider client={queryClient}>...</QueryClientProvider>\n}\n```\n\n**Options**\n\n- `client: QueryClient`\n  - **Required**\n  - the QueryClient instance to provide\n"
  },
  {
    "path": "docs/framework/react/reference/QueryErrorResetBoundary.md",
    "content": "---\nid: QueryErrorResetBoundary\ntitle: QueryErrorResetBoundary\n---\n\nWhen using **suspense** or **throwOnError** in your queries, you need a way to let queries know that you want to try again when re-rendering after some error occurred. With the `QueryErrorResetBoundary` component you can reset any query errors within the boundaries of the component.\n\n```tsx\nimport { QueryErrorResetBoundary } from '@tanstack/react-query'\nimport { ErrorBoundary } from 'react-error-boundary'\n\nconst App = () => (\n  <QueryErrorResetBoundary>\n    {({ reset }) => (\n      <ErrorBoundary\n        onReset={reset}\n        fallbackRender={({ resetErrorBoundary }) => (\n          <div>\n            There was an error!\n            <Button onClick={() => resetErrorBoundary()}>Try again</Button>\n          </div>\n        )}\n      >\n        <Page />\n      </ErrorBoundary>\n    )}\n  </QueryErrorResetBoundary>\n)\n```\n"
  },
  {
    "path": "docs/framework/react/reference/hydration.md",
    "content": "---\nid: hydration\ntitle: hydration\n---\n\n## `dehydrate`\n\n`dehydrate` creates a frozen representation of a `cache` that can later be hydrated with `HydrationBoundary` or `hydrate`. This is useful for passing prefetched queries from server to client or persisting queries to localStorage or other persistent locations. It only includes currently successful queries by default.\n\n```tsx\nimport { dehydrate } from '@tanstack/react-query'\n\nconst dehydratedState = dehydrate(queryClient, {\n  shouldDehydrateQuery,\n  shouldDehydrateMutation,\n})\n```\n\n**Options**\n\n- `client: QueryClient`\n  - **Required**\n  - The `queryClient` that should be dehydrated\n- `options: DehydrateOptions`\n  - Optional\n  - `shouldDehydrateMutation: (mutation: Mutation) => boolean`\n    - Optional\n    - Whether to dehydrate mutations.\n    - The function is called for each mutation in the cache\n      - Return `true` to include this mutation in dehydration, or `false` otherwise\n    - Defaults to only including paused mutations\n    - If you would like to extend the function while retaining the default behavior, import and execute `defaultShouldDehydrateMutation` as part of the return statement\n  - `shouldDehydrateQuery: (query: Query) => boolean`\n    - Optional\n    - Whether to dehydrate queries.\n    - The function is called for each query in the cache\n      - Return `true` to include this query in dehydration, or `false` otherwise\n    - Defaults to only including successful queries\n    - If you would like to extend the function while retaining the default behavior, import and execute `defaultShouldDehydrateQuery` as part of the return statement\n  - `serializeData?: (data: any) => any` A function to transform (serialize) data during dehydration.\n  - `shouldRedactErrors?: (error: unknown) => boolean`\n    - Optional\n    - Whether to redact errors from the server during dehydration.\n    - The function is called for each error in the cache\n      - Return `true` to redact this error, or `false` otherwise\n    - Defaults to redacting all errors\n\n**Returns**\n\n- `dehydratedState: DehydratedState`\n  - This includes everything that is needed to hydrate the `queryClient` at a later point\n  - You **should not** rely on the exact format of this response, it is not part of the public API and can change at any time\n  - This result is not in serialized form, you need to do that yourself if desired\n\n### Limitations\n\nSome storage systems (such as browser [Web Storage API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API)) require values to be JSON serializable. If you need to dehydrate values that are not automatically serializable to JSON (like `Error` or `undefined`), you have to serialize them for yourself. Since only successful queries are included per default, to also include `Errors`, you have to provide `shouldDehydrateQuery`, e.g.:\n\n```tsx\n// server\nconst state = dehydrate(client, { shouldDehydrateQuery: () => true }) // to also include Errors\nconst serializedState = mySerialize(state) // transform Error instances to objects\n\n// client\nconst state = myDeserialize(serializedState) // transform objects back to Error instances\nhydrate(client, state)\n```\n\n## `hydrate`\n\n`hydrate` adds a previously dehydrated state into a `cache`.\n\n```tsx\nimport { hydrate } from '@tanstack/react-query'\n\nhydrate(queryClient, dehydratedState, options)\n```\n\n**Options**\n\n- `client: QueryClient`\n  - **Required**\n  - The `queryClient` to hydrate the state into\n- `dehydratedState: DehydratedState`\n  - **Required**\n  - The state to hydrate into the client\n- `options: HydrateOptions`\n  - Optional\n  - `defaultOptions: DefaultOptions`\n    - Optional\n    - `mutations: MutationOptions` The default mutation options to use for the hydrated mutations.\n    - `queries: QueryOptions` The default query options to use for the hydrated queries.\n    - `deserializeData?: (data: any) => any` A function to transform (deserialize) data before it is put into the cache.\n  - `queryClient?: QueryClient`\n    - Use this to use a custom QueryClient. Otherwise, the one from the nearest context will be used.\n\n### Limitations\n\nIf the queries you're trying to hydrate already exist in the queryCache, `hydrate` will only overwrite them if the data is newer than the data present in the cache. Otherwise, it will **not** get applied.\n\n[//]: # 'HydrationBoundary'\n\n## `HydrationBoundary`\n\n`HydrationBoundary` adds a previously dehydrated state into the `queryClient` that would be returned by `useQueryClient()`. If the client already contains data, the new queries will be intelligently merged based on update timestamp.\n\n```tsx\nimport { HydrationBoundary } from '@tanstack/react-query'\n\nfunction App() {\n  return <HydrationBoundary state={dehydratedState}>...</HydrationBoundary>\n}\n```\n\n> Note: Only `queries` can be dehydrated with an `HydrationBoundary`.\n\n**Options**\n\n- `state: DehydratedState`\n  - The state to hydrate\n- `options: HydrateOptions`\n  - Optional\n  - `defaultOptions: QueryOptions`\n    - The default query options to use for the hydrated queries.\n  - `queryClient?: QueryClient`\n    - Use this to use a custom QueryClient. Otherwise, the one from the nearest context will be used.\n\n[//]: # 'HydrationBoundary'\n"
  },
  {
    "path": "docs/framework/react/reference/infiniteQueryOptions.md",
    "content": "---\nid: infiniteQueryOptions\ntitle: infiniteQueryOptions\n---\n\n```tsx\ninfiniteQueryOptions({\n  queryKey,\n  ...options,\n})\n```\n\n**Options**\n\nYou can generally pass everything to `infiniteQueryOptions` that you can also pass to [`useInfiniteQuery`](./useInfiniteQuery.md). Some options will have no effect when then forwarded to a function like `queryClient.prefetchInfiniteQuery`, but TypeScript will still be fine with those excess properties.\n\n- `queryKey: QueryKey`\n  - **Required**\n  - The query key to generate options for.\n\nSee [useInfiniteQuery](./useInfiniteQuery.md) for more information.\n"
  },
  {
    "path": "docs/framework/react/reference/mutationOptions.md",
    "content": "---\nid: mutationOptions\ntitle: mutationOptions\n---\n\n```tsx\nmutationOptions({\n  mutationFn,\n  ...options,\n})\n```\n\n**Options**\n\nYou can generally pass everything to `mutationOptions` that you can also pass to [`useMutation`](./useMutation.md).\n"
  },
  {
    "path": "docs/framework/react/reference/queryOptions.md",
    "content": "---\nid: queryOptions\ntitle: queryOptions\n---\n\n```tsx\nqueryOptions({\n  queryKey,\n  ...options,\n})\n```\n\n**Options**\n\nYou can generally pass everything to `queryOptions` that you can also pass to [`useQuery`](./useQuery.md). Some options will have no effect when then forwarded to a function like `queryClient.prefetchQuery`, but TypeScript will still be fine with those excess properties.\n\n- `queryKey: QueryKey`\n  - **Required**\n  - The query key to generate options for.\n- `experimental_prefetchInRender?: boolean`\n  - Optional\n  - Defaults to `false`\n  - When set to `true`, queries will be prefetched during render, which can be useful for certain optimization scenarios\n  - Needs to be turned on for the experimental `useQuery().promise` functionality\n\n[//]: # 'Materials'\n\n## Further reading\n\nTo learn more about `QueryOptions`, have a look at [this article by TkDodo The Query Options API](https://tkdodo.eu/blog/the-query-options-api).\n\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/react/reference/useInfiniteQuery.md",
    "content": "---\nid: useInfiniteQuery\ntitle: useInfiniteQuery\n---\n\n```tsx\nconst {\n  fetchNextPage,\n  fetchPreviousPage,\n  hasNextPage,\n  hasPreviousPage,\n  isFetchingNextPage,\n  isFetchingPreviousPage,\n  promise,\n  ...result\n} = useInfiniteQuery({\n  queryKey,\n  queryFn: ({ pageParam }) => fetchPage(pageParam),\n  initialPageParam: 1,\n  ...options,\n  getNextPageParam: (lastPage, allPages, lastPageParam, allPageParams) =>\n    lastPage.nextCursor,\n  getPreviousPageParam: (firstPage, allPages, firstPageParam, allPageParams) =>\n    firstPage.prevCursor,\n})\n```\n\n**Options**\n\nThe options for `useInfiniteQuery` are identical to the [`useQuery` hook](../reference/useQuery.md) with the addition of the following:\n\n- `queryFn: (context: QueryFunctionContext) => Promise<TData>`\n  - **Required, but only if no default query function has been defined** [`defaultQueryFn`](../guides/default-query-function.md)\n  - The function that the query will use to request data.\n  - Receives a [QueryFunctionContext](../guides/query-functions.md#queryfunctioncontext)\n  - Must return a promise that will either resolve data or throw an error.\n- `initialPageParam: TPageParam`\n  - **Required**\n  - The default page param to use when fetching the first page.\n- `getNextPageParam: (lastPage, allPages, lastPageParam, allPageParams) => TPageParam | undefined | null`\n  - **Required**\n  - When new data is received for this query, this function receives both the last page of the infinite list of data and the full array of all pages, as well as pageParam information.\n  - It should return a **single variable** that will be passed as the last optional parameter to your query function.\n  - Return `undefined` or `null` to indicate there is no next page available.\n- `getPreviousPageParam: (firstPage, allPages, firstPageParam, allPageParams) => TPageParam | undefined | null`\n  - When new data is received for this query, this function receives both the first page of the infinite list of data and the full array of all pages, as well as pageParam information.\n  - It should return a **single variable** that will be passed as the last optional parameter to your query function.\n  - Return `undefined` or `null`to indicate there is no previous page available.\n- `maxPages: number | undefined`\n  - The maximum number of pages to store in the infinite query data.\n  - When the maximum number of pages is reached, fetching a new page will result in the removal of either the first or last page from the pages array, depending on the specified direction.\n  - If `undefined` or equals `0`, the number of pages is unlimited\n  - Default value is `undefined`\n  - `getNextPageParam` and `getPreviousPageParam` must be properly defined if `maxPages` value is greater than `0` to allow fetching a page in both directions when needed.\n\n**Returns**\n\nThe returned properties for `useInfiniteQuery` are identical to the [`useQuery` hook](../reference/useQuery.md), with the addition of the following properties and a small difference in `isRefetching` and `isRefetchError`:\n\n- `data.pages: TData[]`\n  - Array containing all pages.\n- `data.pageParams: unknown[]`\n  - Array containing all page params.\n- `isFetchingNextPage: boolean`\n  - Will be `true` while fetching the next page with `fetchNextPage`.\n- `isFetchingPreviousPage: boolean`\n  - Will be `true` while fetching the previous page with `fetchPreviousPage`.\n- `fetchNextPage: (options?: FetchNextPageOptions) => Promise<UseInfiniteQueryResult>`\n  - This function allows you to fetch the next \"page\" of results.\n  - `options.cancelRefetch: boolean` if set to `true`, calling `fetchNextPage` repeatedly will invoke `queryFn` every time, whether the previous\n    invocation has resolved or not. Also, the result from previous invocations will be ignored. If set to `false`, calling `fetchNextPage`\n    repeatedly won't have any effect until the first invocation has resolved. Default is `true`.\n- `fetchPreviousPage: (options?: FetchPreviousPageOptions) => Promise<UseInfiniteQueryResult>`\n  - This function allows you to fetch the previous \"page\" of results.\n  - `options.cancelRefetch: boolean` same as for `fetchNextPage`.\n- `hasNextPage: boolean`\n  - Will be `true` if there is a next page to be fetched (known via the `getNextPageParam` option).\n- `hasPreviousPage: boolean`\n  - Will be `true` if there is a previous page to be fetched (known via the `getPreviousPageParam` option).\n- `isFetchNextPageError: boolean`\n  - Will be `true` if the query failed while fetching the next page.\n- `isFetchPreviousPageError: boolean`\n  - Will be `true` if the query failed while fetching the previous page.\n- `isRefetching: boolean`\n  - Will be `true` whenever a background refetch is in-flight, which _does not_ include initial `pending` or fetching of next or previous page\n  - Is the same as `isFetching && !isPending && !isFetchingNextPage && !isFetchingPreviousPage`\n- `isRefetchError: boolean`\n  - Will be `true` if the query failed while refetching a page.\n- `promise: Promise<TData>`\n  - A stable promise that resolves to the query result.\n  - This can be used with `React.use()` to fetch data\n  - Requires the `experimental_prefetchInRender` feature flag to be enabled on the `QueryClient`.\n\nKeep in mind that imperative fetch calls, such as `fetchNextPage`, may interfere with the default refetch behaviour, resulting in outdated data. Make sure to call these functions only in response to user actions, or add conditions like `hasNextPage && !isFetching`.\n"
  },
  {
    "path": "docs/framework/react/reference/useIsFetching.md",
    "content": "---\nid: useIsFetching\ntitle: useIsFetching\n---\n\n`useIsFetching` is an optional hook that returns the `number` of the queries that your application is loading or fetching in the background (useful for app-wide loading indicators).\n\n```tsx\nimport { useIsFetching } from '@tanstack/react-query'\n// How many queries are fetching?\nconst isFetching = useIsFetching()\n// How many queries matching the posts prefix are fetching?\nconst isFetchingPosts = useIsFetching({ queryKey: ['posts'] })\n```\n\n**Options**\n\n- `filters?: QueryFilters`: [Query Filters](../guides/filters.md#query-filters)\n- `queryClient?: QueryClient`\n  - Use this to use a custom QueryClient. Otherwise, the one from the nearest context will be used.\n\n**Returns**\n\n- `isFetching: number`\n  - Will be the `number` of the queries that your application is currently loading or fetching in the background.\n"
  },
  {
    "path": "docs/framework/react/reference/useIsMutating.md",
    "content": "---\nid: useIsMutating\ntitle: useIsMutating\n---\n\n`useIsMutating` is an optional hook that returns the `number` of mutations that your application is fetching (useful for app-wide loading indicators).\n\n```tsx\nimport { useIsMutating } from '@tanstack/react-query'\n// How many mutations are fetching?\nconst isMutating = useIsMutating()\n// How many mutations matching the posts prefix are fetching?\nconst isMutatingPosts = useIsMutating({ mutationKey: ['posts'] })\n```\n\n**Options**\n\n- `filters?: MutationFilters`: [Mutation Filters](../guides/filters.md#mutation-filters)\n- `queryClient?: QueryClient`\n  - Use this to use a custom QueryClient. Otherwise, the one from the nearest context will be used.\n\n**Returns**\n\n- `isMutating: number`\n  - Will be the `number` of the mutations that your application is currently fetching.\n"
  },
  {
    "path": "docs/framework/react/reference/useMutation.md",
    "content": "---\nid: useMutation\ntitle: useMutation\n---\n\n```tsx\nconst {\n  data,\n  error,\n  isError,\n  isIdle,\n  isPending,\n  isPaused,\n  isSuccess,\n  failureCount,\n  failureReason,\n  mutate,\n  mutateAsync,\n  reset,\n  status,\n  submittedAt,\n  variables,\n} = useMutation(\n  {\n    mutationFn,\n    gcTime,\n    meta,\n    mutationKey,\n    networkMode,\n    onError,\n    onMutate,\n    onSettled,\n    onSuccess,\n    retry,\n    retryDelay,\n    scope,\n    throwOnError,\n  },\n  queryClient,\n)\n\nmutate(variables, {\n  onError,\n  onSettled,\n  onSuccess,\n})\n```\n\n**Parameter1 (Options)**\n\n- `mutationFn: (variables: TVariables, context: MutationFunctionContext) => Promise<TData>`\n  - **Required, but only if no default mutation function has been defined**\n  - A function that performs an asynchronous task and returns a promise.\n  - `variables` is an object that `mutate` will pass to your `mutationFn`\n  - `context` is an object that `mutate` will pass to your `mutationFn`. Contains reference to `QueryClient`, `mutationKey` and optional `meta` object.\n- `gcTime: number | Infinity`\n  - The time in milliseconds that unused/inactive cache data remains in memory. When a mutation's cache becomes unused or inactive, that cache data will be garbage collected after this duration. When different cache times are specified, the longest one will be used.\n  - If set to `Infinity`, will disable garbage collection\n  - Note: the maximum allowed time is about [24 days](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout#maximum_delay_value), although it is possible to work around this limit using [timeoutManager.setTimeoutProvider](../../../reference/timeoutManager.md#timeoutmanagersettimeoutprovider).\n- `mutationKey: unknown[]`\n  - Optional\n  - A mutation key can be set to inherit defaults set with `queryClient.setMutationDefaults`.\n- `networkMode: 'online' | 'always' | 'offlineFirst'`\n  - Optional\n  - defaults to `'online'`\n  - see [Network Mode](../guides/network-mode.md) for more information.\n- `onMutate: (variables: TVariables, context: MutationFunctionContext) => Promise<TOnMutateResult | void> | TOnMutateResult | void`\n  - Optional\n  - This function will fire before the mutation function is fired and is passed the same variables the mutation function would receive\n  - Useful to perform optimistic updates to a resource in hopes that the mutation succeeds\n  - The value returned from this function will be passed to both the `onError` and `onSettled` functions in the event of a mutation failure and can be useful for rolling back optimistic updates.\n- `onSuccess: (data: TData, variables: TVariables, onMutateResult: TOnMutateResult | undefined, context: MutationFunctionContext) => Promise<unknown> | unknown`\n  - Optional\n  - This function will fire when the mutation is successful and will be passed the mutation's result.\n  - If a promise is returned, it will be awaited and resolved before proceeding\n- `onError: (err: TError, variables: TVariables, onMutateResult: TOnMutateResult | undefined, context: MutationFunctionContext) => Promise<unknown> | unknown`\n  - Optional\n  - This function will fire if the mutation encounters an error and will be passed the error.\n  - If a promise is returned, it will be awaited and resolved before proceeding\n- `onSettled: (data: TData, error: TError, variables: TVariables, onMutateResult: TOnMutateResult | undefined, context: MutationFunctionContext) => Promise<unknown> | unknown`\n  - Optional\n  - This function will fire when the mutation is either successfully fetched or encounters an error and be passed either the data or error\n  - If a promise is returned, it will be awaited and resolved before proceeding\n- `retry: boolean | number | (failureCount: number, error: TError) => boolean`\n  - Defaults to `0`.\n  - If `false`, failed mutations will not retry.\n  - If `true`, failed mutations will retry infinitely.\n  - If set to an `number`, e.g. `3`, failed mutations will retry until the failed mutations count meets that number.\n- `retryDelay: number | (retryAttempt: number, error: TError) => number`\n  - This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds.\n  - A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff.\n  - A function like `attempt => attempt * 1000` applies linear backoff.\n- `scope: { id: string }`\n  - Optional\n  - Defaults to a unique id (so that all mutations run in parallel)\n  - Mutations with the same scope id will run in serial\n- `throwOnError: undefined | boolean | (error: TError) => boolean`\n  - Set this to `true` if you want mutation errors to be thrown in the render phase and propagate to the nearest error boundary\n  - Set this to `false` to disable the behavior of throwing errors to the error boundary.\n  - If set to a function, it will be passed the error and should return a boolean indicating whether to show the error in an error boundary (`true`) or return the error as state (`false`)\n- `meta: Record<string, unknown>`\n  - Optional\n  - If set, stores additional information on the mutation cache entry that can be used as needed. It will be accessible wherever the `mutation` is available (eg. `onError`, `onSuccess` functions of the `MutationCache`).\n\n**Parameter2 (QueryClient)**\n\n- `queryClient?: QueryClient`\n  - Use this to use a custom QueryClient. Otherwise, the one from the nearest context will be used.\n\n**Returns**\n\n- `mutate: (variables: TVariables, { onSuccess, onSettled, onError }) => void`\n  - The mutation function you can call with variables to trigger the mutation and optionally hooks on additional callback options.\n  - `variables: TVariables`\n    - Optional\n    - The variables object to pass to the `mutationFn`.\n  - `onSuccess: (data: TData, variables: TVariables, onMutateResult: TOnMutateResult | undefined, context: MutationFunctionContext) => void`\n    - Optional\n    - This function will fire when the mutation is successful and will be passed the mutation's result.\n    - Void function, the returned value will be ignored\n  - `onError: (err: TError, variables: TVariables, onMutateResult: TOnMutateResult | undefined, context: MutationFunctionContext) => void`\n    - Optional\n    - This function will fire if the mutation encounters an error and will be passed the error.\n    - Void function, the returned value will be ignored\n  - `onSettled: (data: TData | undefined, error: TError | null, variables: TVariables, onMutateResult: TOnMutateResult | undefined, context: MutationFunctionContext) => void`\n    - Optional\n    - This function will fire when the mutation is either successfully fetched or encounters an error and be passed either the data or error\n    - Void function, the returned value will be ignored\n  - If you make multiple requests, `onSuccess` will fire only after the latest call you've made.\n- `mutateAsync: (variables: TVariables, { onSuccess, onSettled, onError }) => Promise<TData>`\n  - Similar to `mutate` but returns a promise which can be awaited.\n- `status: MutationStatus`\n  - Will be:\n    - `idle` initial status prior to the mutation function executing.\n    - `pending` if the mutation is currently executing.\n    - `error` if the last mutation attempt resulted in an error.\n    - `success` if the last mutation attempt was successful.\n- `isIdle`, `isPending`, `isSuccess`, `isError`: boolean variables derived from `status`\n- `isPaused: boolean`\n  - will be `true` if the mutation has been `paused`\n  - see [Network Mode](../guides/network-mode.md) for more information.\n- `data: undefined | unknown`\n  - Defaults to `undefined`\n  - The last successfully resolved data for the mutation.\n- `error: null | TError`\n  - The error object for the query, if an error was encountered.\n- `reset: () => void`\n  - A function to clean the mutation internal state (i.e., it resets the mutation to its initial state).\n- `failureCount: number`\n  - The failure count for the mutation.\n  - Incremented every time the mutation fails.\n  - Reset to `0` when the mutation succeeds.\n- `failureReason: null | TError`\n  - The failure reason for the mutation retry.\n  - Reset to `null` when the mutation succeeds.\n- `submittedAt: number`\n  - The timestamp for when the mutation was submitted.\n  - Defaults to `0`.\n- `variables: undefined | TVariables`\n  - The `variables` object passed to the `mutationFn`.\n  - Defaults to `undefined`.\n"
  },
  {
    "path": "docs/framework/react/reference/useMutationState.md",
    "content": "---\nid: useMutationState\ntitle: useMutationState\n---\n\n`useMutationState` is a hook that gives you access to all mutations in the `MutationCache`. You can pass `filters` to it to narrow down your mutations, and `select` to transform the mutation state.\n\n**Example 1: Get all variables of all running mutations**\n\n```tsx\nimport { useMutationState } from '@tanstack/react-query'\n\nconst variables = useMutationState({\n  filters: { status: 'pending' },\n  select: (mutation) => mutation.state.variables,\n})\n```\n\n**Example 2: Get all data for specific mutations via the `mutationKey`**\n\n```tsx\nimport { useMutation, useMutationState } from '@tanstack/react-query'\n\nconst mutationKey = ['posts']\n\n// Some mutation that we want to get the state for\nconst mutation = useMutation({\n  mutationKey,\n  mutationFn: (newPost) => {\n    return axios.post('/posts', newPost)\n  },\n})\n\nconst data = useMutationState({\n  // this mutation key needs to match the mutation key of the given mutation (see above)\n  filters: { mutationKey },\n  select: (mutation) => mutation.state.data,\n})\n```\n\n**Example 3: Access the latest mutation data via the `mutationKey`**.\nEach invocation of `mutate` adds a new entry to the mutation cache for `gcTime` milliseconds.\n\nTo access the latest invocation, you can check for the last item that `useMutationState` returns.\n\n```tsx\nimport { useMutation, useMutationState } from '@tanstack/react-query'\n\nconst mutationKey = ['posts']\n\n// Some mutation that we want to get the state for\nconst mutation = useMutation({\n  mutationKey,\n  mutationFn: (newPost) => {\n    return axios.post('/posts', newPost)\n  },\n})\n\nconst data = useMutationState({\n  // this mutation key needs to match the mutation key of the given mutation (see above)\n  filters: { mutationKey },\n  select: (mutation) => mutation.state.data,\n})\n\n// Latest mutation data\nconst latest = data[data.length - 1]\n```\n\n**Options**\n\n- `options`\n  - `filters?: MutationFilters`: [Mutation Filters](../guides/filters.md#mutation-filters)\n  - `select?: (mutation: Mutation) => TResult`\n    - Use this to transform the mutation state.\n- `queryClient?: QueryClient`\n  - Use this to use a custom QueryClient. Otherwise, the one from the nearest context will be used.\n\n**Returns**\n\n- `Array<TResult>`\n  - Will be an Array of whatever `select` returns for each matching mutation.\n"
  },
  {
    "path": "docs/framework/react/reference/usePrefetchInfiniteQuery.md",
    "content": "---\nid: usePrefetchInfiniteQuery\ntitle: usePrefetchInfiniteQuery\n---\n\n```tsx\nusePrefetchInfiniteQuery(options)\n```\n\n**Options**\n\nYou can pass everything to `usePrefetchInfiniteQuery` that you can pass to [`queryClient.prefetchInfiniteQuery`](../../../reference/QueryClient.md#queryclientprefetchinfinitequery). Remember that some of them are required as below:\n\n- `queryKey: QueryKey`\n  - **Required**\n  - The query key to prefetch during render\n\n- `queryFn: (context: QueryFunctionContext) => Promise<TData>`\n  - **Required, but only if no default query function has been defined** See [Default Query Function](../guides/default-query-function.md) for more information.\n\n- `initialPageParam: TPageParam`\n  - **Required**\n  - The default page param to use when fetching the first page.\n\n- `getNextPageParam: (lastPage, allPages, lastPageParam, allPageParams) => TPageParam | undefined | null`\n  - **Required**\n  - When new data is received for this query, this function receives both the last page of the infinite list of data and the full array of all pages, as well as pageParam information.\n  - It should return a **single variable** that will be passed as the last optional parameter to your query function.\n  - Return `undefined` or `null` to indicate there is no next page available.\n\n- **Returns**\n\nThe `usePrefetchInfiniteQuery` does not return anything, it should be used just to fire a prefetch during render, before a suspense boundary that wraps a component that uses [`useSuspenseInfiniteQuery`](./useSuspenseInfiniteQuery.md)\n"
  },
  {
    "path": "docs/framework/react/reference/usePrefetchQuery.md",
    "content": "---\nid: usePrefetchQuery\ntitle: usePrefetchQuery\n---\n\n```tsx\nusePrefetchQuery(options)\n```\n\n**Options**\n\nYou can pass everything to `usePrefetchQuery` that you can pass to [`queryClient.prefetchQuery`](../../../reference/QueryClient.md#queryclientprefetchquery). Remember that some of them are required as below:\n\n- `queryKey: QueryKey`\n  - **Required**\n  - The query key to prefetch during render\n\n- `queryFn: (context: QueryFunctionContext) => Promise<TData>`\n  - **Required, but only if no default query function has been defined** See [Default Query Function](../guides/default-query-function.md) for more information.\n\n**Returns**\n\nThe `usePrefetchQuery` does not return anything, it should be used just to fire a prefetch during render, before a suspense boundary that wraps a component that uses [`useSuspenseQuery`](./useSuspenseQuery.md).\n"
  },
  {
    "path": "docs/framework/react/reference/useQueries.md",
    "content": "---\nid: useQueries\ntitle: useQueries\n---\n\nThe `useQueries` hook can be used to fetch a variable number of queries:\n\n```tsx\nconst ids = [1, 2, 3]\nconst results = useQueries({\n  queries: ids.map((id) => ({\n    queryKey: ['post', id],\n    queryFn: () => fetchPost(id),\n    staleTime: Infinity,\n  })),\n})\n```\n\n**Options**\n\nThe `useQueries` hook accepts an options object with a **queries** key whose value is an array with query option objects identical to the [`useQuery` hook](./useQuery.md) (excluding the `queryClient` option - because the `QueryClient` can be passed in on the top level).\n\n- `queryClient?: QueryClient`\n  - Use this to provide a custom QueryClient. Otherwise, the one from the nearest context will be used.\n- `combine?: (result: UseQueriesResults) => TCombinedResult`\n  - Use this to combine the results of the queries into a single value.\n\n> Having the same query key more than once in the array of query objects may cause some data to be shared between queries. To avoid this, consider de-duplicating the queries and map the results back to the desired structure.\n\n**placeholderData**\n\nThe `placeholderData` option exists for `useQueries` as well, but it doesn't get information passed from previously rendered Queries like `useQuery` does, because the input to `useQueries` can be a different number of Queries on each render.\n\n**Returns**\n\nThe `useQueries` hook returns an array with all the query results. The order returned is the same as the input order.\n\n## Combine\n\nIf you want to combine `data` (or other Query information) from the results into a single value, you can use the `combine` option. The result will be structurally shared to be as referentially stable as possible.\n\n```tsx\nconst ids = [1, 2, 3]\nconst combinedQueries = useQueries({\n  queries: ids.map((id) => ({\n    queryKey: ['post', id],\n    queryFn: () => fetchPost(id),\n  })),\n  combine: (results) => {\n    return {\n      data: results.map((result) => result.data),\n      pending: results.some((result) => result.isPending),\n    }\n  },\n})\n```\n\nIn the above example, `combinedQueries` will be an object with a `data` and a `pending` property. Note that all other properties of the Query results will be lost.\n\n### Memoization\n\nThe `combine` function will only re-run if:\n\n- the `combine` function itself changed referentially\n- any of the query results changed\n\nThis means that an inlined `combine` function, as shown above, will run on every render. To avoid this, you can wrap the `combine` function in `useCallback`, or extract it to a stable function reference if it doesn't have any dependencies.\n"
  },
  {
    "path": "docs/framework/react/reference/useQuery.md",
    "content": "---\nid: useQuery\ntitle: useQuery\n---\n\n```tsx\nconst {\n  data,\n  dataUpdatedAt,\n  error,\n  errorUpdatedAt,\n  failureCount,\n  failureReason,\n  fetchStatus,\n  isError,\n  isFetched,\n  isFetchedAfterMount,\n  isFetching,\n  isInitialLoading,\n  isLoading,\n  isLoadingError,\n  isPaused,\n  isPending,\n  isPlaceholderData,\n  isRefetchError,\n  isRefetching,\n  isStale,\n  isSuccess,\n  isEnabled,\n  promise,\n  refetch,\n  status,\n} = useQuery(\n  {\n    queryKey,\n    queryFn,\n    gcTime,\n    enabled,\n    networkMode,\n    initialData,\n    initialDataUpdatedAt,\n    meta,\n    notifyOnChangeProps,\n    placeholderData,\n    queryKeyHashFn,\n    refetchInterval,\n    refetchIntervalInBackground,\n    refetchOnMount,\n    refetchOnReconnect,\n    refetchOnWindowFocus,\n    retry,\n    retryOnMount,\n    retryDelay,\n    select,\n    staleTime,\n    structuralSharing,\n    subscribed,\n    throwOnError,\n  },\n  queryClient,\n)\n```\n\n**Parameter1 (Options)**\n\n- `queryKey: unknown[]`\n  - **Required**\n  - The query key to use for this query.\n  - The query key will be hashed into a stable hash. See [Query Keys](../guides/query-keys.md) for more information.\n  - The query will automatically update when this key changes (as long as `enabled` is not set to `false`).\n- `queryFn: (context: QueryFunctionContext) => Promise<TData>`\n  - **Required, but only if no default query function has been defined** See [Default Query Function](../guides/default-query-function.md) for more information.\n  - The function that the query will use to request data.\n  - Receives a [QueryFunctionContext](../guides/query-functions.md#queryfunctioncontext)\n  - Must return a promise that will either resolve data or throw an error. The data cannot be `undefined`.\n- `enabled: boolean | (query: Query) => boolean`\n  - Set this to `false` to disable this query from automatically running.\n  - Can be used for [Dependent Queries](../guides/dependent-queries.md).\n- `networkMode: 'online' | 'always' | 'offlineFirst'`\n  - optional\n  - defaults to `'online'`\n  - see [Network Mode](../guides/network-mode.md) for more information.\n- `retry: boolean | number | (failureCount: number, error: TError) => boolean`\n  - If `false`, failed queries will not retry by default.\n  - If `true`, failed queries will retry infinitely.\n  - If set to a `number`, e.g. `3`, failed queries will retry until the failed query count meets that number.\n  - If set to a function, it will be called with `failureCount` (starting at `0` for the first retry) and `error` to determine if a retry should be attempted.\n  - defaults to `3` on the client and `0` on the server\n- `retryOnMount: boolean`\n  - If set to `false`, the query will not be retried on mount if it contains an error. Defaults to `true`.\n- `retryDelay: number | (retryAttempt: number, error: TError) => number`\n  - This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds.\n  - A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff.\n  - A function like `attempt => attempt * 1000` applies linear backoff.\n- `staleTime: number | 'static' | ((query: Query) => number | 'static')`\n  - Optional\n  - Defaults to `0`\n  - The time in milliseconds after which data is considered stale. This value only applies to the hook it is defined on.\n  - If set to `Infinity`, the data will not be considered stale unless manually invalidated\n  - If set to a function, the function will be executed with the query to compute a `staleTime`.\n  - If set to `'static'`, the data will never be considered stale\n- `gcTime: number | Infinity`\n  - Defaults to `5 * 60 * 1000` (5 minutes) or `Infinity` during SSR\n  - The time in milliseconds that unused/inactive cache data remains in memory. When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration. When different garbage collection times are specified, the longest one will be used.\n  - Note: the maximum allowed time is about [24 days](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout#maximum_delay_value), although it is possible to work around this limit using [timeoutManager.setTimeoutProvider](../../../reference/timeoutManager.md#timeoutmanagersettimeoutprovider).\n  - If set to `Infinity`, will disable garbage collection\n- `queryKeyHashFn: (queryKey: QueryKey) => string`\n  - Optional\n  - If specified, this function is used to hash the `queryKey` to a string.\n- `refetchInterval: number | false | ((query: Query) => number | false | undefined)`\n  - Optional\n  - If set to a number, all queries will continuously refetch at this frequency in milliseconds\n  - If set to a function, the function will be executed with the query to compute a frequency\n- `refetchIntervalInBackground: boolean`\n  - Optional\n  - If set to `true`, queries that are set to continuously refetch with a `refetchInterval` will continue to refetch while their tab/window is in the background\n- `refetchOnMount: boolean | \"always\" | ((query: Query) => boolean | \"always\")`\n  - Optional\n  - Defaults to `true`\n  - If set to `true`, the query will refetch on mount if the data is stale.\n  - If set to `false`, the query will not refetch on mount.\n  - If set to `\"always\"`, the query will always refetch on mount (except when `staleTime: 'static'` is used).\n  - If set to a function, the function will be executed with the query to compute the value\n- `refetchOnWindowFocus: boolean | \"always\" | ((query: Query) => boolean | \"always\")`\n  - Optional\n  - Defaults to `true`\n  - If set to `true`, the query will refetch on window focus if the data is stale.\n  - If set to `false`, the query will not refetch on window focus.\n  - If set to `\"always\"`, the query will always refetch on window focus (except when `staleTime: 'static'` is used).\n  - If set to a function, the function will be executed with the query to compute the value\n- `refetchOnReconnect: boolean | \"always\" | ((query: Query) => boolean | \"always\")`\n  - Optional\n  - Defaults to `true`\n  - If set to `true`, the query will refetch on reconnect if the data is stale.\n  - If set to `false`, the query will not refetch on reconnect.\n  - If set to `\"always\"`, the query will always refetch on reconnect (except when `staleTime: 'static'` is used).\n  - If set to a function, the function will be executed with the query to compute the value\n- `notifyOnChangeProps: string[] | \"all\" | (() => string[] | \"all\" | undefined)`\n  - Optional\n  - If set, the component will only re-render if any of the listed properties change.\n  - If set to `['data', 'error']` for example, the component will only re-render when the `data` or `error` properties change.\n  - If set to `\"all\"`, the component will opt-out of smart tracking and re-render whenever a query is updated.\n  - If set to a function, the function will be executed to compute the list of properties.\n  - By default, access to properties will be tracked, and the component will only re-render when one of the tracked properties change.\n- `select: (data: TData) => unknown`\n  - Optional\n  - This option can be used to transform or select a part of the data returned by the query function. It affects the returned `data` value, but does not affect what gets stored in the query cache.\n  - The `select` function will only run if `data` changed, or if the reference to the `select` function itself changes. To optimize, wrap the function in `useCallback`.\n- `initialData: TData | () => TData`\n  - Optional\n  - If set, this value will be used as the initial data for the query cache (as long as the query hasn't been created or cached yet)\n  - If set to a function, the function will be called **once** during the shared/root query initialization, and be expected to synchronously return the initialData\n  - Initial data is considered stale by default unless a `staleTime` has been set.\n  - `initialData` **is persisted** to the cache\n- `initialDataUpdatedAt: number | (() => number | undefined)`\n  - Optional\n  - If set, this value will be used as the time (in milliseconds) of when the `initialData` itself was last updated.\n- `placeholderData: TData | (previousValue: TData | undefined, previousQuery: Query | undefined) => TData`\n  - Optional\n  - If set, this value will be used as the placeholder data for this particular query observer while the query is still in the `pending` state.\n  - `placeholderData` is **not persisted** to the cache\n  - If you provide a function for `placeholderData`, as a first argument you will receive previously watched query data if available, and the second argument will be the complete previousQuery instance.\n- `structuralSharing: boolean | (oldData: unknown | undefined, newData: unknown) => unknown`\n  - Optional\n  - Defaults to `true`\n  - If set to `false`, structural sharing between query results will be disabled.\n  - If set to a function, the old and new data values will be passed through this function, which should combine them into resolved data for the query. This way, you can retain references from the old data to improve performance even when that data contains non-serializable values.\n- `subscribed: boolean`\n  - Optional\n  - Defaults to `true`\n  - If set to `false`, this instance of `useQuery` will not be subscribed to the cache. This means it won't trigger the `queryFn` on its own, and it won't receive updates if data gets into cache by other means.\n- `throwOnError: undefined | boolean | (error: TError, query: Query) => boolean`\n  - Set this to `true` if you want errors to be thrown in the render phase and propagate to the nearest error boundary\n  - Set this to `false` to disable `suspense`'s default behavior of throwing errors to the error boundary.\n  - If set to a function, it will be passed the error and the query, and it should return a boolean indicating whether to show the error in an error boundary (`true`) or return the error as state (`false`)\n- `meta: Record<string, unknown>`\n  - Optional\n  - If set, stores additional information on the query cache entry that can be used as needed. It will be accessible wherever the `query` is available, and is also part of the `QueryFunctionContext` provided to the `queryFn`.\n\n**Parameter2 (QueryClient)**\n\n- `queryClient?: QueryClient`\n  - Use this to use a custom QueryClient. Otherwise, the one from the nearest context will be used.\n\n**Returns**\n\n- `status: QueryStatus`\n  - Will be:\n    - `pending` if there's no cached data and no query attempt was finished yet.\n    - `error` if the query attempt resulted in an error. The corresponding `error` property has the error received from the attempted fetch\n    - `success` if the query has received a response with no errors and is ready to display its data. The corresponding `data` property on the query is the data received from the successful fetch or if the query's `enabled` property is set to `false` and has not been fetched yet `data` is the first `initialData` supplied to the query on initialization.\n- `isPending: boolean`\n  - A derived boolean from the `status` variable above, provided for convenience.\n- `isSuccess: boolean`\n  - A derived boolean from the `status` variable above, provided for convenience.\n- `isError: boolean`\n  - A derived boolean from the `status` variable above, provided for convenience.\n- `isLoadingError: boolean`\n  - Will be `true` if the query failed while fetching for the first time.\n- `isRefetchError: boolean`\n  - Will be `true` if the query failed while refetching.\n- `data: TData`\n  - Defaults to `undefined`.\n  - The last successfully resolved data for the query.\n- `dataUpdatedAt: number`\n  - The timestamp for when the query most recently returned the `status` as `\"success\"`.\n- `error: null | TError`\n  - Defaults to `null`\n  - The error object for the query, if an error was thrown.\n- `errorUpdatedAt: number`\n  - The timestamp for when the query most recently returned the `status` as `\"error\"`.\n- `isStale: boolean`\n  - Will be `true` if the data in the cache is invalidated or if the data is older than the given `staleTime`.\n- `isPlaceholderData: boolean`\n  - Will be `true` if the data shown is the placeholder data.\n- `isFetched: boolean`\n  - Will be `true` if the query has been fetched.\n- `isFetchedAfterMount: boolean`\n  - Will be `true` if the query has been fetched after the component mounted.\n  - This property can be used to not show any previously cached data.\n- `fetchStatus: FetchStatus`\n  - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetches.\n  - `paused`: The query wanted to fetch, but has been `paused`.\n  - `idle`: The query is not fetching.\n  - see [Network Mode](../guides/network-mode.md) for more information.\n- `isFetching: boolean`\n  - A derived boolean from the `fetchStatus` variable above, provided for convenience.\n- `isPaused: boolean`\n  - A derived boolean from the `fetchStatus` variable above, provided for convenience.\n- `isRefetching: boolean`\n  - Is `true` whenever a background refetch is in-flight, which _does not_ include initial `pending`\n  - Is the same as `isFetching && !isPending`\n- `isLoading: boolean`\n  - Is `true` whenever the first fetch for a query is in-flight\n  - Is the same as `isFetching && isPending`\n- `isInitialLoading: boolean`\n  - **deprecated**\n  - An alias for `isLoading`, will be removed in the next major version.\n- `isEnabled: boolean`\n  - Is `true` if this query observer is enabled, `false` otherwise.\n- `failureCount: number`\n  - The failure count for the query.\n  - Incremented every time the query fails.\n  - Reset to `0` when the query succeeds.\n- `failureReason: null | TError`\n  - The failure reason for the query retry.\n  - Reset to `null` when the query succeeds.\n- `errorUpdateCount: number`\n  - The sum of all errors.\n- `refetch: (options: { throwOnError: boolean, cancelRefetch: boolean }) => Promise<UseQueryResult>`\n  - A function to manually refetch the query.\n  - If the query errors, the error will only be logged. If you want an error to be thrown, pass the `throwOnError: true` option\n  - `cancelRefetch?: boolean`\n    - Defaults to `true`\n      - Per default, a currently running request will be cancelled before a new request is made\n    - When set to `false`, no refetch will be made if there is already a request running.\n- `promise: Promise<TData>`\n  - A stable promise that will be resolved with the data of the query.\n  - Requires the `experimental_prefetchInRender` feature flag to be enabled on the `QueryClient`.\n"
  },
  {
    "path": "docs/framework/react/reference/useQueryClient.md",
    "content": "---\nid: useQueryClient\ntitle: useQueryClient\n---\n\nThe `useQueryClient` hook returns the current `QueryClient` instance.\n\n```tsx\nimport { useQueryClient } from '@tanstack/react-query'\n\nconst queryClient = useQueryClient(queryClient?: QueryClient)\n```\n\n**Options**\n\n- `queryClient?: QueryClient`\n  - Use this to use a custom QueryClient. Otherwise, the one from the nearest context will be used.\n"
  },
  {
    "path": "docs/framework/react/reference/useQueryErrorResetBoundary.md",
    "content": "---\nid: useQueryErrorResetBoundary\ntitle: useQueryErrorResetBoundary\n---\n\nThis hook will reset any query errors within the closest `QueryErrorResetBoundary`. If there is no boundary defined it will reset them globally:\n\n```tsx\nimport { useQueryErrorResetBoundary } from '@tanstack/react-query'\nimport { ErrorBoundary } from 'react-error-boundary'\n\nconst App = () => {\n  const { reset } = useQueryErrorResetBoundary()\n  return (\n    <ErrorBoundary\n      onReset={reset}\n      fallbackRender={({ resetErrorBoundary }) => (\n        <div>\n          There was an error!\n          <Button onClick={() => resetErrorBoundary()}>Try again</Button>\n        </div>\n      )}\n    >\n      <Page />\n    </ErrorBoundary>\n  )\n}\n```\n"
  },
  {
    "path": "docs/framework/react/reference/useSuspenseInfiniteQuery.md",
    "content": "---\nid: useSuspenseInfiniteQuery\ntitle: useSuspenseInfiniteQuery\n---\n\n```tsx\nconst result = useSuspenseInfiniteQuery(options)\n```\n\n**Options**\n\nThe same as for [useInfiniteQuery](./useInfiniteQuery.md), except for:\n\n- `suspense`\n- `throwOnError`\n- `enabled`\n- `placeholderData`\n\n**Returns**\n\nSame object as [useInfiniteQuery](./useInfiniteQuery.md), except that:\n\n- `data` is guaranteed to be defined\n- `isPlaceholderData` is missing\n- `status` is either `success` or `error`\n  - the derived flags are set accordingly.\n\n**Caveat**\n\n[Cancellation](../guides/query-cancellation.md) does not work.\n"
  },
  {
    "path": "docs/framework/react/reference/useSuspenseQueries.md",
    "content": "---\nid: useSuspenseQueries\ntitle: useSuspenseQueries\n---\n\n```tsx\nconst result = useSuspenseQueries(options)\n```\n\n**Options**\n\nThe same as for [useQueries](./useQueries.md), except that each `query` can't have:\n\n- `suspense`\n- `throwOnError`\n- `enabled`\n- `placeholderData`\n\n**Returns**\n\nSame structure as [useQueries](./useQueries.md), except that for each `query`:\n\n- `data` is guaranteed to be defined\n- `isPlaceholderData` is missing\n- `status` is either `success` or `error`\n  - the derived flags are set accordingly.\n\n**Caveats**\n\nKeep in mind that the component will only re-mount after **all queries** have finished loading. Hence, if a query has gone stale in the time it took for all the queries to complete, it will be fetched again at re-mount. To avoid this, make sure to set a high enough `staleTime`.\n\n[Cancellation](../guides/query-cancellation.md) does not work.\n"
  },
  {
    "path": "docs/framework/react/reference/useSuspenseQuery.md",
    "content": "---\nid: useSuspenseQuery\ntitle: useSuspenseQuery\n---\n\n```tsx\nconst result = useSuspenseQuery(options)\n```\n\n**Options**\n\nThe same as for [useQuery](./useQuery.md), except for:\n\n- `throwOnError`\n- `enabled`\n- `placeholderData`\n\n**Returns**\n\nSame object as [useQuery](./useQuery.md), except that:\n\n- `data` is guaranteed to be defined\n- `isPlaceholderData` is missing\n- `status` is either `success` or `error`\n  - the derived flags are set accordingly.\n\n**Caveat**\n\n[Cancellation](../guides/query-cancellation.md) does not work.\n"
  },
  {
    "path": "docs/framework/react/typescript.md",
    "content": "---\nid: typescript\ntitle: TypeScript\n---\n\nReact Query is now written in **TypeScript** to make sure the library and your projects are type-safe!\n\nThings to keep in mind:\n\n- TanStack Query follows [DefinitelyTyped's support window](https://github.com/DefinitelyTyped/DefinitelyTyped#support-window) and supports TypeScript versions released within the last 2 years. At the moment, that means TypeScript **5.4** and newer.\n- Changes to types in this repository are considered **non-breaking** and are usually released as **patch** semver changes (otherwise every type enhancement would be a major version!).\n- It is **highly recommended that you lock your react-query package version to a specific patch release and upgrade with the expectation that types may be fixed or upgraded between any release**\n- The non-type-related public API of React Query still follows semver very strictly.\n\n## Type Inference\n\nTypes in React Query generally flow through very well so that you don't have to provide type annotations for yourself\n\n[//]: # 'TypeInference1'\n\n```tsx\nconst { data } = useQuery({\n  //    ^? const data: number | undefined\n  queryKey: ['test'],\n  queryFn: () => Promise.resolve(5),\n})\n```\n\n[typescript playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgVwM4FMCKz1QJ5wC+cAZlBCHAORToCGAxjALQCOO+VAsAFC8MQAdqnhIAJnRh0icALwoM2XHgAUAbSqDkIAEa4qAXQA0cFQEo5APjgAFciGAYAdLVQQANgDd0KgKxmzXgB6ILgw8IA9AH5eIA)\n\n[//]: # 'TypeInference1'\n[//]: # 'TypeInference2'\n\n```tsx\nconst { data } = useQuery({\n  //      ^? const data: string | undefined\n  queryKey: ['test'],\n  queryFn: () => Promise.resolve(5),\n  select: (data) => data.toString(),\n})\n```\n\n[typescript playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgVwM4FMCKz1QJ5wC+cAZlBCHAORToCGAxjALQCOO+VAsAFC8MQAdqnhIAJnRh0icALwoM2XHgAUAbSox0IqgF0ANHBUBKOQD44ABXIhgGAHS1UEADYA3dCoCsxw0gwu6EwAXHASUuZhknT2MBAAyjBQwIIA5iaExrwA9Nlw+QUAegD8vEA)\n\n[//]: # 'TypeInference2'\n\nThis works best if your `queryFn` has a well-defined returned type. Keep in mind that most data fetching libraries return `any` per default, so make sure to extract it to a properly typed function:\n\n[//]: # 'TypeInference3'\n\n```tsx\nconst fetchGroups = (): Promise<Group[]> =>\n  axios.get('/groups').then((response) => response.data)\n\nconst { data } = useQuery({ queryKey: ['groups'], queryFn: fetchGroups })\n//      ^? const data: Group[] | undefined\n```\n\n[typescript playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgVwM4FMCKz1QJ5wC+cAZlBCHAORToCGAxjALQCOO+VAsAFCiSw4dAB7AIqUuUpURY1Nx68YeMOjgBxcsjBwAvIjjAAJgC44AO2QgARriK9eDCOdTwS6GAwAWmiNon6ABQAlGYAClLAGAA8vtoA2gC6AHx6qbLiAHQA5h6BVAD02Vpg8sGZMF7o5oG0qJAuarqpdQ0YmUZ0MHTBDjxOLvBInd1EeigY2Lh4gfFUxX6lVIkANKQe3nGlvTwFBXAHhwB6APxwA65wI3RmW0lwAD4o5kboJMDm6Ea8QA)\n\n[//]: # 'TypeInference3'\n\n## Type Narrowing\n\nReact Query uses a [discriminated union type](https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-func.html#discriminated-unions) for the query result, discriminated by the `status` field and the derived status boolean flags. This will allow you to check for e.g. `success` status to make `data` defined:\n\n[//]: # 'TypeNarrowing'\n\n```tsx\nconst { data, isSuccess } = useQuery({\n  queryKey: ['test'],\n  queryFn: () => Promise.resolve(5),\n})\n\nif (isSuccess) {\n  data\n  //  ^? const data: number\n}\n```\n\n[typescript playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgVwM4FMCKz1QJ5wC+cAZlBCHAORToCGAxjALQCOO+VAsAFC8MQAdqnhIAJnRh0ANHGCoAysgYN0qVETgBeFBmy48ACgDaVGGphUAurMMBKbQD44ABXIh56AHS1UEADYAbuiGAKx2dry8wCRwhvJKKmqoDgi8cBlwElK8APS5GQB6APy8hLxAA)\n\n[//]: # 'TypeNarrowing'\n\n## Typing the error field\n\nThe type for error defaults to `Error`, because that is what most users expect.\n\n[//]: # 'TypingError'\n\n```tsx\nconst { error } = useQuery({ queryKey: ['groups'], queryFn: fetchGroups })\n//      ^? const error: Error\n```\n\n[typescript playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgVwM4FMCKz1QJ5wC+cAZlBCHAOQACMAhgHaoMDGA1gPRTr2swBaAI458VALAAoUJFhx6AD2ARUpcpSqLlqCZKkw8YdHADi5ZGDgBeRHGAATAFxxGyEACNcRKVNYRm8CToMKwAFmYQFqo2ABQAlM4ACurAGAA8ERYA2gC6AHzWBVoqAHQA5sExVJxl5mA6cSUwoeiMMTyokMzGVgUdXRgl9vQMcT6SfgG2uORQRNYoGNi4eDFZVLWR9VQ5ADSkwWGZ9WOSnJxwl1cAegD8QA)\n\n[//]: # 'TypingError'\n\nIf you want to throw a custom error, or something that isn't an `Error` at all, you can specify the type of the error field:\n\n[//]: # 'TypingError2'\n\n```tsx\nconst { error } = useQuery<Group[], string>(['groups'], fetchGroups)\n//      ^? const error: string | null\n```\n\n[//]: # 'TypingError2'\n\nHowever, this has the drawback that type inference for all other generics of `useQuery` will not work anymore. It is generally not considered a good practice to throw something that isn't an `Error`, so if you have a subclass like `AxiosError` you can use _type narrowing_ to make the error field more specific:\n\n[//]: # 'TypingError3'\n\n```tsx\nimport axios from 'axios'\n\nconst { error } = useQuery({ queryKey: ['groups'], queryFn: fetchGroups })\n//      ^? const error: Error | null\n\nif (axios.isAxiosError(error)) {\n  error\n  // ^? const error: AxiosError\n}\n```\n\n[typescript playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgVwM4FMCKz1QJ5wC+cAZlBCHAOQACMAhgHaoMDGA1gPRTr2swBaAI458VALAAoUJFhx6AD2ARUpcpSqLlqCZKkw8YdHADi5ZGDgBeRHGAATAFxxGyEACNcRKVNYRm8CToMKwAFmYQFqo2ABQAlM4ACurAGAA8ERYA2gC6AHzWBVoqAHQA5sExVJxl5mA6cSUwoeiMMTyokMzGVgUdXRgl9vQMcT6SfgG2uORQRNYoGNi4eDFIIisA0uh4zllUtZH1VDkANHAb+ABijM5BIeF1qoRjkpyccJ9fAHoA-OPAEhwGLFVAlVIAQSUKgAolBZjEZtA4nFEFJPkioOi4O84H8pIQgA)\n\n[//]: # 'TypingError3'\n\n### Registering a global Error\n\nTanStack Query v5 allows for a way to set a global Error type for everything, without having to specify generics on call-sides, by amending the `Register` interface. This will make sure inference still works, but the error field will be of the specified type. If you want to enforce that call-sides must do explicit type-narrowing, set `defaultError` to `unknown`:\n\n[//]: # 'RegisterErrorType'\n\n```tsx\nimport '@tanstack/react-query'\n\ndeclare module '@tanstack/react-query' {\n  interface Register {\n    // Use unknown so call sites must narrow explicitly.\n    defaultError: unknown\n  }\n}\n\nconst { error } = useQuery({ queryKey: ['groups'], queryFn: fetchGroups })\n//      ^? const error: unknown | null\n```\n\n[//]: # 'RegisterErrorType'\n[//]: # 'TypingMeta'\n\n## Typing meta\n\n### Registering global Meta\n\nSimilarly to registering a [global error type](#registering-a-global-error) you can also register a global `Meta` type. This ensures the optional `meta` field on [queries](./reference/useQuery.md) and [mutations](./reference/useMutation.md) stays consistent and is type-safe. Note that the registered type must extend `Record<string, unknown>` so that `meta` remains an object.\n\n```ts\nimport '@tanstack/react-query'\n\ninterface MyMeta extends Record<string, unknown> {\n  // Your meta type definition.\n}\n\ndeclare module '@tanstack/react-query' {\n  interface Register {\n    queryMeta: MyMeta\n    mutationMeta: MyMeta\n  }\n}\n```\n\n[//]: # 'TypingMeta'\n[//]: # 'TypingQueryAndMutationKeys'\n\n## Typing query and mutation keys\n\n### Registering the query and mutation key types\n\nAlso similarly to registering a [global error type](#registering-a-global-error), you can also register a global `QueryKey` and `MutationKey` type. This allows you to provide more structure to your keys, that matches your application's hierarchy, and have them be typed across all of the library's surface area. Note that the registered type must extend the `Array` type, so that your keys remain an array.\n\n```ts\nimport '@tanstack/react-query'\n\ntype QueryKey = ['dashboard' | 'marketing', ...ReadonlyArray<unknown>]\n\ndeclare module '@tanstack/react-query' {\n  interface Register {\n    queryKey: QueryKey\n    mutationKey: QueryKey\n  }\n}\n```\n\n[//]: # 'TypingQueryAndMutationKeys'\n[//]: # 'TypingQueryOptions'\n\n## Typing Query Options\n\nIf you inline query options into `useQuery`, you'll get automatic type inference. However, you might want to extract the query options into a separate function to share them between `useQuery` and e.g. `prefetchQuery`. In that case, you'd lose type inference. To get it back, you can use the `queryOptions` helper:\n\n```ts\nimport { queryOptions } from '@tanstack/react-query'\n\nfunction groupOptions() {\n  return queryOptions({\n    queryKey: ['groups'],\n    queryFn: fetchGroups,\n    staleTime: 5 * 1000,\n  })\n}\n\nuseQuery(groupOptions())\nqueryClient.prefetchQuery(groupOptions())\n```\n\nFurther, the `queryKey` returned from `queryOptions` knows about the `queryFn` associated with it, and we can leverage that type information to make functions like `queryClient.getQueryData` aware of those types as well:\n\n```ts\nfunction groupOptions() {\n  return queryOptions({\n    queryKey: ['groups'],\n    queryFn: fetchGroups,\n    staleTime: 5 * 1000,\n  })\n}\n\nconst data = queryClient.getQueryData(groupOptions().queryKey)\n//     ^? const data: Group[] | undefined\n```\n\nWithout `queryOptions`, the type of `data` would be `unknown`, unless we'd pass a generic to it:\n\n```ts\nconst data = queryClient.getQueryData<Group[]>(['groups'])\n```\n\nNote that type inference via `queryOptions` does _not_ work for `queryClient.getQueriesData`, because it returns an array of tuples with heterogeneous, `unknown` data. If you are sure of the type of data that your query will return, specify it explicitly:\n\n```ts\nconst entries = queryClient.getQueriesData<Group[]>(groupOptions().queryKey)\n//     ^? const entries: Array<[QueryKey, Group[] | undefined]>\n```\n\n## Typing Mutation Options\n\nSimilarly to `queryOptions`, you can use `mutationOptions` to extract mutation options into a separate function:\n\n```ts\nfunction groupMutationOptions() {\n  return mutationOptions({\n    mutationKey: ['addGroup'],\n    mutationFn: addGroup,\n  })\n}\n\nuseMutation({\n  ...groupMutationOptions(),\n  onSuccess: () => queryClient.invalidateQueries({ queryKey: ['groups'] }),\n})\nuseIsMutating(groupMutationOptions())\nqueryClient.isMutating(groupMutationOptions())\n```\n\n[//]: # 'TypingQueryOptions'\n\n## Typesafe disabling of queries using `skipToken`\n\nIf you are using TypeScript, you can use the `skipToken` to disable a query. This is useful when you want to disable a query based on a condition, but you still want to keep the query to be type safe.\nRead more about it in the [Disabling Queries](./guides/disabling-queries.md) guide.\n\n[//]: # 'Materials'\n\n## Further Reading\n\nFor tips and tricks around type inference, see the article [React Query and TypeScript](https://tkdodo.eu/blog/react-query-and-type-script). To find out how to get the best possible type-safety, you can read [Type-safe React Query](https://tkdodo.eu/blog/type-safe-react-query). [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) outlines how type inference works with the `queryOptions` helper function.\n\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/solid/devtools.md",
    "content": "---\nid: devtools\ntitle: Devtools\n---\n\nWave your hands in the air and shout hooray because Solid Query comes with dedicated devtools! 🥳\n\nWhen you begin your Solid Query journey, you'll want these devtools by your side. They help visualize all of the inner workings of Solid Query and will likely save you hours of debugging if you find yourself in a pinch!\n\n> For Chrome, Firefox, and Edge users: Third-party browser extensions are available for debugging TanStack Query directly in browser DevTools. These provide the same functionality as the framework-specific devtools packages:\n>\n> - <img alt=\"Chrome logo\" src=\"https://www.google.com/chrome/static/images/chrome-logo.svg\" width=\"16\" height=\"16\" class=\"inline mr-1 not-prose\" /> [Devtools for Chrome](https://chromewebstore.google.com/detail/tanstack-query-devtools/annajfchloimdhceglpgglpeepfghfai)\n> - <img alt=\"Firefox logo\" src=\"https://upload.wikimedia.org/wikipedia/commons/a/a0/Firefox_logo%2C_2019.svg\" width=\"16\" height=\"16\" class=\"inline mr-1 not-prose\" /> [Devtools for Firefox](https://addons.mozilla.org/en-US/firefox/addon/tanstack-query-devtools/)\n> - <img alt=\"Edge logo\" src=\"https://upload.wikimedia.org/wikipedia/commons/9/98/Microsoft_Edge_logo_%282019%29.svg\" width=\"16\" height=\"16\" class=\"inline mr-1 not-prose\" /> [Devtools for Edge](https://microsoftedge.microsoft.com/addons/detail/tanstack-query-devtools/edmdpkgkacmjopodhfolmphdenmddobj)\n\n## Install and Import the Devtools\n\nThe devtools are a separate package that you need to install:\n\n```bash\nnpm i @tanstack/solid-query-devtools\n```\n\nor\n\n```bash\npnpm add @tanstack/solid-query-devtools\n```\n\nor\n\n```bash\nyarn add @tanstack/solid-query-devtools\n```\n\nor\n\n```bash\nbun add @tanstack/solid-query-devtools\n```\n\nYou can import the devtools like this:\n\n```tsx\nimport { SolidQueryDevtools } from '@tanstack/solid-query-devtools'\n```\n\nBy default, Solid Query Devtools are only included in bundles when `isServer === true` ([`isServer`](https://github.com/solidjs/solid/blob/a72d393a07b22f9b7496e5eb93712188ccce0d28/packages/solid/web/src/index.ts#L37) comes from the `solid-js/web` package), so you don't need to worry about excluding them during a production build.\n\n## Floating Mode\n\nFloating Mode will mount the devtools as a fixed, floating element in your app and provide a toggle in the corner of the screen to show and hide the devtools. This toggle state will be stored and remembered in localStorage across reloads.\n\nPlace the following code as high in your Solid app as you can. The closer it is to the root of the page, the better it will work!\n\n```tsx\nimport { SolidQueryDevtools } from '@tanstack/solid-query-devtools'\n\nfunction App() {\n  return (\n    <QueryClientProvider client={queryClient}>\n      {/* The rest of your application */}\n      <SolidQueryDevtools initialIsOpen={false} />\n    </QueryClientProvider>\n  )\n}\n```\n\n### Options\n\n- `initialIsOpen: boolean`\n  - Set this `true` if you want the dev tools to default to being open\n- `buttonPosition?: \"top-left\" | \"top-right\" | \"bottom-left\" | \"bottom-right\"`\n  - Defaults to `bottom-right`\n  - The position of the Solid Query logo to open and close the devtools panel\n- `position?: \"top\" | \"bottom\" | \"left\" | \"right\"`\n  - Defaults to `bottom`\n  - The position of the Solid Query devtools panel\n- `client?: QueryClient`,\n  - Use this to use a custom QueryClient. Otherwise, the one from the nearest context will be used.\n- `errorTypes?: { name: string; initializer: (query: Query) => TError}`\n  - Use this to predefine some errors that can be triggered on your queries. Initializer will be called (with the specific query) when that error is toggled on from the UI. It must return an Error.\n- `styleNonce?: string`\n  - 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.\n- `shadowDOMTarget?: ShadowRoot`\n  - Default behavior will apply the devtool's styles to the head tag within the DOM.\n  - Use this to pass a shadow DOM target to the devtools so that the styles will be applied within the shadow DOM instead of within the head tag in the light DOM.\n"
  },
  {
    "path": "docs/framework/solid/guides/advanced-ssr.md",
    "content": "---\nid: advanced-ssr\ntitle: Advanced Server Rendering\n---\n\nWill come soon\n"
  },
  {
    "path": "docs/framework/solid/guides/background-fetching-indicators.md",
    "content": "---\nid: background-fetching-indicators\ntitle: Background Fetching Indicators\nref: docs/framework/react/guides/background-fetching-indicators.md\nreplace: { 'hook': 'function' }\n---\n\n[//]: # 'Example'\n\n```tsx\nimport { Switch, Match, Show, For } from 'solid-js'\n\nfunction Todos() {\n  const todosQuery = useQuery(() => ({\n    queryKey: ['todos'],\n    queryFn: fetchTodos,\n  }))\n\n  return (\n    <Switch>\n      <Match when={todosQuery.isPending}>\n        <span>Loading...</span>\n      </Match>\n      <Match when={todosQuery.isError}>\n        <span>Error: {todosQuery.error.message}</span>\n      </Match>\n      <Match when={todosQuery.isSuccess}>\n        <Show when={todosQuery.isFetching}>\n          <div>Refreshing...</div>\n        </Show>\n        <div>\n          <For each={todosQuery.data}>{(todo) => <Todo todo={todo} />}</For>\n        </div>\n      </Match>\n    </Switch>\n  )\n}\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```tsx\nimport { useIsFetching } from '@tanstack/solid-query'\n\nfunction GlobalLoadingIndicator() {\n  const isFetching = useIsFetching()\n\n  return (\n    <Show when={isFetching()}>\n      <div>Queries are fetching in the background...</div>\n    </Show>\n  )\n}\n```\n\n[//]: # 'Example2'\n"
  },
  {
    "path": "docs/framework/solid/guides/caching.md",
    "content": "---\nid: caching\ntitle: Caching Examples\nref: docs/framework/react/guides/caching.md\nreplace:\n  {\n    'useQuery[(][{] queryKey': 'useQuery(() => ({ queryKey',\n    'fetchTodos [}][)]': 'fetchTodos }))',\n  }\n---\n"
  },
  {
    "path": "docs/framework/solid/guides/default-query-function.md",
    "content": "---\nid: default-query-function\ntitle: Default Query Function\nref: docs/framework/react/guides/default-query-function.md\n---\n\n[//]: # 'Example'\n\n```tsx\n// Define a default query function that will receive the query key\nconst defaultQueryFn = async ({ queryKey }) => {\n  const { data } = await axios.get(\n    `https://jsonplaceholder.typicode.com${queryKey[0]}`,\n  )\n  return data\n}\n\n// provide the default query function to your app with defaultOptions\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      queryFn: defaultQueryFn,\n    },\n  },\n})\n\nfunction App() {\n  return (\n    <QueryClientProvider client={queryClient}>\n      <YourApp />\n    </QueryClientProvider>\n  )\n}\n\n// All you have to do now is pass a key!\nfunction Posts() {\n  const postsQuery = useQuery(() => ({ queryKey: ['/posts'] }))\n\n  // ...\n}\n\n// You can even leave out the queryFn and just go straight into options\nfunction Post(props) {\n  const postQuery = useQuery(() => ({\n    queryKey: [`/posts/${props.postId}`],\n    enabled: !!props.postId,\n  }))\n\n  // ...\n}\n```\n\n[//]: # 'Example'\n"
  },
  {
    "path": "docs/framework/solid/guides/dependent-queries.md",
    "content": "---\nid: dependent-queries\ntitle: Dependent Queries\nref: docs/framework/react/guides/dependent-queries.md\n---\n\n[//]: # 'Example'\n\n```tsx\n// Get the user\nconst userQuery = useQuery(() => ({\n  queryKey: ['user', email],\n  queryFn: getUserByEmail,\n}))\n\nconst userId = () => userQuery.data?.id\n\n// Then get the user's projects\nconst projectsQuery = useQuery(() => ({\n  queryKey: ['projects', userId()],\n  queryFn: getProjectsByUser,\n  // The query will not execute until the userId exists\n  enabled: !!userId(),\n}))\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```tsx\n// Get the users ids\nconst usersQuery = useQuery(() => ({\n  queryKey: ['users'],\n  queryFn: getUsersData,\n  select: (users) => users.map((user) => user.id),\n}))\n\n// Then get the users messages\nconst usersMessages = useQueries(() => ({\n  queries: usersQuery.data\n    ? usersQuery.data.map((id) => {\n        return {\n          queryKey: ['messages', id],\n          queryFn: () => getMessagesByUsers(id),\n        }\n      })\n    : [], // if usersQuery.data is undefined, an empty array will be returned\n}))\n```\n\n[//]: # 'Example2'\n"
  },
  {
    "path": "docs/framework/solid/guides/disabling-queries.md",
    "content": "---\nid: disabling-queries\ntitle: Disabling/Pausing Queries\nref: docs/framework/react/guides/disabling-queries.md\n---\n\n[//]: # 'Example'\n\n```tsx\nimport { Switch, Match, Show, For } from 'solid-js'\n\nfunction Todos() {\n  const todosQuery = useQuery(() => ({\n    queryKey: ['todos'],\n    queryFn: fetchTodoList,\n    enabled: false,\n  }))\n\n  return (\n    <div>\n      <button onClick={() => todosQuery.refetch()}>Fetch Todos</button>\n\n      <Switch>\n        <Match when={todosQuery.data}>\n          <ul>\n            <For each={todosQuery.data}>{(todo) => <li>{todo.title}</li>}</For>\n          </ul>\n        </Match>\n        <Match when={todosQuery.isError}>\n          <span>Error: {todosQuery.error.message}</span>\n        </Match>\n        <Match when={todosQuery.isLoading}>\n          <span>Loading...</span>\n        </Match>\n        <Match when={true}>\n          <span>Not ready ...</span>\n        </Match>\n      </Switch>\n\n      <div>{todosQuery.isFetching ? 'Fetching...' : null}</div>\n    </div>\n  )\n}\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```tsx\nimport { createSignal } from 'solid-js'\n\nfunction Todos() {\n  const [filter, setFilter] = createSignal('')\n\n  const todosQuery = useQuery(() => ({\n    queryKey: ['todos', filter()],\n    queryFn: () => fetchTodos(filter()),\n    // ⬇️ disabled as long as the filter is empty\n    enabled: !!filter(),\n  }))\n\n  return (\n    <div>\n      {/* 🚀 applying the filter will enable and execute the query */}\n      <FiltersForm onApply={setFilter} />\n      <Show when={todosQuery.data}>\n        <TodosTable data={todosQuery.data} />\n      </Show>\n    </div>\n  )\n}\n```\n\n[//]: # 'Example2'\n[//]: # 'Example3'\n\n```tsx\nimport { createSignal } from 'solid-js'\nimport { skipToken, useQuery } from '@tanstack/solid-query'\n\nfunction Todos() {\n  const [filter, setFilter] = createSignal<string | undefined>()\n\n  const todosQuery = useQuery(() => ({\n    queryKey: ['todos', filter()],\n    // ⬇️ disabled as long as the filter is undefined or empty\n    queryFn: filter() ? () => fetchTodos(filter()!) : skipToken,\n  }))\n\n  return (\n    <div>\n      {/* 🚀 applying the filter will enable and execute the query */}\n      <FiltersForm onApply={setFilter} />\n      <Show when={todosQuery.data}>\n        <TodosTable data={todosQuery.data} />\n      </Show>\n    </div>\n  )\n}\n```\n\n[//]: # 'Example3'\n"
  },
  {
    "path": "docs/framework/solid/guides/does-this-replace-client-state.md",
    "content": "---\nid: does-this-replace-client-state\ntitle: Does TanStack Query replace global state managers?\nref: docs/framework/react/guides/does-this-replace-client-state.md\nreplace: { 'hook': 'function' }\n---\n"
  },
  {
    "path": "docs/framework/solid/guides/filters.md",
    "content": "---\nid: filters\ntitle: Filters\nref: docs/framework/react/guides/filters.md\n---\n"
  },
  {
    "path": "docs/framework/solid/guides/important-defaults.md",
    "content": "---\nid: important-defaults\ntitle: Important Defaults\nref: docs/framework/react/guides/important-defaults.md\n---\n\n[//]: # 'StructuralSharing'\n\n- Query results by default are **structurally shared to detect if data has actually changed** and if not, **the data reference remains unchanged** to better help with value stabilization. If this concept sounds foreign, then don't worry about it! 99.9% of the time you will not need to disable this and it makes your app more performant at zero cost to you.\n\n[//]: # 'StructuralSharing'\n[//]: # 'Materials'\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/solid/guides/infinite-queries.md",
    "content": "---\nid: infinite-queries\ntitle: Infinite Queries\nref: docs/framework/react/guides/infinite-queries.md\n---\n\n[//]: # 'Example'\n\n```tsx\nimport { Switch, Match, For, Show } from 'solid-js'\nimport { useInfiniteQuery } from '@tanstack/solid-query'\n\nfunction Projects() {\n  const fetchProjects = async ({ pageParam }) => {\n    const res = await fetch('/api/projects?cursor=' + pageParam)\n    return res.json()\n  }\n\n  const projectsQuery = useInfiniteQuery(() => ({\n    queryKey: ['projects'],\n    queryFn: fetchProjects,\n    initialPageParam: 0,\n    getNextPageParam: (lastPage, pages) => lastPage.nextCursor,\n  }))\n\n  return (\n    <Switch>\n      <Match when={projectsQuery.isPending}>\n        <p>Loading...</p>\n      </Match>\n      <Match when={projectsQuery.isError}>\n        <p>Error: {projectsQuery.error.message}</p>\n      </Match>\n      <Match when={projectsQuery.isSuccess}>\n        <For each={projectsQuery.data.pages}>\n          {(group) => (\n            <For each={group.data}>{(project) => <p>{project.name}</p>}</For>\n          )}\n        </For>\n        <div>\n          <button\n            onClick={() => projectsQuery.fetchNextPage()}\n            disabled={!projectsQuery.hasNextPage || projectsQuery.isFetching}\n          >\n            {projectsQuery.isFetchingNextPage\n              ? 'Loading more...'\n              : projectsQuery.hasNextPage\n                ? 'Load More'\n                : 'Nothing more to load'}\n          </button>\n        </div>\n        <Show\n          when={projectsQuery.isFetching && !projectsQuery.isFetchingNextPage}\n        >\n          <div>Fetching...</div>\n        </Show>\n      </Match>\n    </Switch>\n  )\n}\n```\n\n[//]: # 'Example'\n[//]: # 'Example1'\n\n```jsx\n<List\n  onEndReached={() =>\n    projectsQuery.hasNextPage &&\n    !projectsQuery.isFetching &&\n    projectsQuery.fetchNextPage()\n  }\n/>\n```\n\n[//]: # 'Example1'\n[//]: # 'Example3'\n\n```tsx\nuseInfiniteQuery(() => ({\n  queryKey: ['projects'],\n  queryFn: fetchProjects,\n  initialPageParam: 0,\n  getNextPageParam: (lastPage, pages) => lastPage.nextCursor,\n  getPreviousPageParam: (firstPage, pages) => firstPage.prevCursor,\n}))\n```\n\n[//]: # 'Example3'\n[//]: # 'Example4'\n\n```tsx\nuseInfiniteQuery(() => ({\n  queryKey: ['projects'],\n  queryFn: fetchProjects,\n  select: (data) => ({\n    pages: [...data.pages].reverse(),\n    pageParams: [...data.pageParams].reverse(),\n  }),\n}))\n```\n\n[//]: # 'Example4'\n[//]: # 'Example8'\n\n```tsx\nuseInfiniteQuery(() => ({\n  queryKey: ['projects'],\n  queryFn: fetchProjects,\n  initialPageParam: 0,\n  getNextPageParam: (lastPage, pages) => lastPage.nextCursor,\n  getPreviousPageParam: (firstPage, pages) => firstPage.prevCursor,\n  maxPages: 3,\n}))\n```\n\n[//]: # 'Example8'\n[//]: # 'Example9'\n\n```tsx\nreturn useInfiniteQuery(() => ({\n  queryKey: ['projects'],\n  queryFn: fetchProjects,\n  initialPageParam: 0,\n  getNextPageParam: (lastPage, allPages, lastPageParam) => {\n    if (lastPage.length === 0) {\n      return undefined\n    }\n    return lastPageParam + 1\n  },\n  getPreviousPageParam: (firstPage, allPages, firstPageParam) => {\n    if (firstPageParam <= 1) {\n      return undefined\n    }\n    return firstPageParam - 1\n  },\n}))\n```\n\n[//]: # 'Example9'\n"
  },
  {
    "path": "docs/framework/solid/guides/initial-query-data.md",
    "content": "---\nid: initial-query-data\ntitle: Initial Query Data\nref: docs/framework/react/guides/initial-query-data.md\nreplace:\n  {\n    '@tanstack/react-query': '@tanstack/solid-query',\n    'useMutationState[(]': 'useMutationState(() => ',\n    'useMutation[(]': 'useMutation(() => ',\n    'useQuery[(]': 'useQuery(() => ',\n    'useQueries[(]': 'useQueries(() => ',\n    'useInfiniteQuery[(]': 'useInfiniteQuery(() => ',\n  }\n---\n\n[//]: # 'Example'\n\n```tsx\nconst todosQuery = useQuery(() => ({\n  queryKey: ['todos'],\n  queryFn: () => fetch('/todos'),\n  initialData: initialTodos,\n}))\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```tsx\n// Will show initialTodos immediately, but also immediately refetch todos after mount\nconst todosQuery = useQuery(() => ({\n  queryKey: ['todos'],\n  queryFn: () => fetch('/todos'),\n  initialData: initialTodos,\n}))\n```\n\n[//]: # 'Example2'\n[//]: # 'Example3'\n\n```tsx\n// Show initialTodos immediately, but won't refetch until another interaction event is encountered after 1000 ms\nconst todosQuery = useQuery(() => ({\n  queryKey: ['todos'],\n  queryFn: () => fetch('/todos'),\n  initialData: initialTodos,\n  staleTime: 1000,\n}))\n```\n\n[//]: # 'Example3'\n[//]: # 'Example4'\n\n```tsx\n// Show initialTodos immediately, but won't refetch until another interaction event is encountered after 1000 ms\nconst todosQuery = useQuery(() => ({\n  queryKey: ['todos'],\n  queryFn: () => fetch('/todos'),\n  initialData: initialTodos,\n  staleTime: 60 * 1000, // 1 minute\n  // This could be 10 seconds ago or 10 minutes ago\n  initialDataUpdatedAt: initialTodosUpdatedTimestamp, // eg. 1608412420052\n}))\n```\n\n[//]: # 'Example4'\n[//]: # 'Example5'\n\n```tsx\nconst todosQuery = useQuery(() => ({\n  queryKey: ['todos'],\n  queryFn: () => fetch('/todos'),\n  initialData: () => getExpensiveTodos(),\n}))\n```\n\n[//]: # 'Example5'\n[//]: # 'Example6'\n\n```tsx\nconst todoQuery = useQuery(() => ({\n  queryKey: ['todo', todoId],\n  queryFn: () => fetch('/todos'),\n  initialData: () => {\n    // Use a todo from the 'todos' query as the initial data for this todo query\n    return queryClient.getQueryData(['todos'])?.find((d) => d.id === todoId)\n  },\n}))\n```\n\n[//]: # 'Example6'\n[//]: # 'Example7'\n\n```tsx\nconst todoQuery = useQuery(() => ({\n  queryKey: ['todos', todoId],\n  queryFn: () => fetch(`/todos/${todoId}`),\n  initialData: () =>\n    queryClient.getQueryData(['todos'])?.find((d) => d.id === todoId),\n  initialDataUpdatedAt: () =>\n    queryClient.getQueryState(['todos'])?.dataUpdatedAt,\n}))\n```\n\n[//]: # 'Example7'\n[//]: # 'Example8'\n\n```tsx\nconst todoQuery = useQuery(() => ({\n  queryKey: ['todo', todoId],\n  queryFn: () => fetch(`/todos/${todoId}`),\n  initialData: () => {\n    // Get the query state\n    const state = queryClient.getQueryState(['todos'])\n\n    // If the query exists and has data that is no older than 10 seconds...\n    if (state && Date.now() - state.dataUpdatedAt <= 10 * 1000) {\n      // return the individual todo\n      return state.data.find((d) => d.id === todoId)\n    }\n\n    // Otherwise, return undefined and let it fetch from a hard loading state!\n  },\n}))\n```\n\n[//]: # 'Example8'\n"
  },
  {
    "path": "docs/framework/solid/guides/invalidations-from-mutations.md",
    "content": "---\nid: invalidations-from-mutations\ntitle: Invalidations from Mutations\nref: docs/framework/react/guides/invalidations-from-mutations.md\nreplace:\n  {\n    'React': 'Solid',\n    '@tanstack/react-query': '@tanstack/solid-query',\n    'useMutationState[(]': 'useMutationState(() => ',\n    'useMutation[(]': 'useMutation(() => ',\n    'useQuery[(]': 'useQuery(() => ',\n    'useQueries[(]': 'useQueries(() => ',\n    'useInfiniteQuery[(]': 'useInfiniteQuery(() => ',\n    'hook': 'function',\n  }\n---\n"
  },
  {
    "path": "docs/framework/solid/guides/mutations.md",
    "content": "---\nid: mutations\ntitle: Mutations\nref: docs/framework/react/guides/mutations.md\nreplace: { 'hook': 'function' }\n---\n\n[//]: # 'Example'\n\n```tsx\nimport { Switch, Match, Show } from 'solid-js'\n\nfunction App() {\n  const mutation = useMutation(() => ({\n    mutationFn: (newTodo) => {\n      return axios.post('/todos', newTodo)\n    },\n  }))\n\n  return (\n    <div>\n      <Switch>\n        <Match when={mutation.isPending}>Adding todo...</Match>\n        <Match when={true}>\n          <Show when={mutation.isError}>\n            <div>An error occurred: {mutation.error.message}</div>\n          </Show>\n\n          <Show when={mutation.isSuccess}>\n            <div>Todo added!</div>\n          </Show>\n\n          <button\n            onClick={() => {\n              mutation.mutate({ id: new Date(), title: 'Do Laundry' })\n            }}\n          >\n            Create Todo\n          </button>\n        </Match>\n      </Switch>\n    </div>\n  )\n}\n```\n\n[//]: # 'Example'\n[//]: # 'Info1'\n[//]: # 'Info1'\n[//]: # 'Example2'\n\n```tsx\nconst CreateTodo = () => {\n  const mutation = useMutation(() => ({\n    mutationFn: (formData) => {\n      return fetch('/api', formData)\n    },\n  }))\n  const onSubmit = (event) => {\n    event.preventDefault()\n    mutation.mutate(new FormData(event.target))\n  }\n\n  return <form onSubmit={onSubmit}>...</form>\n}\n```\n\n[//]: # 'Example2'\n[//]: # 'Example3'\n\n```tsx\nimport { createSignal, Show } from 'solid-js'\n\nconst CreateTodo = () => {\n  const [title, setTitle] = createSignal('')\n  const mutation = useMutation(() => ({ mutationFn: createTodo }))\n\n  const onCreateTodo = (e) => {\n    e.preventDefault()\n    mutation.mutate({ title: title() })\n  }\n\n  return (\n    <form onSubmit={onCreateTodo}>\n      <Show when={mutation.error}>\n        <h5 onClick={() => mutation.reset()}>{mutation.error}</h5>\n      </Show>\n      <input\n        type=\"text\"\n        value={title()}\n        onInput={(e) => setTitle(e.currentTarget.value)}\n      />\n      <br />\n      <button type=\"submit\">Create Todo</button>\n    </form>\n  )\n}\n```\n\n[//]: # 'Example3'\n[//]: # 'Example4'\n\n```tsx\nuseMutation(() => ({\n  mutationFn: addTodo,\n  onMutate: (variables, context) => {\n    // A mutation is about to happen!\n\n    // Optionally return a result containing data to use when for example rolling back\n    return { id: 1 }\n  },\n  onError: (error, variables, onMutateResult, context) => {\n    // An error happened!\n    console.log(`rolling back optimistic update with id ${onMutateResult.id}`)\n  },\n  onSuccess: (data, variables, onMutateResult, context) => {\n    // Boom baby!\n  },\n  onSettled: (data, error, variables, onMutateResult, context) => {\n    // Error or success... doesn't matter!\n  },\n}))\n```\n\n[//]: # 'Example4'\n[//]: # 'Example5'\n\n```tsx\nuseMutation(() => ({\n  mutationFn: addTodo,\n  onSuccess: async () => {\n    console.log(\"I'm first!\")\n  },\n  onSettled: async () => {\n    console.log(\"I'm second!\")\n  },\n}))\n```\n\n[//]: # 'Example5'\n[//]: # 'Example6'\n\n```tsx\nuseMutation(() => ({\n  mutationFn: addTodo,\n  onSuccess: (data, variables, onMutateResult, context) => {\n    // I will fire first\n  },\n  onError: (error, variables, onMutateResult, context) => {\n    // I will fire first\n  },\n  onSettled: (data, error, variables, onMutateResult, context) => {\n    // I will fire first\n  },\n}))\n\nmutate(todo, {\n  onSuccess: (data, variables, onMutateResult, context) => {\n    // I will fire second!\n  },\n  onError: (error, variables, onMutateResult, context) => {\n    // I will fire second!\n  },\n  onSettled: (data, error, variables, onMutateResult, context) => {\n    // I will fire second!\n  },\n})\n```\n\n[//]: # 'Example6'\n[//]: # 'Example7'\n\n```tsx\nuseMutation(() => ({\n  mutationFn: addTodo,\n  onSuccess: (data, variables, onMutateResult, context) => {\n    // Will be called 3 times\n  },\n}))\n\nconst todos = ['Todo 1', 'Todo 2', 'Todo 3']\ntodos.forEach((todo) => {\n  mutate(todo, {\n    onSuccess: (data, variables, onMutateResult, context) => {\n      // Will execute only once, for the last mutation (Todo 3),\n      // regardless which mutation resolves first\n    },\n  })\n})\n```\n\n[//]: # 'Example7'\n[//]: # 'Example8'\n\n```tsx\nconst mutation = useMutation(() => ({ mutationFn: addTodo }))\n\ntry {\n  const todo = await mutation.mutateAsync(todo)\n  console.log(todo)\n} catch (error) {\n  console.error(error)\n} finally {\n  console.log('done')\n}\n```\n\n[//]: # 'Example8'\n[//]: # 'Example9'\n\n```tsx\nconst mutation = useMutation(() => ({\n  mutationFn: addTodo,\n  retry: 3,\n}))\n```\n\n[//]: # 'Example9'\n[//]: # 'Example10'\n\n```tsx\nconst queryClient = new QueryClient()\n\n// Define the \"addTodo\" mutation\nqueryClient.setMutationDefaults(['addTodo'], {\n  mutationFn: addTodo,\n  onMutate: async (variables, context) => {\n    // Cancel current queries for the todos list\n    await context.client.cancelQueries({ queryKey: ['todos'] })\n\n    // Create optimistic todo\n    const optimisticTodo = { id: uuid(), title: variables.title }\n\n    // Add optimistic todo to todos list\n    context.client.setQueryData(['todos'], (old) => [...old, optimisticTodo])\n\n    // Return a result with the optimistic todo\n    return { optimisticTodo }\n  },\n  onSuccess: (result, variables, onMutateResult, context) => {\n    // Replace optimistic todo in the todos list with the result\n    context.client.setQueryData(['todos'], (old) =>\n      old.map((todo) =>\n        todo.id === onMutateResult.optimisticTodo.id ? result : todo,\n      ),\n    )\n  },\n  onError: (error, variables, onMutateResult, context) => {\n    // Remove optimistic todo from the todos list\n    context.client.setQueryData(['todos'], (old) =>\n      old.filter((todo) => todo.id !== onMutateResult.optimisticTodo.id),\n    )\n  },\n  retry: 3,\n})\n\n// Start mutation in some component:\nconst mutation = useMutation(() => ({ mutationKey: ['addTodo'] }))\nmutation.mutate({ title: 'title' })\n\n// If the mutation has been paused because the device is for example offline,\n// Then the paused mutation can be dehydrated when the application quits:\nconst state = dehydrate(queryClient)\n\n// The mutation can then be hydrated again when the application is started:\nhydrate(queryClient, state)\n\n// Resume the paused mutations:\nqueryClient.resumePausedMutations()\n```\n\n[//]: # 'Example10'\n[//]: # 'PersistOfflineIntro'\n\n### Persisting Offline mutations\n\nIf you persist offline mutations with the `persistQueryClient` plugin, mutations cannot be resumed when the page is reloaded unless you provide a default mutation function.\n\n[//]: # 'PersistOfflineIntro'\n[//]: # 'OfflineExampleLink'\n[//]: # 'OfflineExampleLink'\n[//]: # 'ExampleScopes'\n\n```tsx\nconst mutation = useMutation(() => ({\n  mutationFn: addTodo,\n  scope: {\n    id: 'todo',\n  },\n}))\n```\n\n[//]: # 'ExampleScopes'\n[//]: # 'Materials'\n\n## Further reading\n\nFor more information about mutations, have a look at [TkDodo's article on Mastering Mutations in TanStack Query](https://tkdodo.eu/blog/mastering-mutations-in-react-query).\n\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/solid/guides/network-mode.md",
    "content": "---\nid: network-mode\ntitle: Network Mode\nref: docs/framework/react/guides/network-mode.md\n---\n"
  },
  {
    "path": "docs/framework/solid/guides/optimistic-updates.md",
    "content": "---\nid: optimistic-updates\ntitle: Optimistic Updates\nref: docs/framework/react/guides/optimistic-updates.md\nreplace: { 'React Query': 'Solid Query', 'hook': 'function' }\n---\n\n[//]: # 'ExampleUI1'\n\n```tsx\nconst addTodoMutation = useMutation(() => ({\n  mutationFn: (newTodo: string) => axios.post('/api/data', { text: newTodo }),\n  // make sure to _return_ the Promise from the query invalidation\n  // so that the mutation stays in `pending` state until the refetch is finished\n  onSettled: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),\n}))\n```\n\n[//]: # 'ExampleUI1'\n[//]: # 'ExampleUI2'\n\n```tsx\n<ul>\n  <For each={todoQuery.data}>{(todo) => <li>{todo.text}</li>}</For>\n  <Show when={addTodoMutation.isPending}>\n    <li style={{ opacity: 0.5 }}>{addTodoMutation.variables}</li>\n  </Show>\n</ul>\n```\n\n[//]: # 'ExampleUI2'\n[//]: # 'ExampleUI3'\n\n```tsx\n<Show when={addTodoMutation.isError}>\n  <li style={{ color: 'red' }}>\n    {addTodoMutation.variables}\n    <button onClick={() => addTodoMutation.mutate(addTodoMutation.variables)}>\n      Retry\n    </button>\n  </li>\n</Show>\n```\n\n[//]: # 'ExampleUI3'\n[//]: # 'ExampleUI4'\n\n```tsx\n// somewhere in your app\nconst mutation = useMutation(() => ({\n  mutationFn: (newTodo: string) => axios.post('/api/data', { text: newTodo }),\n  onSettled: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),\n  mutationKey: ['addTodo'],\n}))\n\n// access variables somewhere else\nconst variables = useMutationState(() => ({\n  filters: { mutationKey: ['addTodo'], status: 'pending' },\n  select: (mutation) => mutation.state.variables,\n}))\n```\n\n[//]: # 'ExampleUI4'\n[//]: # 'Example'\n\n```tsx\nconst queryClient = useQueryClient()\n\nuseMutation(() => ({\n  mutationFn: updateTodo,\n  // When mutate is called:\n  onMutate: async (newTodo, context) => {\n    // Cancel any outgoing refetches\n    // (so they don't overwrite our optimistic update)\n    await context.client.cancelQueries({ queryKey: ['todos'] })\n\n    // Snapshot the previous value\n    const previousTodos = context.client.getQueryData(['todos'])\n\n    // Optimistically update to the new value\n    context.client.setQueryData(['todos'], (old) => [...old, newTodo])\n\n    // Return a result with the snapshotted value\n    return { previousTodos }\n  },\n  // If the mutation fails,\n  // use the result returned from onMutate to roll back\n  onError: (err, newTodo, onMutateResult, context) => {\n    context.client.setQueryData(['todos'], onMutateResult.previousTodos)\n  },\n  // Always refetch after error or success:\n  onSettled: (data, error, variables, onMutateResult, context) =>\n    context.client.invalidateQueries({ queryKey: ['todos'] }),\n}))\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```tsx\nuseMutation(() => ({\n  mutationFn: updateTodo,\n  // When mutate is called:\n  onMutate: async (newTodo, context) => {\n    // Cancel any outgoing refetches\n    // (so they don't overwrite our optimistic update)\n    await context.client.cancelQueries({ queryKey: ['todos', newTodo.id] })\n\n    // Snapshot the previous value\n    const previousTodo = context.client.getQueryData(['todos', newTodo.id])\n\n    // Optimistically update to the new value\n    context.client.setQueryData(['todos', newTodo.id], newTodo)\n\n    // Return a result with the previous and new todo\n    return { previousTodo, newTodo }\n  },\n  // If the mutation fails, use the result we returned above\n  onError: (err, newTodo, onMutateResult, context) => {\n    context.client.setQueryData(\n      ['todos', onMutateResult.newTodo.id],\n      onMutateResult.previousTodo,\n    )\n  },\n  // Always refetch after error or success:\n  onSettled: (newTodo, error, variables, onMutateResult, context) =>\n    context.client.invalidateQueries({ queryKey: ['todos', newTodo.id] }),\n}))\n```\n\n[//]: # 'Example2'\n[//]: # 'Example3'\n\n```tsx\nuseMutation(() => ({\n  mutationFn: updateTodo,\n  // ...\n  onSettled: async (newTodo, error, variables, onMutateResult, context) => {\n    if (error) {\n      // do something\n    }\n  },\n}))\n```\n\n[//]: # 'Example3'\n"
  },
  {
    "path": "docs/framework/solid/guides/paginated-queries.md",
    "content": "---\nid: paginated-queries\ntitle: Paginated / Lagged Queries\nref: docs/framework/react/guides/paginated-queries.md\nreplace: { 'hook': 'function' }\n---\n\n[//]: # 'Example'\n\n```tsx\nconst projectsQuery = useQuery(() => ({\n  queryKey: ['projects', page()],\n  queryFn: () => fetchProjects(page()),\n}))\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```tsx\nimport { createSignal, Switch, Match, Show, For } from 'solid-js'\nimport { keepPreviousData, useQuery } from '@tanstack/solid-query'\n\nfunction Todos() {\n  const [page, setPage] = createSignal(0)\n\n  const fetchProjects = (page = 0) =>\n    fetch('/api/projects?page=' + page).then((res) => res.json())\n\n  const projectsQuery = useQuery(() => ({\n    queryKey: ['projects', page()],\n    queryFn: () => fetchProjects(page()),\n    placeholderData: keepPreviousData,\n  }))\n\n  return (\n    <div>\n      <Switch>\n        <Match when={projectsQuery.isPending}>\n          <div>Loading...</div>\n        </Match>\n        <Match when={projectsQuery.isError}>\n          <div>Error: {projectsQuery.error.message}</div>\n        </Match>\n        <Match when={projectsQuery.isSuccess}>\n          <div>\n            <For each={projectsQuery.data.projects}>\n              {(project) => <p>{project.name}</p>}\n            </For>\n          </div>\n        </Match>\n      </Switch>\n      <span>Current Page: {page() + 1}</span>\n      <button\n        onClick={() => setPage((old) => Math.max(old - 1, 0))}\n        disabled={page() === 0}\n      >\n        Previous Page\n      </button>\n      <button\n        onClick={() => {\n          if (!projectsQuery.isPlaceholderData && projectsQuery.data?.hasMore) {\n            setPage((old) => old + 1)\n          }\n        }}\n        // Disable the Next Page button until we know a next page is available\n        disabled={\n          projectsQuery.isPlaceholderData || !projectsQuery.data?.hasMore\n        }\n      >\n        Next Page\n      </button>\n      <Show when={projectsQuery.isFetching}>\n        <span> Loading...</span>\n      </Show>\n    </div>\n  )\n}\n```\n\n[//]: # 'Example2'\n"
  },
  {
    "path": "docs/framework/solid/guides/parallel-queries.md",
    "content": "---\nid: parallel-queries\ntitle: Parallel Queries\nref: docs/framework/react/guides/parallel-queries.md\nreplace:\n  {\n    '@tanstack/react-query': '@tanstack/solid-query',\n    'useMutationState[(]': 'useMutationState(() => ',\n    'useMutation[(]': 'useMutation(() => ',\n    'useQuery[(]': 'useQuery(() => ',\n    'useQueries[(]': 'useQueries(() => ',\n    'useInfiniteQuery[(]': 'useInfiniteQuery(() => ',\n    'hooks': 'functions',\n  }\n---\n\n[//]: # 'Example'\n\n```tsx\nfunction App () {\n  // The following queries will execute in parallel\n  const usersQuery = useQuery(() => ({ queryKey: ['users'], queryFn: fetchUsers }))\n  const teamsQuery = useQuery(() => ({ queryKey: ['teams'], queryFn: fetchTeams }))\n  const projectsQuery = useQuery(() => ({ queryKey: ['projects'], queryFn: fetchProjects }))\n  ...\n}\n```\n\n[//]: # 'Example'\n[//]: # 'Info'\n[//]: # 'Info'\n[//]: # 'DynamicParallelIntro'\n\nIf the number of queries you need to execute changes, you cannot use manual querying since that would break reactivity. Instead, TanStack Query provides a `useQueries` function, which you can use to dynamically execute as many queries in parallel as you'd like.\n\n[//]: # 'DynamicParallelIntro'\n[//]: # 'DynamicParallelDescription'\n\n`useQueries` accepts an **accessor that returns an options object** with a **queries key** whose value is an **array of query objects**. It returns an **array of query results**:\n\n[//]: # 'DynamicParallelDescription'\n[//]: # 'Example2'\n\n```tsx\nfunction App(props) {\n  const userQueries = useQueries(() => ({\n    queries: props.users.map((user) => {\n      return {\n        queryKey: ['user', user.id],\n        queryFn: () => fetchUserById(user.id),\n      }\n    }),\n  }))\n}\n```\n\n[//]: # 'Example2'\n"
  },
  {
    "path": "docs/framework/solid/guides/placeholder-query-data.md",
    "content": "---\nid: placeholder-query-data\ntitle: Placeholder Query Data\nref: docs/framework/react/guides/placeholder-query-data.md\n---\n\n[//]: # 'ExampleValue'\n\n```tsx\nfunction Todos() {\n  const todosQuery = useQuery(() => ({\n    queryKey: ['todos'],\n    queryFn: () => fetch('/todos'),\n    placeholderData: placeholderTodos,\n  }))\n}\n```\n\n[//]: # 'ExampleValue'\n[//]: # 'Memoization'\n\n### Placeholder Data Memoization\n\nIf the process for accessing a query's placeholder data is intensive or just not something you want to perform on every render, you can memoize the value:\n\n```tsx\nfunction Todos() {\n  const placeholderData = createMemo(() => generateFakeTodos())\n  const todosQuery = useQuery(() => ({\n    queryKey: ['todos'],\n    queryFn: () => fetch('/todos'),\n    placeholderData: placeholderData(),\n  }))\n}\n```\n\n[//]: # 'Memoization'\n[//]: # 'ExampleFunction'\n\n```tsx\nconst todosQuery = useQuery(() => ({\n  queryKey: ['todos', id],\n  queryFn: () => fetch(`/todos/${id}`),\n  placeholderData: (previousData, previousQuery) => previousData,\n}))\n```\n\n[//]: # 'ExampleFunction'\n[//]: # 'ExampleCache'\n\n```tsx\nfunction BlogPost(props) {\n  const queryClient = useQueryClient()\n  const blogPostQuery = useQuery(() => ({\n    queryKey: ['blogPost', props.blogPostId],\n    queryFn: () => fetch(`/blogPosts/${props.blogPostId}`),\n    placeholderData: () => {\n      // Use the smaller/preview version of the blogPost from the 'blogPosts'\n      // query as the placeholder data for this blogPost query\n      return queryClient\n        .getQueryData(['blogPosts'])\n        ?.find((d) => d.id === props.blogPostId)\n    },\n  }))\n}\n```\n\n[//]: # 'ExampleCache'\n"
  },
  {
    "path": "docs/framework/solid/guides/prefetching.md",
    "content": "---\nid: prefetching\ntitle: Prefetching & Router Integration\nref: docs/framework/react/guides/prefetching.md\n---\n\n[//]: # 'ExampleComponent'\n\n```tsx\nimport { Switch, Match } from 'solid-js'\n\nfunction Article(props) {\n  const articleQuery = useQuery(() => ({\n    queryKey: ['article', props.id],\n    queryFn: getArticleById,\n  }))\n\n  return (\n    <Switch>\n      <Match when={articleQuery.isPending}>\n        Loading article...\n      </Match>\n      <Match when={articleQuery.isSuccess}>\n        <ArticleHeader articleData={articleQuery.data} />\n        <ArticleBody articleData={articleQuery.data} />\n        <Comments id={props.id} />\n      </Match>\n    </Switch>\n  )\n}\n\nfunction Comments(props) {\n  const commentsQuery = useQuery(() => ({\n    queryKey: ['article-comments', props.id],\n    queryFn: getArticleCommentsById,\n  }))\n\n  ...\n}\n```\n\n[//]: # 'ExampleComponent'\n[//]: # 'ExampleParentComponent'\n\n```tsx\nimport { Switch, Match } from 'solid-js'\n\nfunction Article(props) {\n  const articleQuery = useQuery(() => ({\n    queryKey: ['article', props.id],\n    queryFn: getArticleById,\n  }))\n\n  // Prefetch\n  useQuery(() => ({\n    queryKey: ['article-comments', props.id],\n    queryFn: getArticleCommentsById,\n    // Optional optimization to avoid rerenders when this query changes:\n    notifyOnChangeProps: [],\n  }))\n\n  return (\n    <Switch>\n      <Match when={articleQuery.isPending}>\n        Loading article...\n      </Match>\n      <Match when={articleQuery.isSuccess}>\n        <ArticleHeader articleData={articleQuery.data} />\n        <ArticleBody articleData={articleQuery.data} />\n        <Comments id={props.id} />\n      </Match>\n    </Switch>\n  )\n}\n\nfunction Comments(props) {\n  const commentsQuery = useQuery(() => ({\n    queryKey: ['article-comments', props.id],\n    queryFn: getArticleCommentsById,\n  }))\n\n  ...\n}\n```\n\n[//]: # 'ExampleParentComponent'\n[//]: # 'Suspense'\n\nAnother way is to prefetch inside of the query function. This makes sense if you know that every time an article is fetched it's very likely comments will also be needed. For this, we'll use `queryClient.prefetchQuery`:\n\n```tsx\nconst queryClient = useQueryClient()\nconst articleQuery = useQuery(() => ({\n  queryKey: ['article', id],\n  queryFn: (...args) => {\n    queryClient.prefetchQuery({\n      queryKey: ['article-comments', id],\n      queryFn: getArticleCommentsById,\n    })\n\n    return getArticleById(...args)\n  },\n}))\n```\n\nPrefetching in an effect also works:\n\n```tsx\nimport { createEffect } from 'solid-js'\n\nconst queryClient = useQueryClient()\n\ncreateEffect(() => {\n  queryClient.prefetchQuery({\n    queryKey: ['article-comments', id],\n    queryFn: getArticleCommentsById,\n  })\n})\n```\n\nTo recap, if you want to prefetch a query during the component lifecycle, there are a few different ways to do it, pick the one that suits your situation best:\n\n- Use `useQuery` and ignore the result\n- Prefetch inside the query function\n- Prefetch in an effect\n\nLet's look at a slightly more advanced case next.\n\n[//]: # 'Suspense'\n[//]: # 'ExampleConditionally1'\n\n```tsx\nimport { lazy, Switch, Match, For } from 'solid-js'\n\n// This lazy loads the GraphFeedItem component, meaning\n// it wont start loading until something renders it\nconst GraphFeedItem = lazy(() => import('./GraphFeedItem'))\n\nfunction Feed() {\n  const feedQuery = useQuery(() => ({\n    queryKey: ['feed'],\n    queryFn: getFeed,\n  }))\n\n  return (\n    <Switch>\n      <Match when={feedQuery.isPending}>\n        Loading feed...\n      </Match>\n      <Match when={feedQuery.isSuccess}>\n        <For each={feedQuery.data}>\n          {(feedItem) => {\n            if (feedItem.type === 'GRAPH') {\n              return <GraphFeedItem feedItem={feedItem} />\n            }\n            return <StandardFeedItem feedItem={feedItem} />\n          }}\n        </For>\n      </Match>\n    </Switch>\n  )\n}\n\n// GraphFeedItem.tsx\nfunction GraphFeedItem(props) {\n  const graphQuery = useQuery(() => ({\n    queryKey: ['graph', props.feedItem.id],\n    queryFn: getGraphDataById,\n  }))\n\n  ...\n}\n```\n\n[//]: # 'ExampleConditionally1'\n[//]: # 'ExampleConditionally2'\n\n```tsx\nfunction Feed() {\n  const queryClient = useQueryClient()\n  const feedQuery = useQuery(() => ({\n    queryKey: ['feed'],\n    queryFn: async (...args) => {\n      const feed = await getFeed(...args)\n\n      for (const feedItem of feed) {\n        if (feedItem.type === 'GRAPH') {\n          queryClient.prefetchQuery({\n            queryKey: ['graph', feedItem.id],\n            queryFn: getGraphDataById,\n          })\n        }\n      }\n\n      return feed\n    }\n  }))\n\n  ...\n}\n```\n\n[//]: # 'ExampleConditionally2'\n[//]: # 'Router'\n\n## Router Integration\n\nBecause data fetching in the component tree itself can easily lead to request waterfalls and the different fixes for that can be cumbersome as they accumulate throughout the application, an attractive way to do prefetching is integrating it at the router level.\n\nIn this approach, you explicitly declare for each _route_ what data is going to be needed for that component tree, ahead of time. Because Server Rendering has traditionally needed all data to be loaded before rendering starts, this has been the dominating approach for SSR'd apps for a long time. This is still a common approach and you can read more about it in the [Server Rendering & Hydration guide](./ssr.md).\n\nFor now, let's focus on the client side case and look at an example of how you can make this work with [TanStack Router](https://tanstack.com/router). These examples leave out a lot of setup and boilerplate to stay concise, you can check out a [full Solid Query example](https://tanstack.com/router/latest/docs/framework/solid/examples/basic-solid-query-file-based) over in the [TanStack Router docs](https://tanstack.com/router/latest/docs).\n\nWhen integrating at the router level, you can choose to either _block_ rendering of that route until all data is present, or you can start a prefetch but not await the result. That way, you can start rendering the route as soon as possible. You can also mix these two approaches and await some critical data, but start rendering before all the secondary data has finished loading. In this example, we'll configure an `/article` route to not render until the article data has finished loading, as well as start prefetching comments as soon as possible, but not block rendering the route if comments haven't finished loading yet.\n\n```tsx\nconst queryClient = new QueryClient()\nconst routerContext = new RouterContext()\nconst rootRoute = routerContext.createRootRoute({\n  component: () => { ... }\n})\n\nconst articleRoute = new Route({\n  getParentRoute: () => rootRoute,\n  path: 'article',\n  beforeLoad: () => {\n    return {\n      articleQueryOptions: { queryKey: ['article'], queryFn: fetchArticle },\n      commentsQueryOptions: { queryKey: ['comments'], queryFn: fetchComments },\n    }\n  },\n  loader: async ({\n    context: { queryClient },\n    routeContext: { articleQueryOptions, commentsQueryOptions },\n  }) => {\n    // Fetch comments asap, but don't block\n    queryClient.prefetchQuery(commentsQueryOptions)\n\n    // Don't render the route at all until article has been fetched\n    await queryClient.prefetchQuery(articleQueryOptions)\n  },\n  component: ({ useRouteContext }) => {\n    const { articleQueryOptions, commentsQueryOptions } = useRouteContext()\n    const articleQuery = useQuery(() => articleQueryOptions)\n    const commentsQuery = useQuery(() => commentsQueryOptions)\n\n    return (\n      ...\n    )\n  },\n  errorComponent: () => 'Oh crap!',\n})\n```\n\nIntegration with other routers is also possible.\n\n[//]: # 'Router'\n"
  },
  {
    "path": "docs/framework/solid/guides/queries.md",
    "content": "---\nid: queries\ntitle: Queries\nref: docs/framework/react/guides/queries.md\n---\n\n[//]: # 'SubscribeDescription'\n\nTo subscribe to a query in your components, call the `useQuery` function with at least:\n[//]: # 'SubscribeDescription'\n\n[//]: # 'Example'\n\n```tsx\nimport { useQuery } from '@tanstack/solid-query'\n\nfunction App() {\n  const todosQuery = useQuery(() => ({\n    queryKey: ['todos'],\n    queryFn: fetchTodoList,\n  }))\n}\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```tsx\nconst todosQuery = useQuery(() => ({\n  queryKey: ['todos'],\n  queryFn: fetchTodoList,\n}))\n```\n\n[//]: # 'Example2'\n[//]: # 'Example3'\n\n```tsx\nimport { Switch, Match, For } from 'solid-js'\n\nfunction Todos() {\n  const todosQuery = useQuery(() => ({\n    queryKey: ['todos'],\n    queryFn: fetchTodoList,\n  }))\n\n  return (\n    <Switch>\n      <Match when={todosQuery.isPending}>\n        <span>Loading...</span>\n      </Match>\n      <Match when={todosQuery.isError}>\n        <span>Error: {todosQuery.error.message}</span>\n      </Match>\n      <Match when={todosQuery.isSuccess}>\n        <ul>\n          <For each={todosQuery.data}>{(todo) => <li>{todo.title}</li>}</For>\n        </ul>\n      </Match>\n    </Switch>\n  )\n}\n```\n\n[//]: # 'Example3'\n[//]: # 'Example4'\n\n```tsx\nimport { Switch, Match, For } from 'solid-js'\n\nfunction Todos() {\n  const todosQuery = useQuery(() => ({\n    queryKey: ['todos'],\n    queryFn: fetchTodoList,\n  }))\n\n  return (\n    <Switch>\n      <Match when={todosQuery.status === 'pending'}>\n        <span>Loading...</span>\n      </Match>\n      <Match when={todosQuery.status === 'error'}>\n        <span>Error: {todosQuery.error.message}</span>\n      </Match>\n      <Match when={todosQuery.status === 'success'}>\n        <ul>\n          <For each={todosQuery.data}>{(todo) => <li>{todo.title}</li>}</For>\n        </ul>\n      </Match>\n    </Switch>\n  )\n}\n```\n\n[//]: # 'Example4'\n[//]: # 'Materials'\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/solid/guides/query-cancellation.md",
    "content": "---\nid: query-cancellation\ntitle: Query Cancellation\nref: docs/framework/react/guides/query-cancellation.md\nreplace:\n  {\n    '@tanstack/react-query': '@tanstack/solid-query',\n    'useMutationState[(]': 'useMutationState(() => ',\n    'useMutation[(]': 'useMutation(() => ',\n    'useQuery[(]': 'useQuery(() => ',\n    'useQueries[(]': 'useQueries(() => ',\n    'useInfiniteQuery[(]': 'useInfiniteQuery(() => ',\n  }\n---\n\n[//]: # 'Example'\n\n```tsx\nconst todosQuery = useQuery(() => ({\n  queryKey: ['todos'],\n  queryFn: async ({ signal }) => {\n    const todosResponse = await fetch('/todos', {\n      // Pass the signal to one fetch\n      signal,\n    })\n    const todos = await todosResponse.json()\n\n    const todoDetails = todos.map(async ({ details }) => {\n      const response = await fetch(details, {\n        // Or pass it to several\n        signal,\n      })\n      return response.json()\n    })\n\n    return Promise.all(todoDetails)\n  },\n}))\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```tsx\nimport axios from 'axios'\n\nconst todosQuery = useQuery(() => ({\n  queryKey: ['todos'],\n  queryFn: ({ signal }) =>\n    axios.get('/todos', {\n      // Pass the signal to `axios`\n      signal,\n    }),\n}))\n```\n\n[//]: # 'Example2'\n[//]: # 'Example3'\n\n```tsx\nimport axios from 'axios'\n\nconst todosQuery = useQuery(() => ({\n  queryKey: ['todos'],\n  queryFn: ({ signal }) => {\n    // Create a new CancelToken source for this request\n    const CancelToken = axios.CancelToken\n    const source = CancelToken.source()\n\n    const promise = axios.get('/todos', {\n      // Pass the source token to your request\n      cancelToken: source.token,\n    })\n\n    // Cancel the request if TanStack Query signals to abort\n    signal?.addEventListener('abort', () => {\n      source.cancel('Query was cancelled by TanStack Query')\n    })\n\n    return promise\n  },\n}))\n```\n\n[//]: # 'Example3'\n[//]: # 'Example4'\n\n```tsx\nconst todosQuery = useQuery(() => ({\n  queryKey: ['todos'],\n  queryFn: ({ signal }) => {\n    return new Promise((resolve, reject) => {\n      var oReq = new XMLHttpRequest()\n      oReq.addEventListener('load', () => {\n        resolve(JSON.parse(oReq.responseText))\n      })\n      signal?.addEventListener('abort', () => {\n        oReq.abort()\n        reject()\n      })\n      oReq.open('GET', '/todos')\n      oReq.send()\n    })\n  },\n}))\n```\n\n[//]: # 'Example4'\n[//]: # 'Example5'\n\n```tsx\nconst client = new GraphQLClient(endpoint)\n\nconst todosQuery = useQuery(() => ({\n  queryKey: ['todos'],\n  queryFn: ({ signal }) => {\n    client.request({ document: query, signal })\n  },\n}))\n```\n\n[//]: # 'Example5'\n[//]: # 'Example6'\n\n```tsx\nconst todosQuery = useQuery(() => ({\n  queryKey: ['todos'],\n  queryFn: ({ signal }) => {\n    const client = new GraphQLClient(endpoint, {\n      signal,\n    })\n    return client.request(query, variables)\n  },\n}))\n```\n\n[//]: # 'Example6'\n[//]: # 'Example7'\n\n```tsx\nconst todosQuery = useQuery(() => ({\n  queryKey: ['todos'],\n  queryFn: async ({ signal }) => {\n    const resp = await fetch('/todos', { signal })\n    return resp.json()\n  },\n}))\n\nconst queryClient = useQueryClient()\n\nreturn (\n  <button\n    onClick={(e) => {\n      e.preventDefault()\n      queryClient.cancelQueries({ queryKey: ['todos'] })\n    }}\n  >\n    Cancel\n  </button>\n)\n```\n\n[//]: # 'Example7'\n[//]: # 'Limitations'\n[//]: # 'Limitations'\n"
  },
  {
    "path": "docs/framework/solid/guides/query-functions.md",
    "content": "---\nid: query-functions\ntitle: Query Functions\nref: docs/framework/react/guides/query-functions.md\n---\n\n[//]: # 'Example'\n\n```tsx\nuseQuery(() => ({ queryKey: ['todos'], queryFn: fetchAllTodos }))\nuseQuery(() => ({\n  queryKey: ['todos', todoId],\n  queryFn: () => fetchTodoById(todoId),\n}))\nuseQuery(() => ({\n  queryKey: ['todos', todoId],\n  queryFn: async () => {\n    const data = await fetchTodoById(todoId)\n    return data\n  },\n}))\nuseQuery(() => ({\n  queryKey: ['todos', todoId],\n  queryFn: ({ queryKey }) => fetchTodoById(queryKey[1]),\n}))\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```tsx\nconst todosQuery = useQuery(() => ({\n  queryKey: ['todos', todoId],\n  queryFn: async () => {\n    if (somethingGoesWrong) {\n      throw new Error('Oh no!')\n    }\n    if (somethingElseGoesWrong) {\n      return Promise.reject(new Error('Oh no!'))\n    }\n\n    return data\n  },\n}))\n```\n\n[//]: # 'Example2'\n[//]: # 'Example3'\n\n```tsx\nuseQuery(() => ({\n  queryKey: ['todos', todoId],\n  queryFn: async () => {\n    const response = await fetch('/todos/' + todoId)\n    if (!response.ok) {\n      throw new Error('Network response was not ok')\n    }\n    return response.json()\n  },\n}))\n```\n\n[//]: # 'Example3'\n[//]: # 'Example4'\n\n```tsx\nfunction Todos(props) {\n  const todosQuery = useQuery(() => ({\n    queryKey: ['todos', { status: props.status, page: props.page }],\n    queryFn: fetchTodoList,\n  }))\n}\n\n// Access the key, status and page variables in your query function!\nfunction fetchTodoList({ queryKey }) {\n  const [_key, { status, page }] = queryKey\n  return new Promise()\n}\n```\n\n[//]: # 'Example4'\n"
  },
  {
    "path": "docs/framework/solid/guides/query-invalidation.md",
    "content": "---\nid: query-invalidation\ntitle: Query Invalidation\nref: docs/framework/react/guides/query-invalidation.md\nreplace:\n  {\n    '@tanstack/react-query': '@tanstack/solid-query',\n    'useMutationState[(]': 'useMutationState(() => ',\n    'useMutation[(]': 'useMutation(() => ',\n    'useQuery[(]': 'useQuery(() => ',\n    'useQueries[(]': 'useQueries(() => ',\n    'useInfiniteQuery[(]': 'useInfiniteQuery(() => ',\n    'hooks': 'functions',\n  }\n---\n"
  },
  {
    "path": "docs/framework/solid/guides/query-keys.md",
    "content": "---\nid: query-keys\ntitle: Query Keys\nref: docs/framework/react/guides/query-keys.md\nreplace:\n  {\n    '@tanstack/react-query': '@tanstack/solid-query',\n    'useMutationState[(]': 'useMutationState(() => ',\n    'useMutation[(]': 'useMutation(() => ',\n    'useQuery[(]': 'useQuery(() => ',\n    'useQueries[(]': 'useQueries(() => ',\n    'useInfiniteQuery[(]': 'useInfiniteQuery(() => ',\n    'React Query Keys': 'TanStack Query Keys',\n  }\n---\n\n[//]: # 'Example'\n\n```tsx\n// A list of todos\nuseQuery(() => ({ queryKey: ['todos'], ... }))\n\n// Something else, whatever!\nuseQuery(() => ({ queryKey: ['something', 'special'], ... }))\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```tsx\n// An individual todo\nuseQuery(() => ({ queryKey: ['todo', 5], ... }))\n\n// An individual todo in a \"preview\" format\nuseQuery(() => ({ queryKey: ['todo', 5, { preview: true }], ...}))\n\n// A list of todos that are \"done\"\nuseQuery(() => ({ queryKey: ['todos', { type: 'done' }], ... }))\n```\n\n[//]: # 'Example2'\n[//]: # 'Example3'\n\n```tsx\nuseQuery(() => ({ queryKey: ['todos', { status, page }], ... }))\nuseQuery(() => ({ queryKey: ['todos', { page, status }], ...}))\nuseQuery(() => ({ queryKey: ['todos', { page, status, other: undefined }], ... }))\n```\n\n[//]: # 'Example3'\n[//]: # 'Example4'\n\n```tsx\nuseQuery(() => ({ queryKey: ['todos', status, page], ... }))\nuseQuery(() => ({ queryKey: ['todos', page, status], ...}))\nuseQuery(() => ({ queryKey: ['todos', undefined, page, status], ...}))\n```\n\n[//]: # 'Example4'\n[//]: # 'Example5'\n\n```tsx\nfunction Todos(props) {\n  const todosQuery = useQuery(() => ({\n    queryKey: ['todos', props.todoId],\n    queryFn: () => fetchTodoById(props.todoId),\n  }))\n}\n```\n\n[//]: # 'Example5'\n"
  },
  {
    "path": "docs/framework/solid/guides/query-options.md",
    "content": "---\nid: query-options\ntitle: Query Options\nref: docs/framework/react/guides/query-options.md\nreplace:\n  {\n    '@tanstack/react-query': '@tanstack/solid-query',\n    'useMutationState[(]': 'useMutationState(() => ',\n    'useMutation[(]': 'useMutation(() => ',\n    'useQuery[(]': 'useQuery(() => ',\n    'useQueries[(]': 'useQueries(() => ',\n    'useInfiniteQuery[(]': 'useInfiniteQuery(() => ',\n  }\n---\n\n[//]: # 'Example1'\n\n```ts\nimport { queryOptions } from '@tanstack/solid-query'\n\nfunction groupOptions(id: number) {\n  return queryOptions({\n    queryKey: ['groups', id],\n    queryFn: () => fetchGroups(id),\n    staleTime: 5 * 1000,\n  })\n}\n\n// usage:\n\nuseQuery(() => groupOptions(1))\nuseQueries(() => ({\n  queries: [groupOptions(1), groupOptions(2)],\n}))\nqueryClient.prefetchQuery(groupOptions(23))\nqueryClient.setQueryData(groupOptions(42).queryKey, newGroups)\n```\n\n[//]: # 'Example1'\n[//]: # 'SelectDescription'\n\nYou can still override some options at the component level. A very common and useful pattern is to create per-component `select` functions:\n\n[//]: # 'SelectDescription'\n[//]: # 'Example2'\n\n```ts\n// Type inference still works, so query.data will be the return type of select instead of queryFn\n\nconst groupQuery = useQuery(() => ({\n  ...groupOptions(1),\n  select: (data) => data.groupName,\n}))\n```\n\n[//]: # 'Example2'\n"
  },
  {
    "path": "docs/framework/solid/guides/query-retries.md",
    "content": "---\nid: query-retries\ntitle: Query Retries\nref: docs/framework/react/guides/query-retries.md\nreplace:\n  {\n    '@tanstack/react-query': '@tanstack/solid-query',\n    'useMutationState[(]': 'useMutationState(() => ',\n    'useMutation[(]': 'useMutation(() => ',\n    'useQuery[(]': 'useQuery(() => ',\n    'useQueries[(]': 'useQueries(() => ',\n    'useInfiniteQuery[(]': 'useInfiniteQuery(() => ',\n  }\n---\n"
  },
  {
    "path": "docs/framework/solid/guides/request-waterfalls.md",
    "content": "---\nid: request-waterfalls\ntitle: Performance & Request Waterfalls\nref: docs/framework/react/guides/request-waterfalls.md\nreplace: { 'React Query': 'Solid Query' }\n---\n\n[//]: # 'AdvancedSSRLink'\n[//]: # 'AdvancedSSRLink'\n[//]: # 'DependentExample'\n\n```tsx\n// Get the user\nconst userQuery = useQuery(() => ({\n  queryKey: ['user', email],\n  queryFn: getUserByEmail,\n}))\n\nconst userId = () => userQuery.data?.id\n\n// Then get the user's projects\nconst projectsQuery = useQuery(() => ({\n  queryKey: ['projects', userId()],\n  queryFn: getProjectsByUser,\n  // The query will not execute until the userId exists\n  enabled: !!userId(),\n}))\n```\n\n[//]: # 'DependentExample'\n[//]: # 'ServerComponentsNote1'\n[//]: # 'ServerComponentsNote1'\n[//]: # 'SuspenseSerial'\n[//]: # 'SuspenseSerial'\n[//]: # 'NestedIntro'\n\nNested Component Waterfalls is when both a parent and a child component contains queries, and the parent does not render the child until its query is done.\n\n[//]: # 'NestedIntro'\n[//]: # 'NestedExample'\n\n```tsx\nimport { Switch, Match } from 'solid-js'\n\nfunction Article(props) {\n  const articleQuery = useQuery(() => ({\n    queryKey: ['article', props.id],\n    queryFn: getArticleById,\n  }))\n\n  return (\n    <Switch>\n      <Match when={articleQuery.isPending}>\n        Loading article...\n      </Match>\n      <Match when={articleQuery.isSuccess}>\n        <ArticleHeader articleData={articleQuery.data} />\n        <ArticleBody articleData={articleQuery.data} />\n        <Comments id={props.id} />\n      </Match>\n    </Switch>\n  )\n}\n\nfunction Comments(props) {\n  const commentsQuery = useQuery(() => ({\n    queryKey: ['article-comments', props.id],\n    queryFn: getArticleCommentsById,\n  }))\n\n  ...\n}\n```\n\n[//]: # 'NestedExample'\n[//]: # 'NestedHoistedExample'\n\n```tsx\nimport { Switch, Match, Show } from 'solid-js'\n\nfunction Article(props) {\n  const articleQuery = useQuery(() => ({\n    queryKey: ['article', props.id],\n    queryFn: getArticleById,\n  }))\n\n  const commentsQuery = useQuery(() => ({\n    queryKey: ['article-comments', props.id],\n    queryFn: getArticleCommentsById,\n  }))\n\n  return (\n    <Switch>\n      <Match when={articleQuery.isPending}>Loading article...</Match>\n      <Match when={articleQuery.isSuccess}>\n        <ArticleHeader articleData={articleQuery.data} />\n        <ArticleBody articleData={articleQuery.data} />\n        <Switch>\n          <Match when={commentsQuery.isPending}>Loading comments...</Match>\n          <Match when={commentsQuery.isSuccess}>\n            <Comments commentsData={commentsQuery.data} />\n          </Match>\n        </Switch>\n      </Match>\n    </Switch>\n  )\n}\n```\n\n[//]: # 'NestedHoistedExample'\n[//]: # 'NestedHoistedOutro'\n\nThe two queries will now fetch in parallel.\n\n[//]: # 'NestedHoistedOutro'\n[//]: # 'DependentNestedExample'\n\n```tsx\nimport { Switch, Match, For } from 'solid-js'\n\nfunction Feed() {\n  const feedQuery = useQuery(() => ({\n    queryKey: ['feed'],\n    queryFn: getFeed,\n  }))\n\n  return (\n    <Switch>\n      <Match when={feedQuery.isPending}>\n        Loading feed...\n      </Match>\n      <Match when={feedQuery.isSuccess}>\n        <For each={feedQuery.data}>\n          {(feedItem) => {\n            if (feedItem.type === 'GRAPH') {\n              return <GraphFeedItem feedItem={feedItem} />\n            }\n            return <StandardFeedItem feedItem={feedItem} />\n          }}\n        </For>\n      </Match>\n    </Switch>\n  )\n}\n\nfunction GraphFeedItem(props) {\n  const graphQuery = useQuery(() => ({\n    queryKey: ['graph', props.feedItem.id],\n    queryFn: getGraphDataById,\n  }))\n\n  ...\n}\n```\n\n[//]: # 'DependentNestedExample'\n[//]: # 'ServerComponentsNote2'\n\nIn this example, we can't trivially flatten the waterfall by just hoisting the query to the parent, or even adding prefetching. Just like the dependent query example at the beginning of this guide, one option is to refactor our API to include the graph data in the `getFeed` query.\n\n[//]: # 'ServerComponentsNote2'\n[//]: # 'LazyExample'\n\n```tsx\nimport { lazy, Switch, Match, For } from 'solid-js'\n\n// This lazy loads the GraphFeedItem component, meaning\n// it wont start loading until something renders it\nconst GraphFeedItem = lazy(() => import('./GraphFeedItem'))\n\nfunction Feed() {\n  const feedQuery = useQuery(() => ({\n    queryKey: ['feed'],\n    queryFn: getFeed,\n  }))\n\n  return (\n    <Switch>\n      <Match when={feedQuery.isPending}>\n        Loading feed...\n      </Match>\n      <Match when={feedQuery.isSuccess}>\n        <For each={feedQuery.data}>\n          {(feedItem) => {\n            if (feedItem.type === 'GRAPH') {\n              return <GraphFeedItem feedItem={feedItem} />\n            }\n            return <StandardFeedItem feedItem={feedItem} />\n          }}\n        </For>\n      </Match>\n    </Switch>\n  )\n}\n\n// GraphFeedItem.tsx\nfunction GraphFeedItem(props) {\n  const graphQuery = useQuery(() => ({\n    queryKey: ['graph', props.feedItem.id],\n    queryFn: getGraphDataById,\n  }))\n\n  ...\n}\n```\n\n[//]: # 'LazyExample'\n[//]: # 'ServerComponentsNote3'\n[//]: # 'ServerComponentsNote3'\n"
  },
  {
    "path": "docs/framework/solid/guides/scroll-restoration.md",
    "content": "---\nid: scroll-restoration\ntitle: Scroll Restoration\nref: docs/framework/react/guides/scroll-restoration.md\nreplace: { 'React Router’s ScrollRestoration, ': '' }\n---\n"
  },
  {
    "path": "docs/framework/solid/guides/ssr.md",
    "content": "---\nid: ssr\ntitle: SSR\n---\n\nWill come soon\n"
  },
  {
    "path": "docs/framework/solid/guides/suspense.md",
    "content": "---\nid: suspense\ntitle: Suspense\n---\n\nSolid Query can also be used with Solid's [Suspense](https://docs.solidjs.com/reference/components/suspense) API's.\n\nTo do that you need to wrap your suspendable component with `Suspense` component provided by Solid\n\n```tsx\nimport { Suspense } from 'solid-js'\n;<Suspense fallback={<LoadingSpinner />}>\n  <SuspendableComponent />\n</Suspense>\n```\n\nYou can use async `suspense` function that is provided by `solid-query`.\n\n```tsx\nimport { useQuery } from '@tanstack/solid-query'\n\nconst todoFetcher = async () =>\n  await fetch('https://jsonplaceholder.cypress.io/todos').then((response) =>\n    response.json(),\n  )\n\nfunction SuspendableComponent() {\n  const todosQuery = useQuery(() => ({\n    queryKey: ['todos'],\n    queryFn: todoFetcher,\n  }))\n\n  // Accessing todosQuery.data directly inside a <Suspense> boundary\n  // automatically triggers suspension until data is ready\n  return <div>Data: {JSON.stringify(todosQuery.data)}</div>\n}\n```\n\n## Fetch-on-render vs Render-as-you-fetch\n\nOut of the box, Solid Query in `suspense` mode works really well as a **Fetch-on-render** solution with no additional configuration. This means that when your components attempt to mount, they will trigger query fetching and suspend, but only once you have imported them and mounted them. If you want to take it to the next level and implement a **Render-as-you-fetch** model, we recommend implementing [Prefetching](./prefetching) on routing callbacks and/or user interactions events to start loading queries before they are mounted and hopefully even before you start importing or mounting their parent components.\n"
  },
  {
    "path": "docs/framework/solid/guides/testing.md",
    "content": "---\nid: testing\ntitle: Testing\n---\n"
  },
  {
    "path": "docs/framework/solid/guides/updates-from-mutation-responses.md",
    "content": "---\nid: updates-from-mutation-responses\ntitle: Updates from Mutation Responses\nref: docs/framework/react/guides/updates-from-mutation-responses.md\nreplace: { 'hook': 'function' }\n---\n\n[//]: # 'Example'\n\n```tsx\nconst queryClient = useQueryClient()\n\nconst mutation = useMutation(() => ({\n  mutationFn: editTodo,\n  onSuccess: (data) => {\n    queryClient.setQueryData(['todo', { id: 5 }], data)\n  },\n}))\n\nmutation.mutate({\n  id: 5,\n  name: 'Do the laundry',\n})\n\n// The query below will be updated with the response from the\n// successful mutation\nconst todoQuery = useQuery(() => ({\n  queryKey: ['todo', { id: 5 }],\n  queryFn: fetchTodoById,\n}))\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```tsx\nconst useMutateTodo = () => {\n  const queryClient = useQueryClient()\n\n  return useMutation(() => ({\n    mutationFn: editTodo,\n    // Notice the second argument is the variables object that the `mutate` function receives\n    onSuccess: (data, variables) => {\n      queryClient.setQueryData(['todo', { id: variables.id }], data)\n    },\n  }))\n}\n```\n\n[//]: # 'Example2'\n"
  },
  {
    "path": "docs/framework/solid/guides/window-focus-refetching.md",
    "content": "---\nid: window-focus-refetching\ntitle: Window Focus Refetching\nref: docs/framework/react/guides/window-focus-refetching.md\nreplace: { '@tanstack/react-query': '@tanstack/solid-query' }\n---\n\n[//]: # 'Example2'\n\n```tsx\nuseQuery(() => ({\n  queryKey: ['todos'],\n  queryFn: fetchTodos,\n  refetchOnWindowFocus: false,\n}))\n```\n\n[//]: # 'Example2'\n[//]: # 'ReactNative'\n[//]: # 'ReactNative'\n"
  },
  {
    "path": "docs/framework/solid/installation.md",
    "content": "---\nid: installation\ntitle: Installation\n---\n\nYou can install Solid Query via [NPM](https://npmjs.com/),\nor a good ol' `<script>` via\n[ESM.sh](https://esm.sh/).\n\n### NPM\n\n```bash\nnpm i @tanstack/solid-query\n```\n\nor\n\n```bash\npnpm add @tanstack/solid-query\n```\n\nor\n\n```bash\nyarn add @tanstack/solid-query\n```\n\nor\n\n```bash\nbun add @tanstack/solid-query\n```\n\n> Wanna give it a spin before you download? Try out the [simple](./examples/simple) or [basic](./examples/basic) examples!\n\n### CDN\n\nIf you're not using a module bundler or package manager, you can also use this library via an ESM-compatible CDN such as [ESM.sh](https://esm.sh/). Simply add a `<script type=\"module\">` tag to the bottom of your HTML file:\n\n```html\n<script type=\"module\">\n  import { QueryClient } from 'https://esm.sh/@tanstack/solid-query'\n</script>\n```\n\n### Requirements\n\nSolid Query is optimized for modern browsers. It is compatible with the following browsers config\n\n```\nChrome >= 91\nFirefox >= 90\nEdge >= 91\nSafari >= 15\niOS >= 15\nOpera >= 77\n```\n\n> Depending on your environment, you might need to add polyfills. If you want to support older browsers, you need to transpile the library from `node_modules` yourselves.\n"
  },
  {
    "path": "docs/framework/solid/overview.md",
    "content": "---\nid: overview\ntitle: Overview\n---\n\nSolid Query is the official SolidJS adapter of TanStack Query that makes **fetching, caching, synchronizing and updating server state** in your web applications a breeze.\n\n## Motivation\n\nSolidJS has been gaining popularity as a fast, reactive, and declarative library for building user interfaces. It comes packed with a lot of features out of the box. Primitives like `createSignal`, `createStore` are great for managing client state. And, unlike other UI libraries, SolidJS has strong opinions about managing asynchronous data. The `createResource` API is a great primitive for handling server state in SolidJS apps. A `resource` is a special kind of signal that can be used to trigger `Suspense` boundaries when the data is in a loading state.\n\n```tsx\nimport { createResource, ErrorBoundary, Suspense } from 'solid-js'\nimport { render } from 'solid-js/web'\n\nfunction App() {\n  const [repository] = createResource(async () => {\n    const result = await fetch('https://api.github.com/repos/TanStack/query')\n    if (!result.ok) throw new Error('Failed to fetch data')\n    return result.json()\n  })\n\n  return (\n    <div>\n      <div>Static Content</div>\n      {/* An error while fetching will be caught by the ErrorBoundary */}\n      <ErrorBoundary fallback={<div>Something went wrong!</div>}>\n        {/* Suspense will trigger a loading state while the data is being fetched */}\n        <Suspense fallback={<div>Loading...</div>}>\n          <div>{repository()?.updated_at}</div>\n        </Suspense>\n      </ErrorBoundary>\n    </div>\n  )\n}\n\nconst root = document.getElementById('root')\n\nrender(() => <App />, root!)\n```\n\nThis is amazing! In a few lines of code, you can fetch data from an API and handle loading and error states. But, as your application grows in complexity, you will need more features to manage server state effectively. This is because **server state is totally different from client state**. For starters, server state:\n\n- Is persisted remotely in a location you do not control or own\n- Requires asynchronous APIs for fetching and updating\n- Implies shared ownership and can be changed by other people without your knowledge\n- Can potentially become \"out of date\" in your applications if you're not careful\n\nOnce you grasp the nature of server state in your application, **even more challenges will arise** as you go, for example:\n\n- Caching... (possibly the hardest thing to do in programming)\n- Deduping multiple requests for the same data into a single request\n- Updating \"out of date\" data in the background\n- Knowing when data is \"out of date\"\n- Reflecting updates to data as quickly as possible\n- Performance optimizations like pagination and lazy loading data\n- Managing memory and garbage collection of server state\n- Memoizing query results with structural sharing\n\nThis is where **Solid Query** comes in. The library wraps around `createResource` and provides a set of hooks and utilities to manage server state effectively. It works amazingly well **out-of-the-box, with zero-config, and can be customized** to your liking as your application grows.\n\nOn a more technical note, Solid Query will likely:\n\n- Help you remove **many** lines of complicated and misunderstood code from your application and replace with just a handful of lines of Solid Query logic.\n- Make your application more maintainable and easier to build new features without worrying about wiring up new server state data sources\n- Have a direct impact on your end-users by making your application feel faster and more responsive than ever before.\n- Potentially help you save on bandwidth and increase memory performance\n\n## Enough talk, show me some code already!\n\nIn the example below, you can see Solid Query in its most basic and simple form being used to fetch the GitHub stats for the TanStack Query GitHub project itself:\n\n```tsx\nimport { ErrorBoundary, Suspense } from 'solid-js'\nimport {\n  useQuery,\n  QueryClient,\n  QueryClientProvider,\n} from '@tanstack/solid-query'\n\nfunction App() {\n  const repositoryQuery = useQuery(() => ({\n    queryKey: ['TanStack Query'],\n    queryFn: async () => {\n      const result = await fetch('https://api.github.com/repos/TanStack/query')\n      if (!result.ok) throw new Error('Failed to fetch data')\n      return result.json()\n    },\n    staleTime: 1000 * 60 * 5, // 5 minutes\n    throwOnError: true, // Throw an error if the query fails\n  }))\n\n  return (\n    <div>\n      <div>Static Content</div>\n      {/* An error while fetching will be caught by the ErrorBoundary */}\n      <ErrorBoundary fallback={<div>Something went wrong!</div>}>\n        {/* Suspense will trigger a loading state while the data is being fetched */}\n        <Suspense fallback={<div>Loading...</div>}>\n          {/* \n            The `data` property on a query is a SolidJS resource  \n            so it will work with Suspense and transitions out of the box! \n          */}\n          <div>{repositoryQuery.data?.updated_at}</div>\n        </Suspense>\n      </ErrorBoundary>\n    </div>\n  )\n}\n\nconst root = document.getElementById('root')\nconst client = new QueryClient()\n\nrender(\n  () => (\n    <QueryClientProvider client={client}>\n      <App />\n    </QueryClientProvider>\n  ),\n  root!,\n)\n```\n\n## Well, that seems like more lines of code to do the same thing?\n\nYes it is! But, these few lines of code unlock a whole new world of possibilities. In the example above, your query is cached for 5 minutes, meaning that if a new component mounts anywhere in your app that uses the same query within 5 minutes, it will not re-fetch the data but instead use the cached data. This is just one of the many features that Solid Query provides out of the box. Some other features include:\n\n- **Automatic Refetching**: Queries automatically refetch in the background when they become \"stale\" (out of date according to the `staleTime` option)\n- **Automatic Caching**: Queries are cached by default and shared across your application\n- **Request Deduplication**: Multiple components can share the same query and make one request\n- **Automatic Garbage Collection**: Queries are garbage collected when they are no longer needed\n- **Window Focus Refetching**: Queries automatically refetch when the application comes back into focus\n- **Pagination**: Built-in support for pagination\n- **Request Cancellation**: Automatically cancels outdated or unwanted requests\n- **Polling/Realtime**: It's easy to add polling or realtime updates to your queries with a simple `refetchInterval` option\n- **SSR Support**: Solid Query works great with server-side rendering\n- **Optimistic Updates**: Easily update your cache with optimistic updates\n- **And much more...**\n"
  },
  {
    "path": "docs/framework/solid/plugins/broadcastQueryClient.md",
    "content": "---\nid: broadcastQueryClient\ntitle: broadcastQueryClient (Experimental)\nref: docs/framework/react/plugins/broadcastQueryClient.md\n---\n"
  },
  {
    "path": "docs/framework/solid/plugins/createPersister.md",
    "content": "---\nid: createPersister\ntitle: experimental_createPersister\nref: docs/framework/react/plugins/createPersister.md\nreplace: { 'react-query': 'solid-query' }\n---\n"
  },
  {
    "path": "docs/framework/solid/quick-start.md",
    "content": "---\nid: quick-start\ntitle: Quick Start\n---\n\nThe `@tanstack/solid-query` package provides a 1st-class API for using TanStack Query with SolidJS.\n\n## Example\n\n```tsx\nimport {\n  QueryClient,\n  QueryClientProvider,\n  useQuery,\n} from '@tanstack/solid-query'\nimport { Switch, Match, For } from 'solid-js'\n\nconst queryClient = new QueryClient()\n\nfunction Example() {\n  const query = useQuery(() => ({\n    queryKey: ['todos'],\n    queryFn: fetchTodos,\n  }))\n\n  return (\n    <div>\n      <Switch>\n        <Match when={query.isPending}>\n          <p>Loading...</p>\n        </Match>\n        <Match when={query.isError}>\n          <p>Error: {query.error.message}</p>\n        </Match>\n        <Match when={query.isSuccess}>\n          <For each={query.data}>{(todo) => <p>{todo.title}</p>}</For>\n        </Match>\n      </Switch>\n    </div>\n  )\n}\n\nfunction App() {\n  return (\n    <QueryClientProvider client={queryClient}>\n      <Example />\n    </QueryClientProvider>\n  )\n}\n```\n\n## Important Differences between Solid Query & React Query\n\nSolid Query offers an API similar to React Query, but there are some key differences to be mindful of.\n\n- Arguments to `solid-query` primitives (like `useQuery`, `useMutation`, `useIsFetching`) are functions, so that they can be tracked in a reactive scope.\n\n```tsx\n// ❌ react version\nuseQuery({\n  queryKey: ['todos', todo],\n  queryFn: fetchTodos,\n})\n\n// ✅ solid version\nuseQuery(() => ({\n  queryKey: ['todos', todo],\n  queryFn: fetchTodos,\n}))\n```\n\n- Suspense works for queries out of the box if you access the query data inside a `<Suspense>` boundary.\n\n```tsx\nimport { For, Suspense } from 'solid-js'\n\nfunction Example() {\n  const query = useQuery(() => ({\n    queryKey: ['todos'],\n    queryFn: fetchTodos,\n  }))\n  return (\n    <div>\n      {/* ✅ Will trigger loading fallback, data accessed in a suspense boundary. */}\n      <Suspense fallback={'Loading...'}>\n        <For each={query.data}>{(todo) => <div>{todo.title}</div>}</For>\n      </Suspense>\n      {/* ❌ Will not trigger loading fallback, data not accessed in a suspense boundary. */}\n      <For each={query.data}>{(todo) => <div>{todo.title}</div>}</For>\n    </div>\n  )\n}\n```\n\n- Solid Query primitives do not support destructuring. The return value from these functions is a store, and their properties are only tracked in a reactive context.\n\n```tsx\nimport {\n  QueryClient,\n  QueryClientProvider,\n  useQuery,\n} from '@tanstack/solid-query'\nimport { Match, Switch } from 'solid-js'\n\nconst queryClient = new QueryClient()\n\nexport default function App() {\n  return (\n    <QueryClientProvider client={queryClient}>\n      <Example />\n    </QueryClientProvider>\n  )\n}\n\nfunction Example() {\n  // ❌ react version -- supports destructing outside reactive context\n  // const { isPending, error, data } = useQuery({\n  //   queryKey: ['repoData'],\n  //   queryFn: () =>\n  //     fetch('https://api.github.com/repos/tannerlinsley/react-query').then(\n  //       (res) => res.json()\n  //     ),\n  // })\n\n  // ✅ solid version -- does not support destructuring outside reactive context\n  const query = useQuery(() => ({\n    queryKey: ['repoData'],\n    queryFn: () =>\n      fetch('https://api.github.com/repos/tannerlinsley/react-query').then(\n        (res) => res.json(),\n      ),\n  }))\n\n  // ✅ access query properties in JSX reactive context\n  return (\n    <Switch>\n      <Match when={query.isPending}>Loading...</Match>\n      <Match when={query.isError}>Error: {query.error.message}</Match>\n      <Match when={query.isSuccess}>\n        <div>\n          <h1>{query.data.name}</h1>\n          <p>{query.data.description}</p>\n          <strong>👀 {query.data.subscribers_count}</strong>{' '}\n          <strong>✨ {query.data.stargazers_count}</strong>{' '}\n          <strong>🍴 {query.data.forks_count}</strong>\n        </div>\n      </Match>\n    </Switch>\n  )\n}\n```\n\n- Signals and store values can be passed in directly to function arguments. Solid Query will update the query `store` automatically.\n\n```tsx\nimport {\n  QueryClient,\n  QueryClientProvider,\n  useQuery,\n} from '@tanstack/solid-query'\nimport { createSignal, For } from 'solid-js'\n\nconst queryClient = new QueryClient()\n\nfunction Example() {\n  const [enabled, setEnabled] = createSignal(false)\n  const [todo, setTodo] = createSignal(0)\n\n  // ✅ passing a signal directly is safe and observers update\n  // automatically when the value of a signal changes\n  const todosQuery = useQuery(() => ({\n    queryKey: ['todos'],\n    queryFn: fetchTodos,\n    enabled: enabled(),\n  }))\n\n  const todoDetailsQuery = useQuery(() => ({\n    queryKey: ['todo', todo()],\n    queryFn: fetchTodo,\n    enabled: todo() > 0,\n  }))\n\n  return (\n    <div>\n      <Switch>\n        <Match when={todosQuery.isPending}>\n          <p>Loading...</p>\n        </Match>\n        <Match when={todosQuery.isError}>\n          <p>Error: {todosQuery.error.message}</p>\n        </Match>\n        <Match when={todosQuery.isSuccess}>\n          <For each={todosQuery.data}>\n            {(todo) => (\n              <button onClick={() => setTodo(todo.id)}>{todo.title}</button>\n            )}\n          </For>\n        </Match>\n      </Switch>\n      <button onClick={() => setEnabled(!enabled())}>Toggle enabled</button>\n    </div>\n  )\n}\n\nfunction App() {\n  return (\n    <QueryClientProvider client={queryClient}>\n      <Example />\n    </QueryClientProvider>\n  )\n}\n```\n\n- Errors can be caught and reset using SolidJS' native `ErrorBoundary` component.\n  Set `throwOnError` or the `suspense` option to `true` to make sure errors are thrown to the `ErrorBoundary`\n\n- Since Property tracking is handled through Solid's fine grained reactivity, options like `notifyOnChangeProps` are not needed\n"
  },
  {
    "path": "docs/framework/solid/reference/hydration.md",
    "content": "---\nid: hydration\ntitle: hydration\nref: docs/framework/react/reference/hydration.md\nreplace: { '@tanstack/react-query': '@tanstack/solid-query' }\n---\n\n[//]: # 'HydrationBoundary'\n[//]: # 'HydrationBoundary'\n"
  },
  {
    "path": "docs/framework/solid/reference/infiniteQueryOptions.md",
    "content": "---\nid: infiniteQueryOptions\ntitle: infiniteQueryOptions\nref: docs/framework/react/reference/infiniteQueryOptions.md\n---\n"
  },
  {
    "path": "docs/framework/solid/reference/mutationOptions.md",
    "content": "---\nid: mutationOptions\ntitle: mutationOptions\nref: docs/framework/react/reference/mutationOptions.md\n---\n"
  },
  {
    "path": "docs/framework/solid/reference/queryOptions.md",
    "content": "---\nid: queryOptions\ntitle: queryOptions\nref: docs/framework/react/reference/queryOptions.md\n---\n"
  },
  {
    "path": "docs/framework/solid/reference/useInfiniteQuery.md",
    "content": "---\nid: useInfiniteQuery\ntitle: useInfiniteQuery\nref: docs/framework/react/reference/useInfiniteQuery.md\nreplace:\n  {\n    '@tanstack/react-query': '@tanstack/solid-query',\n    'useInfiniteQuery[(]': 'useInfiniteQuery(() => ',\n    'useMutation[(]': 'useMutation(() => ',\n  }\n---\n"
  },
  {
    "path": "docs/framework/solid/reference/useIsFetching.md",
    "content": "---\nid: useIsFetching\ntitle: useIsFetching\nref: docs/framework/react/reference/useIsFetching.md\nreplace: { '@tanstack/react-query': '@tanstack/solid-query' }\n---\n"
  },
  {
    "path": "docs/framework/solid/reference/useIsMutating.md",
    "content": "---\nid: useIsMutating\ntitle: useIsMutating\nref: docs/framework/react/reference/useIsMutating.md\nreplace: { '@tanstack/react-query': '@tanstack/solid-query' }\n---\n"
  },
  {
    "path": "docs/framework/solid/reference/useMutation.md",
    "content": "---\nid: useMutation\ntitle: useMutation\nref: docs/framework/react/reference/useMutation.md\nreplace:\n  {\n    '@tanstack/react-query': '@tanstack/solid-query',\n    'useMutationState[(]': 'useMutationState(() => ',\n    'useMutation[(]': 'useMutation(() => ',\n  }\n---\n"
  },
  {
    "path": "docs/framework/solid/reference/useMutationState.md",
    "content": "---\nid: useMutationState\ntitle: useMutationState\nref: docs/framework/react/reference/useMutationState.md\nreplace:\n  {\n    '@tanstack/react-query': '@tanstack/solid-query',\n    'useMutationState[(]': 'useMutationState(() => ',\n    'useMutation[(]': 'useMutation(() => ',\n  }\n---\n"
  },
  {
    "path": "docs/framework/solid/reference/useQueries.md",
    "content": "---\nid: useQueries\ntitle: useQueries\nref: docs/framework/react/reference/useQueries.md\nreplace:\n  {\n    '@tanstack/react-query': '@tanstack/solid-query',\n    'useQueries[(]': 'useQueries(() => ',\n  }\n---\n"
  },
  {
    "path": "docs/framework/solid/reference/useQuery.md",
    "content": "---\nid: useQuery\ntitle: useQuery\n---\n\n```tsx\nconst {\n  data,\n  dataUpdatedAt,\n  error,\n  errorUpdatedAt,\n  failureCount,\n  failureReason,\n  fetchStatus,\n  isError,\n  isFetched,\n  isFetchedAfterMount,\n  isFetching,\n  isInitialLoading,\n  isLoading,\n  isLoadingError,\n  isPaused,\n  isPending,\n  isPlaceholderData,\n  isRefetchError,\n  isRefetching,\n  isStale,\n  isSuccess,\n  refetch,\n  status,\n} = useQuery(\n  () => ({\n    queryKey,\n    queryFn,\n    enabled,\n    select,\n    placeholderData,\n    deferStream,\n    reconcile,\n    gcTime,\n    networkMode,\n    initialData,\n    initialDataUpdatedAt,\n    meta,\n    queryKeyHashFn,\n    refetchInterval,\n    refetchIntervalInBackground,\n    refetchOnMount,\n    refetchOnReconnect,\n    refetchOnWindowFocus,\n    retry,\n    retryOnMount,\n    retryDelay,\n    staleTime,\n    throwOnError,\n  }),\n  () => queryClient,\n)\n```\n\n## Usage example\n\nHere are some examples of how to use the `useQuery` primitive in Solid Query.\n\n### Basic\n\nThe most basic usage of `useQuery` is to create a query that fetches data from an API.\n\n```tsx\nimport { useQuery } from '@tanstack/solid-query'\n\nfunction App() {\n  const todos = useQuery(() => ({\n    queryKey: 'todos',\n    queryFn: async () => {\n      const response = await fetch('/api/todos')\n      if (!response.ok) {\n        throw new Error('Failed to fetch todos')\n      }\n      return response.json()\n    },\n  }))\n\n  return (\n    <div>\n      <Show when={todos.isError}>\n        <div>Error: {todos.error.message}</div>\n      </Show>\n      <Show when={todos.isLoading}>\n        <div>Loading...</div>\n      </Show>\n      <Show when={todos.isSuccess}>\n        <div>\n          <div>Todos:</div>\n          <ul>\n            <For each={todos.data}>{(todo) => <li>{todo.title}</li>}</For>\n          </ul>\n        </div>\n      </Show>\n    </div>\n  )\n}\n```\n\n### Reactive Options\n\nThe reason why `useQuery` accepts a function that returns an object is to allow for reactive options. This is useful when query options depend on other values/signals that might change over time. Solid Query can track the passed function in a reactive scope and re-run it whenever the dependencies change.\n\n```tsx\nimport { useQuery } from '@tanstack/solid-query'\n\nfunction App() {\n  const [filter, setFilter] = createSignal('all')\n\n  const todos = useQuery(() => ({\n    queryKey: ['todos', filter()],\n    queryFn: async () => {\n      const response = await fetch(`/api/todos?filter=${filter()}`)\n      if (!response.ok) {\n        throw new Error('Failed to fetch todos')\n      }\n      return response.json()\n    },\n  }))\n\n  return (\n    <div>\n      <div>\n        <button onClick={() => setFilter('all')}>All</button>\n        <button onClick={() => setFilter('active')}>Active</button>\n        <button onClick={() => setFilter('completed')}>Completed</button>\n      </div>\n      <Show when={todos.isError}>\n        <div>Error: {todos.error.message}</div>\n      </Show>\n      <Show when={todos.isLoading}>\n        <div>Loading...</div>\n      </Show>\n      <Show when={todos.isSuccess}>\n        <div>\n          <div>Todos:</div>\n          <ul>\n            <For each={todos.data}>{(todo) => <li>{todo.title}</li>}</For>\n          </ul>\n        </div>\n      </Show>\n    </div>\n  )\n}\n```\n\n### Usage with `Suspense`\n\n`useQuery` supports triggering SolidJS `Suspense` and `ErrorBoundary` components when the query is in a pending or error state. This allows you to easily handle loading and error states in your components.\n\n```tsx\nimport { useQuery } from '@tanstack/solid-query'\n\nfunction App() {\n  const todos = useQuery(() => ({\n    queryKey: 'todos',\n    queryFn: async () => {\n      const response = await fetch('/api/todos')\n      if (!response.ok) {\n        throw new Error('Failed to fetch todos')\n      }\n      return response.json()\n    },\n    throwOnError: true,\n  }))\n\n  return (\n    <ErrorBoundary fallback={<div>Error: {todos.error.message}</div>}>\n      <Suspense fallback={<div>Loading...</div>}>\n        <div>\n          <div>Todos:</div>\n          <ul>\n            <For each={todos.data}>{(todo) => <li>{todo.title}</li>}</For>\n          </ul>\n        </div>\n      </Suspense>\n    </ErrorBoundary>\n  )\n}\n```\n\n## `useQuery` Parameters\n\n- ### Query Options - `Accessor<QueryOptions>`\n  - ##### `queryKey: unknown[]`\n    - **Required**\n    - The query key to use for this query.\n    - The query key will be hashed into a stable hash. See [Query Keys](../guides/query-keys.md) for more information.\n    - The query will automatically update when this key changes (as long as `enabled` is not set to `false`).\n  - ##### `queryFn: (context: QueryFunctionContext) => Promise<TData>`\n    - **Required, but only if no default query function has been defined** See [Default Query Function](../guides/default-query-function.md) for more information.\n    - The function that the query will use to request data.\n    - Receives a [QueryFunctionContext](../guides/query-functions.md#queryfunctioncontext)\n    - Must return a promise that will either resolve data or throw an error. The data cannot be `undefined`.\n  - ##### `enabled: boolean`\n    - Set this to `false` to disable this query from automatically running.\n    - Can be used for [Dependent Queries](../guides/dependent-queries.md) for more information.\n  - ##### `select: (data: TData) => unknown`\n    - Optional\n    - This option can be used to transform or select a part of the data returned by the query function. It affects the returned `data` value, but does not affect what gets stored in the query cache.\n    - The `select` function will only run if `data` changed, or if the reference to the `select` function itself changes. To optimize, wrap the function in `useCallback`.\n  - ##### `placeholderData: TData | (previousValue: TData | undefined; previousQuery: Query | undefined,) => TData`\n    - Optional\n    - If set, this value will be used as the placeholder data for this particular query observer while the query is still in the `pending` state.\n    - `placeholderData` is **not persisted** to the cache\n    - If you provide a function for `placeholderData`, as a first argument you will receive previously watched query data if available, and the second argument will be the complete previousQuery instance.\n  - ##### `deferStream: boolean`\n    - Optional\n    - Defaults to `false`\n    - Only applicable while rendering queries on the server with streaming.\n    - Set `deferStream` to `true` to wait for the query to resolve on the server before flushing the stream.\n    - This can be useful to avoid sending a loading state to the client before the query has resolved.\n  - ##### `reconcile: false | string | ((oldData: TData | undefined, newData: TData) => TData)`\n    - Optional\n    - Defaults to `false`\n    - Set this to a string to enable reconciliation between query results based on the string key.\n    - Set this to a function which accepts the old and new data and returns resolved data of the same type to implement custom reconciliation logic.\n  - ##### `gcTime: number | Infinity`\n    - Defaults to `5 * 60 * 1000` (5 minutes) or `Infinity` during SSR\n    - The time in milliseconds that unused/inactive cache data remains in memory. When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration. When different garbage collection times are specified, the longest one will be used.\n    - Note: the maximum allowed time is about [24 days](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout#maximum_delay_value), although it is possible to work around this limit using [timeoutManager.setTimeoutProvider](../../../reference/timeoutManager.md#timeoutmanagersettimeoutprovider).\n    - If set to `Infinity`, will disable garbage collection\n  - ##### `networkMode: 'online' | 'always' | 'offlineFirst'`\n    - optional\n    - defaults to `'online'`\n    - see [Network Mode](../guides/network-mode.md) for more information.\n  - ##### `initialData: TData | () => TData`\n    - Optional\n    - If set, this value will be used as the initial data for the query cache (as long as the query hasn't been created or cached yet)\n    - If set to a function, the function will be called **once** during the shared/root query initialization, and be expected to synchronously return the initialData\n    - Initial data is considered stale by default unless a `staleTime` has been set.\n    - `initialData` **is persisted** to the cache\n  - ##### `initialDataUpdatedAt: number | (() => number | undefined)`\n    - Optional\n    - If set, this value will be used as the time (in milliseconds) of when the `initialData` itself was last updated.\n  - ##### `meta: Record<string, unknown>`\n    - Optional\n    - If set, stores additional information on the query cache entry that can be used as needed. It will be accessible wherever the `query` is available, and is also part of the `QueryFunctionContext` provided to the `queryFn`.\n  - ##### `queryKeyHashFn: (queryKey: QueryKey) => string`\n    - Optional\n    - If specified, this function is used to hash the `queryKey` to a string.\n  - ##### `refetchInterval: number | false | ((query: Query) => number | false | undefined)`\n    - Optional\n    - If set to a number, all queries will continuously refetch at this frequency in milliseconds\n    - If set to a function, the function will be executed with the query to compute a frequency\n  - ##### `refetchIntervalInBackground: boolean`\n    - Optional\n    - If set to `true`, queries that are set to continuously refetch with a `refetchInterval` will continue to refetch while their tab/window is in the background\n  - ##### `refetchOnMount: boolean | \"always\" | ((query: Query) => boolean | \"always\")`\n    - Optional\n    - Defaults to `true`\n    - If set to `true`, the query will refetch on mount if the data is stale.\n    - If set to `false`, the query will not refetch on mount.\n    - If set to `\"always\"`, the query will always refetch on mount.\n    - If set to a function, the function will be executed with the query to compute the value\n  - ##### `refetchOnWindowFocus: boolean | \"always\" | ((query: Query) => boolean | \"always\")`\n    - Optional\n    - Defaults to `true`\n    - If set to `true`, the query will refetch on window focus if the data is stale.\n    - If set to `false`, the query will not refetch on window focus.\n    - If set to `\"always\"`, the query will always refetch on window focus.\n    - If set to a function, the function will be executed with the query to compute the value\n  - ##### `refetchOnReconnect: boolean | \"always\" | ((query: Query) => boolean | \"always\")`\n    - Optional\n    - Defaults to `true`\n    - If set to `true`, the query will refetch on reconnect if the data is stale.\n    - If set to `false`, the query will not refetch on reconnect.\n    - If set to `\"always\"`, the query will always refetch on reconnect.\n    - If set to a function, the function will be executed with the query to compute the value\n  - ##### `retry: boolean | number | (failureCount: number, error: TError) => boolean`\n    - If `false`, failed queries will not retry by default.\n    - If `true`, failed queries will retry infinitely.\n    - If set to a `number`, e.g. `3`, failed queries will retry until the failed query count meets that number.\n    - defaults to `3` on the client and `0` on the server\n  - ##### `retryOnMount: boolean`\n    - If set to `false`, the query will not be retried on mount if it contains an error. Defaults to `true`.\n  - ##### `retryDelay: number | (retryAttempt: number, error: TError) => number`\n    - This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds.\n    - A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff.\n    - A function like `attempt => attempt * 1000` applies linear backoff.\n  - ##### `staleTime: number | Infinity`\n    - Optional\n    - Defaults to `0`\n    - The time in milliseconds after data is considered stale. This value only applies to the hook it is defined on.\n    - If set to `Infinity`, the data will never be considered stale\n  - ##### `throwOnError: undefined | boolean | (error: TError, query: Query) => boolean`\n    - Set this to `true` if you want errors to be thrown in the render phase and propagate to the nearest error boundary\n    - Set this to `false` to disable `suspense`'s default behavior of throwing errors to the error boundary.\n    - If set to a function, it will be passed the error and the query, and it should return a boolean indicating whether to show the error in an error boundary (`true`) or return the error as state (`false`)\n\n- ### Query Client - `Accessor<QueryClient>`\n  - Optional\n  - Use this to use a custom QueryClient. Otherwise, the one from the nearest context will be used.\n\n## `useQuery` Return Value - `Store<QueryResult<TData, TError>>`\n\n`useQuery` returns a SolidJS store with the following properties:\n\n- ##### `status: QueryStatus`\n  - Will be:\n    - `pending` if there's no cached data and no query attempt was finished yet.\n    - `error` if the query attempt resulted in an error. The corresponding `error` property has the error received from the attempted fetch\n    - `success` if the query has received a response with no errors and is ready to display its data. The corresponding `data` property on the query is the data received from the successful fetch or if the query's `enabled` property is set to `false` and has not been fetched yet `data` is the first `initialData` supplied to the query on initialization.\n- ##### `isPending: boolean`\n  - A derived boolean from the `status` variable above, provided for convenience.\n- ##### `isSuccess: boolean`\n  - A derived boolean from the `status` variable above, provided for convenience.\n- ##### `isError: boolean`\n  - A derived boolean from the `status` variable above, provided for convenience.\n- ##### `isLoadingError: boolean`\n  - Will be `true` if the query failed while fetching for the first time.\n- ##### `isRefetchError: boolean`\n  - Will be `true` if the query failed while refetching.\n- ##### `data: Resource<TData>`\n  - Defaults to `undefined`.\n  - The last successfully resolved data for the query.\n  - **Important**: The `data` property is a SolidJS resource. This means that if the data is accessed underneath a `<Suspense>` component,\n    it will trigger the Suspense boundary if the data is not available yet.\n- ##### `dataUpdatedAt: number`\n  - The timestamp for when the query most recently returned the `status` as `\"success\"`.\n- ##### `error: null | TError`\n  - Defaults to `null`\n  - The error object for the query, if an error was thrown.\n- ##### `errorUpdatedAt: number`\n  - The timestamp for when the query most recently returned the `status` as `\"error\"`.\n- ##### `isStale: boolean`\n  - Will be `true` if the data in the cache is invalidated or if the data is older than the given `staleTime`.\n- ##### `isPlaceholderData: boolean`\n  - Will be `true` if the data shown is the placeholder data.\n- ##### `isFetched: boolean`\n  - Will be `true` if the query has been fetched.\n- ##### `isFetchedAfterMount: boolean`\n  - Will be `true` if the query has been fetched after the component mounted.\n  - This property can be used to not show any previously cached data.\n- ##### `fetchStatus: FetchStatus`\n  - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetches.\n  - `paused`: The query wanted to fetch, but has been `paused`.\n  - `idle`: The query is not fetching.\n  - see [Network Mode](../guides/network-mode.md) for more information.\n- ##### `isFetching: boolean`\n  - A derived boolean from the `fetchStatus` variable above, provided for convenience.\n- ##### `isPaused: boolean`\n  - A derived boolean from the `fetchStatus` variable above, provided for convenience.\n- ##### `isRefetching: boolean`\n  - Is `true` whenever a background refetch is in-flight, which _does not_ include initial `pending`\n  - Is the same as `isFetching && !isPending`\n- ##### `isLoading: boolean`\n  - Is `true` whenever the first fetch for a query is in-flight\n  - Is the same as `isFetching && isPending`\n- ##### `isInitialLoading: boolean`\n  - **deprecated**\n  - An alias for `isLoading`, will be removed in the next major version.\n- ##### `failureCount: number`\n  - The failure count for the query.\n  - Incremented every time the query fails.\n  - Reset to `0` when the query succeeds.\n- ##### `failureReason: null | TError`\n  - The failure reason for the query retry.\n  - Reset to `null` when the query succeeds.\n- ##### `errorUpdateCount: number`\n  - The sum of all errors.\n- ##### `refetch: (options: { throwOnError: boolean, cancelRefetch: boolean }) => Promise<UseQueryResult>`\n  - A function to manually refetch the query.\n  - If the query errors, the error will only be logged. If you want an error to be thrown, pass the `throwOnError: true` option\n  - `cancelRefetch?: boolean`\n    - Defaults to `true`\n      - Per default, a currently running request will be cancelled before a new request is made\n    - When set to `false`, no refetch will be made if there is already a request running.\n"
  },
  {
    "path": "docs/framework/solid/typescript.md",
    "content": "---\nid: typescript\ntitle: TypeScript\n---\n\nSolid Query is written in **TypeScript** to make sure the library and your projects are type-safe!\n\nThings to keep in mind:\n\n- TanStack Query follows [DefinitelyTyped's support window](https://github.com/DefinitelyTyped/DefinitelyTyped#support-window) and supports TypeScript versions released within the last 2 years. At the moment, that means TypeScript **5.4** and newer.\n- Changes to types in this repository are considered **non-breaking** and are usually released as **patch** semver changes (otherwise every type enhancement would be a major version!).\n- It is **highly recommended that you lock your solid-query package version to a specific patch release and upgrade with the expectation that types may be fixed or upgraded between any release**\n- The non-type-related public API of Solid Query still follows semver very strictly.\n\n## Type Inference\n\nTypes in Solid Query generally flow through very well so that you don't have to provide type annotations for yourself\n\n```tsx\nimport { useQuery } from '@tanstack/solid-query'\n\nconst query = useQuery(() => ({\n  queryKey: ['number'],\n  queryFn: () => Promise.resolve(5),\n}))\n\nquery.data\n//    ^? (property) data: number | undefined\n```\n\n[typescript playground](https://www.typescriptlang.org/play/?#code/JYWwDg9gTgLgBAbzgYygUwIYzQRQK5pQCecAvnAGZQQhwDkAAjBgHYDOzyA1gPRsQAbYABMAtAEcCxOgFgAUPOQR28SYRIBeFOiy4pRABQGAlHA0A+OAYTy4duGuIBpNEQBccANp0WeEACNCOgBdABo4W3tHIgAxFg8TM0sABWoQYDY0ADp0fgEANzQDAFZjeVJjMoU5aKzhLAx5Hh57OAA9AH55brkgA)\n\n```tsx\nimport { useQuery } from '@tanstack/solid-query'\n\nconst query = useQuery(() => ({\n  queryKey: ['test'],\n  queryFn: () => Promise.resolve(5),\n  select: (data) => data.toString(),\n}))\n\nquery.data\n//    ^? (property) data: string | undefined\n```\n\n[typescript playground](https://www.typescriptlang.org/play/?#code/JYWwDg9gTgLgBAbzgYygUwIYzQRQK5pQCecAvnAGZQQhwDkAAjBgHYDOzyA1gPRsQAbYABMAtAEcCxOgFgAUPOQR28SYRIBeFOiy4pRABQGAlHA0A+OAYTy4duGuIBpNEQBccANp1sHOgF0AGjhbe0ciADEWDxMzSwAFahBgNjQAOnR+AQA3NAMAVmNA0LtUgTRkGBjhLAxTCzga5jSYCABlGChgFgBzE2K5UmNjeXlwtKaMeR4eezgAPQB+UYU5IA)\n\nThis works best if your `queryFn` has a well-defined returned type. Keep in mind that most data fetching libraries return `any` per default, so make sure to extract it to a properly typed function:\n\n```tsx\nconst fetchGroups = (): Promise<Group[]> =>\n  axios.get('/groups').then((response) => response.data)\n\nconst query = useQuery(() => ({\n  queryKey: ['groups'],\n  queryFn: fetchGroups,\n}))\n\nquery.data\n//    ^? (property) data: Group[] | undefined\n```\n\n[typescript playground](https://www.typescriptlang.org/play/?ssl=11&ssc=4&pln=6&pc=1#code/JYWwDg9gTgLgBAbzgYygUwIYzQRQK5pQCecAvnAGZQQhwDkAAjBgHYDOzyA1gPRsQAbYABMAtAEcCxOgFgAUKEiw4GAB7AIbStVp01GtrLnyYRMGjgBxanjBwAvIjgiAXHBZ4QAI0Jl585Ah2eAo0GGQAC2sIWy1HAAoASjcABR1gNjQAHmjbAG0AXQA+BxL9TQA6AHMw+LoeKpswQ0SKmAi0Fnj0Nkh2C3sSnr7MiuEsDET-OUDguElCEkdUTGx8Rfik0rh4hHk4A-mpIgBpNCI3PLpGmOa6AoAaOH3DheIAMRY3UPCoprYHvJSIkpsY5G8iGMJvIeDxDnAAHoAfmm8iAA)\n\n## Type Narrowing\n\nSolid Query uses a [discriminated union type](https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-func.html#discriminated-unions) for the query result, discriminated by the `status` field and the derived status boolean flags. This will allow you to check for e.g. `success` status to make `data` defined:\n\n```tsx\nconst query = useQuery(() => ({\n  queryKey: ['number'],\n  queryFn: () => Promise.resolve(5),\n}))\n\nif (query.isSuccess) {\n  const data = query.data\n  //     ^? const data: number\n}\n```\n\n[typescript playground](https://www.typescriptlang.org/play/?#code/JYWwDg9gTgLgBAbzgYygUwIYzQRQK5pQCecAvnAGZQQhwDkAAjBgHYDOzyA1gPRsQAbYABMAtAEcCxOgFgAUKEixEKdFjQBRChTTJ45KjXr8hYgFZtZc+cgjt4kwiQC8qzNnxOAFF4CUcZwA+OC8EeTg4R2IAaTQiAC44AG06FjwQACNCOgBdABpwyKkiADEWRL8A4IAFahBgNjQAOnQTADc0LwBWXwK5Ul9feXlgChCooiaGgGU8ZGQ0NjZ-MLkIiNt7OGEsDACipyad5kKInh51iIA9AH55UmHrOSA)\n\n## Typing the error field\n\nThe type for error defaults to `Error`, because that is what most users expect.\n\n```tsx\nconst query = useQuery(() => ({\n  queryKey: ['groups'],\n  queryFn: fetchGroups,\n}))\n\nquery.error\n//    ^? (property) error: Error | null\n```\n\n[typescript playground](https://www.typescriptlang.org/play/?#code/JYWwDg9gTgLgBAbzgYygUwIYzQRQK5pQCecAvnAGZQQhwDkAAjBgHYDOzyA1gPRsQAbYABMAtAEcCxOgFgAUKEiw4GAB7AIbStVp01GtrLnyYRMGjgBxanjBwAvIjgiAXHBZ4QAI0Jl585Ah2eAo0GGQAC2sIWy1HAAoASjcABR1gNjQAHmjbAG0AXQA+BxL9TQA6AHMw+LoeKpswQ0SKmAi0Fnj0Nkh2C3sSnr7MiuEsDET-OUDguElCEkdUTGx8Rfik0rh4hHk4A-mpIgBpNCI3PLpGmOa6AoAaOH3DheIAMRY3UPCoprYHvJSIkpsY5G8iBVCNQoPIeDxDnAAHoAfmm8iAA)\n\nIf you want to throw a custom error, or something that isn't an `Error` at all, you can specify the type of the error field:\n\n```tsx\nconst query = useQuery<Group[], string>(() => ({\n  queryKey: ['groups'],\n  queryFn: fetchGroups,\n}))\n\nquery.error\n//    ^? (property) error: string | null\n```\n\nHowever, this has the drawback that type inference for all other generics of `useQuery` will not work anymore. It is generally not considered a good practice to throw something that isn't an `Error`, so if you have a subclass like `AxiosError` you can use _type narrowing_ to make the error field more specific:\n\n```tsx\nimport axios from 'axios'\n\nconst query = useQuery(() => ({\n  queryKey: ['groups'],\n  queryFn: fetchGroups,\n}))\n\nquery.error\n//    ^? (property) error: Error | null\n\nif (axios.isAxiosError(query.error)) {\n  query.error\n  //    ^? (property) error: AxiosError\n}\n```\n\n[typescript playground](https://www.typescriptlang.org/play/?#code/JYWwDg9gTgLgBAbzgYygUwIYzQRQK5pQCecAvnAGZQQhwDkAAjBgHYDOzyA1gPRsQAbYABMAtAEcCxOgFgAUKEiw4GAB7AIbStVp01GtrLnyYRMGjgBxanjBwAvIjgiAXHBZ4QAI0Jl585Ah2eAo0GGQAC2sIWy1HAAoASjcABR1gNjQAHmjbAG0AXQA+BxL9TQA6AHMw+LoeKpswQ0SKmAi0Fnj0Nkh2C3sSnr7MiuEsDET-OUDguElCEkdUTGx8Rfik0rh4hHk4A-mpIgBpNCI3PLpGmOa6AoAaOH3DheIAMRY3UPCoprYHvJSIkpsY5G8iBVCNQoPIeDxDnAAHoAfmmwAoO3KbAqGQAgupNABRKAw+IQqGk6AgxAvA4U6HQOlweGI1FA+RAA)\n\n[//]: # 'RegisterErrorType'\n\n```tsx\nimport '@tanstack/solid-query'\n\ndeclare module '@tanstack/solid-query' {\n  interface Register {\n    // Use unknown so call sites must narrow explicitly.\n    defaultError: unknown\n  }\n}\n\nconst query = useQuery(() => ({\n  queryKey: ['groups'],\n  queryFn: fetchGroups,\n}))\n\nquery.error\n//    ^? (property) error: unknown | null\n```\n\n[//]: # 'RegisterErrorType'\n\n## Registering global `Meta`\n\nSimilarly to registering a [global error type](#registering-a-global-error) you can also register a global `Meta` type. This ensures the optional `meta` field on [queries](./reference/useQuery.md) and [mutations](./reference/useMutation.md) stays consistent and is type-safe. Note that the registered type must extend `Record<string, unknown>` so that `meta` remains an object.\n\n```ts\nimport '@tanstack/solid-query'\n\ninterface MyMeta extends Record<string, unknown> {\n  // Your meta type definition.\n}\n\ndeclare module '@tanstack/solid-query' {\n  interface Register {\n    queryMeta: MyMeta\n    mutationMeta: MyMeta\n  }\n}\n```\n\n## Typing Query Options\n\nIf you inline query options into `useQuery`, you'll get automatic type inference. However, you might want to extract the query options into a separate function to share them between `useQuery` and e.g. `prefetchQuery`. In that case, you'd lose type inference. To get it back, you can use `queryOptions` helper:\n\n```ts\nimport { queryOptions } from '@tanstack/solid-query'\n\nfunction groupOptions() {\n  return queryOptions({\n    queryKey: ['groups'],\n    queryFn: fetchGroups,\n    staleTime: 5 * 1000,\n  })\n}\n\nuseQuery(groupOptions)\nqueryClient.prefetchQuery(groupOptions())\n```\n\nFurther, the `queryKey` returned from `queryOptions` knows about the `queryFn` associated with it, and we can leverage that type information to make functions like `queryClient.getQueryData` aware of those types as well:\n\n```ts\nfunction groupOptions() {\n  return queryOptions({\n    queryKey: ['groups'],\n    queryFn: fetchGroups,\n    staleTime: 5 * 1000,\n  })\n}\n\nconst data = queryClient.getQueryData(groupOptions().queryKey)\n//    ^? const data: Group[] | undefined\n```\n\nWithout `queryOptions`, the type of `data` would be `unknown`, unless we'd pass a generic to it:\n\n```ts\nconst data = queryClient.getQueryData<Group[]>(['groups'])\n```\n\n## Typesafe disabling of queries using `skipToken`\n\nIf you are using TypeScript, you can use the `skipToken` to disable a query. This is useful when you want to disable a query based on a condition, but you still want to keep the query to be type safe.\n\nRead more about it in the [Disabling Queries](./guides/disabling-queries.md) guide.\n"
  },
  {
    "path": "docs/framework/svelte/devtools.md",
    "content": "---\nid: devtools\ntitle: Devtools\n---\n\n> For Chrome, Firefox, and Edge users: Third-party browser extensions are available for debugging TanStack Query directly in browser DevTools. These provide the same functionality as the framework-specific devtools packages:\n>\n> - <img alt=\"Chrome logo\" src=\"https://www.google.com/chrome/static/images/chrome-logo.svg\" width=\"16\" height=\"16\" class=\"inline mr-1 not-prose\" /> [Devtools for Chrome](https://chromewebstore.google.com/detail/tanstack-query-devtools/annajfchloimdhceglpgglpeepfghfai)\n> - <img alt=\"Firefox logo\" src=\"https://upload.wikimedia.org/wikipedia/commons/a/a0/Firefox_logo%2C_2019.svg\" width=\"16\" height=\"16\" class=\"inline mr-1 not-prose\" /> [Devtools for Firefox](https://addons.mozilla.org/en-US/firefox/addon/tanstack-query-devtools/)\n> - <img alt=\"Edge logo\" src=\"https://upload.wikimedia.org/wikipedia/commons/9/98/Microsoft_Edge_logo_%282019%29.svg\" width=\"16\" height=\"16\" class=\"inline mr-1 not-prose\" /> [Devtools for Edge](https://microsoftedge.microsoft.com/addons/detail/tanstack-query-devtools/edmdpkgkacmjopodhfolmphdenmddobj)\n\n## Install and Import the Devtools\n\nThe devtools are a separate package that you need to install:\n\n```bash\nnpm i @tanstack/svelte-query-devtools\n```\n\nor\n\n```bash\npnpm add @tanstack/svelte-query-devtools\n```\n\nor\n\n```bash\nyarn add @tanstack/svelte-query-devtools\n```\n\nor\n\n```bash\nbun add @tanstack/svelte-query-devtools\n```\n\nYou can import the devtools like this:\n\n```ts\nimport { SvelteQueryDevtools } from '@tanstack/svelte-query-devtools'\n```\n\n## Floating Mode\n\nFloating Mode will mount the devtools as a fixed, floating element in your app and provide a toggle in the corner of the screen to show and hide the devtools. This toggle state will be stored and remembered in localStorage across reloads.\n\nPlace the following code as high in your Svelte app as you can. The closer it is to the root of the page, the better it will work!\n\n```ts\n<script>\n  import { QueryClientProvider } from '@tanstack/svelte-query'\n  import { SvelteQueryDevtools } from '@tanstack/svelte-query-devtools'\n</script>\n\n<QueryClientProvider client={queryClient}>\n  {/* The rest of your application */}\n  <SvelteQueryDevtools />\n</QueryClientProvider>\n```\n\n### Options\n\n- `initialIsOpen: boolean`\n  - Set this `true` if you want the dev tools to default to being open\n- `buttonPosition?: \"top-left\" | \"top-right\" | \"bottom-left\" | \"bottom-right\" | \"relative\"`\n  - Defaults to `bottom-right`\n  - The position of the TanStack logo to open and close the devtools panel\n  - If `relative`, the button is placed in the location that you render the devtools.\n- `position?: \"top\" | \"bottom\" | \"left\" | \"right\"`\n  - Defaults to `bottom`\n  - The position of the Svelte Query devtools panel\n- `client?: QueryClient`,\n  - Use this to use a custom QueryClient. Otherwise, the one from the nearest context will be used.\n- `errorTypes?: { name: string; initializer: (query: Query) => TError}`\n  - Use this to predefine some errors that can be triggered on your queries. Initializer will be called (with the specific query) when that error is toggled on from the UI. It must return an Error.\n- `styleNonce?: string`\n  - 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.\n- `shadowDOMTarget?: ShadowRoot`\n  - Default behavior will apply the devtool's styles to the head tag within the DOM.\n  - Use this to pass a shadow DOM target to the devtools so that the styles will be applied within the shadow DOM instead of within the head tag in the light DOM.\n"
  },
  {
    "path": "docs/framework/svelte/installation.md",
    "content": "---\nid: installation\ntitle: Installation\n---\n\nYou can install Svelte Query via [NPM](https://npmjs.com).\n\n### NPM\n\n```bash\nnpm i @tanstack/svelte-query\n```\n\nor\n\n```bash\npnpm add @tanstack/svelte-query\n```\n\nor\n\n```bash\nyarn add @tanstack/svelte-query\n```\n\nor\n\n```bash\nbun add @tanstack/svelte-query\n```\n\n> Wanna give it a spin before you download? Try out the [basic](./examples/basic) example!\n"
  },
  {
    "path": "docs/framework/svelte/migrate-from-v5-to-v6.md",
    "content": "While Svelte v5 has legacy compatibility with the stores syntax from Svelte v3/v4, it has been somewhat buggy and unreliable for this adapter. The `@tanstack/svelte-query` v6 adapter fully migrates to the runes syntax, which relies on signals. This rewrite should also simplify the code required to ensure your query inputs remain reactive.\n\n## Installation\n\nPlease ensure your project has [Svelte v5.25.0](https://github.com/sveltejs/svelte/releases/tag/svelte%405.25.0) or newer.\n\nRun `pnpm add @tanstack/svelte-query@latest` (or your package manager's equivalent).\n\n> Note that `@tanstack/svelte-query` v6 depends on `@tanstack/query-core` v5.\n\n## Function Inputs\n\nLike the Angular and Solid adapters, most functions for the Svelte adapter now require options to be provided as a \"thunk\" (`() => options`) to provide reactivity. TypeScript will be your friend here and warn you if you're missing this notation.\n\n```ts\n- const query = createQuery({  // [!code --]\n+ const query = createQuery(() => ({ // [!code ++]\n    queryKey: ['todos'],\n    queryFn: () => fetchTodos(),\n- }) // [!code --]\n+ })) // [!code ++]\n```\n\n## Accessing Properties\n\nGiven the adapter no longer uses stores, it is no longer necessary to prefix with `$`.\n\n```svelte\n- {#if $todos.isSuccess} // [!code --]\n+ {#if todos.isSuccess} // [!code ++]\n    <ul>\n-     {#each $todos.data.items as item} // [!code --]\n+     {#each todos.data.items as item} // [!code ++]\n        <li>{item}</li>\n      {/each}\n    </ul>\n  {/if}\n```\n\n## Reactivity\n\nYou previously needed to do some funky things with stores to achieve reactivity for inputs. This is no longer the case! You don't even need to wrap your query in a `$derived`.\n\n```ts\n- const intervalMs = writable(1000) // [!code --]\n+ let intervalMs = $state(1000) // [!code ++]\n\n- const query = createQuery(derived(intervalMs, ($intervalMs) => ({ // [!code --]\n+ const query = createQuery(() => ({ // [!code ++]\n    queryKey: ['refetch'],\n    queryFn: async () => await fetch('/api/data').then((r) => r.json()),\n-   refetchInterval: $intervalMs, // [!code --]\n+   refetchInterval: intervalMs, // [!code ++]\n- }))) // [!code --]\n+ })) // [!code ++]\n```\n\n## Disabling Legacy Mode\n\nIf your component has any stores, it might not properly switch to runes mode. You can ensure your application is using runes in two ways:\n\n### On a per-file basis\n\nIn each `.svelte` file, once you have migrated to runes, add `<svelte:options runes={true} />`. This is better for large applications requiring gradual migration.\n\n### On an project-wide basis\n\nIn your `svelte.config.js`, add the following to config:\n\n```json\n  compilerOptions: {\n    runes: true,\n  },\n```\n\nThis can be added once you've 100% eradicated stores syntax from your app.\n"
  },
  {
    "path": "docs/framework/svelte/overview.md",
    "content": "---\nid: overview\ntitle: Overview\n---\n\nThe `@tanstack/svelte-query` package offers a 1st-class API for using TanStack Query via Svelte.\n\n> Migrating from stores to the runes syntax? See the [migration guide](./migrate-from-v5-to-v6).\n\n## Example\n\nInclude the QueryClientProvider near the root of your project:\n\n```svelte\n<script lang=\"ts\">\n  import { QueryClient, QueryClientProvider } from '@tanstack/svelte-query'\n  import Example from './lib/Example.svelte'\n\n  const queryClient = new QueryClient()\n</script>\n\n<QueryClientProvider client={queryClient}>\n  <Example />\n</QueryClientProvider>\n```\n\nThen call any function (e.g. createQuery) from any component:\n\n```svelte\n<script lang=\"ts\">\n  import { createQuery } from '@tanstack/svelte-query'\n\n  const query = createQuery(() => ({\n    queryKey: ['todos'],\n    queryFn: () => fetchTodos(),\n  }))\n</script>\n\n<div>\n  {#if query.isLoading}\n    <p>Loading...</p>\n  {:else if query.isError}\n    <p>Error: {query.error.message}</p>\n  {:else if query.isSuccess}\n    {#each query.data as todo}\n      <p>{todo.title}</p>\n    {/each}\n  {/if}\n</div>\n```\n\n## SvelteKit\n\nIf you are using SvelteKit, please have a look at [SSR & SvelteKit](./ssr).\n\n## Available Functions\n\nSvelte Query offers useful functions and components that will make managing server state in Svelte apps easier.\n\n- `createQuery`\n- `createQueries`\n- `createInfiniteQuery`\n- `createMutation`\n- `useQueryClient`\n- `useIsFetching`\n- `useIsMutating`\n- `useMutationState`\n- `useIsRestoring`\n- `useHydrate`\n- `<QueryClientProvider>`\n- `<HydrationBoundary>`\n\n## Important Differences between Svelte Query & React Query\n\nSvelte Query offers an API similar to React Query, but there are some key differences to be mindful of.\n\n- The arguments to the `create*` functions must be wrapped in a function to preserve reactivity.\n"
  },
  {
    "path": "docs/framework/svelte/reference/functions/createInfiniteQuery.md",
    "content": "---\nid: createInfiniteQuery\ntitle: createInfiniteQuery\n---\n\n# Function: createInfiniteQuery()\n\n```ts\nfunction createInfiniteQuery<TQueryFnData, TError, TData, TQueryKey, TPageParam>(options, queryClient?): CreateInfiniteQueryResult<TData, TError>;\n```\n\nDefined in: [packages/svelte-query/src/createInfiniteQuery.ts:16](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/createInfiniteQuery.ts#L16)\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData`\n\n### TError\n\n`TError` = `Error`\n\n### TData\n\n`TData` = `InfiniteData`\\<`TQueryFnData`, `unknown`\\>\n\n### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n### TPageParam\n\n`TPageParam` = `unknown`\n\n## Parameters\n\n### options\n\n[`Accessor`](../type-aliases/Accessor.md)\\<[`CreateInfiniteQueryOptions`](../type-aliases/CreateInfiniteQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\>\\>\n\n### queryClient?\n\n[`Accessor`](../type-aliases/Accessor.md)\\<`QueryClient`\\>\n\n## Returns\n\n[`CreateInfiniteQueryResult`](../type-aliases/CreateInfiniteQueryResult.md)\\<`TData`, `TError`\\>\n"
  },
  {
    "path": "docs/framework/svelte/reference/functions/createMutation.md",
    "content": "---\nid: createMutation\ntitle: createMutation\n---\n\n# Function: createMutation()\n\n```ts\nfunction createMutation<TData, TError, TVariables, TContext>(options, queryClient?): CreateMutationResult<TData, TError, TVariables, TContext>;\n```\n\nDefined in: [packages/svelte-query/src/createMutation.svelte.ts:17](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/createMutation.svelte.ts#L17)\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `Error`\n\n### TVariables\n\n`TVariables` = `void`\n\n### TContext\n\n`TContext` = `unknown`\n\n## Parameters\n\n### options\n\n[`Accessor`](../type-aliases/Accessor.md)\\<[`CreateMutationOptions`](../type-aliases/CreateMutationOptions.md)\\<`TData`, `TError`, `TVariables`, `TContext`\\>\\>\n\nA function that returns mutation options\n\n### queryClient?\n\n[`Accessor`](../type-aliases/Accessor.md)\\<`QueryClient`\\>\n\nCustom query client which overrides provider\n\n## Returns\n\n[`CreateMutationResult`](../type-aliases/CreateMutationResult.md)\\<`TData`, `TError`, `TVariables`, `TContext`\\>\n"
  },
  {
    "path": "docs/framework/svelte/reference/functions/createQueries.md",
    "content": "---\nid: createQueries\ntitle: createQueries\n---\n\n# Function: createQueries()\n\n```ts\nfunction createQueries<T, TCombinedResult>(createQueriesOptions, queryClient?): TCombinedResult;\n```\n\nDefined in: [packages/svelte-query/src/createQueries.svelte.ts:189](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/createQueries.svelte.ts#L189)\n\n## Type Parameters\n\n### T\n\n`T` *extends* `any`[]\n\n### TCombinedResult\n\n`TCombinedResult` = `T` *extends* \\[\\] ? \\[\\] : `T` *extends* \\[`Head`\\] ? \\[`GetCreateQueryResult`\\<`Head`\\>\\] : `T` *extends* \\[`Head`, `...Tails[]`\\] ? \\[`...Tails[]`\\] *extends* \\[\\] ? \\[\\] : \\[`...Tails[]`\\] *extends* \\[`Head`\\] ? \\[`GetCreateQueryResult`\\<`Head`\\>, `GetCreateQueryResult`\\<`Head`\\>\\] : \\[`...Tails[]`\\] *extends* \\[`Head`, `...Tails[]`\\] ? \\[`...Tails[]`\\] *extends* \\[\\] ? \\[\\] : \\[`...Tails[]`\\] *extends* \\[`Head`\\] ? \\[`GetCreateQueryResult`\\<`Head`\\>, `GetCreateQueryResult`\\<`Head`\\>, `GetCreateQueryResult`\\<`Head`\\>\\] : \\[`...Tails[]`\\] *extends* \\[`Head`, `...Tails[]`\\] ? \\[`...(...)[]`\\] *extends* \\[\\] ? \\[\\] : ... *extends* ... ? ... : ... : \\[`...{ [K in (...)]: (...) }[]`\\] : \\[...\\{ \\[K in string \\| number \\| symbol\\]: GetCreateQueryResult\\<Tails\\[K\\<(...)\\>\\]\\> \\}\\[\\]\\] : \\{ \\[K in string \\| number \\| symbol\\]: GetCreateQueryResult\\<T\\[K\\<K\\>\\]\\> \\}\n\n## Parameters\n\n### createQueriesOptions\n\n[`Accessor`](../type-aliases/Accessor.md)\\<\\{\n  `combine?`: (`result`) => `TCombinedResult`;\n  `queries`:   \\| readonly \\[`T` *extends* \\[\\] ? \\[\\] : `T` *extends* \\[`Head`\\] ? \\[`GetCreateQueryOptionsForCreateQueries`\\<`Head`\\>\\] : `T` *extends* \\[`Head`, `...Tails[]`\\] ? \\[`...Tails[]`\\] *extends* \\[\\] ? \\[\\] : \\[`...Tails[]`\\] *extends* \\[`Head`\\] ? \\[`GetCreateQueryOptionsForCreateQueries`\\<...\\>, `GetCreateQueryOptionsForCreateQueries`\\<...\\>\\] : \\[`...(...)[]`\\] *extends* \\[..., `...(...)[]`\\] ? ... *extends* ... ? ... : ... : ... *extends* ... ? ... : ... : readonly `unknown`[] *extends* `T` ? `T` : `T` *extends* `CreateQueryOptionsForCreateQueries`\\<..., ..., ..., ...\\>[] ? `CreateQueryOptionsForCreateQueries`\\<..., ..., ..., ...\\>[] : `CreateQueryOptionsForCreateQueries`\\<..., ..., ..., ...\\>[]\\]\n     \\| readonly \\[\\{ \\[K in string \\| number \\| symbol\\]: GetCreateQueryOptionsForCreateQueries\\<T\\[K\\<K\\>\\]\\> \\}\\];\n\\}\\>\n\n### queryClient?\n\n[`Accessor`](../type-aliases/Accessor.md)\\<`QueryClient`\\>\n\n## Returns\n\n`TCombinedResult`\n"
  },
  {
    "path": "docs/framework/svelte/reference/functions/createQuery.md",
    "content": "---\nid: createQuery\ntitle: createQuery\n---\n\n# Function: createQuery()\n\n## Call Signature\n\n```ts\nfunction createQuery<TQueryFnData, TError, TData, TQueryKey>(options, queryClient?): CreateQueryResult<TData, TError>;\n```\n\nDefined in: [packages/svelte-query/src/createQuery.ts:15](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/createQuery.ts#L15)\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `TQueryFnData`\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n### Parameters\n\n#### options\n\n[`Accessor`](../type-aliases/Accessor.md)\\<[`UndefinedInitialDataOptions`](../type-aliases/UndefinedInitialDataOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>\\>\n\n#### queryClient?\n\n[`Accessor`](../type-aliases/Accessor.md)\\<`QueryClient`\\>\n\n### Returns\n\n[`CreateQueryResult`](../type-aliases/CreateQueryResult.md)\\<`TData`, `TError`\\>\n\n## Call Signature\n\n```ts\nfunction createQuery<TQueryFnData, TError, TData, TQueryKey>(options, queryClient?): DefinedCreateQueryResult<TData, TError>;\n```\n\nDefined in: [packages/svelte-query/src/createQuery.ts:27](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/createQuery.ts#L27)\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `TQueryFnData`\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n### Parameters\n\n#### options\n\n[`Accessor`](../type-aliases/Accessor.md)\\<[`DefinedInitialDataOptions`](../type-aliases/DefinedInitialDataOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>\\>\n\n#### queryClient?\n\n[`Accessor`](../type-aliases/Accessor.md)\\<`QueryClient`\\>\n\n### Returns\n\n[`DefinedCreateQueryResult`](../type-aliases/DefinedCreateQueryResult.md)\\<`TData`, `TError`\\>\n\n## Call Signature\n\n```ts\nfunction createQuery<TQueryFnData, TError, TData, TQueryKey>(options, queryClient?): CreateQueryResult<TData, TError>;\n```\n\nDefined in: [packages/svelte-query/src/createQuery.ts:39](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/createQuery.ts#L39)\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `TQueryFnData`\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n### Parameters\n\n#### options\n\n[`Accessor`](../type-aliases/Accessor.md)\\<[`CreateQueryOptions`](../type-aliases/CreateQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>\\>\n\n#### queryClient?\n\n[`Accessor`](../type-aliases/Accessor.md)\\<`QueryClient`\\>\n\n### Returns\n\n[`CreateQueryResult`](../type-aliases/CreateQueryResult.md)\\<`TData`, `TError`\\>\n"
  },
  {
    "path": "docs/framework/svelte/reference/functions/getIsRestoringContext.md",
    "content": "---\nid: getIsRestoringContext\ntitle: getIsRestoringContext\n---\n\n# Function: getIsRestoringContext()\n\n```ts\nfunction getIsRestoringContext(): Box<boolean>;\n```\n\nDefined in: [packages/svelte-query/src/context.ts:27](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/context.ts#L27)\n\nRetrieves a `isRestoring` from Svelte's context\n\n## Returns\n\n`Box`\\<`boolean`\\>\n"
  },
  {
    "path": "docs/framework/svelte/reference/functions/getQueryClientContext.md",
    "content": "---\nid: getQueryClientContext\ntitle: getQueryClientContext\n---\n\n# Function: getQueryClientContext()\n\n```ts\nfunction getQueryClientContext(): QueryClient;\n```\n\nDefined in: [packages/svelte-query/src/context.ts:8](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/context.ts#L8)\n\nRetrieves a Client from Svelte's context\n\n## Returns\n\n`QueryClient`\n"
  },
  {
    "path": "docs/framework/svelte/reference/functions/infiniteQueryOptions.md",
    "content": "---\nid: infiniteQueryOptions\ntitle: infiniteQueryOptions\n---\n\n# Function: infiniteQueryOptions()\n\n```ts\nfunction infiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>(options): CreateInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>;\n```\n\nDefined in: [packages/svelte-query/src/infiniteQueryOptions.ts:4](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/infiniteQueryOptions.ts#L4)\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData`\n\n### TError\n\n`TError` = `Error`\n\n### TData\n\n`TData` = `InfiniteData`\\<`TQueryFnData`, `unknown`\\>\n\n### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n### TPageParam\n\n`TPageParam` = `unknown`\n\n## Parameters\n\n### options\n\n[`CreateInfiniteQueryOptions`](../type-aliases/CreateInfiniteQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\>\n\n## Returns\n\n[`CreateInfiniteQueryOptions`](../type-aliases/CreateInfiniteQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\\>\n"
  },
  {
    "path": "docs/framework/svelte/reference/functions/mutationOptions.md",
    "content": "---\nid: mutationOptions\ntitle: mutationOptions\n---\n\n# Function: mutationOptions()\n\n## Call Signature\n\n```ts\nfunction mutationOptions<TData, TError, TVariables, TOnMutateResult>(options): WithRequired<CreateMutationOptions<TData, TError, TVariables, TOnMutateResult>, 'mutationKey'>\n```\n\nDefined in: [packages/svelte-query/src/mutationOptions.ts](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/mutationOptions.ts)\n\n### Type Parameters\n\n#### TData\n\n`TData` = `unknown`\n\n#### TError\n\n`TError` = `Error`\n\n#### TVariables\n\n`TVariables` = `void`\n\n#### TOnMutateResult\n\n`TOnMutateResult` = `unknown`\n\n### Parameters\n\n#### options\n\n`WithRequired`\\<[`CreateMutationOptions`](../type-aliases/CreateMutationOptions.md)\\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\\>, `'mutationKey'`\\>\n\n### Returns\n\n`WithRequired`\\<[`CreateMutationOptions`](../type-aliases/CreateMutationOptions.md)\\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\\>, `'mutationKey'`\\>\n\n## Call Signature\n\n```ts\nfunction mutationOptions<TData, TError, TVariables, TOnMutateResult>(options): Omit<CreateMutationOptions<TData, TError, TVariables, TOnMutateResult>, 'mutationKey'>\n```\n\nDefined in: [packages/svelte-query/src/mutationOptions.ts](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/mutationOptions.ts)\n\n### Type Parameters\n\n#### TData\n\n`TData` = `unknown`\n\n#### TError\n\n`TError` = `Error`\n\n#### TVariables\n\n`TVariables` = `void`\n\n#### TOnMutateResult\n\n`TOnMutateResult` = `unknown`\n\n### Parameters\n\n#### options\n\n`Omit`\\<[`CreateMutationOptions`](../type-aliases/CreateMutationOptions.md)\\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\\>, `'mutationKey'`\\>\n\n### Returns\n\n`Omit`\\<[`CreateMutationOptions`](../type-aliases/CreateMutationOptions.md)\\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\\>, `'mutationKey'`\\>\n"
  },
  {
    "path": "docs/framework/svelte/reference/functions/queryOptions.md",
    "content": "---\nid: queryOptions\ntitle: queryOptions\n---\n\n# Function: queryOptions()\n\n## Call Signature\n\n```ts\nfunction queryOptions<TQueryFnData, TError, TData, TQueryKey>(options): CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey> & object & object;\n```\n\nDefined in: [packages/svelte-query/src/queryOptions.ts:30](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/queryOptions.ts#L30)\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `TQueryFnData`\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n### Parameters\n\n#### options\n\n[`DefinedInitialDataOptions`](../type-aliases/DefinedInitialDataOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>\n\n### Returns\n\n[`CreateQueryOptions`](../type-aliases/CreateQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\> & `object` & `object`\n\n## Call Signature\n\n```ts\nfunction queryOptions<TQueryFnData, TError, TData, TQueryKey>(options): CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey> & object & object;\n```\n\nDefined in: [packages/svelte-query/src/queryOptions.ts:41](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/queryOptions.ts#L41)\n\n### Type Parameters\n\n#### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n#### TError\n\n`TError` = `Error`\n\n#### TData\n\n`TData` = `TQueryFnData`\n\n#### TQueryKey\n\n`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]\n\n### Parameters\n\n#### options\n\n[`UndefinedInitialDataOptions`](../type-aliases/UndefinedInitialDataOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\>\n\n### Returns\n\n[`CreateQueryOptions`](../type-aliases/CreateQueryOptions.md)\\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\\> & `object` & `object`\n"
  },
  {
    "path": "docs/framework/svelte/reference/functions/setIsRestoringContext.md",
    "content": "---\nid: setIsRestoringContext\ntitle: setIsRestoringContext\n---\n\n# Function: setIsRestoringContext()\n\n```ts\nfunction setIsRestoringContext(isRestoring): void;\n```\n\nDefined in: [packages/svelte-query/src/context.ts:39](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/context.ts#L39)\n\nSets a `isRestoring` on Svelte's context\n\n## Parameters\n\n### isRestoring\n\n`Box`\\<`boolean`\\>\n\n## Returns\n\n`void`\n"
  },
  {
    "path": "docs/framework/svelte/reference/functions/setQueryClientContext.md",
    "content": "---\nid: setQueryClientContext\ntitle: setQueryClientContext\n---\n\n# Function: setQueryClientContext()\n\n```ts\nfunction setQueryClientContext(client): void;\n```\n\nDefined in: [packages/svelte-query/src/context.ts:20](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/context.ts#L20)\n\nSets a QueryClient on Svelte's context\n\n## Parameters\n\n### client\n\n`QueryClient`\n\n## Returns\n\n`void`\n"
  },
  {
    "path": "docs/framework/svelte/reference/functions/useHydrate.md",
    "content": "---\nid: useHydrate\ntitle: useHydrate\n---\n\n# Function: useHydrate()\n\n```ts\nfunction useHydrate(\n   state?, \n   options?, \n   queryClient?): void;\n```\n\nDefined in: [packages/svelte-query/src/useHydrate.ts:5](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/useHydrate.ts#L5)\n\n## Parameters\n\n### state?\n\n`unknown`\n\n### options?\n\n`HydrateOptions`\n\n### queryClient?\n\n`QueryClient`\n\n## Returns\n\n`void`\n"
  },
  {
    "path": "docs/framework/svelte/reference/functions/useIsFetching.md",
    "content": "---\nid: useIsFetching\ntitle: useIsFetching\n---\n\n# Function: useIsFetching()\n\n```ts\nfunction useIsFetching(filters?, queryClient?): ReactiveValue<number>;\n```\n\nDefined in: [packages/svelte-query/src/useIsFetching.svelte.ts:5](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/useIsFetching.svelte.ts#L5)\n\n## Parameters\n\n### filters?\n\n`QueryFilters`\\<readonly `unknown`[]\\>\n\n### queryClient?\n\n`QueryClient`\n\n## Returns\n\n`ReactiveValue`\\<`number`\\>\n"
  },
  {
    "path": "docs/framework/svelte/reference/functions/useIsMutating.md",
    "content": "---\nid: useIsMutating\ntitle: useIsMutating\n---\n\n# Function: useIsMutating()\n\n```ts\nfunction useIsMutating(filters?, queryClient?): ReactiveValue<number>;\n```\n\nDefined in: [packages/svelte-query/src/useIsMutating.svelte.ts:5](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/useIsMutating.svelte.ts#L5)\n\n## Parameters\n\n### filters?\n\n`MutationFilters`\\<`unknown`, `Error`, `unknown`, `unknown`\\>\n\n### queryClient?\n\n`QueryClient`\n\n## Returns\n\n`ReactiveValue`\\<`number`\\>\n"
  },
  {
    "path": "docs/framework/svelte/reference/functions/useIsRestoring.md",
    "content": "---\nid: useIsRestoring\ntitle: useIsRestoring\n---\n\n# Function: useIsRestoring()\n\n```ts\nfunction useIsRestoring(): Box<boolean>;\n```\n\nDefined in: [packages/svelte-query/src/useIsRestoring.ts:4](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/useIsRestoring.ts#L4)\n\n## Returns\n\n`Box`\\<`boolean`\\>\n"
  },
  {
    "path": "docs/framework/svelte/reference/functions/useMutationState.md",
    "content": "---\nid: useMutationState\ntitle: useMutationState\n---\n\n# Function: useMutationState()\n\n```ts\nfunction useMutationState<TResult>(options, queryClient?): TResult[];\n```\n\nDefined in: [packages/svelte-query/src/useMutationState.svelte.ts:22](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/useMutationState.svelte.ts#L22)\n\n## Type Parameters\n\n### TResult\n\n`TResult` = `MutationState`\\<`unknown`, `Error`, `unknown`, `unknown`\\>\n\n## Parameters\n\n### options\n\n[`MutationStateOptions`](../type-aliases/MutationStateOptions.md)\\<`TResult`\\> = `{}`\n\n### queryClient?\n\n`QueryClient`\n\n## Returns\n\n`TResult`[]\n"
  },
  {
    "path": "docs/framework/svelte/reference/functions/useQueryClient.md",
    "content": "---\nid: useQueryClient\ntitle: useQueryClient\n---\n\n# Function: useQueryClient()\n\n```ts\nfunction useQueryClient(queryClient?): QueryClient;\n```\n\nDefined in: [packages/svelte-query/src/useQueryClient.ts:4](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/useQueryClient.ts#L4)\n\n## Parameters\n\n### queryClient?\n\n`QueryClient`\n\n## Returns\n\n`QueryClient`\n"
  },
  {
    "path": "docs/framework/svelte/reference/index.md",
    "content": "---\nid: \"@tanstack/svelte-query\"\ntitle: \"@tanstack/svelte-query\"\n---\n\n# @tanstack/svelte-query\n\n## Type Aliases\n\n- [Accessor](type-aliases/Accessor.md)\n- [CreateBaseMutationResult](type-aliases/CreateBaseMutationResult.md)\n- [CreateBaseQueryOptions](type-aliases/CreateBaseQueryOptions.md)\n- [CreateBaseQueryResult](type-aliases/CreateBaseQueryResult.md)\n- [CreateInfiniteQueryOptions](type-aliases/CreateInfiniteQueryOptions.md)\n- [CreateInfiniteQueryResult](type-aliases/CreateInfiniteQueryResult.md)\n- [CreateMutateAsyncFunction](type-aliases/CreateMutateAsyncFunction.md)\n- [CreateMutateFunction](type-aliases/CreateMutateFunction.md)\n- [CreateMutationOptions](type-aliases/CreateMutationOptions.md)\n- [CreateMutationResult](type-aliases/CreateMutationResult.md)\n- [CreateQueryOptions](type-aliases/CreateQueryOptions.md)\n- [CreateQueryResult](type-aliases/CreateQueryResult.md)\n- [DefinedCreateBaseQueryResult](type-aliases/DefinedCreateBaseQueryResult.md)\n- [DefinedCreateQueryResult](type-aliases/DefinedCreateQueryResult.md)\n- [DefinedInitialDataOptions](type-aliases/DefinedInitialDataOptions.md)\n- [HydrationBoundary](type-aliases/HydrationBoundary.md)\n- [MutationStateOptions](type-aliases/MutationStateOptions.md)\n- [QueriesOptions](type-aliases/QueriesOptions.md)\n- [QueriesResults](type-aliases/QueriesResults.md)\n- [QueryClientProviderProps](type-aliases/QueryClientProviderProps.md)\n- [UndefinedInitialDataOptions](type-aliases/UndefinedInitialDataOptions.md)\n\n## Variables\n\n- [HydrationBoundary](variables/HydrationBoundary.md)\n\n## Functions\n\n- [createInfiniteQuery](functions/createInfiniteQuery.md)\n- [createMutation](functions/createMutation.md)\n- [createQueries](functions/createQueries.md)\n- [createQuery](functions/createQuery.md)\n- [getIsRestoringContext](functions/getIsRestoringContext.md)\n- [getQueryClientContext](functions/getQueryClientContext.md)\n- [infiniteQueryOptions](functions/infiniteQueryOptions.md)\n- [queryOptions](functions/queryOptions.md)\n- [setIsRestoringContext](functions/setIsRestoringContext.md)\n- [setQueryClientContext](functions/setQueryClientContext.md)\n- [useHydrate](functions/useHydrate.md)\n- [useIsFetching](functions/useIsFetching.md)\n- [useIsMutating](functions/useIsMutating.md)\n- [useIsRestoring](functions/useIsRestoring.md)\n- [useMutationState](functions/useMutationState.md)\n- [useQueryClient](functions/useQueryClient.md)\n\n## References\n\n### QueryClientProvider\n\nRenames and re-exports [HydrationBoundary](variables/HydrationBoundary.md)\n"
  },
  {
    "path": "docs/framework/svelte/reference/type-aliases/Accessor.md",
    "content": "---\nid: Accessor\ntitle: Accessor\n---\n\n# Type Alias: Accessor()\\<T\\>\n\n```ts\ntype Accessor<T> = () => T;\n```\n\nDefined in: [packages/svelte-query/src/types.ts:21](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/types.ts#L21)\n\n## Type Parameters\n\n### T\n\n`T`\n\n## Returns\n\n`T`\n"
  },
  {
    "path": "docs/framework/svelte/reference/type-aliases/CreateBaseMutationResult.md",
    "content": "---\nid: CreateBaseMutationResult\ntitle: CreateBaseMutationResult\n---\n\n# Type Alias: CreateBaseMutationResult\\<TData, TError, TVariables, TOnMutateResult\\>\n\n```ts\ntype CreateBaseMutationResult<TData, TError, TVariables, TOnMutateResult> = Override<MutationObserverResult<TData, TError, TVariables, TOnMutateResult>, {\n  mutate: CreateMutateFunction<TData, TError, TVariables, TOnMutateResult>;\n}> & object;\n```\n\nDefined in: [packages/svelte-query/src/types.ts:114](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/types.ts#L114)\n\n## Type Declaration\n\n### mutateAsync\n\n```ts\nmutateAsync: CreateMutateAsyncFunction<TData, TError, TVariables, TOnMutateResult>;\n```\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TVariables\n\n`TVariables` = `unknown`\n\n### TOnMutateResult\n\n`TOnMutateResult` = `unknown`\n"
  },
  {
    "path": "docs/framework/svelte/reference/type-aliases/CreateBaseQueryOptions.md",
    "content": "---\nid: CreateBaseQueryOptions\ntitle: CreateBaseQueryOptions\n---\n\n# Type Alias: CreateBaseQueryOptions\\<TQueryFnData, TError, TData, TQueryData, TQueryKey\\>\n\n```ts\ntype CreateBaseQueryOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey> = QueryObserverOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>;\n```\n\nDefined in: [packages/svelte-query/src/types.ts:24](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/types.ts#L24)\n\nOptions for createBaseQuery\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `TQueryFnData`\n\n### TQueryData\n\n`TQueryData` = `TQueryFnData`\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n"
  },
  {
    "path": "docs/framework/svelte/reference/type-aliases/CreateBaseQueryResult.md",
    "content": "---\nid: CreateBaseQueryResult\ntitle: CreateBaseQueryResult\n---\n\n# Type Alias: CreateBaseQueryResult\\<TData, TError\\>\n\n```ts\ntype CreateBaseQueryResult<TData, TError> = QueryObserverResult<TData, TError>;\n```\n\nDefined in: [packages/svelte-query/src/types.ts:33](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/types.ts#L33)\n\nResult from createBaseQuery\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n"
  },
  {
    "path": "docs/framework/svelte/reference/type-aliases/CreateInfiniteQueryOptions.md",
    "content": "---\nid: CreateInfiniteQueryOptions\ntitle: CreateInfiniteQueryOptions\n---\n\n# Type Alias: CreateInfiniteQueryOptions\\<TQueryFnData, TError, TData, TQueryKey, TPageParam\\>\n\n```ts\ntype CreateInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam> = InfiniteQueryObserverOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>;\n```\n\nDefined in: [packages/svelte-query/src/types.ts:53](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/types.ts#L53)\n\nOptions for createInfiniteQuery\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `TQueryFnData`\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n\n### TPageParam\n\n`TPageParam` = `unknown`\n"
  },
  {
    "path": "docs/framework/svelte/reference/type-aliases/CreateInfiniteQueryResult.md",
    "content": "---\nid: CreateInfiniteQueryResult\ntitle: CreateInfiniteQueryResult\n---\n\n# Type Alias: CreateInfiniteQueryResult\\<TData, TError\\>\n\n```ts\ntype CreateInfiniteQueryResult<TData, TError> = InfiniteQueryObserverResult<TData, TError>;\n```\n\nDefined in: [packages/svelte-query/src/types.ts:68](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/types.ts#L68)\n\nResult from createInfiniteQuery\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n"
  },
  {
    "path": "docs/framework/svelte/reference/type-aliases/CreateMutateAsyncFunction.md",
    "content": "---\nid: CreateMutateAsyncFunction\ntitle: CreateMutateAsyncFunction\n---\n\n# Type Alias: CreateMutateAsyncFunction\\<TData, TError, TVariables, TOnMutateResult\\>\n\n```ts\ntype CreateMutateAsyncFunction<TData, TError, TVariables, TOnMutateResult> = MutateFunction<TData, TError, TVariables, TOnMutateResult>;\n```\n\nDefined in: [packages/svelte-query/src/types.ts:107](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/types.ts#L107)\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TVariables\n\n`TVariables` = `void`\n\n### TOnMutateResult\n\n`TOnMutateResult` = `unknown`\n"
  },
  {
    "path": "docs/framework/svelte/reference/type-aliases/CreateMutateFunction.md",
    "content": "---\nid: CreateMutateFunction\ntitle: CreateMutateFunction\n---\n\n# Type Alias: CreateMutateFunction()\\<TData, TError, TVariables, TOnMutateResult\\>\n\n```ts\ntype CreateMutateFunction<TData, TError, TVariables, TOnMutateResult> = (...args) => void;\n```\n\nDefined in: [packages/svelte-query/src/types.ts:96](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/types.ts#L96)\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TVariables\n\n`TVariables` = `void`\n\n### TOnMutateResult\n\n`TOnMutateResult` = `unknown`\n\n## Parameters\n\n### args\n\n...`Parameters`\\<`MutateFunction`\\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\\>\\>\n\n## Returns\n\n`void`\n"
  },
  {
    "path": "docs/framework/svelte/reference/type-aliases/CreateMutationOptions.md",
    "content": "---\nid: CreateMutationOptions\ntitle: CreateMutationOptions\n---\n\n# Type Alias: CreateMutationOptions\\<TData, TError, TVariables, TOnMutateResult\\>\n\n```ts\ntype CreateMutationOptions<TData, TError, TVariables, TOnMutateResult> = OmitKeyof<MutationObserverOptions<TData, TError, TVariables, TOnMutateResult>, \"_defaulted\">;\n```\n\nDefined in: [packages/svelte-query/src/types.ts:86](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/types.ts#L86)\n\nOptions for createMutation\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TVariables\n\n`TVariables` = `void`\n\n### TOnMutateResult\n\n`TOnMutateResult` = `unknown`\n"
  },
  {
    "path": "docs/framework/svelte/reference/type-aliases/CreateMutationResult.md",
    "content": "---\nid: CreateMutationResult\ntitle: CreateMutationResult\n---\n\n# Type Alias: CreateMutationResult\\<TData, TError, TVariables, TOnMutateResult\\>\n\n```ts\ntype CreateMutationResult<TData, TError, TVariables, TOnMutateResult> = CreateBaseMutationResult<TData, TError, TVariables, TOnMutateResult>;\n```\n\nDefined in: [packages/svelte-query/src/types.ts:132](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/types.ts#L132)\n\nResult from createMutation\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TVariables\n\n`TVariables` = `unknown`\n\n### TOnMutateResult\n\n`TOnMutateResult` = `unknown`\n"
  },
  {
    "path": "docs/framework/svelte/reference/type-aliases/CreateQueryOptions.md",
    "content": "---\nid: CreateQueryOptions\ntitle: CreateQueryOptions\n---\n\n# Type Alias: CreateQueryOptions\\<TQueryFnData, TError, TData, TQueryKey\\>\n\n```ts\ntype CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey> = CreateBaseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>;\n```\n\nDefined in: [packages/svelte-query/src/types.ts:39](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/types.ts#L39)\n\nOptions for createQuery\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `TQueryFnData`\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n"
  },
  {
    "path": "docs/framework/svelte/reference/type-aliases/CreateQueryResult.md",
    "content": "---\nid: CreateQueryResult\ntitle: CreateQueryResult\n---\n\n# Type Alias: CreateQueryResult\\<TData, TError\\>\n\n```ts\ntype CreateQueryResult<TData, TError> = CreateBaseQueryResult<TData, TError>;\n```\n\nDefined in: [packages/svelte-query/src/types.ts:47](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/types.ts#L47)\n\nResult from createQuery\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n"
  },
  {
    "path": "docs/framework/svelte/reference/type-aliases/DefinedCreateBaseQueryResult.md",
    "content": "---\nid: DefinedCreateBaseQueryResult\ntitle: DefinedCreateBaseQueryResult\n---\n\n# Type Alias: DefinedCreateBaseQueryResult\\<TData, TError\\>\n\n```ts\ntype DefinedCreateBaseQueryResult<TData, TError> = DefinedQueryObserverResult<TData, TError>;\n```\n\nDefined in: [packages/svelte-query/src/types.ts:74](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/types.ts#L74)\n\nOptions for createBaseQuery with initialData\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n"
  },
  {
    "path": "docs/framework/svelte/reference/type-aliases/DefinedCreateQueryResult.md",
    "content": "---\nid: DefinedCreateQueryResult\ntitle: DefinedCreateQueryResult\n---\n\n# Type Alias: DefinedCreateQueryResult\\<TData, TError\\>\n\n```ts\ntype DefinedCreateQueryResult<TData, TError> = DefinedCreateBaseQueryResult<TData, TError>;\n```\n\nDefined in: [packages/svelte-query/src/types.ts:80](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/types.ts#L80)\n\nOptions for createQuery with initialData\n\n## Type Parameters\n\n### TData\n\n`TData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n"
  },
  {
    "path": "docs/framework/svelte/reference/type-aliases/DefinedInitialDataOptions.md",
    "content": "---\nid: DefinedInitialDataOptions\ntitle: DefinedInitialDataOptions\n---\n\n# Type Alias: DefinedInitialDataOptions\\<TQueryFnData, TError, TData, TQueryKey\\>\n\n```ts\ntype DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> = CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey> & object;\n```\n\nDefined in: [packages/svelte-query/src/queryOptions.ts:19](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/queryOptions.ts#L19)\n\n## Type Declaration\n\n### initialData\n\n```ts\ninitialData: \n  | NonUndefinedGuard<TQueryFnData>\n| () => NonUndefinedGuard<TQueryFnData>;\n```\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `TQueryFnData`\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n"
  },
  {
    "path": "docs/framework/svelte/reference/type-aliases/HydrationBoundary.md",
    "content": "---\nid: HydrationBoundary\ntitle: HydrationBoundary\n---\n\n# Type Alias: HydrationBoundary\n\n```ts\ntype HydrationBoundary = SvelteComponent;\n```\n\nDefined in: node\\_modules/.pnpm/svelte@5.39.3/node\\_modules/svelte/types/index.d.ts:3092\n"
  },
  {
    "path": "docs/framework/svelte/reference/type-aliases/MutationStateOptions.md",
    "content": "---\nid: MutationStateOptions\ntitle: MutationStateOptions\n---\n\n# Type Alias: MutationStateOptions\\<TResult\\>\n\n```ts\ntype MutationStateOptions<TResult> = object;\n```\n\nDefined in: [packages/svelte-query/src/types.ts:140](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/types.ts#L140)\n\nOptions for useMutationState\n\n## Type Parameters\n\n### TResult\n\n`TResult` = `MutationState`\n\n## Properties\n\n### filters?\n\n```ts\noptional filters: MutationFilters;\n```\n\nDefined in: [packages/svelte-query/src/types.ts:141](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/types.ts#L141)\n\n***\n\n### select()?\n\n```ts\noptional select: (mutation) => TResult;\n```\n\nDefined in: [packages/svelte-query/src/types.ts:142](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/types.ts#L142)\n\n#### Parameters\n\n##### mutation\n\n`Mutation`\\<`unknown`, `DefaultError`, `unknown`, `unknown`\\>\n\n#### Returns\n\n`TResult`\n"
  },
  {
    "path": "docs/framework/svelte/reference/type-aliases/QueriesOptions.md",
    "content": "---\nid: QueriesOptions\ntitle: QueriesOptions\n---\n\n# Type Alias: QueriesOptions\\<T, TResults, TDepth\\>\n\n```ts\ntype QueriesOptions<T, TResults, TDepth> = TDepth[\"length\"] extends MAXIMUM_DEPTH ? CreateQueryOptionsForCreateQueries[] : T extends [] ? [] : T extends [infer Head] ? [...TResults, GetCreateQueryOptionsForCreateQueries<Head>] : T extends [infer Head, ...(infer Tails)] ? QueriesOptions<[...Tails], [...TResults, GetCreateQueryOptionsForCreateQueries<Head>], [...TDepth, 1]> : ReadonlyArray<unknown> extends T ? T : T extends CreateQueryOptionsForCreateQueries<infer TQueryFnData, infer TError, infer TData, infer TQueryKey>[] ? CreateQueryOptionsForCreateQueries<TQueryFnData, TError, TData, TQueryKey>[] : CreateQueryOptionsForCreateQueries[];\n```\n\nDefined in: [packages/svelte-query/src/createQueries.svelte.ts:129](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/createQueries.svelte.ts#L129)\n\nQueriesOptions reducer recursively unwraps function arguments to infer/enforce type param\n\n## Type Parameters\n\n### T\n\n`T` *extends* `any`[]\n\n### TResults\n\n`TResults` *extends* `any`[] = \\[\\]\n\n### TDepth\n\n`TDepth` *extends* `ReadonlyArray`\\<`number`\\> = \\[\\]\n"
  },
  {
    "path": "docs/framework/svelte/reference/type-aliases/QueriesResults.md",
    "content": "---\nid: QueriesResults\ntitle: QueriesResults\n---\n\n# Type Alias: QueriesResults\\<T, TResults, TDepth\\>\n\n```ts\ntype QueriesResults<T, TResults, TDepth> = TDepth[\"length\"] extends MAXIMUM_DEPTH ? CreateQueryResult[] : T extends [] ? [] : T extends [infer Head] ? [...TResults, GetCreateQueryResult<Head>] : T extends [infer Head, ...(infer Tails)] ? QueriesResults<[...Tails], [...TResults, GetCreateQueryResult<Head>], [...TDepth, 1]> : { [K in keyof T]: GetCreateQueryResult<T[K]> };\n```\n\nDefined in: [packages/svelte-query/src/createQueries.svelte.ts:171](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/createQueries.svelte.ts#L171)\n\nQueriesResults reducer recursively maps type param to results\n\n## Type Parameters\n\n### T\n\n`T` *extends* `any`[]\n\n### TResults\n\n`TResults` *extends* `any`[] = \\[\\]\n\n### TDepth\n\n`TDepth` *extends* `ReadonlyArray`\\<`number`\\> = \\[\\]\n"
  },
  {
    "path": "docs/framework/svelte/reference/type-aliases/QueryClientProviderProps.md",
    "content": "---\nid: QueryClientProviderProps\ntitle: QueryClientProviderProps\n---\n\n# Type Alias: QueryClientProviderProps\n\n```ts\ntype QueryClientProviderProps = object;\n```\n\nDefined in: [packages/svelte-query/src/types.ts:147](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/types.ts#L147)\n\n## Properties\n\n### children\n\n```ts\nchildren: Snippet;\n```\n\nDefined in: [packages/svelte-query/src/types.ts:149](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/types.ts#L149)\n\n***\n\n### client\n\n```ts\nclient: QueryClient;\n```\n\nDefined in: [packages/svelte-query/src/types.ts:148](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/types.ts#L148)\n"
  },
  {
    "path": "docs/framework/svelte/reference/type-aliases/UndefinedInitialDataOptions.md",
    "content": "---\nid: UndefinedInitialDataOptions\ntitle: UndefinedInitialDataOptions\n---\n\n# Type Alias: UndefinedInitialDataOptions\\<TQueryFnData, TError, TData, TQueryKey\\>\n\n```ts\ntype UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> = CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey> & object;\n```\n\nDefined in: [packages/svelte-query/src/queryOptions.ts:10](https://github.com/TanStack/query/blob/main/packages/svelte-query/src/queryOptions.ts#L10)\n\n## Type Declaration\n\n### initialData?\n\n```ts\noptional initialData: InitialDataFunction<NonUndefinedGuard<TQueryFnData>>;\n```\n\n## Type Parameters\n\n### TQueryFnData\n\n`TQueryFnData` = `unknown`\n\n### TError\n\n`TError` = `DefaultError`\n\n### TData\n\n`TData` = `TQueryFnData`\n\n### TQueryKey\n\n`TQueryKey` *extends* `QueryKey` = `QueryKey`\n"
  },
  {
    "path": "docs/framework/svelte/reference/variables/HydrationBoundary.md",
    "content": "---\nid: HydrationBoundary\ntitle: HydrationBoundary\n---\n\n# Variable: HydrationBoundary\n\n```ts\nconst HydrationBoundary: LegacyComponentType;\n```\n\nDefined in: node\\_modules/.pnpm/svelte@5.39.3/node\\_modules/svelte/types/index.d.ts:3092\n"
  },
  {
    "path": "docs/framework/svelte/ssr.md",
    "content": "---\nid: overview\ntitle: SSR and SvelteKit\n---\n\n## Setup\n\nSvelteKit defaults to rendering routes with SSR. Because of this, you need to disable the query on the server. Otherwise, your query will continue executing on the server asynchronously, even after the HTML has been sent to the client.\n\nThe recommended way to achieve this is to use the `browser` module from SvelteKit in your `QueryClient` object. This will not disable `queryClient.prefetchQuery()`, which is used in one of the solutions below.\n\n**src/routes/+layout.svelte**\n\n```svelte\n<script lang=\"ts\">\n  import { browser } from '$app/environment'\n  import { QueryClient, QueryClientProvider } from '@tanstack/svelte-query'\n\n  const queryClient = new QueryClient({\n    defaultOptions: {\n      queries: {\n        enabled: browser,\n      },\n    },\n  })\n</script>\n\n<QueryClientProvider client={queryClient}>\n  <slot />\n</QueryClientProvider>\n```\n\n## Prefetching data\n\nSvelte Query supports two ways of prefetching data on the server and passing that to the client with SvelteKit.\n\nIf you wish to view the ideal SSR setup, please have a look at the [SSR example](./examples/ssr).\n\n### Using `initialData`\n\nTogether with SvelteKit's [`load`](https://kit.svelte.dev/docs/load), you can pass the data loaded server-side into `createQuery`'s' `initialData` option:\n\n**src/routes/+page.ts**\n\n```ts\nexport async function load() {\n  const posts = await getPosts()\n  return { posts }\n}\n```\n\n**src/routes/+page.svelte**\n\n```svelte\n<script>\n  import { createQuery } from '@tanstack/svelte-query'\n  import type { PageData } from './$types'\n\n  export let data: PageData\n\n  const query = createQuery(() => ({\n    queryKey: ['posts'],\n    queryFn: getPosts,\n    initialData: data.posts,\n  }))\n</script>\n```\n\nPros:\n\n- This setup is minimal and this can be a quick solution for some cases\n- Works with both `+page.ts`/`+layout.ts` and `+page.server.ts`/`+layout.server.ts` load functions\n\nCons:\n\n- If you are calling `createQuery` in a component deeper down in the tree you need to pass the `initialData` down to that point\n- If you are calling `createQuery` with the same query in multiple locations, you need to pass `initialData` to all of them\n- There is no way to know at what time the query was fetched on the server, so `dataUpdatedAt` and determining if the query needs refetching is based on when the page loaded instead\n\n### Using `prefetchQuery`\n\nSvelte Query supports prefetching queries on the server. Using this setup below, you can fetch data and pass it into QueryClientProvider before it is sent to the user's browser. Therefore, this data is already available in the cache, and no initial fetch occurs client-side.\n\n**src/routes/+layout.ts**\n\n```ts\nimport { browser } from '$app/environment'\nimport { QueryClient } from '@tanstack/svelte-query'\n\nexport async function load() {\n  const queryClient = new QueryClient({\n    defaultOptions: {\n      queries: {\n        enabled: browser,\n      },\n    },\n  })\n\n  return { queryClient }\n}\n```\n\n**src/routes/+layout.svelte**\n\n```svelte\n<script lang=\"ts\">\n  import { QueryClientProvider } from '@tanstack/svelte-query'\n  import type { LayoutData } from './$types'\n\n  export let data: LayoutData\n</script>\n\n<QueryClientProvider client={data.queryClient}>\n  <slot />\n</QueryClientProvider>\n```\n\n**src/routes/+page.ts**\n\n```ts\nexport async function load({ parent, fetch }) {\n  const { queryClient } = await parent()\n\n  // You need to use the SvelteKit fetch function here\n  await queryClient.prefetchQuery({\n    queryKey: ['posts'],\n    queryFn: async () => (await fetch('/api/posts')).json(),\n  })\n}\n```\n\n**src/routes/+page.svelte**\n\n```svelte\n<script lang=\"ts\">\n  import { createQuery } from '@tanstack/svelte-query'\n\n  // This data is cached by prefetchQuery in +page.ts so no fetch actually happens here\n  const query = createQuery(() => ({\n    queryKey: ['posts'],\n    queryFn: async () => (await fetch('/api/posts')).json(),\n  }))\n</script>\n```\n\nPros:\n\n- Server-loaded data can be accessed anywhere without prop-drilling\n- No initial fetch occurs client-side once the page is rendered, as the query cache retains all information about the query was made including `dataUpdatedAt`\n\nCons:\n\n- Requires more files for initial setup\n- Will not work with `+page.server.ts`/`+layout.server.ts` load functions (however, APIs which are used with TanStack Query need to be fully exposed to the browser anyway)\n"
  },
  {
    "path": "docs/framework/vue/devtools.md",
    "content": "---\nid: devtools\ntitle: Devtools\n---\n\nWave your hands in the air and shout hooray because Vue Query comes with dedicated devtools! 🥳\n\nWhen you begin your Vue Query journey, you'll want these devtools by your side. They help visualize all of the inner workings of Vue Query and will likely save you hours of debugging if you find yourself in a pinch!\n\n> For Chrome, Firefox, and Edge users: Third-party browser extensions are available for debugging TanStack Query directly in browser DevTools. These provide the same functionality as the framework-specific devtools packages:\n>\n> - <img alt=\"Chrome logo\" src=\"https://www.google.com/chrome/static/images/chrome-logo.svg\" width=\"16\" height=\"16\" class=\"inline mr-1 not-prose\" /> [Devtools for Chrome](https://chromewebstore.google.com/detail/tanstack-query-devtools/annajfchloimdhceglpgglpeepfghfai)\n> - <img alt=\"Firefox logo\" src=\"https://upload.wikimedia.org/wikipedia/commons/a/a0/Firefox_logo%2C_2019.svg\" width=\"16\" height=\"16\" class=\"inline mr-1 not-prose\" /> [Devtools for Firefox](https://addons.mozilla.org/en-US/firefox/addon/tanstack-query-devtools/)\n> - <img alt=\"Edge logo\" src=\"https://upload.wikimedia.org/wikipedia/commons/9/98/Microsoft_Edge_logo_%282019%29.svg\" width=\"16\" height=\"16\" class=\"inline mr-1 not-prose\" /> [Devtools for Edge](https://microsoftedge.microsoft.com/addons/detail/tanstack-query-devtools/edmdpkgkacmjopodhfolmphdenmddobj)\n\n## Component based Devtools (Vue 3)\n\nYou can directly integrate the devtools component into your page using a dedicated package.\nComponent-based devtools use a framework-agnostic implementation and are always up-to-date.\n\nThe devtools component is a separate package that you need to install:\n\n```bash\nnpm i @tanstack/vue-query-devtools\n```\n\nor\n\n```bash\npnpm add @tanstack/vue-query-devtools\n```\n\nor\n\n```bash\nyarn add @tanstack/vue-query-devtools\n```\n\nor\n\n```bash\nbun add @tanstack/vue-query-devtools\n```\n\nBy default, Vue Query Devtools are only included in bundles when `process.env.NODE_ENV === 'development'`, so you don't need to worry about excluding them during a production build.\n\n## Floating Mode\n\nDevtools will be mounted as a fixed, floating element in your app and provide a toggle in the corner of the screen to show and hide the devtools. This toggle state will be stored and remembered in localStorage across reloads.\n\nPlace the following code as high in your Vue app as you can. The closer it is to the root of the page, the better it will work!\n\n```vue\n<script setup>\nimport { VueQueryDevtools } from '@tanstack/vue-query-devtools'\n</script>\n\n<template>\n  <h1>The app!</h1>\n  <VueQueryDevtools />\n</template>\n```\n\n### Options\n\n- `initialIsOpen: boolean`\n  - Set this `true` if you want the dev tools to default to being open.\n- `buttonPosition?: \"top-left\" | \"top-right\" | \"bottom-left\" | \"bottom-right\"`\n  - Defaults to `bottom-right`.\n  - The position of the React Query logo to open and close the devtools panel.\n- `position?: \"top\" | \"bottom\" | \"left\" | \"right\"`\n  - Defaults to `bottom`.\n  - The position of the React Query devtools panel.\n- `client?: QueryClient`\n  - Use this to use a custom QueryClient. Otherwise, the one from the nearest context will be used.\n- `errorTypes?: { name: string; initializer: (query: Query) => TError}`\n  - Use this to predefine some errors that can be triggered on your queries. The initializer will be called (with the specific query) when that error is toggled on from the UI. It must return an Error.\n- `styleNonce?: string`\n  - 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.\n- `shadowDOMTarget?: ShadowRoot`\n  - Default behavior will apply the devtool's styles to the head tag within the DOM.\n  - Use this to pass a shadow DOM target to the devtools so that the styles will be applied within the shadow DOM instead of within the head tag in the light DOM.\n\n## Embedded Mode\n\nEmbedded mode will show the development tools as a fixed element in your application, so you can use our panel in your own development tools.\n\nPlace the following code as high in your React app as you can. The closer it is to the root of the page, the better it will work!\n\n```vue\n<script setup>\nimport { VueQueryDevtoolsPanel } from '@tanstack/vue-query-devtools'\nconst isDevtoolsOpen = ref(false)\nfunction toggleDevtools() {\n  isDevtoolsOpen.value = !isDevtoolsOpen.value\n}\n</script>\n\n<template>\n  <h1>The app!</h1>\n  <button @click=\"toggleDevtools\">Open Devtools</button>\n  <VueQueryDevtoolsPanel v-if=\"isDevtoolsOpen\" :onClose=\"toggleDevtools\" />\n</template>\n```\n\n### Options\n\n- `style?: React.CSSProperties`\n  - Custom styles for the devtools panel\n  - Default: `{ height: '500px' }`\n  - Example: `{ height: '100%' }`\n  - Example: `{ height: '100%', width: '100%' }`\n- `onClose?: () => unknown`\n  - Callback function that is called when the devtools panel is closed\n- `client?: QueryClient`,\n  - Use this to use a custom QueryClient. Otherwise, the one from the nearest context will be used.\n- `errorTypes?: { name: string; initializer: (query: Query) => TError}[]`\n  - Use this to predefine some errors that can be triggered on your queries. Initializer will be called (with the specific query) when that error is toggled on from the UI. It must return an Error.\n- `styleNonce?: string`\n  - 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.\n- `shadowDOMTarget?: ShadowRoot`\n  - Default behavior will apply the devtool's styles to the head tag within the DOM.\n  - Use this to pass a shadow DOM target to the devtools so that the styles will be applied within the shadow DOM instead of within the head tag in the light DOM.\n\n## Traditional Devtools\n\nVue Query will seamlessly integrate with the [Official Vue devtools](https://github.com/vuejs/devtools-next), adding custom inspector and timeline events.\nDevtool code will be treeshaken from production bundles by default.\n\nTo make it work, you only need to enable it in the plugin options:\n\n```ts\napp.use(VueQueryPlugin, {\n  enableDevtoolsV6Plugin: true,\n})\n```\n\nBoth v6 and v7 versions of devtools are supported.\n"
  },
  {
    "path": "docs/framework/vue/graphql.md",
    "content": "---\nid: graphql\ntitle: GraphQL\nref: docs/framework/react/graphql.md\nreplace: { 'React': 'Vue', 'react-query': 'vue-query' }\n---\n\n[//]: # 'Codegen'\n[//]: # 'Codegen'\n"
  },
  {
    "path": "docs/framework/vue/guides/background-fetching-indicators.md",
    "content": "---\nid: background-fetching-indicators\ntitle: Background Fetching Indicators\nref: docs/framework/react/guides/background-fetching-indicators.md\n---\n\n[//]: # 'Example'\n\n```vue\n<script setup>\nimport { useQuery } from '@tanstack/vue-query'\n\nconst { isPending, isFetching, isError, data, error } = useQuery({\n  queryKey: ['todos'],\n  queryFn: getTodos,\n})\n</script>\n\n<template>\n  <div v-if=\"isFetching\">Refreshing...</div>\n  <span v-if=\"isPending\">Loading...</span>\n  <span v-else-if=\"isError\">Error: {{ error.message }}</span>\n  <!-- We can assume by this point that `isSuccess === true` -->\n  <ul v-else-if=\"data\">\n    <li v-for=\"todo in data\" :key=\"todo.id\">{{ todo.title }}</li>\n  </ul>\n</template>\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```vue\n<script setup>\nimport { useIsFetching } from '@tanstack/vue-query'\n\nconst isFetching = useIsFetching()\n</script>\n\n<template>\n  <div v-if=\"isFetching\">Queries are fetching in the background...</div>\n</template>\n```\n\n[//]: # 'Example2'\n"
  },
  {
    "path": "docs/framework/vue/guides/caching.md",
    "content": "---\nid: caching\ntitle: Caching Examples\nref: docs/framework/react/guides/caching.md\n---\n"
  },
  {
    "path": "docs/framework/vue/guides/custom-client.md",
    "content": "---\nid: custom-client\ntitle: Custom Client\n---\n\n### Custom client\n\nVue Query allows providing custom `QueryClient` for Vue context.\n\nIt might be handy when you need to create `QueryClient` beforehand to integrate it with other libraries that do not have access to the Vue context.\n\nFor this reason, `VueQueryPlugin` accepts either `QueryClientConfig` or `QueryClient` as a plugin options.\n\nIf You provide `QueryClientConfig`, `QueryClient` instance will be created internally and provided to Vue context.\n\n```tsx\nconst vueQueryPluginOptions: VueQueryPluginOptions = {\n  queryClientConfig: {\n    defaultOptions: { queries: { staleTime: 3600 } },\n  },\n}\napp.use(VueQueryPlugin, vueQueryPluginOptions)\n```\n\n```tsx\nconst myClient = new QueryClient(queryClientConfig)\nconst vueQueryPluginOptions: VueQueryPluginOptions = {\n  queryClient: myClient,\n}\napp.use(VueQueryPlugin, vueQueryPluginOptions)\n```\n\n### Custom context key\n\nYou can also customize the key under which `QueryClient` will be accessible in Vue context. This can be useful is you want to avoid name clashing between multiple apps on the same page with Vue2.\n\nIt works both with default, and custom `QueryClient`\n\n```tsx\nconst vueQueryPluginOptions: VueQueryPluginOptions = {\n  queryClientKey: 'Foo',\n}\napp.use(VueQueryPlugin, vueQueryPluginOptions)\n```\n\n```tsx\nconst myClient = new QueryClient(queryClientConfig)\nconst vueQueryPluginOptions: VueQueryPluginOptions = {\n  queryClient: myClient,\n  queryClientKey: 'Foo',\n}\napp.use(VueQueryPlugin, vueQueryPluginOptions)\n```\n\nTo use the custom client key, You have to provide it as a query options\n\n```js\nuseQuery({\n  queryKey: ['query1'],\n  queryFn: fetcher,\n  queryClientKey: 'foo',\n})\n```\n\nInternally custom key will be combined with default query key as a suffix. But user do not have to worry about it.\n\n```tsx\nconst vueQueryPluginOptions: VueQueryPluginOptions = {\n  queryClientKey: 'Foo',\n}\napp.use(VueQueryPlugin, vueQueryPluginOptions) // -> VUE_QUERY_CLIENT:Foo\n```\n"
  },
  {
    "path": "docs/framework/vue/guides/default-query-function.md",
    "content": "---\nid: default-query-function\ntitle: Default Query Function\nref: docs/framework/react/guides/default-query-function.md\n---\n\n[//]: # 'Example'\n\n```tsx\n// Define a default query function that will receive the query key\nconst defaultQueryFn = async ({ queryKey }) => {\n  const { data } = await axios.get(\n    `https://jsonplaceholder.typicode.com${queryKey[0]}`,\n  )\n  return data\n}\n\n// provide the default query function to your app with defaultOptions\nconst vueQueryPluginOptions: VueQueryPluginOptions = {\n  queryClientConfig: {\n    defaultOptions: { queries: { queryFn: defaultQueryFn } },\n  },\n}\napp.use(VueQueryPlugin, vueQueryPluginOptions)\n\n// All you have to do now is pass a key!\nconst { status, data, error, isFetching } = useQuery({\n  queryKey: [`/posts/${postId}`],\n})\n```\n\n[//]: # 'Example'\n"
  },
  {
    "path": "docs/framework/vue/guides/dependent-queries.md",
    "content": "---\nid: dependent-queries\ntitle: Dependent Queries\nref: docs/framework/react/guides/dependent-queries.md\n---\n\n[//]: # 'Example'\n\n```js\n// Get the user\nconst { data: user } = useQuery({\n  queryKey: ['user', email],\n  queryFn: () => getUserByEmail(email.value),\n})\n\nconst userId = computed(() => user.value?.id)\nconst enabled = computed(() => !!user.value?.id)\n\n// Then get the user's projects\nconst { isIdle, data: projects } = useQuery({\n  queryKey: ['projects', userId],\n  queryFn: () => getProjectsByUser(userId.value),\n  enabled, // The query will not execute until `enabled == true`\n})\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```tsx\n// Get the users ids\nconst { data: userIds } = useQuery({\n  queryKey: ['users'],\n  queryFn: getUsersData,\n  select: (users) => users.map((user) => user.id),\n})\n\nconst queries = computed(() => {\n  return userIds.value.length\n    ? userIds.value.map((id) => {\n        return {\n          queryKey: ['messages', id],\n          queryFn: () => getMessagesByUsers(id),\n        }\n      })\n    : []\n})\n\n// Then get the users messages\nconst usersMessages = useQueries({\n  queries, // if userIds.value is undefined or has no items, an empty array will be returned\n})\n```\n\n[//]: # 'Example2'\n"
  },
  {
    "path": "docs/framework/vue/guides/disabling-queries.md",
    "content": "---\nid: disabling-queries\ntitle: Disabling/Pausing Queries\nref: docs/framework/react/guides/disabling-queries.md\n---\n\n[//]: # 'Example'\n\n```vue\n<script setup>\nimport { useQuery } from '@tanstack/vue-query'\n\nconst { isLoading, isError, data, error, refetch, isFetching } = useQuery({\n  queryKey: ['todos'],\n  queryFn: fetchTodoList,\n  enabled: false,\n})\n</script>\n\n<template>\n  <button @click=\"refetch()\">Fetch Todos</button>\n  <span v-if=\"isLoading\">Loading...</span>\n  <span v-else-if=\"isError\">Error: {{ error?.message }}</span>\n  <div v-else-if=\"data\">\n    <span v-if=\"isFetching\">Fetching...</span>\n    <ul>\n      <li v-for=\"todo in data\" :key=\"todo.id\">{{ todo.title }}</li>\n    </ul>\n  </div>\n  <span v-else>Not ready...</span>\n</template>\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```vue\n<script setup>\nimport { useQuery } from '@tanstack/vue-query'\n\nconst filter = ref('')\nconst isEnabled = computed(() => !!filter.value)\nconst { data } = useQuery({\n  queryKey: ['todos', filter],\n  queryFn: () => fetchTodos(filter),\n  // ⬇️ disabled as long as the filter is empty\n  enabled: isEnabled,\n})\n</script>\n\n<template>\n  <span v-if=\"data\">Filter was set and data is here!</span>\n</template>\n```\n\n[//]: # 'Example2'\n[//]: # 'Example3'\n\n```vue\n<script setup>\nimport { useQuery, skipToken } from '@tanstack/vue-query'\n\nconst filter = ref('')\nconst queryFn = computed(() =>\n  !!filter.value ? () => fetchTodos(filter) : skipToken,\n)\nconst { data } = useQuery({\n  queryKey: ['todos', filter],\n  // ⬇️ disabled as long as the filter is undefined or empty\n  queryFn: queryFn,\n})\n</script>\n\n<template>\n  <span v-if=\"data\">Filter was set and data is here!</span>\n</template>\n```\n\n[//]: # 'Example3'\n"
  },
  {
    "path": "docs/framework/vue/guides/does-this-replace-client-state.md",
    "content": "---\nid: does-this-replace-client-state\ntitle: Does Vue Query replace Vuex, Pinia or other global state managers?\nref: docs/framework/react/guides/does-this-replace-client-state.md\nreplace: { 'Redux, MobX': 'Vuex, Pinia' }\n---\n"
  },
  {
    "path": "docs/framework/vue/guides/filters.md",
    "content": "---\nid: filters\ntitle: Filters\nref: docs/framework/react/guides/filters.md\n---\n"
  },
  {
    "path": "docs/framework/vue/guides/important-defaults.md",
    "content": "---\nid: important-defaults\ntitle: Important Defaults\nref: docs/framework/react/guides/important-defaults.md\n---\n\n[//]: # 'Materials'\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/vue/guides/infinite-queries.md",
    "content": "---\nid: infinite-queries\ntitle: Infinite Queries\nref: docs/framework/react/guides/infinite-queries.md\n---\n\n[//]: # 'Example'\n\n```vue\n<script setup>\nimport { useInfiniteQuery } from '@tanstack/vue-query'\n\nconst fetchProjects = async ({ pageParam }) => {\n  const res = await fetch('/api/projects?cursor=' + pageParam)\n  return res.json()\n}\n\nconst {\n  data,\n  error,\n  fetchNextPage,\n  hasNextPage,\n  isFetching,\n  isFetchingNextPage,\n  isPending,\n  isError,\n} = useInfiniteQuery({\n  queryKey: ['projects'],\n  queryFn: fetchProjects,\n  initialPageParam: 0,\n  getNextPageParam: (lastPage, pages) => lastPage.nextCursor,\n})\n</script>\n\n<template>\n  <span v-if=\"isPending\">Loading...</span>\n  <span v-else-if=\"isError\">Error: {{ error.message }}</span>\n  <div v-else-if=\"data\">\n    <span v-if=\"isFetching && !isFetchingNextPage\">Fetching...</span>\n    <ul v-for=\"(group, index) in data.pages\" :key=\"index\">\n      <li v-for=\"project in group.projects\" :key=\"project.id\">\n        {{ project.name }}\n      </li>\n    </ul>\n    <button\n      @click=\"() => fetchNextPage()\"\n      :disabled=\"!hasNextPage || isFetchingNextPage\"\n    >\n      <span v-if=\"isFetchingNextPage\">Loading more...</span>\n      <span v-else-if=\"hasNextPage\">Load More</span>\n      <span v-else>Nothing more to load</span>\n    </button>\n  </div>\n</template>\n```\n\n[//]: # 'Example'\n"
  },
  {
    "path": "docs/framework/vue/guides/initial-query-data.md",
    "content": "---\nid: initial-query-data\ntitle: Initial Query Data\nref: docs/framework/react/guides/initial-query-data.md\n---\n\n[//]: # 'Materials'\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/vue/guides/invalidations-from-mutations.md",
    "content": "---\nid: invalidations-from-mutations\ntitle: Invalidations from Mutations\nref: docs/framework/react/guides/invalidations-from-mutations.md\n---\n\n[//]: # 'Example2'\n\n```tsx\nimport { useMutation, useQueryClient } from '@tanstack/vue-query'\n\nconst queryClient = useQueryClient()\n\n// When this mutation succeeds, invalidate any queries with the `todos` or `reminders` query key\nconst mutation = useMutation({\n  mutationFn: addTodo,\n  onSuccess: () => {\n    queryClient.invalidateQueries({ queryKey: ['todos'] })\n    queryClient.invalidateQueries({ queryKey: ['reminders'] })\n  },\n})\n```\n\n[//]: # 'Example2'\n"
  },
  {
    "path": "docs/framework/vue/guides/migrating-to-v5.md",
    "content": "---\nid: migrating-to-tanstack-query-5\ntitle: Migrating to TanStack Query v5\nref: docs/framework/react/guides/migrating-to-v5.md\n---\n\n[//]: # 'FrameworkSpecificBreakingChanges'\n\n## Vue Query Breaking Changes\n\n### `useQueries` composable returns `ref` instead of `reactive`\n\nTo fix compatibility with Vue 2, `useQueries` composable now returns `queries` array wrapped in `ref`.\nPreviously `reactive` was returned which led to multiple problems:\n\n- User could spread return value loosing reactivity.\n- `readonly` wrapper used for return value was breaking Vue 2 reactivity detection mechanism. This was a silent issue in Vue 2.6, but appeared as error in Vue 2.7.\n- Vue 2 does not support arrays as a root value of `reactive`.\n\nWith this change all of those issues are fixed.\n\nAlso this aligns `useQueries` with other composables which return all of the values as `refs`.\n\n### Vue v3.3 is now required\n\nTo be able to provide new features following Vue releases, we now require Vue 3 to be at least in v3.3 version.\nRequirements for Vue 2.x remain unchanged.\n\n[//]: # 'FrameworkSpecificBreakingChanges'\n[//]: # 'FrameworkSpecificNewFeatures'\n\n### Ability to run `vue-query` composables in `injectionContext`\n\nPreviously `vue-query` composables could be run only within `setup` function of the component.  \nWe had an escape hatch in place to allow those hooks to be run anywhere if user would provide `queryClient` as a composable option.\n\nNow you can use `vue-query` composables in any function that supports `injectionContext`. Ex. router navigation guards.\nWhen using this new feature, make sure that `vue-query` composable is running within `effectScope`. Otherwise it might lead to memory leaks.\nWe have added `dev-only` warnings to inform users about potential misusage.\n\n[//]: # 'FrameworkSpecificNewFeatures'\n"
  },
  {
    "path": "docs/framework/vue/guides/mutations.md",
    "content": "---\nid: mutations\ntitle: Mutations\nref: docs/framework/react/guides/mutations.md\n---\n\n[//]: # 'Example'\n\n```vue\n<script setup>\nimport { useMutation } from '@tanstack/vue-query'\n\nconst { isPending, isError, error, isSuccess, mutate } = useMutation({\n  mutationFn: (newTodo) => axios.post('/todos', newTodo),\n})\n\nfunction addTodo() {\n  mutate({ id: new Date(), title: 'Do Laundry' })\n}\n</script>\n\n<template>\n  <span v-if=\"isPending\">Adding todo...</span>\n  <span v-else-if=\"isError\">An error occurred: {{ error.message }}</span>\n  <span v-else-if=\"isSuccess\">Todo added!</span>\n  <button @click=\"addTodo\">Create Todo</button>\n</template>\n```\n\n[//]: # 'Example'\n[//]: # 'Info1'\n[//]: # 'Info1'\n[//]: # 'Example2'\n[//]: # 'Example2'\n[//]: # 'Example3'\n\n```vue\n<script>\nimport { useMutation } from '@tanstack/vue-query'\n\nconst { error, mutate, reset } = useMutation({\n  mutationFn: (newTodo) => axios.post('/todos', newTodo),\n})\n\nfunction addTodo() {\n  mutate({ id: new Date(), title: 'Do Laundry' })\n}\n</script>\n\n<template>\n  <span v-else-if=\"error\">\n    <span>An error occurred: {{ error.message }}</span>\n    <button @click=\"reset\">Reset error</button>\n  </span>\n  <button @click=\"addTodo\">Create Todo</button>\n</template>\n```\n\n[//]: # 'Example3'\n[//]: # 'Example11'\n\n```js\nconst client = new QueryClient({\n  defaultOptions: {\n    queries: {\n      gcTime: 1000 * 60 * 60 * 24, // 24 hours\n    },\n  },\n})\n\n// we need a default mutation function so that paused mutations can resume after a page reload\nqueryClient.setMutationDefaults({\n  mutationKey: ['todos'],\n  mutationFn: ({ id, data }) => {\n    return api.updateTodo(id, data)\n  },\n})\n\nconst vueQueryOptions: VueQueryPluginOptions = {\n  queryClient: client,\n  clientPersister: (queryClient) => {\n    return persistQueryClient({\n      queryClient,\n      persister: createAsyncStoragePersister({ storage: localStorage }),\n    })\n  },\n  clientPersisterOnSuccess: (queryClient) => {\n    queryClient.resumePausedMutations()\n  },\n}\n\ncreateApp(App).use(VueQueryPlugin, vueQueryOptions).mount('#app')\n```\n\n[//]: # 'Example11'\n[//]: # 'Materials'\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/vue/guides/network-mode.md",
    "content": "---\nid: network-mode\ntitle: Network Mode\nref: docs/framework/react/guides/network-mode.md\n---\n"
  },
  {
    "path": "docs/framework/vue/guides/optimistic-updates.md",
    "content": "---\nid: optimistic-updates\ntitle: Optimistic Updates\nref: docs/framework/react/guides/optimistic-updates.md\nreplace: { 'React': 'Vue' }\n---\n"
  },
  {
    "path": "docs/framework/vue/guides/paginated-queries.md",
    "content": "---\nid: paginated-queries\ntitle: Paginated / Lagged Queries\nref: docs/framework/react/guides/paginated-queries.md\n---\n\n[//]: # 'Example2'\n\n```vue\n<script setup lang=\"ts\">\nimport { ref, Ref } from 'vue'\nimport { useQuery, keepPreviousData } from '@tanstack/vue-query'\n\nconst fetcher = (page: Ref<number>) =>\n  fetch(\n    `https://jsonplaceholder.typicode.com/posts?_page=${page.value}&_limit=10`,\n  ).then((response) => response.json())\n\nconst page = ref(1)\nconst { isPending, isError, data, error, isFetching, isPlaceholderData } =\n  useQuery({\n    queryKey: ['projects', page],\n    queryFn: () => fetcher(page),\n    placeholderData: keepPreviousData,\n  })\nconst prevPage = () => {\n  page.value = Math.max(page.value - 1, 1)\n}\nconst nextPage = () => {\n  if (!isPlaceholderData.value) {\n    page.value = page.value + 1\n  }\n}\n</script>\n\n<template>\n  <h1>Posts</h1>\n  <p>Current Page: {{ page }} | Previous data: {{ isPlaceholderData }}</p>\n  <button @click=\"prevPage\">Prev Page</button>\n  <button @click=\"nextPage\">Next Page</button>\n  <div v-if=\"isPending\">Loading...</div>\n  <div v-else-if=\"isError\">An error has occurred: {{ error }}</div>\n  <div v-else-if=\"data\">\n    <ul>\n      <li v-for=\"item in data\" :key=\"item.id\">\n        {{ item.title }}\n      </li>\n    </ul>\n  </div>\n</template>\n```\n\n[//]: # 'Example2'\n"
  },
  {
    "path": "docs/framework/vue/guides/parallel-queries.md",
    "content": "---\nid: parallel-queries\ntitle: Parallel Queries\nref: docs/framework/react/guides/parallel-queries.md\n---\n\n[//]: # 'Example'\n\n```vue\n<script setup lang=\"ts\">\n// The following queries will execute in parallel\nconst usersQuery = useQuery({ queryKey: ['users'], queryFn: fetchUsers })\nconst teamsQuery = useQuery({ queryKey: ['teams'], queryFn: fetchTeams })\nconst projectsQuery = useQuery({\n  queryKey: ['projects'],\n  queryFn: fetchProjects,\n})\n</script>\n```\n\n[//]: # 'Example'\n[//]: # 'Info'\n[//]: # 'Info'\n[//]: # 'Example2'\n\n```js\nconst users = computed(...)\nconst queries = computed(() => users.value.map(user => {\n    return {\n      queryKey: ['user', user.id],\n      queryFn: () => fetchUserById(user.id),\n    }\n  })\n);\nconst userQueries = useQueries({queries: queries})\n```\n\n[//]: # 'Example2'\n"
  },
  {
    "path": "docs/framework/vue/guides/placeholder-query-data.md",
    "content": "---\nid: placeholder-query-data\ntitle: Placeholder Query Data\nref: docs/framework/react/guides/placeholder-query-data.md\n---\n\n[//]: # 'ExampleValue'\n\n```tsx\nconst result = useQuery({\n  queryKey: ['todos'],\n  queryFn: () => fetch('/todos'),\n  placeholderData: placeholderTodos,\n})\n```\n\n[//]: # 'ExampleValue'\n[//]: # 'Memoization'\n[//]: # 'Memoization'\n[//]: # 'ExampleCache'\n\n```tsx\nconst result = useQuery({\n  queryKey: ['blogPost', blogPostId],\n  queryFn: () => fetch(`/blogPosts/${blogPostId}`),\n  placeholderData: () => {\n    // Use the smaller/preview version of the blogPost from the 'blogPosts'\n    // query as the placeholder data for this blogPost query\n    return queryClient\n      .getQueryData(['blogPosts'])\n      ?.find((d) => d.id === blogPostId)\n  },\n})\n```\n\n[//]: # 'ExampleCache'\n[//]: # 'Materials'\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/vue/guides/prefetching.md",
    "content": "---\nid: prefetching\ntitle: Prefetching\n---\n\nIf you're lucky enough, you may know enough about what your users will do to be able to prefetch the data they need before it's needed! If this is the case, you can use the `prefetchQuery` method to prefetch the results of a query to be placed into the cache:\n\n[//]: # 'ExamplePrefetching'\n\n```tsx\nconst prefetchTodos = async () => {\n  // The results of this query will be cached like a normal query\n  await queryClient.prefetchQuery({\n    queryKey: ['todos'],\n    queryFn: fetchTodos,\n  })\n}\n```\n\n[//]: # 'ExamplePrefetching'\n\n- If **fresh** data for this query is already in the cache, the data will not be fetched\n- If a `staleTime` is passed eg. `prefetchQuery({ queryKey: ['todos'], queryFn: fn, staleTime: 5000 })` and the data is older than the specified `staleTime`, the query will be fetched\n- If no instances of `useQuery` appear for a prefetched query, it will be deleted and garbage collected after the time specified in `gcTime`.\n\n## Prefetching Infinite Queries\n\nInfinite Queries can be prefetched like regular Queries. Per default, only the first page of the Query will be prefetched and will be stored under the given QueryKey. If you want to prefetch more than one page, you can use the `pages` option, in which case you also have to provide a `getNextPageParam` function:\n\n[//]: # 'ExampleInfiniteQuery'\n\n```tsx\nconst prefetchProjects = async () => {\n  // The results of this query will be cached like a normal query\n  await queryClient.prefetchInfiniteQuery({\n    queryKey: ['projects'],\n    queryFn: fetchProjects,\n    initialPageParam: 0,\n    getNextPageParam: (lastPage, pages) => lastPage.nextCursor,\n    pages: 3, // prefetch the first 3 pages\n  })\n}\n```\n\n[//]: # 'ExampleInfiniteQuery'\n\nThe above code will try to prefetch 3 pages in order, and `getNextPageParam` will be executed for each page to determine the next page to prefetch. If `getNextPageParam` returns `undefined`, the prefetching will stop.\n"
  },
  {
    "path": "docs/framework/vue/guides/queries.md",
    "content": "---\nid: queries\ntitle: Queries\nref: docs/framework/react/guides/queries.md\n---\n\n[//]: # 'Example'\n\n```ts\nimport { useQuery } from '@tanstack/vue-query'\n\nconst result = useQuery({ queryKey: ['todos'], queryFn: fetchTodoList })\n```\n\n[//]: # 'Example'\n[//]: # 'Example3'\n\n```vue\n<script setup>\nimport { useQuery } from '@tanstack/vue-query'\n\nconst { isPending, isError, data, error } = useQuery({\n  queryKey: ['todos'],\n  queryFn: fetchTodoList,\n})\n</script>\n\n<template>\n  <span v-if=\"isPending\">Loading...</span>\n  <span v-else-if=\"isError\">Error: {{ error.message }}</span>\n  <!-- We can assume by this point that `isSuccess === true` -->\n  <ul v-else-if=\"data\">\n    <li v-for=\"todo in data\" :key=\"todo.id\">{{ todo.title }}</li>\n  </ul>\n</template>\n```\n\n[//]: # 'Example3'\n[//]: # 'Example4'\n\n```vue\n<script setup>\nimport { useQuery } from '@tanstack/vue-query'\n\nconst { status, data, error } = useQuery({\n  queryKey: ['todos'],\n  queryFn: fetchTodoList,\n})\n</script>\n\n<template>\n  <span v-if=\"status === 'pending'\">Loading...</span>\n  <span v-else-if=\"status === 'error'\">Error: {{ error.message }}</span>\n  <!-- also status === 'success', but \"else\" logic works, too -->\n  <ul v-else-if=\"data\">\n    <li v-for=\"todo in data\" :key=\"todo.id\">{{ todo.title }}</li>\n  </ul>\n</template>\n```\n\n[//]: # 'Example4'\n[//]: # 'Materials'\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/vue/guides/query-cancellation.md",
    "content": "---\nid: query-cancellation\ntitle: Query Cancellation\nref: docs/framework/react/guides/query-cancellation.md\n---\n\n[//]: # 'Example7'\n\n```ts\nconst query = useQuery({\n  queryKey: ['todos'],\n  queryFn: async ({ signal }) => {\n    const resp = await fetch('/todos', { signal })\n    return resp.json()\n  },\n})\n\nconst queryClient = useQueryClient()\n\nfunction onButtonClick() {\n  queryClient.cancelQueries({ queryKey: ['todos'] })\n}\n```\n\n[//]: # 'Example7'\n"
  },
  {
    "path": "docs/framework/vue/guides/query-functions.md",
    "content": "---\nid: query-functions\ntitle: Query Functions\nref: docs/framework/react/guides/query-functions.md\n---\n\n[//]: # 'Example4'\n\n```js\nconst result = useQuery({\n  queryKey: ['todos', { status, page }],\n  queryFn: fetchTodoList,\n})\n\n// Access the key, status and page variables in your query function!\nfunction fetchTodoList({ queryKey }) {\n  const [_key, { status, page }] = queryKey\n  return new Promise()\n}\n```\n\n[//]: # 'Example4'\n"
  },
  {
    "path": "docs/framework/vue/guides/query-invalidation.md",
    "content": "---\nid: query-invalidation\ntitle: Query Invalidation\nref: docs/framework/react/guides/query-invalidation.md\nreplace: { 'react-query': 'vue-query' }\n---\n"
  },
  {
    "path": "docs/framework/vue/guides/query-keys.md",
    "content": "---\nid: query-keys\ntitle: Query Keys\nref: docs/framework/react/guides/query-keys.md\n---\n\n[//]: # 'Example5'\n\n```ts\nimport type { Ref } from 'vue'\n\nfunction useTodos(todoId: Ref<string>) {\n  const queryKey = ['todos', todoId]\n  return useQuery({\n    queryKey,\n    queryFn: () => fetchTodoById(todoId.value),\n  })\n}\n```\n\n[//]: # 'Example5'\n"
  },
  {
    "path": "docs/framework/vue/guides/query-options.md",
    "content": "---\nid: query-options\ntitle: Query Options\nref: docs/framework/react/guides/query-options.md\nreplace: { '@tanstack/react-query': '@tanstack/vue-query' }\n---\n"
  },
  {
    "path": "docs/framework/vue/guides/query-retries.md",
    "content": "---\nid: query-retries\ntitle: Query Retries\nref: docs/framework/react/guides/query-retries.md\nreplace: { 'Provider': 'Plugin' }\n---\n\n[//]: # 'Example'\n\n```tsx\nimport { useQuery } from '@tanstack/vue-query'\n\n// Make a specific query retry a certain number of times\nconst result = useQuery({\n  queryKey: ['todos', 1],\n  queryFn: fetchTodoListPage,\n  retry: 10, // Will retry failed requests 10 times before displaying an error\n})\n```\n\n[//]: # 'Example'\n[//]: # 'Example2'\n\n```ts\nimport { VueQueryPlugin } from '@tanstack/vue-query'\n\nconst vueQueryPluginOptions = {\n  queryClientConfig: {\n    defaultOptions: {\n      queries: {\n        retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000),\n      },\n    },\n  },\n}\napp.use(VueQueryPlugin, vueQueryPluginOptions)\n```\n\n[//]: # 'Example2'\n"
  },
  {
    "path": "docs/framework/vue/guides/scroll-restoration.md",
    "content": "---\nid: scroll-restoration\ntitle: Scroll Restoration\nref: docs/framework/react/guides/scroll-restoration.md\n---\n"
  },
  {
    "path": "docs/framework/vue/guides/ssr.md",
    "content": "---\nid: ssr\ntitle: SSR\n---\n\nVue Query supports prefetching multiple queries on the server and then _dehydrating_ those queries to the queryClient. This means the server can prerender markup that is immediately available on page load and as soon as JS is available, Vue Query can upgrade or _hydrate_ those queries with the full functionality of the library. This includes refetching those queries on the client if they have become stale since the time they were rendered on the server.\n\n## Using Nuxt.js\n\n### Nuxt 3\n\nFirst create `vue-query.ts` file in your `plugins` directory with the following content:\n\n```ts\nimport type {\n  DehydratedState,\n  VueQueryPluginOptions,\n} from '@tanstack/vue-query'\nimport {\n  VueQueryPlugin,\n  QueryClient,\n  hydrate,\n  dehydrate,\n} from '@tanstack/vue-query'\n// Nuxt 3 app aliases\nimport { defineNuxtPlugin, useState } from '#imports'\n\nexport default defineNuxtPlugin((nuxt) => {\n  const vueQueryState = useState<DehydratedState | null>('vue-query')\n\n  // Modify your Vue Query global settings here\n  const queryClient = new QueryClient({\n    defaultOptions: { queries: { staleTime: 5000 } },\n  })\n  const options: VueQueryPluginOptions = { queryClient }\n\n  nuxt.vueApp.use(VueQueryPlugin, options)\n\n  if (import.meta.server) {\n    nuxt.hooks.hook('app:rendered', () => {\n      vueQueryState.value = dehydrate(queryClient)\n    })\n  }\n\n  if (import.meta.client) {\n    hydrate(queryClient, vueQueryState.value)\n  }\n})\n```\n\nNow you are ready to prefetch some data in your pages with `onServerPrefetch`.\n\n- Prefetch all the queries that you need with `queryClient.prefetchQuery` or `suspense`\n\n```ts\nexport default defineComponent({\n  setup() {\n    const { data, suspense } = useQuery({\n      queryKey: ['test'],\n      queryFn: fetcher,\n    })\n\n    onServerPrefetch(async () => {\n      await suspense()\n    })\n\n    return { data }\n  },\n})\n```\n\n### Nuxt 2\n\nFirst create `vue-query.js` file in your `plugins` directory with the following content:\n\n```js\nimport Vue from 'vue'\nimport { VueQueryPlugin, QueryClient, hydrate } from '@tanstack/vue-query'\n\nexport default (context) => {\n  // Modify your Vue Query global settings here\n  const queryClient = new QueryClient({\n    defaultOptions: { queries: { staleTime: 5000 } },\n  })\n\n  if (process.server) {\n    context.ssrContext.VueQuery = queryClient\n  }\n\n  if (process.client) {\n    Vue.use(VueQueryPlugin, { queryClient })\n\n    if (context.nuxtState && context.nuxtState.vueQueryState) {\n      hydrate(queryClient, context.nuxtState.vueQueryState)\n    }\n  }\n}\n```\n\nAdd this plugin to your `nuxt.config.js`\n\n```js\nmodule.exports = {\n  ...\n  plugins: ['~/plugins/vue-query.js'],\n}\n```\n\nNow you are ready to prefetch some data in your pages with `onServerPrefetch`.\n\n- Use `useContext` to get nuxt context\n- Use `useQueryClient` to get server-side instance of `queryClient`\n- Prefetch all the queries that you need with `queryClient.prefetchQuery` or `suspense`\n- Dehydrate `queryClient` to the `nuxtContext`\n\n```vue\n// pages/todos.vue\n<template>\n  <div>\n    <button @click=\"refetch\">Refetch</button>\n    <p>{{ data }}</p>\n  </div>\n</template>\n\n<script lang=\"ts\">\nimport {\n  defineComponent,\n  onServerPrefetch,\n  useContext,\n} from '@nuxtjs/composition-api'\nimport { useQuery, useQueryClient, dehydrate } from '@tanstack/vue-query'\n\nexport default defineComponent({\n  setup() {\n    // Get QueryClient either from SSR context, or Vue context\n    const { ssrContext } = useContext()\n    // Make sure to provide `queryClient` as a second parameter to `useQuery` calls\n    const queryClient =\n      (ssrContext != null && ssrContext.VueQuery) || useQueryClient()\n\n    // This will be prefetched and sent from the server\n    const { data, refetch, suspense } = useQuery(\n      {\n        queryKey: ['todos'],\n        queryFn: getTodos,\n      },\n      queryClient,\n    )\n    // This won't be prefetched, it will start fetching on client side\n    const { data2 } = useQuery(\n      {\n        queryKey: 'todos2',\n        queryFn: getTodos,\n      },\n      queryClient,\n    )\n\n    onServerPrefetch(async () => {\n      await suspense()\n      ssrContext.nuxt.vueQueryState = dehydrate(queryClient)\n    })\n\n    return {\n      refetch,\n      data,\n    }\n  },\n})\n</script>\n```\n\nAs demonstrated, it's fine to prefetch some queries and let others fetch on the queryClient. This means you can control what content server renders or not by adding or removing `prefetchQuery` or `suspense` for a specific query.\n\n## Using Vite SSR\n\nSync VueQuery client state with [vite-ssr](https://github.com/frandiox/vite-ssr) in order to serialize it in the DOM:\n\n```js\n// main.js (entry point)\nimport App from './App.vue'\nimport viteSSR from 'vite-ssr/vue'\nimport {\n  QueryClient,\n  VueQueryPlugin,\n  hydrate,\n  dehydrate,\n} from '@tanstack/vue-query'\n\nexport default viteSSR(App, { routes: [] }, ({ app, initialState }) => {\n  // -- This is Vite SSR main hook, which is called once per request\n\n  // Create a fresh VueQuery client\n  const queryClient = new QueryClient()\n\n  // Sync initialState with the client state\n  if (import.meta.env.SSR) {\n    // Indicate how to access and serialize VueQuery state during SSR\n    initialState.vueQueryState = { toJSON: () => dehydrate(queryClient) }\n  } else {\n    // Reuse the existing state in the browser\n    hydrate(queryClient, initialState.vueQueryState)\n  }\n\n  // Mount and provide the client to the app components\n  app.use(VueQueryPlugin, { queryClient })\n})\n```\n\nThen, call VueQuery from any component using Vue's `onServerPrefetch`:\n\n```html\n<!-- MyComponent.vue -->\n<template>\n  <div>\n    <button @click=\"refetch\">Refetch</button>\n    <p>{{ data }}</p>\n  </div>\n</template>\n\n<script setup>\n  import { useQuery } from '@tanstack/vue-query'\n  import { onServerPrefetch } from 'vue'\n\n  // This will be prefetched and sent from the server\n  const { refetch, data, suspense } = useQuery({\n    queryKey: ['todos'],\n    queryFn: getTodos,\n  })\n\n  onServerPrefetch(suspense)\n</script>\n```\n\n## Tips, Tricks and Caveats\n\n### Only successful queries are included in dehydration\n\nAny query with an error is automatically excluded from dehydration. This means that the default behavior is to pretend these queries were never loaded on the server, usually showing a loading state instead, and retrying the queries on the queryClient. This happens regardless of error.\n\nSometimes this behavior is not desirable, maybe you want to render an error page with a correct status code instead on certain errors or queries. In those cases, use `fetchQuery` and catch any errors to handle those manually.\n\n### Staleness is measured from when the query was fetched on the server\n\nA query is considered stale depending on when it was `dataUpdatedAt`. A caveat here is that the server needs to have the correct time for this to work properly, but UTC time is used, so timezones do not factor into this.\n\nBecause `staleTime` defaults to `0`, queries will be refetched in the background on page load by default. You might want to use a higher `staleTime` to avoid this double fetching, especially if you don't cache your markup.\n\nThis refetching of stale queries is a perfect match when caching markup in a CDN! You can set the cache time of the page itself decently high to avoid having to re-render pages on the server, but configure the `staleTime` of the queries lower to make sure data is refetched in the background as soon as a user visits the page. Maybe you want to cache the pages for a week, but refetch the data automatically on page load if it's older than a day?\n\n### High memory consumption on server\n\nIn case you are creating the `QueryClient` for every request, Vue Query creates the isolated cache for this client, which is preserved in memory for the `gcTime` period. That may lead to high memory consumption on server in case of high number of requests during that period.\n\nOn the server, `gcTime` defaults to `Infinity` which disables manual garbage collection and will automatically clear memory once a request has finished. If you are explicitly setting a non-Infinity `gcTime` then you will be responsible for clearing the cache early.\n\nTo clear the cache after it is not needed and to lower memory consumption, you can add a call to [`queryClient.clear()`](../../../reference/QueryClient/#queryclientclear) after the request is handled and dehydrated state has been sent to the client.\n\nAlternatively, you can set a smaller `gcTime`.\n"
  },
  {
    "path": "docs/framework/vue/guides/suspense.md",
    "content": "---\nid: suspense\ntitle: Suspense (experimental)\n---\n\n> NOTE: Suspense mode for Vue Query is experimental, same as Vue's Suspense itself. These APIs WILL change and should not be used in production unless you lock both your Vue and Vue Query versions to patch-level versions that are compatible with each other.\n\nVue Query can also be used with Vue's new [Suspense](https://vuejs.org/guide/built-ins/suspense.html) API's.\n\nTo do that you need to wrap your suspendable component with `Suspense` component provided by Vue\n\n```vue\n<script setup>\nimport SuspendableComponent from './SuspendableComponent.vue'\n</script>\n\n<template>\n  <Suspense>\n    <template #default>\n      <SuspendableComponent />\n    </template>\n    <template #fallback>\n      <div>Loading...</div>\n    </template>\n  </Suspense>\n</template>\n```\n\nAnd change your `setup` function in suspendable component to be `async`. Then you can use async `suspense` function that is provided by `vue-query`.\n\n```vue\n<script>\nimport { defineComponent } from 'vue'\nimport { useQuery } from '@tanstack/vue-query'\n\nconst todoFetcher = async () =>\n  await fetch('https://jsonplaceholder.cypress.io/todos').then((response) =>\n    response.json(),\n  )\nexport default defineComponent({\n  name: 'SuspendableComponent',\n  async setup() {\n    const { data, suspense } = useQuery(['todos'], todoFetcher)\n    await suspense()\n\n    return { data }\n  },\n})\n</script>\n```\n\n## Fetch-on-render vs Render-as-you-fetch\n\nOut of the box, Vue Query in `suspense` mode works really well as a **Fetch-on-render** solution with no additional configuration. This means that when your components attempt to mount, they will trigger query fetching and suspend, but only once you have imported them and mounted them. If you want to take it to the next level and implement a **Render-as-you-fetch** model, we recommend implementing [Prefetching](./prefetching) on routing callbacks and/or user interactions events to start loading queries before they are mounted and hopefully even before you start importing or mounting their parent components.\n"
  },
  {
    "path": "docs/framework/vue/guides/testing.md",
    "content": "---\nid: testing\ntitle: Testing\n---\n"
  },
  {
    "path": "docs/framework/vue/guides/updates-from-mutation-responses.md",
    "content": "---\nid: updates-from-mutation-responses\ntitle: Updates from Mutation Responses\nref: docs/framework/react/guides/updates-from-mutation-responses.md\n---\n"
  },
  {
    "path": "docs/framework/vue/guides/window-focus-refetching.md",
    "content": "---\nid: window-focus-refetching\ntitle: Window Focus Refetching\nref: docs/framework/react/guides/window-focus-refetching.md\nreplace: { '@tanstack/react-query': '@tanstack/vue-query' }\n---\n\n[//]: # 'Example'\n\n```js\nconst vueQueryPluginOptions: VueQueryPluginOptions = {\n  queryClientConfig: {\n    defaultOptions: {\n      queries: {\n        refetchOnWindowFocus: false,\n      },\n    },\n  },\n}\napp.use(VueQueryPlugin, vueQueryPluginOptions)\n```\n\n[//]: # 'Example'\n[//]: # 'ReactNative'\n[//]: # 'ReactNative'\n"
  },
  {
    "path": "docs/framework/vue/installation.md",
    "content": "---\nid: installation\ntitle: Installation\n---\n\nYou can install Vue Query via [NPM](https://npmjs.com).\n\n### NPM\n\n```bash\nnpm i @tanstack/vue-query\n```\n\nor\n\n```bash\npnpm add @tanstack/vue-query\n```\n\nor\n\n```bash\nyarn add @tanstack/vue-query\n```\n\nor\n\n```bash\nbun add @tanstack/vue-query\n```\n\n> Wanna give it a spin before you download? Try out the [basic](./examples/basic) example!\n\nVue Query is compatible with Vue 2.x and 3.x\n\n> If you are using Vue 2.6, make sure to also setup [@vue/composition-api](https://github.com/vuejs/composition-api)\n\n### Vue Query Initialization\n\nBefore using Vue Query, you need to initialize it using `VueQueryPlugin`\n\n```tsx\nimport { VueQueryPlugin } from '@tanstack/vue-query'\n\napp.use(VueQueryPlugin)\n```\n\n### Use of Composition API with `<script setup>`\n\nAll examples in our documentation use [`<script setup>`](https://staging.vuejs.org/api/sfc-script-setup.html) syntax.\n\nVue 2 users can also use that syntax using [this plugin](https://github.com/antfu/unplugin-vue2-script-setup). Please check the plugin documentation for installation details.\n\nIf you are not a fan of `<script setup>` syntax, you can easily translate all the examples into normal Composition API syntax by moving the code under `setup()` function and returning the values used in the template.\n\n```vue\n<script setup>\nimport { useQuery } from '@tanstack/vue-query'\n\nconst { isPending, isFetching, isError, data, error } = useQuery({\n  queryKey: ['todos'],\n  queryFn: getTodos,\n})\n</script>\n\n<template>...</template>\n```\n"
  },
  {
    "path": "docs/framework/vue/overview.md",
    "content": "---\nid: overview\ntitle: Overview\nref: docs/framework/react/overview.md\nreplace: { 'React': 'Vue', 'react-query': 'vue-query' }\n---\n\n[//]: # 'Example'\n[//]: # 'Example'\n[//]: # 'Materials'\n\n## You talked me into it, so what now?\n\n- Learn Vue Query at your own pace with our amazingly thorough [Walkthrough Guide](./installation) and [API Reference](./reference/useQuery)\n\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/framework/vue/plugins/broadcastQueryClient.md",
    "content": "---\nid: broadcastQueryClient\ntitle: broadcastQueryClient (Experimental)\nref: docs/framework/react/plugins/broadcastQueryClient.md\n---\n"
  },
  {
    "path": "docs/framework/vue/plugins/createPersister.md",
    "content": "---\nid: createPersister\ntitle: experimental_createQueryPersister\n---\n\n## Installation\n\nThis utility comes as a separate package and is available under the `'@tanstack/query-persist-client-core'` import.\n\n```bash\nnpm install @tanstack/query-persist-client-core\n```\n\nor\n\n```bash\npnpm add @tanstack/query-persist-client-core\n```\n\nor\n\n```bash\nyarn add @tanstack/query-persist-client-core\n```\n\nor\n\n```bash\nbun add @tanstack/query-persist-client-core\n```\n\n## Usage\n\n- Import the `experimental_createQueryPersister` function\n- Create a new `experimental_createQueryPersister`\n  - you can pass any `storage` to it that adheres to the `AsyncStorage` interface\n- Pass that `persister` as an option to your Query. This can be done either by passing it to the `defaultOptions` of the `QueryClient` or to any `useQuery` hook instance.\n  - If you pass this `persister` as `defaultOptions`, all queries will be persisted to the provided `storage`. You can additionally narrow this down by passing `filters`. In contrast to the `persistClient` plugin, this will not persist the whole query client as a single item, but each query separately. As a key, the query hash is used.\n  - If you provide this `persister` to a single `useQuery` hook, only this Query will be persisted.\n- Note: `queryClient.setQueryData()` operations are not persisted, this means that if you perform an optimistic update and refresh the page before the query has been invalidated, your changes to the query data will be lost. See https://github.com/TanStack/query/issues/6310\n\nThis way, you do not need to store whole `QueryClient`, but choose what is worth to be persisted in your application. Each query is lazily restored (when the Query is first used) and persisted (after each run of the `queryFn`), so it does not need to be throttled. `staleTime` is also respected after restoring the Query, so if data is considered `stale`, it will be refetched immediately after restoring. If data is `fresh`, the `queryFn` will not run.\n\nGarbage collecting a Query from memory **does not** affect the persisted data. That means Queries can be kept in memory for a shorter period of time to be more **memory efficient**. If they are used the next time, they will just be restored from the persistent storage again.\n\n```tsx\nimport { QueryClient } from '@tanstack/vue-query'\nimport { experimental_createQueryPersister } from '@tanstack/query-persist-client-core'\n\nconst persister = experimental_createQueryPersister({\n  storage: AsyncStorage,\n  maxAge: 1000 * 60 * 60 * 12, // 12 hours\n})\n\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      gcTime: 1000 * 30, // 30 seconds\n      persister: persister.persisterFn,\n    },\n  },\n})\n```\n\n### Adapted defaults\n\nThe `createPersister` plugin technically wraps the `queryFn`, so it doesn't restore if the `queryFn` doesn't run. In that way, it acts as a caching layer between the Query and the network. Thus, the `networkMode` defaults to `'offlineFirst'` when a persister is used, so that restoring from the persistent storage can also happen even if there is no network connection.\n\n## Additional utilities\n\nInvoking `experimental_createQueryPersister` returns additional utilities in addition to `persisterFn` for easier implementation of userland functionalities.\n\n### `persistQueryByKey(queryKey: QueryKey, queryClient: QueryClient): Promise<void>`\n\nThis function will persist `Query` to storage and key defined when creating persister.  \nThis utility might be used along `setQueryData` to persist optimistic update to storage without waiting for invalidation.\n\n```tsx\nconst persister = experimental_createQueryPersister({\n  storage: AsyncStorage,\n  maxAge: 1000 * 60 * 60 * 12, // 12 hours\n})\n\nconst queryClient = useQueryClient()\n\nuseMutation({\n  mutationFn: updateTodo,\n  onMutate: async (newTodo) => {\n    ...\n    // Optimistically update to the new value\n    queryClient.setQueryData(['todos'], (old) => [...old, newTodo])\n    // And persist it to storage\n    persister.persistQueryByKey(['todos'], queryClient)\n    ...\n  },\n})\n```\n\n### `retrieveQuery<T>(queryHash: string): Promise<T | undefined>`\n\nThis function would attempt to retrieve persisted query by `queryHash`.  \nIf `query` is `expired`, `busted` or `malformed` it would be removed from the storage instead, and `undefined` would be returned.\n\n### `persisterGc(): Promise<void>`\n\nThis function can be used to sporadically clean up stoage from `expired`, `busted` or `malformed` entries.\n\nFor this function to work, your storage must expose `entries` method that would return a `key-value tuple array`.  \nFor example `Object.entries(localStorage)` for `localStorage` or `entries` from `idb-keyval`.\n\n### `restoreQueries(queryClient: QueryClient, filters): Promise<void>`\n\nThis function can be used to restore queries that are currently stored by persister.  \nFor example when your app is starting up in offline mode, or you want all or only specific data from previous session to be immediately available without intermediate `loading` state.\n\nThe filter object supports the following properties:\n\n- `queryKey?: QueryKey`\n  - Set this property to define a query key to match on.\n- `exact?: boolean`\n  - If you don't want to search queries inclusively by query key, you can pass the `exact: true` option to return only the query with the exact query key you have passed.\n\nFor this function to work, your storage must expose `entries` method that would return a `key-value tuple array`.  \nFor example `Object.entries(localStorage)` for `localStorage` or `entries` from `idb-keyval`.\n\n## API\n\n### `experimental_createQueryPersister`\n\n```tsx\nexperimental_createQueryPersister(options: StoragePersisterOptions)\n```\n\n#### `Options`\n\n```tsx\nexport interface StoragePersisterOptions {\n  /** The storage client used for setting and retrieving items from cache.\n   * For SSR pass in `undefined`.\n   */\n  storage: AsyncStorage | Storage | undefined | null\n  /**\n   * How to serialize the data to storage.\n   * @default `JSON.stringify`\n   */\n  serialize?: (persistedQuery: PersistedQuery) => string\n  /**\n   * How to deserialize the data from storage.\n   * @default `JSON.parse`\n   */\n  deserialize?: (cachedString: string) => PersistedQuery\n  /**\n   * A unique string that can be used to forcefully invalidate existing caches,\n   * if they do not share the same buster string\n   */\n  buster?: string\n  /**\n   * The max-allowed age of the cache in milliseconds.\n   * If a persisted cache is found that is older than this\n   * time, it will be discarded\n   * @default 24 hours\n   */\n  maxAge?: number\n  /**\n   * Prefix to be used for storage key.\n   * Storage key is a combination of prefix and query hash in a form of `prefix-queryHash`.\n   */\n  prefix?: string\n  /**\n   * If set to `true`, the query will refetch on successful query restoration if the data is stale.\n   * If set to `false`, the query will not refetch on successful query restoration.\n   * If set to `'always'`, the query will always refetch on successful query restoration.\n   * Defaults to `true`.\n   */\n  refetchOnRestore?: boolean | 'always'\n  /**\n   * Filters to narrow down which Queries should be persisted.\n   */\n  filters?: QueryFilters\n}\n\ninterface AsyncStorage<TStorageValue = string> {\n  getItem: (key: string) => MaybePromise<TStorageValue | undefined | null>\n  setItem: (key: string, value: TStorageValue) => MaybePromise<unknown>\n  removeItem: (key: string) => MaybePromise<void>\n  entries?: () => MaybePromise<Array<[key: string, value: TStorageValue]>>\n}\n```\n\nThe default options are:\n\n```tsx\n{\n  prefix = 'tanstack-query',\n  maxAge = 1000 * 60 * 60 * 24,\n  serialize = JSON.stringify,\n  deserialize = JSON.parse,\n  refetchOnRestore = true,\n}\n```\n"
  },
  {
    "path": "docs/framework/vue/quick-start.md",
    "content": "---\nid: quick-start\ntitle: Quick Start\nref: docs/framework/react/quick-start.md\nreplace: { 'React': 'Vue', 'react-query': 'vue-query' }\n---\n\n[//]: # 'Example'\n\nIf you're looking for a fully functioning example, please have a look at our [basic codesandbox example](./examples/basic)\n\n```vue\n<script setup>\nimport { useQueryClient, useQuery, useMutation } from '@tanstack/vue-query'\n\n// Access QueryClient instance\nconst queryClient = useQueryClient()\n\n// Query\nconst { isPending, isError, data, error } = useQuery({\n  queryKey: ['todos'],\n  queryFn: getTodos,\n})\n\n// Mutation\nconst mutation = useMutation({\n  mutationFn: postTodo,\n  onSuccess: () => {\n    // Invalidate and refetch\n    queryClient.invalidateQueries({ queryKey: ['todos'] })\n  },\n})\n\nfunction onButtonClick() {\n  mutation.mutate({\n    id: Date.now(),\n    title: 'Do Laundry',\n  })\n}\n</script>\n\n<template>\n  <span v-if=\"isPending\">Loading...</span>\n  <span v-else-if=\"isError\">Error: {{ error.message }}</span>\n  <!-- We can assume by this point that `isSuccess === true` -->\n  <ul v-else>\n    <li v-for=\"todo in data\" :key=\"todo.id\">{{ todo.title }}</li>\n  </ul>\n  <button @click=\"onButtonClick\">Add Todo</button>\n</template>\n```\n\n[//]: # 'Example'\n"
  },
  {
    "path": "docs/framework/vue/reactivity.md",
    "content": "---\nid: reactivity\ntitle: Reactivity\n---\n\nVue uses the [the signals paradigm](https://vuejs.org/guide/extras/reactivity-in-depth.html#connection-to-signals) to handle and track reactivity. A key feature of\nthis system is the reactive system only triggers updates on specifically watched reactive properties. A consequence of this is you also need to ensure that the queries are updated when values they consume are updated.\n\n# Keeping Queries Reactive\n\nWhen creating a composable for a query your first choice may be to write it like so:\n\n```ts\nexport function useUserProjects(userId: string) {\n  return useQuery(\n    queryKey: ['userProjects', userId],\n    queryFn: () => api.fetchUserProjects(userId),\n  );\n}\n```\n\nWe might consume this composable like so:\n\n```ts\n// Reactive user ID ref.\nconst userId = ref('1')\n// Fetches the user 1's projects.\nconst { data: projects } = useUserProjects(userId.value)\n\nconst onChangeUser = (newUserId: string) => {\n  // Edits the userId, but the query will not re-fetch.\n  userId.value = newUserId\n}\n```\n\nThis code will not work as intended. This is because we are extracting the value from the userId ref directly. Vue-query is not tracking the `userId` `ref` so it has no way of knowing when the value changes.\n\nLuckily, the fix for this is trivial. The value must be made trackable in the query key. We can Just accept the `ref` directly in the composable and place it in the query key:\n\n```ts\nexport function useUserProjects(userId: Ref<string>) {\n  return useQuery(\n    queryKey: ['userProjects', userId],\n    queryFn: () => api.fetchUserProjects(userId.value),\n  );\n}\n```\n\nNow the query will re-fetch when the `userId` changes.\n\n```ts\nconst onChangeUser = (newUserId: string) => {\n  // Query refetches data with new user ID!\n  userId.value = newUserId\n}\n```\n\nIn vue query any reactive properties within a query key are tracked for changes automatically. This allows vue-query to refetch data whenever the\nparameters for a given request change.\n\n## Accounting for Non-Reactive Queries\n\nWhile far less likely, sometimes passing non-reactive variables is intentional. For example, some entities only need to be fetched once and don't need tracking or we invalidate a mutation a query options object after a mutation.\nIf we use our custom composable defined above the usage in this case feels a bit off:\n\n```ts\nconst { data: projects } = useUserProjects(ref('1'))\n```\n\nWe have to create an intermediate `ref` just to make the parameter type-compatible. We can do better here. Let's instead update our composable to accept both plain values and reactive values:\n\n```ts\nexport function useUserProjects(userId: MaybeRef<string>) {\n  return useQuery(\n    queryKey: ['userProjects', userId],\n    queryFn: () => api.fetchUserProjects(toValue(userId)),\n  );\n}\n```\n\nNow we can use the composable with both plain values and refs:\n\n```ts\n// Fetches the user 1's projects, userId is not expected to change.\nconst { data: projects } = useUserProjects('1')\n\n// Fetches the user 1's projects, queries will react to changes on userId.\nconst userId = ref('1')\n\n// Make some changes to userId...\n\n// Query re-fetches based on any changes to userId.\nconst { data: projects } = useUserProjects(userId)\n```\n\n## Using Derived State inside Queries\n\nIt's quite common to derive some new reactive state from another source of reactive state. Commonly, this problem manifests in situations where you deal with component props. Let's assume our `userId` is a prop passed to a component:\n\n```vue\n<script setup lang=\"ts\">\nconst props = defineProps<{\n  userId: string\n}>()\n</script>\n```\n\nYou may be tempted to use the prop directly in the query like so:\n\n```ts\n// Won't react to changes in props.userId.\nconst { data: projects } = useUserProjects(props.userId)\n```\n\nHowever, similar to the first example, this is not reactive. Property access on `reactive` variables causes reactivity to be lost. We can fix this by making this derived state reactive via a `computed`:\n\n```ts\nconst userId = computed(() => props.userId)\n\n// Reacts to changes in props.userId.\nconst { data: projects } = useUserProjects(userId)\n```\n\nThis works as expected, however, this solution isn't always the most optimal. Aside from the introduction of an intermediate variable, we also create a memoized value that is somewhat unnecessary. For trivial cases of simple property access `computed` is an optimization with no real benefit. In these cases a more appropriate solution is to use [reactive getters](https://blog.vuejs.org/posts/vue-3-3#better-getter-support-with-toref-and-tovalue). Reactive getters are simply functions that return a value based on some reactive state, similar to how `computed` works. Unlike `computed`, reactive getters do not memoize their values so it makes it a good candidate for simple property access.\n\nLet's once again refactor our composable, but this time we'll have it accept a `ref`, plain value, or a reactive getter:\n\n```ts\nexport function useUserProjects(userId: MaybeRefOrGetter<string>) {\n  ...\n}\n```\n\nLet's adjust our usage and now use a reactive getter:\n\n```ts\n// Reacts to changes in props.userId. No `computed` needed!\nconst { data: projects } = useUserProjects(() => props.userId)\n```\n\nThis gives us a terse syntax and the reactivity we need without any unneeded memoization overhead.\n\n## Other tracked Query Options\n\nAbove, we only touched one query option that tracks reactive dependencies. However, in addition to `queryKey`, `enabled` also allows\nthe use of reactive values. This comes in handy in situations where you want to control the fetching of a query based on some derived state:\n\n```ts\nexport function useUserProjects(userId: MaybeRef<string>) {\n  return useQuery(\n    queryKey: ['userProjects', userId],\n    queryFn: () => api.fetchUserProjects(toValue(userId)),\n    enabled: () => userId.value === activeUserId.value,\n  );\n}\n```\n\nMore details on this option can be found on the [useQuery reference](./reference/useQuery.md) page.\n\n## Immutability\n\nResults from `useQuery` are always immutable. This is necessary for performance and caching purposes. If you need to mutate a value returned from `useQuery`, you must create a copy of the data.\n\nOne implication of this design is that passing values from `useQuery` to a two-way binding such as `v-model` will not work. You must create a mutable copy of the data before attempting to update it in place.\n\n# Key Takeaways\n\n- `enabled` and `queryKey` are the two query options that can accept reactive values.\n- Pass query option that accept all three types of values in Vue: refs, plain values, and reactive getters.\n- If you expect a query to react to changes based on the values it consumes, ensure that the values are reactive. (i.e. pass in refs directly to the query, or use reactive getters)\n- If you don't need a query to be reactive pass in a plain value.\n- For trivial derived state such as property access consider using a reactive getter in place of a `computed`.\n- Results from `useQuery` are always immutable.\n"
  },
  {
    "path": "docs/framework/vue/reference/hydration.md",
    "content": "---\nid: hydration\ntitle: hydration\nref: docs/framework/react/reference/hydration.md\nreplace: { '@tanstack/react-query': '@tanstack/vue-query' }\n---\n\n[//]: # 'HydrationBoundary'\n[//]: # 'HydrationBoundary'\n"
  },
  {
    "path": "docs/framework/vue/reference/infiniteQueryOptions.md",
    "content": "---\nid: infiniteQueryOptions\ntitle: infiniteQueryOptions\nref: docs/framework/react/reference/infiniteQueryOptions.md\n---\n"
  },
  {
    "path": "docs/framework/vue/reference/queryOptions.md",
    "content": "---\nid: queryOptions\ntitle: queryOptions\nref: docs/framework/react/reference/queryOptions.md\n---\n"
  },
  {
    "path": "docs/framework/vue/reference/useInfiniteQuery.md",
    "content": "---\nid: useInfiniteQuery\ntitle: useInfiniteQuery\nref: docs/framework/react/reference/useInfiniteQuery.md\nreplace: { '@tanstack/react-query': '@tanstack/vue-query' }\n---\n"
  },
  {
    "path": "docs/framework/vue/reference/useIsFetching.md",
    "content": "---\nid: useIsFetching\ntitle: useIsFetching\nref: docs/framework/react/reference/useIsFetching.md\nreplace: { '@tanstack/react-query': '@tanstack/vue-query' }\n---\n"
  },
  {
    "path": "docs/framework/vue/reference/useIsMutating.md",
    "content": "---\nid: useIsMutating\ntitle: useIsMutating\nref: docs/framework/react/reference/useIsMutating.md\nreplace: { '@tanstack/react-query': '@tanstack/vue-query' }\n---\n"
  },
  {
    "path": "docs/framework/vue/reference/useMutation.md",
    "content": "---\nid: useMutation\ntitle: useMutation\nref: docs/framework/react/reference/useMutation.md\nreplace: { '@tanstack/react-query': '@tanstack/vue-query' }\n---\n"
  },
  {
    "path": "docs/framework/vue/reference/useMutationState.md",
    "content": "---\nid: useMutationState\ntitle: useMutationState\nref: docs/framework/react/reference/useMutationState.md\nreplace: { '@tanstack/react-query': '@tanstack/vue-query' }\n---\n"
  },
  {
    "path": "docs/framework/vue/reference/useQueries.md",
    "content": "---\nid: useQueries\ntitle: useQueries\nref: docs/framework/react/reference/useQueries.md\nreplace: { '@tanstack/react-query': '@tanstack/vue-query' }\n---\n"
  },
  {
    "path": "docs/framework/vue/reference/useQuery.md",
    "content": "---\nid: useQuery\ntitle: useQuery\nref: docs/framework/react/reference/useQuery.md\nreplace: { '@tanstack/react-query': '@tanstack/vue-query' }\n---\n"
  },
  {
    "path": "docs/framework/vue/reference/useQueryClient.md",
    "content": "---\nid: useQueryClient\ntitle: useQueryClient\nref: docs/framework/react/reference/useQueryClient.md\nreplace: { '@tanstack/react-query': '@tanstack/vue-query' }\n---\n"
  },
  {
    "path": "docs/framework/vue/typescript.md",
    "content": "---\nid: typescript\ntitle: TypeScript\nref: docs/framework/react/typescript.md\nreplace:\n  {\n    'React': 'Vue',\n    '@tanstack/react-query': '@tanstack/vue-query',\n    'react-query package version': 'vue-query package version',\n  }\n---\n\n[//]: # 'TypeInference1'\n\n```tsx\nconst { data } = useQuery({\n  //    ^? const data: Ref<number> | Ref<undefined>\n  queryKey: ['test'],\n  queryFn: () => Promise.resolve(5),\n})\n```\n\n[typescript playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgVwM4FMCKz1QJ5wC+cAZlBCHAOQACMAhgHaoMDGA1gPQBuOAtAEcc+KgFgAUBNYRm8JABN6DInAC8KDNlx4AFAglw4nTocMA9APwG4Q7QGl0eAFxwA2lRjoWVALoAaa1t8ADFGFx0ASjUAPjgABXIQYAwAOigvCAAbbnQdAFYIgPFCCKA)\n\n[//]: # 'TypeInference1'\n[//]: # 'TypeInference2'\n\n```tsx\nconst { data } = useQuery({\n  //      ^? const data: Ref<string> | Ref<undefined>\n  queryKey: ['test'],\n  queryFn: () => Promise.resolve(5),\n  select: (data) => data.toString(),\n})\n```\n\n[typescript playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgVwM4FMCKz1QJ5wC+cAZlBCHAOQACMAhgHaoMDGA1gPQBuOAtAEcc+KgFgAUBNYRm8JABN6DInAC8KDNlx4AFAglw4nTodNwAegH4DcIdoDS6PAC44AbSox0LKgF0ANDZ2+ABijK46AJRqAHxwAArkIMAYAHRQ3hAANtzoOgCskYHihhhZ6KwwEYoM0apxNfSpMBAAyjBQwIwA5lHFhJFAA)\n\n[//]: # 'TypeInference2'\n[//]: # 'TypeInference3'\n\n```tsx\nconst fetchGroups = (): Promise<Group[]> =>\n  axios.get('/groups').then((response) => response.data)\n\nconst { data } = useQuery({ queryKey: ['groups'], queryFn: fetchGroups })\n//      ^? const data: Ref<Group[]> | Ref<undefined>\n```\n\n[typescript playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgVwM4FMCKz1QJ5wC+cAZlBCHAOQACMAhgHaoMDGA1gPQBuOAtAEcc+KgFgAUKEiw49AB7AIqUuUpV5i1GPESYeMOjgBxcsjBwAvIjjAAJgC44jZCABGuIhImsIzeCXQYVgALEwgzZSsACgBKRwAFVWAMAB4wswBtAF0APksciThZBSUAOgBzQKiqTnLTMC0Y0phg9EYoqKh0VEhmdBj8uC6e3wxS23oGGK9xHz9rCYYiSxQMbFw8KKQhDYBpdDxHDKo68IaqLIAaOB38ADFGRwCg0PrlQmnxTk4i37gAPQA-EA)\n\n[//]: # 'TypeInference3'\n[//]: # 'TypeNarrowing'\n\n```tsx\nconst { data, isSuccess } = reactive(\n  useQuery({\n    queryKey: ['test'],\n    queryFn: () => Promise.resolve(5),\n  }),\n)\n\nif (isSuccess) {\n  data\n  // ^? const data: number\n}\n```\n\n[typescript playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgVwM4FMCKz1QJ5wC+cAZlBCHAOQACMAhgHaoMDGA1gPQBuOAtAEcc+KgFgAUKEixEcKOnqsYwbuiKlylKr3RUA3BImsIzeEgAm9BgBo4wVAGVkrVulSp1AXjkKlK9AAUaFjCeAEA2lQwbjBUALq2AQCUcJ4AfHAACpr26AB08qgQADaqAQCsSVWGkiRwAfZOLm6oKQgScJ1wlgwSnJydAHoA-BKEEkA)\n\n[//]: # 'TypeNarrowing'\n[//]: # 'TypingError'\n\n```tsx\nconst { error } = useQuery({ queryKey: ['groups'], queryFn: fetchGroups })\n//      ^? const error: Ref<unknown>\n\nif (error.value instanceof Error) {\n  error.value\n  //     ^? const error: Error\n}\n```\n\n[typescript playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgVwM4FMCKz1QJ5wC+cAZlBCHAOQACMAhgHaoMDGA1gPRTr2swBaAI458VALAAoUJFhx6AD2ARUpcpSqLlqCZKkw8YdHADi5ZGDgBeRHGAATAFxxGyEACNcRKVNYRm8CToMKwAFmYQFqo2ABQAlM4ACurAGAA8ERYA2gC6AHzWBVoqAHQA5sExVJxl5mA6cSUwoeiMMTyokMzGVgUdXRgl9vQMcT6SfgG2uORQRNYoGNi4eDFIIisA0uh4zllUtZH1VDkANHAb+ABijM5BIeF1qoRjkpyccJ9fAHoA-OPAEhwGLFVAlVIAQSUKgAolBZjEZtA4nFEFJPkioOi4O84H8pIQgA)\n\n[//]: # 'TypingError'\n[//]: # 'TypingError2'\n[//]: # 'TypingError2'\n[//]: # 'TypingError3'\n[//]: # 'TypingError3'\n[//]: # 'RegisterErrorType'\n\n```tsx\nimport '@tanstack/vue-query'\n\ndeclare module '@tanstack/vue-query' {\n  interface Register {\n    // Use unknown so call sites must narrow explicitly.\n    defaultError: unknown\n  }\n}\n\nconst { error } = useQuery({ queryKey: ['groups'], queryFn: fetchGroups })\n//      ^? const error: unknown | null\n```\n\n[//]: # 'RegisterErrorType'\n[//]: # 'TypingMeta'\n[//]: # 'TypingMeta'\n[//]: # 'TypingQueryOptions'\n[//]: # 'TypingQueryOptions'\n[//]: # 'Materials'\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/reference/InfiniteQueryObserver.md",
    "content": "---\nid: InfiniteQueryObserver\ntitle: InfiniteQueryObserver\n---\n\n## `InfiniteQueryObserver`\n\nThe `InfiniteQueryObserver` can be used to observe and switch between infinite queries.\n\n```tsx\nconst observer = new InfiniteQueryObserver(queryClient, {\n  queryKey: ['posts'],\n  queryFn: fetchPosts,\n  getNextPageParam: (lastPage, allPages) => lastPage.nextCursor,\n  getPreviousPageParam: (firstPage, allPages) => firstPage.prevCursor,\n})\n\nconst unsubscribe = observer.subscribe((result) => {\n  console.log(result)\n  unsubscribe()\n})\n```\n\n**Options**\n\nThe options for the `InfiniteQueryObserver` are exactly the same as those of [`useInfiniteQuery`](../framework/react/reference/useInfiniteQuery).\n"
  },
  {
    "path": "docs/reference/MutationCache.md",
    "content": "---\nid: MutationCache\ntitle: MutationCache\n---\n\nThe `MutationCache` is the storage for mutations.\n\n**Normally, you will not interact with the MutationCache directly and instead use the `QueryClient`.**\n\n```tsx\nimport { MutationCache } from '@tanstack/react-query'\n\nconst mutationCache = new MutationCache({\n  onError: (error) => {\n    console.log(error)\n  },\n  onSuccess: (data) => {\n    console.log(data)\n  },\n})\n```\n\nIts available methods are:\n\n- [`getAll`](#mutationcachegetall)\n- [`subscribe`](#mutationcachesubscribe)\n- [`clear`](#mutationcacheclear)\n\n**Options**\n\n- `onError?: (error: unknown, variables: unknown, onMutateResult: unknown, mutation: Mutation, mutationFnContext: MutationFunctionContext) => Promise<unknown> | unknown`\n  - Optional\n  - This function will be called if some mutation encounters an error.\n  - If you return a Promise from it, it will be awaited\n- `onSuccess?: (data: unknown, variables: unknown, onMutateResult: unknown, mutation: Mutation, mutationFnContext: MutationFunctionContext) => Promise<unknown> | unknown`\n  - Optional\n  - This function will be called if some mutation is successful.\n  - If you return a Promise from it, it will be awaited\n- `onSettled?: (data: unknown | undefined, error: unknown | null, variables: unknown, onMutateResult: unknown, mutation: Mutation, mutationFnContext: MutationFunctionContext) => Promise<unknown> | unknown`\n  - Optional\n  - This function will be called if some mutation is settled (either successful or errored).\n  - If you return a Promise from it, it will be awaited\n- `onMutate?: (variables: unknown, mutation: Mutation, mutationFnContext: MutationFunctionContext) => Promise<unknown> | unknown`\n  - Optional\n  - This function will be called before some mutation executes.\n  - If you return a Promise from it, it will be awaited\n\n## Global callbacks\n\nThe `onError`, `onSuccess`, `onSettled` and `onMutate` callbacks on the MutationCache can be used to handle these events on a global level. They are different to `defaultOptions` provided to the QueryClient because:\n\n- `defaultOptions` can be overridden by each Mutation - the global callbacks will **always** be called.\n- `onMutate` does not allow returning a result.\n\n## `mutationCache.getAll`\n\n`getAll` returns all mutations within the cache.\n\n> Note: This is not typically needed for most applications, but can come in handy when needing more information about a mutation in rare scenarios\n\n```tsx\nconst mutations = mutationCache.getAll()\n```\n\n**Returns**\n\n- `Mutation[]`\n  - Mutation instances from the cache\n\n## `mutationCache.subscribe`\n\nThe `subscribe` method can be used to subscribe to the mutation cache as a whole and be informed of safe/known updates to the cache like mutation states changing or mutations being updated, added or removed.\n\n```tsx\nconst callback = (event) => {\n  console.log(event.type, event.mutation)\n}\n\nconst unsubscribe = mutationCache.subscribe(callback)\n```\n\n**Options**\n\n- `callback: (mutation?: MutationCacheNotifyEvent) => void`\n  - This function will be called with the mutation cache any time it is updated.\n\n**Returns**\n\n- `unsubscribe: Function => void`\n  - This function will unsubscribe the callback from the mutation cache.\n\n## `mutationCache.clear`\n\nThe `clear` method can be used to clear the cache entirely and start fresh.\n\n```tsx\nmutationCache.clear()\n```\n"
  },
  {
    "path": "docs/reference/QueriesObserver.md",
    "content": "---\nid: QueriesObserver\ntitle: QueriesObserver\n---\n\n## `QueriesObserver`\n\nThe `QueriesObserver` can be used to observe multiple queries.\n\n```tsx\nconst observer = new QueriesObserver(queryClient, [\n  { queryKey: ['post', 1], queryFn: fetchPost },\n  { queryKey: ['post', 2], queryFn: fetchPost },\n])\n\nconst unsubscribe = observer.subscribe((result) => {\n  console.log(result)\n  unsubscribe()\n})\n```\n\n**Options**\n\nThe options for the `QueriesObserver` are exactly the same as those of [`useQueries`](../framework/react/reference/useQueries).\n"
  },
  {
    "path": "docs/reference/QueryCache.md",
    "content": "---\nid: QueryCache\ntitle: QueryCache\n---\n\nThe `QueryCache` is the storage mechanism for TanStack Query. It stores all the data, meta information and state of queries it contains.\n\n**Normally, you will not interact with the QueryCache directly and instead use the `QueryClient` for a specific cache.**\n\n```tsx\nimport { QueryCache } from '@tanstack/react-query'\n\nconst queryCache = new QueryCache({\n  onError: (error) => {\n    console.log(error)\n  },\n  onSuccess: (data) => {\n    console.log(data)\n  },\n  onSettled: (data, error) => {\n    console.log(data, error)\n  },\n})\n\nconst query = queryCache.find(['posts'])\n```\n\nIts available methods are:\n\n- [`queryCache.find`](#querycachefind)\n- [`queryCache.findAll`](#querycachefindall)\n- [`queryCache.subscribe`](#querycachesubscribe)\n- [`queryCache.clear`](#querycacheclear)\n- [Further reading](#further-reading)\n\n**Options**\n\n- `onError?: (error: unknown, query: Query) => void`\n  - Optional\n  - This function will be called if some query encounters an error.\n- `onSuccess?: (data: unknown, query: Query) => void`\n  - Optional\n  - This function will be called if some query is successful.\n- `onSettled?: (data: unknown | undefined, error: unknown | null, query: Query) => void`\n  - Optional\n  - This function will be called if some query is settled (either successful or errored).\n\n## `queryCache.find`\n\n`find` is a slightly more advanced synchronous method that can be used to get an existing query instance from the cache. This instance not only contains **all** the state for the query, but all of the instances, and underlying guts of the query as well. If the query does not exist, `undefined` will be returned.\n\n> Note: This is not typically needed for most applications, but can come in handy when needing more information about a query in rare scenarios (eg. Looking at the query.state.dataUpdatedAt timestamp to decide whether a query is fresh enough to be used as an initial value)\n\n```tsx\nconst query = queryCache.find(queryKey)\n```\n\n**Options**\n\n- `filters?: QueryFilters`: [Query Filters](../framework/react/guides/filters#query-filters)\n\n**Returns**\n\n- `Query`\n  - The query instance from the cache\n\n## `queryCache.findAll`\n\n`findAll` is even more advanced synchronous method that can be used to get existing query instances from the cache that partially match query key. If queries do not exist, empty array will be returned.\n\n> Note: This is not typically needed for most applications, but can come in handy when needing more information about a query in rare scenarios\n\n```tsx\nconst queries = queryCache.findAll(queryKey)\n```\n\n**Options**\n\n- `queryKey?: QueryKey`: [Query Keys](../framework/react/guides/query-keys.md)\n- `filters?: QueryFilters`: [Query Filters](../framework/react/guides/filters.md#query-filters)\n\n**Returns**\n\n- `Query[]`\n  - Query instances from the cache\n\n## `queryCache.subscribe`\n\nThe `subscribe` method can be used to subscribe to the query cache as a whole and be informed of safe/known updates to the cache like query states changing or queries being updated, added or removed\n\n```tsx\nconst callback = (event) => {\n  console.log(event.type, event.query)\n}\n\nconst unsubscribe = queryCache.subscribe(callback)\n```\n\n**Options**\n\n- `callback: (event: QueryCacheNotifyEvent) => void`\n  - This function will be called with the query cache any time it is updated via its tracked update mechanisms (eg, `query.setState`, `queryClient.removeQueries`, etc). Out of scope mutations to the cache are not encouraged and will not fire subscription callbacks\n\n**Returns**\n\n- `unsubscribe: Function => void`\n  - This function will unsubscribe the callback from the query cache.\n\n## `queryCache.clear`\n\nThe `clear` method can be used to clear the cache entirely and start fresh.\n\n```tsx\nqueryCache.clear()\n```\n\n[//]: # 'Materials'\n\n## Further reading\n\nTo get a better understanding how the QueryCache works internally, have a look at [the Inside React Query article by TkDodo](https://tkdodo.eu/blog/inside-react-query).\n\n[//]: # 'Materials'\n"
  },
  {
    "path": "docs/reference/QueryClient.md",
    "content": "---\nid: QueryClient\ntitle: QueryClient\n---\n\n## `QueryClient`\n\nThe `QueryClient` can be used to interact with a cache:\n\n```tsx\nimport { QueryClient } from '@tanstack/react-query'\n\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      staleTime: Infinity,\n    },\n  },\n})\n\nawait queryClient.prefetchQuery({ queryKey: ['posts'], queryFn: fetchPosts })\n```\n\nIts available methods are:\n\n- [`queryClient.fetchQuery`](#queryclientfetchquery)\n- [`queryClient.fetchInfiniteQuery`](#queryclientfetchinfinitequery)\n- [`queryClient.prefetchQuery`](#queryclientprefetchquery)\n- [`queryClient.prefetchInfiniteQuery`](#queryclientprefetchinfinitequery)\n- [`queryClient.getQueryData`](#queryclientgetquerydata)\n- [`queryClient.ensureQueryData`](#queryclientensurequerydata)\n- [`queryClient.ensureInfiniteQueryData`](#queryclientensureinfinitequerydata)\n- [`queryClient.getQueriesData`](#queryclientgetqueriesdata)\n- [`queryClient.setQueryData`](#queryclientsetquerydata)\n- [`queryClient.getQueryState`](#queryclientgetquerystate)\n- [`queryClient.setQueriesData`](#queryclientsetqueriesdata)\n- [`queryClient.invalidateQueries`](#queryclientinvalidatequeries)\n- [`queryClient.refetchQueries`](#queryclientrefetchqueries)\n- [`queryClient.cancelQueries`](#queryclientcancelqueries)\n- [`queryClient.removeQueries`](#queryclientremovequeries)\n- [`queryClient.resetQueries`](#queryclientresetqueries)\n- [`queryClient.isFetching`](#queryclientisfetching)\n- [`queryClient.isMutating`](#queryclientismutating)\n- [`queryClient.getDefaultOptions`](#queryclientgetdefaultoptions)\n- [`queryClient.setDefaultOptions`](#queryclientsetdefaultoptions)\n- [`queryClient.getQueryDefaults`](#queryclientgetquerydefaults)\n- [`queryClient.setQueryDefaults`](#queryclientsetquerydefaults)\n- [`queryClient.getMutationDefaults`](#queryclientgetmutationdefaults)\n- [`queryClient.setMutationDefaults`](#queryclientsetmutationdefaults)\n- [`queryClient.getQueryCache`](#queryclientgetquerycache)\n- [`queryClient.getMutationCache`](#queryclientgetmutationcache)\n- [`queryClient.clear`](#queryclientclear)\n- [`queryClient.resumePausedMutations`](#queryclientresumepausedmutations)\n\n**Options**\n\n- `queryCache?: QueryCache`\n  - Optional\n  - The query cache this client is connected to.\n- `mutationCache?: MutationCache`\n  - Optional\n  - The mutation cache this client is connected to.\n- `defaultOptions?: DefaultOptions`\n  - Optional\n  - Define defaults for all queries and mutations using this queryClient.\n  - You can also define defaults to be used for [hydration](../framework/react/reference/hydration.md)\n\n## `queryClient.fetchQuery`\n\n`fetchQuery` is an asynchronous method that can be used to fetch and cache a query. It will either resolve with the data or throw with the error. Use the `prefetchQuery` method if you just want to fetch a query without needing the result.\n\nIf the query exists and the data is not invalidated or older than the given `staleTime`, then the data from the cache will be returned. Otherwise it will try to fetch the latest data.\n\n```tsx\ntry {\n  const data = await queryClient.fetchQuery({ queryKey, queryFn })\n} catch (error) {\n  console.log(error)\n}\n```\n\nSpecify a `staleTime` to only fetch when the data is older than a certain amount of time:\n\n```tsx\ntry {\n  const data = await queryClient.fetchQuery({\n    queryKey,\n    queryFn,\n    staleTime: 10000,\n  })\n} catch (error) {\n  console.log(error)\n}\n```\n\n**Options**\n\nThe options for `fetchQuery` are exactly the same as those of [`useQuery`](../framework/react/reference/useQuery.md), except the following: `enabled, refetchInterval, refetchIntervalInBackground, refetchOnWindowFocus, refetchOnReconnect, refetchOnMount, notifyOnChangeProps, throwOnError, select, suspense, placeholderData`; which are strictly for useQuery and useInfiniteQuery. You can check the [source code](https://github.com/TanStack/query/blob/7cd2d192e6da3df0b08e334ea1cf04cd70478827/packages/query-core/src/types.ts#L119) for more clarity.\n\n**Returns**\n\n- `Promise<TData>`\n\n## `queryClient.fetchInfiniteQuery`\n\n`fetchInfiniteQuery` is similar to `fetchQuery` but can be used to fetch and cache an infinite query.\n\n```tsx\ntry {\n  const data = await queryClient.fetchInfiniteQuery({ queryKey, queryFn })\n  console.log(data.pages)\n} catch (error) {\n  console.log(error)\n}\n```\n\n**Options**\n\nThe options for `fetchInfiniteQuery` are exactly the same as those of [`fetchQuery`](#queryclientfetchquery).\n\n**Returns**\n\n- `Promise<InfiniteData<TData, TPageParam>>`\n\n## `queryClient.prefetchQuery`\n\n`prefetchQuery` is an asynchronous method that can be used to prefetch a query before it is needed or rendered with `useQuery` and friends. The method works the same as `fetchQuery` except that it will not throw or return any data.\n\n```tsx\nawait queryClient.prefetchQuery({ queryKey, queryFn })\n```\n\nYou can even use it with a default queryFn in your config!\n\n```tsx\nawait queryClient.prefetchQuery({ queryKey })\n```\n\n**Options**\n\nThe options for `prefetchQuery` are exactly the same as those of [`fetchQuery`](#queryclientfetchquery).\n\n**Returns**\n\n- `Promise<void>`\n  - A promise is returned that will either immediately resolve if no fetch is needed or after the query has been executed. It will not return any data or throw any errors.\n\n## `queryClient.prefetchInfiniteQuery`\n\n`prefetchInfiniteQuery` is similar to `prefetchQuery` but can be used to prefetch and cache an infinite query.\n\n```tsx\nawait queryClient.prefetchInfiniteQuery({ queryKey, queryFn })\n```\n\n**Options**\n\nThe options for `prefetchInfiniteQuery` are exactly the same as those of [`fetchQuery`](#queryclientfetchquery).\n\n**Returns**\n\n- `Promise<void>`\n  - A promise is returned that will either immediately resolve if no fetch is needed or after the query has been executed. It will not return any data or throw any errors.\n\n## `queryClient.getQueryData`\n\n`getQueryData` is a synchronous function that can be used to get an existing query's cached data. If the query does not exist, `undefined` will be returned.\n\n```tsx\nconst data = queryClient.getQueryData(queryKey)\n```\n\n**Options**\n\n- `queryKey: QueryKey`: [Query Keys](../framework/react/guides/query-keys.md)\n\n**Returns**\n\n- `data: TQueryFnData | undefined`\n  - The data for the cached query, or `undefined` if the query does not exist.\n\n## `queryClient.ensureQueryData`\n\n`ensureQueryData` is an asynchronous function that can be used to get an existing query's cached data. If the query does not exist, `queryClient.fetchQuery` will be called and its results returned.\n\n```tsx\nconst data = await queryClient.ensureQueryData({ queryKey, queryFn })\n```\n\n**Options**\n\n- the same options as [`fetchQuery`](#queryclientfetchquery)\n- `revalidateIfStale: boolean`\n  - Optional\n  - Defaults to `false`\n  - If set to `true`, stale data will be refetched in the background, but cached data will be returned immediately.\n\n**Returns**\n\n- `Promise<TData>`\n\n## `queryClient.ensureInfiniteQueryData`\n\n`ensureInfiniteQueryData` is an asynchronous function that can be used to get an existing infinite query's cached data. If the query does not exist, `queryClient.fetchInfiniteQuery` will be called and its results returned.\n\n```tsx\nconst data = await queryClient.ensureInfiniteQueryData({\n  queryKey,\n  queryFn,\n  initialPageParam,\n  getNextPageParam,\n})\n```\n\n**Options**\n\n- the same options as [`fetchInfiniteQuery`](#queryclientfetchinfinitequery)\n- `revalidateIfStale: boolean`\n  - Optional\n  - Defaults to `false`\n  - If set to `true`, stale data will be refetched in the background, but cached data will be returned immediately.\n\n**Returns**\n\n- `Promise<InfiniteData<TData, TPageParam>>`\n\n## `queryClient.getQueriesData`\n\n`getQueriesData` is a synchronous function that can be used to get the cached data of multiple queries. Only queries that match the passed queryKey or queryFilter will be returned. If there are no matching queries, an empty array will be returned.\n\n```tsx\nconst data = queryClient.getQueriesData(filters)\n```\n\n**Options**\n\n- `filters: QueryFilters`: [Query Filters](../framework/react/guides/filters.md#query-filters)\n  - if a filter is passed, the data with queryKeys matching the filter will be returned\n\n**Returns**\n\n- `[queryKey: QueryKey, data: TQueryFnData | undefined][]`\n  - An array of tuples for the matched query keys, or `[]` if there are no matches. The tuples are the query key and its associated data.\n\n**Caveats**\n\nBecause the returned data in each tuple can be of varying structures (i.e. using a filter to return \"active\" queries can return different data types), the `TData` generic defaults to `unknown`. If you provide a more specific type to `TData` it is assumed that you are certain each tuple's data entry is all the same type.\n\nThis distinction is more a \"convenience\" for ts devs that know which structure will be returned.\n\n## `queryClient.setQueryData`\n\n`setQueryData` is a synchronous function that can be used to immediately update a query's cached data. If the query does not exist, it will be created. **If the query is not utilized by a query hook in the default `gcTime` of 5 minutes, the query will be garbage collected**. To update multiple queries at once and match query keys partially, you need to use [`queryClient.setQueriesData`](#queryclientsetqueriesdata) instead.\n\n> The difference between using `setQueryData` and `fetchQuery` is that `setQueryData` is sync and assumes that you already synchronously have the data available. If you need to fetch the data asynchronously, it's suggested that you either refetch the query key or use `fetchQuery` to handle the asynchronous fetch.\n\n```tsx\nqueryClient.setQueryData(queryKey, updater)\n```\n\n**Options**\n\n- `queryKey: QueryKey`: [Query Keys](../framework/react/guides/query-keys.md)\n- `updater: TQueryFnData | undefined | ((oldData: TQueryFnData | undefined) => TQueryFnData | undefined)`\n  - If non-function is passed, the data will be updated to this value\n  - If a function is passed, it will receive the old data value and be expected to return a new one.\n\n**Using an updater value**\n\n```tsx\nsetQueryData(queryKey, newData)\n```\n\nIf the value is `undefined`, the query data is not updated.\n\n**Using an updater function**\n\nFor convenience in syntax, you can also pass an updater function which receives the current data value and returns the new one:\n\n```tsx\nsetQueryData(queryKey, (oldData) => newData)\n```\n\nIf the updater function returns `undefined`, the query data will not be updated. If the updater function receives `undefined` as input, you can return `undefined` to bail out of the update and thus _not_ create a new cache entry.\n\n**Immutability**\n\nUpdates via `setQueryData` must be performed in an _immutable_ way. **DO NOT** attempt to write directly to the cache by mutating `oldData` or data that you retrieved via `getQueryData` in place.\n\n## `queryClient.getQueryState`\n\n`getQueryState` is a synchronous function that can be used to get an existing query's state. If the query does not exist, `undefined` will be returned.\n\n```tsx\nconst state = queryClient.getQueryState(queryKey)\nconsole.log(state.dataUpdatedAt)\n```\n\n**Options**\n\n- `queryKey: QueryKey`: [Query Keys](../framework/react/guides/query-keys.md)\n\n## `queryClient.setQueriesData`\n\n`setQueriesData` is a synchronous function that can be used to immediately update cached data of multiple queries by using filter function or partially matching the query key. Only queries that match the passed queryKey or queryFilter will be updated - no new cache entries will be created. Under the hood, [`setQueryData`](#queryclientsetquerydata) is called for each existing query.\n\n```tsx\nqueryClient.setQueriesData(filters, updater)\n```\n\n**Options**\n\n- `filters: QueryFilters`: [Query Filters](../framework/react/guides/filters.md#query-filters)\n  - if a filter is passed, queryKeys matching the filter will be updated\n- `updater: TQueryFnData | (oldData: TQueryFnData | undefined) => TQueryFnData`\n  - the [setQueryData](#queryclientsetquerydata) updater function or new data, will be called for each matching queryKey\n\n## `queryClient.invalidateQueries`\n\nThe `invalidateQueries` method can be used to invalidate and refetch single or multiple queries in the cache based on their query keys or any other functionally accessible property/state of the query. By default, all matching queries are immediately marked as invalid and active queries are refetched in the background.\n\n- If you **do not want active queries to refetch**, and simply be marked as invalid, you can use the `refetchType: 'none'` option.\n- If you **want inactive queries to refetch** as well, use the `refetchType: 'all'` option\n- For refetching, [queryClient.refetchQueries](#queryclientrefetchqueries) is called.\n\n```tsx\nawait queryClient.invalidateQueries(\n  {\n    queryKey: ['posts'],\n    exact,\n    refetchType: 'active',\n  },\n  { throwOnError, cancelRefetch },\n)\n```\n\n**Options**\n\n- `filters?: QueryFilters`: [Query Filters](../framework/react/guides/filters.md#query-filters)\n  - `queryKey?: QueryKey`: [Query Keys](../framework/react/guides/query-keys.md)\n  - `refetchType?: 'active' | 'inactive' | 'all' | 'none'`\n    - Defaults to `'active'`\n    - When set to `active`, only queries that match the refetch predicate and are actively being rendered via `useQuery` and friends will be refetched in the background.\n    - When set to `inactive`, only queries that match the refetch predicate and are NOT actively being rendered via `useQuery` and friends will be refetched in the background.\n    - When set to `all`, all queries that match the refetch predicate will be refetched in the background.\n    - When set to `none`, no queries will be refetched, and those that match the refetch predicate will be marked as invalid only.\n- `options?: InvalidateOptions`:\n  - `throwOnError?: boolean`\n    - When set to `true`, this method will throw if any of the query refetch tasks fail.\n  - `cancelRefetch?: boolean`\n    - Defaults to `true`\n      - Per default, a currently running request will be cancelled before a new request is made\n    - When set to `false`, no refetch will be made if there is already a request running.\n\n## `queryClient.refetchQueries`\n\nThe `refetchQueries` method can be used to refetch queries based on certain conditions.\n\nExamples:\n\n```tsx\n// refetch all queries:\nawait queryClient.refetchQueries()\n\n// refetch all stale queries:\nawait queryClient.refetchQueries({ stale: true })\n\n// refetch all active queries partially matching a query key:\nawait queryClient.refetchQueries({ queryKey: ['posts'], type: 'active' })\n\n// refetch all active queries exactly matching a query key:\nawait queryClient.refetchQueries({\n  queryKey: ['posts', 1],\n  type: 'active',\n  exact: true,\n})\n```\n\n**Options**\n\n- `filters?: QueryFilters`: [Query Filters](../framework/react/guides/filters.md#query-filters)\n- `options?: RefetchOptions`:\n  - `throwOnError?: boolean`\n    - When set to `true`, this method will throw if any of the query refetch tasks fail.\n  - `cancelRefetch?: boolean`\n    - Defaults to `true`\n      - Per default, a currently running request will be cancelled before a new request is made\n    - When set to `false`, no refetch will be made if there is already a request running.\n\n**Returns**\n\nThis function returns a promise that will resolve when all of the queries are done being refetched. By default, it **will not** throw an error if any of those queries refetches fail, but this can be configured by setting the `throwOnError` option to `true`\n\n**Notes**\n\n- Queries that are \"disabled\" because they only have disabled Observers will never be refetched.\n- Queries that are \"static\" because they only have Observers with a Static StaleTime will never be refetched.\n\n## `queryClient.cancelQueries`\n\nThe `cancelQueries` method can be used to cancel outgoing queries based on their query keys or any other functionally accessible property/state of the query.\n\nThis is most useful when performing optimistic updates since you will likely need to cancel any outgoing query refetches so they don't clobber your optimistic update when they resolve.\n\n```tsx\nawait queryClient.cancelQueries(\n  { queryKey: ['posts'], exact: true },\n  { silent: true },\n)\n```\n\n**Options**\n\n- `filters?: QueryFilters`: [Query Filters](../framework/react/guides/filters.md#query-filters)\n- `cancelOptions?: CancelOptions`: [Cancel Options](../framework/react/guides/query-cancellation.md#cancel-options)\n\n**Returns**\n\nThis method does not return anything\n\n## `queryClient.removeQueries`\n\nThe `removeQueries` method can be used to remove queries from the cache based on their query keys or any other functionally accessible property/state of the query.\n\n```tsx\nqueryClient.removeQueries({ queryKey, exact: true })\n```\n\n**Options**\n\n- `filters?: QueryFilters`: [Query Filters](../framework/react/guides/filters.md#query-filters)\n\n**Returns**\n\nThis method does not return anything\n\n## `queryClient.resetQueries`\n\nThe `resetQueries` method can be used to reset queries in the cache to their\ninitial state based on their query keys or any other functionally accessible\nproperty/state of the query.\n\nThis will notify subscribers &mdash; unlike `clear`, which removes all\nsubscribers &mdash; and reset the query to its pre-loaded state &mdash; unlike\n`invalidateQueries`. If a query has `initialData`, the query's data will be\nreset to that. If a query is active, it will be refetched.\n\n```tsx\nqueryClient.resetQueries({ queryKey, exact: true })\n```\n\n**Options**\n\n- `filters?: QueryFilters`: [Query Filters](../framework/react/guides/filters.md#query-filters)\n- `options?: ResetOptions`:\n  - `throwOnError?: boolean`\n    - When set to `true`, this method will throw if any of the query refetch tasks fail.\n  - `cancelRefetch?: boolean`\n    - Defaults to `true`\n      - Per default, a currently running request will be cancelled before a new request is made\n    - When set to `false`, no refetch will be made if there is already a request running.\n\n**Returns**\n\nThis method returns a promise that resolves when all active queries have been refetched.\n\n## `queryClient.isFetching`\n\nThis `isFetching` method returns an `integer` representing how many queries, if any, in the cache are currently fetching (including background-fetching, loading new pages, or loading more infinite query results)\n\n```tsx\nif (queryClient.isFetching()) {\n  console.log('At least one query is fetching!')\n}\n```\n\nTanStack Query also exports a handy [`useIsFetching`](../framework/react/reference/useIsFetching.md) hook that will let you subscribe to this state in your components without creating a manual subscription to the query cache.\n\n**Options**\n\n- `filters?: QueryFilters`: [Query Filters](../framework/react/guides/filters.md#query-filters)\n\n**Returns**\n\nThis method returns the number of fetching queries.\n\n## `queryClient.isMutating`\n\nThis `isMutating` method returns an `integer` representing how many mutations, if any, in the cache are currently fetching.\n\n```tsx\nif (queryClient.isMutating()) {\n  console.log('At least one mutation is fetching!')\n}\n```\n\nTanStack Query also exports a handy [`useIsMutating`](../framework/react/reference/useIsMutating.md) hook that will let you subscribe to this state in your components without creating a manual subscription to the mutation cache.\n\n**Options**\n\n- `filters: MutationFilters`: [Mutation Filters](../framework/react/guides/filters.md#mutation-filters)\n\n**Returns**\n\nThis method returns the number of fetching mutations.\n\n## `queryClient.getDefaultOptions`\n\nThe `getDefaultOptions` method returns the default options which have been set when creating the client or with `setDefaultOptions`.\n\n```tsx\nconst defaultOptions = queryClient.getDefaultOptions()\n```\n\n## `queryClient.setDefaultOptions`\n\nThe `setDefaultOptions` method can be used to dynamically set the default options for this queryClient. Previously defined default options will be overwritten.\n\n```tsx\nqueryClient.setDefaultOptions({\n  queries: {\n    staleTime: Infinity,\n  },\n})\n```\n\n## `queryClient.getQueryDefaults`\n\nThe `getQueryDefaults` method returns the default options which have been set for specific queries:\n\n```tsx\nconst defaultOptions = queryClient.getQueryDefaults(['posts'])\n```\n\n> Note that if several query defaults match the given query key, they will be merged together based on the order of registration.\n> See [`setQueryDefaults`](#queryclientsetquerydefaults).\n\n## `queryClient.setQueryDefaults`\n\n`setQueryDefaults` can be used to set default options for specific queries:\n\n```tsx\nqueryClient.setQueryDefaults(['posts'], { queryFn: fetchPosts })\n\nfunction Component() {\n  const { data } = useQuery({ queryKey: ['posts'] })\n}\n```\n\n**Options**\n\n- `queryKey: QueryKey`: [Query Keys](../framework/react/guides/query-keys.md)\n- `options: QueryOptions`\n\n> As stated in [`getQueryDefaults`](#queryclientgetquerydefaults), the order of registration of query defaults does matter.\n> Since the matching defaults are merged by `getQueryDefaults`, the registration should be made in the following order: from the **most generic key** to the **least generic one** .\n> This way, more specific defaults will override more generic defaults.\n\n## `queryClient.getMutationDefaults`\n\nThe `getMutationDefaults` method returns the default options which have been set for specific mutations:\n\n```tsx\nconst defaultOptions = queryClient.getMutationDefaults(['addPost'])\n```\n\n## `queryClient.setMutationDefaults`\n\n`setMutationDefaults` can be used to set default options for specific mutations:\n\n```tsx\nqueryClient.setMutationDefaults(['addPost'], { mutationFn: addPost })\n\nfunction Component() {\n  const { data } = useMutation({ mutationKey: ['addPost'] })\n}\n```\n\n**Options**\n\n- `mutationKey: unknown[]`\n- `options: MutationOptions`\n\n> Similar to [`setQueryDefaults`](#queryclientsetquerydefaults), the order of registration does matter here.\n\n## `queryClient.getQueryCache`\n\nThe `getQueryCache` method returns the query cache this client is connected to.\n\n```tsx\nconst queryCache = queryClient.getQueryCache()\n```\n\n## `queryClient.getMutationCache`\n\nThe `getMutationCache` method returns the mutation cache this client is connected to.\n\n```tsx\nconst mutationCache = queryClient.getMutationCache()\n```\n\n## `queryClient.clear`\n\nThe `clear` method clears all connected caches.\n\n```tsx\nqueryClient.clear()\n```\n\n## `queryClient.resumePausedMutations`\n\nCan be used to resume mutations that have been paused because there was no network connection.\n\n```tsx\nqueryClient.resumePausedMutations()\n```\n"
  },
  {
    "path": "docs/reference/QueryObserver.md",
    "content": "---\nid: QueryObserver\ntitle: QueryObserver\n---\n\nThe `QueryObserver` can be used to observe and switch between queries.\n\n```tsx\nconst observer = new QueryObserver(queryClient, { queryKey: ['posts'] })\n\nconst unsubscribe = observer.subscribe((result) => {\n  console.log(result)\n  unsubscribe()\n})\n```\n\n**Options**\n\nThe options for the `QueryObserver` are exactly the same as those of [`useQuery`](../framework/react/reference/useQuery).\n"
  },
  {
    "path": "docs/reference/environmentManager.md",
    "content": "---\nid: EnvironmentManager\ntitle: environmentManager\n---\n\nThe `environmentManager` manages how TanStack Query detects whether the current runtime should be treated as server-side.\n\nBy default, it uses the same server detection as the exported `isServer` utility from query-core.\n\nUse this manager to override server detection globally for runtimes that are not traditional browser/server environments (for example, extension workers).\n\nIts available methods are:\n\n- [`isServer`](#environmentmanagerisserver)\n- [`setIsServer`](#environmentmanagersetisserver)\n\n## `environmentManager.isServer`\n\nReturns whether the current runtime is treated as a server environment.\n\n```tsx\nimport { environmentManager } from '@tanstack/react-query'\n\nconst server = environmentManager.isServer()\n```\n\n## `environmentManager.setIsServer`\n\nOverrides the server check globally.\n\n```tsx\nimport { environmentManager } from '@tanstack/react-query'\n\n// Override\nenvironmentManager.setIsServer(() => {\n  return typeof window === 'undefined' && !('chrome' in globalThis)\n})\n```\n\n**Options**\n\n- `isServerValue: () => boolean`\n\nTo restore the default behavior, set the function back to query-core's `isServer` utility:\n\n```tsx\nimport { environmentManager, isServer } from '@tanstack/react-query'\n\nenvironmentManager.setIsServer(() => isServer)\n```\n"
  },
  {
    "path": "docs/reference/focusManager.md",
    "content": "---\nid: FocusManager\ntitle: FocusManager\n---\n\nThe `FocusManager` manages the focus state within TanStack Query.\n\nIt can be used to change the default event listeners or to manually change the focus state.\n\nIts available methods are:\n\n- [`setEventListener`](#focusmanagerseteventlistener)\n- [`subscribe`](#focusmanagersubscribe)\n- [`setFocused`](#focusmanagersetfocused)\n- [`isFocused`](#focusmanagerisfocused)\n\n## `focusManager.setEventListener`\n\n`setEventListener` can be used to set a custom event listener:\n\n```tsx\nimport { focusManager } from '@tanstack/react-query'\n\nfocusManager.setEventListener((handleFocus) => {\n  // Listen to visibilitychange\n  if (typeof window !== 'undefined' && window.addEventListener) {\n    window.addEventListener('visibilitychange', handleFocus, false)\n  }\n\n  return () => {\n    // Be sure to unsubscribe if a new handler is set\n    window.removeEventListener('visibilitychange', handleFocus)\n  }\n})\n```\n\n## `focusManager.subscribe`\n\n`subscribe` can be used to subscribe to changes in the visibility state. It returns an unsubscribe function:\n\n```tsx\nimport { focusManager } from '@tanstack/react-query'\n\nconst unsubscribe = focusManager.subscribe((isVisible) => {\n  console.log('isVisible', isVisible)\n})\n```\n\n## `focusManager.setFocused`\n\n`setFocused` can be used to manually set the focus state. Set `undefined` to fall back to the default focus check.\n\n```tsx\nimport { focusManager } from '@tanstack/react-query'\n\n// Set focused\nfocusManager.setFocused(true)\n\n// Set unfocused\nfocusManager.setFocused(false)\n\n// Fallback to the default focus check\nfocusManager.setFocused(undefined)\n```\n\n**Options**\n\n- `focused: boolean | undefined`\n\n## `focusManager.isFocused`\n\n`isFocused` can be used to get the current focus state.\n\n```tsx\nconst isFocused = focusManager.isFocused()\n```\n"
  },
  {
    "path": "docs/reference/notifyManager.md",
    "content": "---\nid: NotifyManager\ntitle: NotifyManager\n---\n\nThe `notifyManager` handles scheduling and batching callbacks in TanStack Query.\n\nIt exposes the following methods:\n\n- [batch](#notifymanagerbatch)\n- [batchCalls](#notifymanagerbatchcalls)\n- [schedule](#notifymanagerschedule)\n- [setNotifyFunction](#notifymanagersetnotifyfunction)\n- [setBatchNotifyFunction](#notifymanagersetbatchnotifyfunction)\n- [setScheduler](#notifymanagersetscheduler)\n\n## `notifyManager.batch`\n\n`batch` can be used to batch all updates scheduled inside the passed callback.\nThis is mainly used internally to optimize queryClient updating.\n\n```ts\nfunction batch<T>(callback: () => T): T\n```\n\n## `notifyManager.batchCalls`\n\n`batchCalls` is a higher-order function that takes a callback and wraps it.\nAll calls to the wrapped function schedule the callback to be run on the next batch.\n\n```ts\ntype BatchCallsCallback<T extends Array<unknown>> = (...args: T) => void\n\nfunction batchCalls<T extends Array<unknown>>(\n  callback: BatchCallsCallback<T>,\n): BatchCallsCallback<T>\n```\n\n## `notifyManager.schedule`\n\n`schedule` schedules a function to be run on the next batch. By default, the batch is run\nwith a setTimeout, but this can be configured.\n\n```ts\nfunction schedule(callback: () => void): void\n```\n\n## `notifyManager.setNotifyFunction`\n\n`setNotifyFunction` overrides the notify function. This function is passed the\ncallback when it should be executed. The default notifyFunction just calls it.\n\nThis can be used to for example wrap notifications with `React.act` while running tests:\n\n```ts\nimport { notifyManager } from '@tanstack/react-query'\nimport { act } from 'react-dom/test-utils'\n\nnotifyManager.setNotifyFunction(act)\n```\n\n## `notifyManager.setBatchNotifyFunction`\n\n`setBatchNotifyFunction` sets the function to use for batched updates\n\nIf your framework supports a custom batching function, you can let TanStack Query know about it by calling notifyManager.setBatchNotifyFunction.\n\nFor example, this is how the batch function is set in solid-query:\n\n```ts\nimport { notifyManager } from '@tanstack/query-core'\nimport { batch } from 'solid-js'\n\nnotifyManager.setBatchNotifyFunction(batch)\n```\n\n## `notifyManager.setScheduler`\n\n`setScheduler` configures a custom callback that should schedules when the next\nbatch runs. The default behaviour is `setTimeout(callback, 0)`.\n\n```ts\nimport { notifyManager } from '@tanstack/react-query'\n\n// Schedule batches in the next microtask\nnotifyManager.setScheduler(queueMicrotask)\n\n// Schedule batches before the next frame is rendered\nnotifyManager.setScheduler(requestAnimationFrame)\n\n// Schedule batches some time in the future\nnotifyManager.setScheduler((cb) => setTimeout(cb, 10))\n```\n"
  },
  {
    "path": "docs/reference/onlineManager.md",
    "content": "---\nid: OnlineManager\ntitle: OnlineManager\n---\n\nThe `OnlineManager` manages the online state within TanStack Query. It can be used to change the default event listeners or to manually change the online state.\n\n> Per default, the `onlineManager` assumes an active network connection, and listens to the `online` and `offline` events on the `window` object to detect changes.\n\n> In previous versions, `navigator.onLine` was used to determine the network status. However, it doesn't work well in Chromium based browsers. There are [a lot of issues](https://bugs.chromium.org/p/chromium/issues/list?q=navigator.online) around false negatives, which lead to Queries being wrongfully marked as `offline`.\n\n> To circumvent this, we now always start with `online: true` and only listen to `online` and `offline` events to update the status.\n\n> This should reduce the likelihood of false negatives, however, it might mean false positives for offline apps that load via serviceWorkers, which can work even without an internet connection.\n\nIts available methods are:\n\n- [`setEventListener`](#onlinemanagerseteventlistener)\n- [`subscribe`](#onlinemanagersubscribe)\n- [`setOnline`](#onlinemanagersetonline)\n- [`isOnline`](#onlinemanagerisonline)\n\n## `onlineManager.setEventListener`\n\n`setEventListener` can be used to set a custom event listener:\n\n```tsx\nimport NetInfo from '@react-native-community/netinfo'\nimport { onlineManager } from '@tanstack/react-query'\n\nonlineManager.setEventListener((setOnline) => {\n  return NetInfo.addEventListener((state) => {\n    setOnline(!!state.isConnected)\n  })\n})\n```\n\n## `onlineManager.subscribe`\n\n`subscribe` can be used to subscribe to changes in the online state. It returns an unsubscribe function:\n\n```tsx\nimport { onlineManager } from '@tanstack/react-query'\n\nconst unsubscribe = onlineManager.subscribe((isOnline) => {\n  console.log('isOnline', isOnline)\n})\n```\n\n## `onlineManager.setOnline`\n\n`setOnline` can be used to manually set the online state.\n\n```tsx\nimport { onlineManager } from '@tanstack/react-query'\n\n// Set to online\nonlineManager.setOnline(true)\n\n// Set to offline\nonlineManager.setOnline(false)\n```\n\n**Options**\n\n- `online: boolean`\n\n## `onlineManager.isOnline`\n\n`isOnline` can be used to get the current online state.\n\n```tsx\nconst isOnline = onlineManager.isOnline()\n```\n"
  },
  {
    "path": "docs/reference/streamedQuery.md",
    "content": "---\nid: streamedQuery\ntitle: streamedQuery\n---\n\n`streamedQuery` is a helper function to create a query function that streams data from an [AsyncIterable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncIterator). Data will be an Array of all the chunks received. The query will be in a `pending` state until the first chunk of data is received, but will go to `success` after that. The query will stay in fetchStatus `fetching` until the stream ends.\n\nTo see `streamedQuery` in action, take a look at our chat example in the [examples/react/chat directory on GitHub](https://github.com/TanStack/query/tree/main/examples/react/chat).\n\n```tsx\nimport { experimental_streamedQuery as streamedQuery } from '@tanstack/react-query'\n\nconst query = queryOptions({\n  queryKey: ['data'],\n  queryFn: streamedQuery({\n    streamFn: fetchDataInChunks,\n  }),\n})\n```\n\n> Note: `streamedQuery` is currently marked as `experimental` because we want to gather feedback from the community. If you've tried out the API and have feedback for us, please provide it in this [GitHub discussion](https://github.com/TanStack/query/discussions/9065).\n\n**Options**\n\n- `streamFn: (context: QueryFunctionContext) => Promise<AsyncIterable<TData>>`\n  - **Required**\n  - The function that returns a Promise of an AsyncIterable with data to stream in.\n  - Receives a [QueryFunctionContext](../framework/react/guides/query-functions.md#queryfunctioncontext)\n- `refetchMode?: 'append' | 'reset' | 'replace'`\n  - Optional\n  - Defines how refetches are handled.\n  - Defaults to `'reset'`\n  - When set to `'reset'`, the query will erase all data and go back into `pending` state.\n  - When set to `'append'`, data will be appended to existing data.\n  - When set to `'replace'`, all data will be written to the cache once the stream ends.\n- `reducer?: (accumulator: TData, chunk: TQueryFnData) => TData`\n  - Optional\n  - Reduces streamed chunks (`TQueryFnData`) into the final data shape (`TData`).\n  - Default: appends each chunk to the end of the accumulator when `TData` is an array.\n  - If `TData` is not an array, you must provide a custom `reducer`.\n- `initialValue?: TData = TQueryFnData`\n  - Optional\n  - Defines the initial data to be used while the first chunk is being fetched, and it is also returned when the stream yields no values.\n  - It is mandatory when custom `reducer` is provided.\n  - Defaults to an empty array.\n"
  },
  {
    "path": "docs/reference/timeoutManager.md",
    "content": "---\nid: TimeoutManager\ntitle: TimeoutManager\n---\n\nThe `TimeoutManager` handles `setTimeout` and `setInterval` timers in TanStack Query.\n\nTanStack Query uses timers to implement features like query `staleTime` and `gcTime`, as well as retries, throttling, and debouncing.\n\nBy default, TimeoutManager uses the global `setTimeout` and `setInterval`, but it can be configured to use custom implementations instead.\n\nIts available methods are:\n\n- [`timeoutManager.setTimeoutProvider`](#timeoutmanagersettimeoutprovider)\n  - [`TimeoutProvider`](#timeoutprovider)\n- [`timeoutManager.setTimeout`](#timeoutmanagersettimeout)\n- [`timeoutManager.clearTimeout`](#timeoutmanagercleartimeout)\n- [`timeoutManager.setInterval`](#timeoutmanagersetinterval)\n- [`timeoutManager.clearInterval`](#timeoutmanagerclearinterval)\n\n## `timeoutManager.setTimeoutProvider`\n\n`setTimeoutProvider` can be used to set a custom implementation of the `setTimeout`, `clearTimeout`, `setInterval`, `clearInterval` functions, called a `TimeoutProvider`.\n\nThis may be useful if you notice event loop performance issues with thousands of queries. A custom TimeoutProvider could also support timer delays longer than the global `setTimeout` maximum delay value of about [24 days](https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout#maximum_delay_value).\n\nIt is important to call `setTimeoutProvider` before creating a QueryClient or queries, so that the same provider is used consistently for all timers in the application, since different TimeoutProviders cannot cancel each others' timers.\n\n```tsx\nimport { timeoutManager, QueryClient } from '@tanstack/react-query'\nimport { CustomTimeoutProvider } from './CustomTimeoutProvider'\n\ntimeoutManager.setTimeoutProvider(new CustomTimeoutProvider())\n\nexport const queryClient = new QueryClient()\n```\n\n### `TimeoutProvider`\n\nTimers are very performance sensitive. Short term timers (such as those with delays less than 5 seconds) tend to be latency sensitive, where long-term timers may benefit more from [timer coalescing](https://en.wikipedia.org/wiki/Timer_coalescing) - batching timers with similar deadlines together - using a data structure like a [hierarchical time wheel](https://www.npmjs.com/package/timer-wheel).\n\nThe `TimeoutProvider` type requires that implementations handle timer ID objects that can be converted to `number` via [Symbol.toPrimitive][toPrimitive] because runtimes like NodeJS return [objects][nodejs-timeout] from their global `setTimeout` and `setInterval` functions. TimeoutProvider implementations are free to coerce timer IDs to number internally, or to return their own custom object type that implements `{ [Symbol.toPrimitive]: () => number }`.\n\n[nodejs-timeout]: https://nodejs.org/api/timers.html#class-timeout\n[toPrimitive]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toPrimitive\n\n```tsx\ntype ManagedTimerId = number | { [Symbol.toPrimitive]: () => number }\n\ntype TimeoutProvider<TTimerId extends ManagedTimerId = ManagedTimerId> = {\n  readonly setTimeout: (callback: TimeoutCallback, delay: number) => TTimerId\n  readonly clearTimeout: (timeoutId: TTimerId | undefined) => void\n\n  readonly setInterval: (callback: TimeoutCallback, delay: number) => TTimerId\n  readonly clearInterval: (intervalId: TTimerId | undefined) => void\n}\n```\n\n## `timeoutManager.setTimeout`\n\n`setTimeout(callback, delayMs)` schedules a callback to run after approximately `delay` milliseconds, like the global [setTimeout function](https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout).The callback can be canceled with `timeoutManager.clearTimeout`.\n\nIt returns a timer ID, which may be a number or an object that can be coerced to a number via [Symbol.toPrimitive][toPrimitive].\n\n```tsx\nimport { timeoutManager } from '@tanstack/react-query'\n\nconst timeoutId = timeoutManager.setTimeout(\n  () => console.log('ran at:', new Date()),\n  1000,\n)\n\nconst timeoutIdNumber: number = Number(timeoutId)\n```\n\n## `timeoutManager.clearTimeout`\n\n`clearTimeout(timerId)` cancels a timeout callback scheduled with `setTimeout`, like the global [clearTimeout function](https://developer.mozilla.org/en-US/docs/Web/API/Window/clearTimeout). It should be called with a timer ID returned by `timeoutManager.setTimeout`.\n\n```tsx\nimport { timeoutManager } from '@tanstack/react-query'\n\nconst timeoutId = timeoutManager.setTimeout(\n  () => console.log('ran at:', new Date()),\n  1000,\n)\n\ntimeoutManager.clearTimeout(timeoutId)\n```\n\n## `timeoutManager.setInterval`\n\n`setInterval(callback, intervalMs)` schedules a callback to be called approximately every `intervalMs`, like the global [setInterval function](https://developer.mozilla.org/en-US/docs/Web/API/Window/setInterval).\n\nLike `setTimeout`, it returns a timer ID, which may be a number or an object that can be coerced to a number via [Symbol.toPrimitive](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toPrimitive).\n\n```tsx\nimport { timeoutManager } from '@tanstack/react-query'\n\nconst intervalId = timeoutManager.setInterval(\n  () => console.log('ran at:', new Date()),\n  1000,\n)\n```\n\n## `timeoutManager.clearInterval`\n\n`clearInterval(intervalId)` can be used to cancel an interval, like the global [clearInterval function](https://developer.mozilla.org/en-US/docs/Web/API/Window/clearInterval). It should be called with an interval ID returned by `timeoutManager.setInterval`.\n\n```tsx\nimport { timeoutManager } from '@tanstack/react-query'\n\nconst intervalId = timeoutManager.setInterval(\n  () => console.log('ran at:', new Date()),\n  1000,\n)\n\ntimeoutManager.clearInterval(intervalId)\n```\n"
  },
  {
    "path": "eslint.config.js",
    "content": "// @ts-check\n\n// @ts-ignore Needed due to moduleResolution Node vs Bundler\nimport { tanstackConfig } from '@tanstack/eslint-config'\nimport pluginCspell from '@cspell/eslint-plugin'\nimport vitest from '@vitest/eslint-plugin'\n\nexport default [\n  ...tanstackConfig,\n  {\n    name: 'tanstack/temp',\n    plugins: {\n      cspell: pluginCspell,\n    },\n    rules: {\n      'cspell/spellchecker': [\n        'warn',\n        {\n          cspell: {\n            words: [\n              'Promisable', // Our public interface\n              'TSES', // @typescript-eslint package's interface\n              'codemod', // We support our codemod\n              'combinate', // Library name\n              'datatag', // Query options tagging\n              'extralight', // Our public interface\n              'jscodeshift',\n              'refetches', // Query refetch operations\n              'retryer', // Our public interface\n              'solidjs', // Our target framework\n              'tabular-nums', // https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-numeric\n              'tanstack', // Our package scope\n              'todos', // Too general word to be caught as error\n              'tsqd', // Our public interface (TanStack Query Devtools shorthand)\n              'tsup', // We use tsup as builder\n              'typecheck', // Field of vite.config.ts\n              'vue-demi', // dependency of @tanstack/vue-query\n              'ɵkind', // Angular specific\n              'ɵproviders', // Angular specific\n            ],\n          },\n        },\n      ],\n      '@typescript-eslint/no-empty-function': 'off',\n      '@typescript-eslint/no-unsafe-function-type': 'off',\n      'no-case-declarations': 'off',\n      'prefer-const': 'off',\n    },\n  },\n  {\n    files: ['**/*.spec.ts*', '**/*.test.ts*', '**/*.test-d.ts*'],\n    plugins: { vitest },\n    rules: {\n      ...vitest.configs.recommended.rules,\n      'vitest/no-standalone-expect': [\n        'error',\n        {\n          additionalTestBlockFunctions: ['testIf'],\n        },\n      ],\n    },\n    settings: { vitest: { typecheck: true } },\n  },\n]\n"
  },
  {
    "path": "examples/angular/auto-refetching/.devcontainer/devcontainer.json",
    "content": "{\n  \"name\": \"Node.js\",\n  \"image\": \"mcr.microsoft.com/devcontainers/javascript-node:22\"\n}\n"
  },
  {
    "path": "examples/angular/auto-refetching/.eslintrc.cjs",
    "content": "// @ts-check\n\n/** @type {import('eslint').Linter.Config} */\nconst config = {}\n\nmodule.exports = config\n"
  },
  {
    "path": "examples/angular/auto-refetching/README.md",
    "content": "# TanStack Query Angular auto-refetching example\n\nTo run this example:\n\n- `npm install` or `yarn` or `pnpm i` or `bun i`\n- `npm run start` or `yarn start` or `pnpm start` or `bun start`\n"
  },
  {
    "path": "examples/angular/auto-refetching/angular.json",
    "content": "{\n  \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n  \"version\": 1,\n  \"cli\": {\n    \"packageManager\": \"pnpm\",\n    \"analytics\": false,\n    \"cache\": {\n      \"enabled\": false\n    }\n  },\n  \"newProjectRoot\": \"projects\",\n  \"projects\": {\n    \"auto-refetching\": {\n      \"projectType\": \"application\",\n      \"schematics\": {\n        \"@schematics/angular:component\": {\n          \"inlineTemplate\": true,\n          \"inlineStyle\": true,\n          \"skipTests\": true\n        },\n        \"@schematics/angular:class\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:directive\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:guard\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:interceptor\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:pipe\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:resolver\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:service\": {\n          \"skipTests\": true\n        }\n      },\n      \"root\": \"\",\n      \"sourceRoot\": \"src\",\n      \"prefix\": \"app\",\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular/build:application\",\n          \"options\": {\n            \"outputPath\": \"dist/auto-refetching\",\n            \"index\": \"src/index.html\",\n            \"browser\": \"src/main.ts\",\n            \"polyfills\": [\"zone.js\"],\n            \"tsConfig\": \"tsconfig.app.json\",\n            \"assets\": [\"src/favicon.ico\", \"src/assets\"],\n            \"styles\": [],\n            \"scripts\": []\n          },\n          \"configurations\": {\n            \"production\": {\n              \"budgets\": [\n                {\n                  \"type\": \"initial\",\n                  \"maximumWarning\": \"500kb\",\n                  \"maximumError\": \"1mb\"\n                },\n                {\n                  \"type\": \"anyComponentStyle\",\n                  \"maximumWarning\": \"2kb\",\n                  \"maximumError\": \"4kb\"\n                }\n              ],\n              \"outputHashing\": \"all\"\n            },\n            \"development\": {\n              \"optimization\": false,\n              \"extractLicenses\": false,\n              \"sourceMap\": true\n            }\n          },\n          \"defaultConfiguration\": \"production\"\n        },\n        \"serve\": {\n          \"builder\": \"@angular/build:dev-server\",\n          \"configurations\": {\n            \"production\": {\n              \"buildTarget\": \"auto-refetching:build:production\"\n            },\n            \"development\": {\n              \"buildTarget\": \"auto-refetching:build:development\"\n            }\n          },\n          \"defaultConfiguration\": \"development\"\n        },\n        \"extract-i18n\": {\n          \"builder\": \"@angular/build:extract-i18n\",\n          \"options\": {\n            \"buildTarget\": \"auto-refetching:build\"\n          }\n        }\n      }\n    }\n  },\n  \"schematics\": {\n    \"@schematics/angular:component\": {\n      \"type\": \"component\"\n    },\n    \"@schematics/angular:directive\": {\n      \"type\": \"directive\"\n    },\n    \"@schematics/angular:service\": {\n      \"type\": \"service\"\n    },\n    \"@schematics/angular:guard\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:interceptor\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:module\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:pipe\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:resolver\": {\n      \"typeSeparator\": \".\"\n    }\n  }\n}\n"
  },
  {
    "path": "examples/angular/auto-refetching/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-angular-auto-refetching\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"ng\": \"ng\",\n    \"start\": \"ng serve\",\n    \"build\": \"ng build\",\n    \"watch\": \"ng build --watch --configuration development\"\n  },\n  \"private\": true,\n  \"dependencies\": {\n    \"@angular/common\": \"^20.0.0\",\n    \"@angular/compiler\": \"^20.0.0\",\n    \"@angular/core\": \"^20.0.0\",\n    \"@angular/platform-browser\": \"^20.0.0\",\n    \"@tanstack/angular-query-experimental\": \"^5.90.28\",\n    \"rxjs\": \"^7.8.2\",\n    \"tslib\": \"^2.8.1\",\n    \"zone.js\": \"0.15.0\"\n  },\n  \"devDependencies\": {\n    \"@angular/build\": \"^20.0.0\",\n    \"@angular/cli\": \"^20.0.0\",\n    \"@angular/compiler-cli\": \"^20.0.0\",\n    \"typescript\": \"5.8.3\"\n  }\n}\n"
  },
  {
    "path": "examples/angular/auto-refetching/src/app/app.component.ts",
    "content": "import { ChangeDetectionStrategy, Component } from '@angular/core'\nimport { AutoRefetchingExampleComponent } from './components/auto-refetching.component'\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  selector: 'app-root',\n  template: `<auto-refetching-example />`,\n  imports: [AutoRefetchingExampleComponent],\n})\nexport class AppComponent {}\n"
  },
  {
    "path": "examples/angular/auto-refetching/src/app/app.config.ts",
    "content": "import {\n  provideHttpClient,\n  withFetch,\n  withInterceptors,\n} from '@angular/common/http'\nimport {\n  QueryClient,\n  provideTanStackQuery,\n} from '@tanstack/angular-query-experimental'\nimport { withDevtools } from '@tanstack/angular-query-experimental/devtools'\nimport { mockInterceptor } from './interceptor/mock-api.interceptor'\nimport type { ApplicationConfig } from '@angular/core'\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideHttpClient(withFetch(), withInterceptors([mockInterceptor])),\n    provideTanStackQuery(\n      new QueryClient({\n        defaultOptions: {\n          queries: {\n            gcTime: 1000 * 60 * 60 * 24, // 24 hours\n          },\n        },\n      }),\n      withDevtools(),\n    ),\n  ],\n}\n"
  },
  {
    "path": "examples/angular/auto-refetching/src/app/components/auto-refetching.component.html",
    "content": "<div>\n  <h1>Auto Refetch with stale-time set to {{ intervalMs() }}ms</h1>\n  <p>\n    This example is best experienced on your own machine, where you can open\n    multiple tabs to the same localhost server and see your changes propagate\n    between the two.\n  </p>\n  <label>\n    Query Interval speed (ms):\n    <input [value]=\"intervalMs()\" (input)=\"inputChange($event)\" />\n    <span\n      [ngStyle]=\"{\n        display: 'inline-block',\n        marginLeft: '.5rem',\n        width: '10px',\n        height: '10px',\n        background: tasks.isFetching() ? 'green' : 'transparent',\n        transition: !tasks.isFetching() ? 'all .3s ease' : 'none',\n        borderRadius: '100%',\n        transform: 'scale(2)',\n      }\"\n    ></span>\n  </label>\n  <h2>Todo List</h2>\n\n  <input placeholder=\"Enter something\" (keydown.enter)=\"addItem($event)\" />\n  <ul>\n    @for (item of tasks.data(); track item) {\n      <li>{{ item }}</li>\n    }\n  </ul>\n  <div>\n    <button (click)=\"clearTasks()\">Clear All</button>\n  </div>\n</div>\n"
  },
  {
    "path": "examples/angular/auto-refetching/src/app/components/auto-refetching.component.ts",
    "content": "import {\n  ChangeDetectionStrategy,\n  Component,\n  inject,\n  signal,\n} from '@angular/core'\nimport {\n  injectMutation,\n  injectQuery,\n} from '@tanstack/angular-query-experimental'\nimport { NgStyle } from '@angular/common'\nimport { TasksService } from '../services/tasks.service'\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  selector: 'auto-refetching-example',\n  templateUrl: './auto-refetching.component.html',\n  imports: [NgStyle],\n})\nexport class AutoRefetchingExampleComponent {\n  readonly #tasksService = inject(TasksService)\n\n  readonly intervalMs = signal(1000)\n\n  readonly tasks = injectQuery(() =>\n    this.#tasksService.allTasks(this.intervalMs()),\n  )\n\n  readonly addMutation = injectMutation(() => this.#tasksService.addTask())\n  readonly clearMutation = injectMutation(() =>\n    this.#tasksService.clearAllTasks(),\n  )\n\n  clearTasks() {\n    this.clearMutation.mutate()\n  }\n\n  inputChange($event: Event) {\n    const target = $event.target as HTMLInputElement\n    this.intervalMs.set(Number(target.value))\n  }\n\n  addItem($event: Event) {\n    const target = $event.target as HTMLInputElement\n    const value = target.value\n    this.addMutation.mutate(value)\n    target.value = ''\n  }\n}\n"
  },
  {
    "path": "examples/angular/auto-refetching/src/app/interceptor/mock-api.interceptor.ts",
    "content": "/**\n * MockApiInterceptor is used to simulate API responses for `/api/tasks` endpoints.\n * It handles the following operations:\n * - GET: Fetches all tasks from localStorage.\n * - POST: Adds a new task to localStorage.\n * - DELETE: Clears all tasks from localStorage.\n * Simulated responses include a delay to mimic network latency.\n */\nimport { HttpResponse } from '@angular/common/http'\nimport { delay, of } from 'rxjs'\nimport type {\n  HttpEvent,\n  HttpHandlerFn,\n  HttpInterceptorFn,\n  HttpRequest,\n} from '@angular/common/http'\nimport type { Observable } from 'rxjs'\n\nexport const mockInterceptor: HttpInterceptorFn = (\n  req: HttpRequest<unknown>,\n  next: HttpHandlerFn,\n): Observable<HttpEvent<any>> => {\n  const respondWith = (status: number, body: any) =>\n    of(new HttpResponse({ status, body })).pipe(delay(100))\n  if (req.url === '/api/tasks') {\n    switch (req.method) {\n      case 'GET':\n        return respondWith(\n          200,\n          JSON.parse(localStorage.getItem('tasks') || '[]'),\n        )\n      case 'POST':\n        const tasks = JSON.parse(localStorage.getItem('tasks') || '[]')\n        tasks.push(req.body)\n        localStorage.setItem('tasks', JSON.stringify(tasks))\n        return respondWith(201, {\n          status: 'success',\n          task: req.body,\n        })\n      case 'DELETE':\n        localStorage.removeItem('tasks')\n        return respondWith(200, { status: 'success' })\n    }\n  }\n  return next(req)\n}\n"
  },
  {
    "path": "examples/angular/auto-refetching/src/app/services/tasks.service.ts",
    "content": "import { HttpClient } from '@angular/common/http'\nimport { Injectable, inject } from '@angular/core'\nimport {\n  QueryClient,\n  mutationOptions,\n  queryOptions,\n} from '@tanstack/angular-query-experimental'\n\nimport { lastValueFrom } from 'rxjs'\n\n@Injectable({\n  providedIn: 'root',\n})\nexport class TasksService {\n  readonly #queryClient = inject(QueryClient) // Manages query state and caching\n  readonly #http = inject(HttpClient) // Handles HTTP requests\n\n  /**\n   * Fetches all tasks from the API.\n   * Returns an observable containing an array of task strings.\n   */\n  allTasks = (intervalMs: number) =>\n    queryOptions({\n      queryKey: ['tasks'],\n      queryFn: () => {\n        return lastValueFrom(this.#http.get<Array<string>>('/api/tasks'))\n      },\n      refetchInterval: intervalMs,\n    })\n\n  /**\n   * Creates a mutation for adding a task.\n   * On success, invalidates and refetches the \"tasks\" query cache to update the task list.\n   */\n  addTask() {\n    return mutationOptions({\n      mutationFn: (task: string) =>\n        lastValueFrom(this.#http.post('/api/tasks', task)),\n      mutationKey: ['tasks'],\n      onSuccess: () => {\n        this.#queryClient.invalidateQueries({ queryKey: ['tasks'] })\n      },\n    })\n  }\n\n  /**\n   * Creates a mutation for clearing all tasks.\n   * On success, invalidates and refetches the \"tasks\" query cache to ensure consistency.\n   */\n  clearAllTasks() {\n    return mutationOptions({\n      mutationFn: () => lastValueFrom(this.#http.delete('/api/tasks')),\n      mutationKey: ['clearTasks'],\n      onSuccess: () => {\n        this.#queryClient.invalidateQueries({ queryKey: ['tasks'] })\n      },\n    })\n  }\n}\n"
  },
  {
    "path": "examples/angular/auto-refetching/src/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>TanStack Query Angular auto-refetching example</title>\n    <base href=\"/\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <link rel=\"icon\" type=\"image/x-icon\" href=\"favicon.ico\" />\n  </head>\n  <body>\n    <app-root></app-root>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/angular/auto-refetching/src/main.ts",
    "content": "import { bootstrapApplication } from '@angular/platform-browser'\nimport { appConfig } from './app/app.config'\nimport { AppComponent } from './app/app.component'\n\nbootstrapApplication(AppComponent, appConfig)\n  .then(() => {\n    // an simple endpoint for getting current list\n    localStorage.setItem(\n      'tasks',\n      JSON.stringify(['Item 1', 'Item 2', 'Item 3']),\n    )\n  })\n  .catch((err) => console.error(err))\n"
  },
  {
    "path": "examples/angular/auto-refetching/tsconfig.app.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./out-tsc/app\",\n    \"types\": []\n  },\n  \"files\": [\"src/main.ts\"],\n  \"include\": [\"src/**/*.d.ts\"]\n}\n"
  },
  {
    "path": "examples/angular/auto-refetching/tsconfig.json",
    "content": "{\n  \"compileOnSave\": false,\n  \"compilerOptions\": {\n    \"outDir\": \"./dist/out-tsc\",\n    \"forceConsistentCasingInFileNames\": true,\n    \"strict\": true,\n    \"noImplicitOverride\": true,\n    \"noPropertyAccessFromIndexSignature\": true,\n    \"noImplicitReturns\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"skipLibCheck\": true,\n    \"isolatedModules\": true,\n    \"esModuleInterop\": true,\n    \"sourceMap\": true,\n    \"declaration\": false,\n    \"experimentalDecorators\": true,\n    \"moduleResolution\": \"Bundler\",\n    \"importHelpers\": true,\n    \"target\": \"ES2022\",\n    \"module\": \"ES2022\",\n    \"useDefineForClassFields\": false,\n    \"lib\": [\"ES2022\", \"dom\"]\n  },\n  \"angularCompilerOptions\": {\n    \"enableI18nLegacyMessageIdFormat\": false,\n    \"strictInjectionParameters\": true,\n    \"strictInputAccessModifiers\": true,\n    \"strictStandalone\": true,\n    \"strictTemplates\": true\n  }\n}\n"
  },
  {
    "path": "examples/angular/basic/.devcontainer/devcontainer.json",
    "content": "{\n  \"name\": \"Node.js\",\n  \"image\": \"mcr.microsoft.com/devcontainers/javascript-node:22\"\n}\n"
  },
  {
    "path": "examples/angular/basic/.eslintrc.cjs",
    "content": "// @ts-check\n\n/** @type {import('eslint').Linter.Config} */\nconst config = {}\n\nmodule.exports = config\n"
  },
  {
    "path": "examples/angular/basic/README.md",
    "content": "# TanStack Query Angular basic example\n\nTo run this example:\n\n- `npm install` or `yarn` or `pnpm i` or `bun i`\n- `npm run start` or `yarn start` or `pnpm start` or `bun start`\n"
  },
  {
    "path": "examples/angular/basic/angular.json",
    "content": "{\n  \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n  \"version\": 1,\n  \"cli\": {\n    \"packageManager\": \"pnpm\",\n    \"analytics\": false,\n    \"cache\": {\n      \"enabled\": false\n    }\n  },\n  \"newProjectRoot\": \"projects\",\n  \"projects\": {\n    \"basic\": {\n      \"projectType\": \"application\",\n      \"schematics\": {\n        \"@schematics/angular:component\": {\n          \"inlineTemplate\": true,\n          \"inlineStyle\": true,\n          \"skipTests\": true\n        },\n        \"@schematics/angular:class\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:directive\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:guard\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:interceptor\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:pipe\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:resolver\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:service\": {\n          \"skipTests\": true\n        }\n      },\n      \"root\": \"\",\n      \"sourceRoot\": \"src\",\n      \"prefix\": \"app\",\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular/build:application\",\n          \"options\": {\n            \"outputPath\": \"dist/basic\",\n            \"index\": \"src/index.html\",\n            \"browser\": \"src/main.ts\",\n            \"polyfills\": [\"zone.js\"],\n            \"tsConfig\": \"tsconfig.app.json\",\n            \"assets\": [\"src/favicon.ico\", \"src/assets\"],\n            \"styles\": [],\n            \"scripts\": []\n          },\n          \"configurations\": {\n            \"production\": {\n              \"budgets\": [\n                {\n                  \"type\": \"initial\",\n                  \"maximumWarning\": \"500kb\",\n                  \"maximumError\": \"1mb\"\n                },\n                {\n                  \"type\": \"anyComponentStyle\",\n                  \"maximumWarning\": \"2kb\",\n                  \"maximumError\": \"4kb\"\n                }\n              ],\n              \"outputHashing\": \"all\"\n            },\n            \"development\": {\n              \"optimization\": false,\n              \"extractLicenses\": false,\n              \"sourceMap\": true\n            }\n          },\n          \"defaultConfiguration\": \"production\"\n        },\n        \"serve\": {\n          \"builder\": \"@angular/build:dev-server\",\n          \"configurations\": {\n            \"production\": {\n              \"buildTarget\": \"basic:build:production\"\n            },\n            \"development\": {\n              \"buildTarget\": \"basic:build:development\"\n            }\n          },\n          \"defaultConfiguration\": \"development\"\n        },\n        \"extract-i18n\": {\n          \"builder\": \"@angular/build:extract-i18n\",\n          \"options\": {\n            \"buildTarget\": \"basic:build\"\n          }\n        }\n      }\n    }\n  },\n  \"schematics\": {\n    \"@schematics/angular:component\": {\n      \"type\": \"component\"\n    },\n    \"@schematics/angular:directive\": {\n      \"type\": \"directive\"\n    },\n    \"@schematics/angular:service\": {\n      \"type\": \"service\"\n    },\n    \"@schematics/angular:guard\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:interceptor\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:module\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:pipe\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:resolver\": {\n      \"typeSeparator\": \".\"\n    }\n  }\n}\n"
  },
  {
    "path": "examples/angular/basic/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-angular-basic\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"ng\": \"ng\",\n    \"start\": \"ng serve\",\n    \"build\": \"ng build\",\n    \"watch\": \"ng build --watch --configuration development\"\n  },\n  \"private\": true,\n  \"dependencies\": {\n    \"@angular/common\": \"^20.0.0\",\n    \"@angular/compiler\": \"^20.0.0\",\n    \"@angular/core\": \"^20.0.0\",\n    \"@angular/platform-browser\": \"^20.0.0\",\n    \"@tanstack/angular-query-experimental\": \"^5.90.28\",\n    \"rxjs\": \"^7.8.2\",\n    \"tslib\": \"^2.8.1\",\n    \"zone.js\": \"0.15.0\"\n  },\n  \"devDependencies\": {\n    \"@angular/build\": \"^20.0.0\",\n    \"@angular/cli\": \"^20.0.0\",\n    \"@angular/compiler-cli\": \"^20.0.0\",\n    \"typescript\": \"5.8.3\"\n  }\n}\n"
  },
  {
    "path": "examples/angular/basic/src/app/app.component.html",
    "content": "<p>\n  As you visit the posts below, you will notice them in a loading state the\n  first time you load them. However, after you return to this list and click on\n  any posts you have already visited again, you will see them load instantly and\n  background refresh right before your eyes!\n  <strong>\n    (You may need to throttle your network speed to simulate longer loading\n    sequences)\n  </strong>\n</p>\n@if (postId() > -1) {\n  <post [postId]=\"postId()\" (setPostId)=\"postId.set($event)\"></post>\n} @else {\n  <posts (setPostId)=\"postId.set($event)\" />\n}\n"
  },
  {
    "path": "examples/angular/basic/src/app/app.component.ts",
    "content": "import { ChangeDetectionStrategy, Component, signal } from '@angular/core'\nimport { PostComponent } from './components/post.component'\nimport { PostsComponent } from './components/posts.component'\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  selector: 'basic-example',\n  templateUrl: './app.component.html',\n  imports: [PostComponent, PostsComponent],\n})\nexport class BasicExampleComponent {\n  readonly postId = signal(-1)\n}\n"
  },
  {
    "path": "examples/angular/basic/src/app/app.config.ts",
    "content": "import { provideHttpClient, withFetch } from '@angular/common/http'\nimport {\n  QueryClient,\n  provideTanStackQuery,\n} from '@tanstack/angular-query-experimental'\nimport { withDevtools } from '@tanstack/angular-query-experimental/devtools'\nimport type { ApplicationConfig } from '@angular/core'\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideHttpClient(withFetch()),\n    provideTanStackQuery(\n      new QueryClient({\n        defaultOptions: {\n          queries: {\n            gcTime: 1000 * 60 * 60 * 24, // 24 hours\n          },\n        },\n      }),\n      withDevtools(),\n    ),\n  ],\n}\n"
  },
  {
    "path": "examples/angular/basic/src/app/components/post.component.html",
    "content": "<div>\n  <div>\n    <a (click)=\"setPostId.emit(-1)\" href=\"#\"> Back </a>\n  </div>\n  @if (postQuery.isPending()) {\n    Loading...\n  } @else if (postQuery.isError()) {\n    Error: {{ postQuery.error().message }}\n  }\n  @if (postQuery.data(); as post) {\n    <h1>{{ post.title }}</h1>\n    <div>\n      <p>{{ post.body }}</p>\n    </div>\n    @if (postQuery.isFetching()) {\n      Background Updating...\n    }\n  }\n</div>\n"
  },
  {
    "path": "examples/angular/basic/src/app/components/post.component.ts",
    "content": "import {\n  ChangeDetectionStrategy,\n  Component,\n  inject,\n  input,\n  output,\n} from '@angular/core'\nimport { injectQuery } from '@tanstack/angular-query-experimental'\nimport { fromEvent, lastValueFrom, takeUntil } from 'rxjs'\nimport { PostsService } from '../services/posts-service'\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  selector: 'post',\n  templateUrl: './post.component.html',\n})\nexport class PostComponent {\n  readonly #postsService = inject(PostsService)\n\n  readonly setPostId = output<number>()\n  readonly postId = input(0)\n\n  readonly postQuery = injectQuery(() => ({\n    enabled: this.postId() > 0,\n    queryKey: ['post', this.postId()],\n    queryFn: (context) => {\n      // Cancels the request when component is destroyed before the request finishes\n      const abort$ = fromEvent(context.signal, 'abort')\n      return lastValueFrom(\n        this.#postsService.postById$(this.postId()).pipe(takeUntil(abort$)),\n      )\n    },\n  }))\n}\n"
  },
  {
    "path": "examples/angular/basic/src/app/components/posts.component.html",
    "content": "<div>\n  <h1>Posts</h1>\n  @if (postsQuery.isPending()) {\n    Loading...\n  } @else if (postsQuery.isError()) {\n    Error: {{ postsQuery.error().message }}\n  } @else if (postsQuery.isSuccess()) {\n    <div class=\"todo-container\">\n      @for (post of postsQuery.data(); track post.id) {\n        <p>\n          <!--          We can access the query data here to show bold links for-->\n          <!--          ones that are cached-->\n          <a\n            href=\"#\"\n            (click)=\"setPostId.emit(post.id)\"\n            [style]=\"\n              queryClient.getQueryData(['post', post.id])\n                ? {\n                    fontWeight: 'bold',\n                    color: 'green',\n                  }\n                : {}\n            \"\n            >{{ post.title }}</a\n          >\n        </p>\n      }\n    </div>\n  }\n  <div>\n    @if (postsQuery.isFetching()) {\n      Background Updating...\n    }\n  </div>\n</div>\n"
  },
  {
    "path": "examples/angular/basic/src/app/components/posts.component.ts",
    "content": "import {\n  ChangeDetectionStrategy,\n  Component,\n  inject,\n  output,\n} from '@angular/core'\nimport { QueryClient, injectQuery } from '@tanstack/angular-query-experimental'\nimport { lastValueFrom } from 'rxjs'\nimport { PostsService } from '../services/posts-service'\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  selector: 'posts',\n  templateUrl: './posts.component.html',\n})\nexport class PostsComponent {\n  readonly queryClient = inject(QueryClient)\n  readonly #postsService = inject(PostsService)\n  readonly setPostId = output<number>()\n\n  readonly postsQuery = injectQuery(() => ({\n    queryKey: ['posts'],\n    queryFn: () => lastValueFrom(this.#postsService.allPosts$()),\n  }))\n}\n"
  },
  {
    "path": "examples/angular/basic/src/app/services/posts-service.ts",
    "content": "import { HttpClient } from '@angular/common/http'\nimport { Injectable, inject } from '@angular/core'\n\n@Injectable({\n  providedIn: 'root',\n})\nexport class PostsService {\n  readonly #http = inject(HttpClient)\n\n  postById$ = (postId: number) =>\n    this.#http.get<Post>(`https://jsonplaceholder.typicode.com/posts/${postId}`)\n\n  allPosts$ = () =>\n    this.#http.get<Array<Post>>('https://jsonplaceholder.typicode.com/posts')\n}\n\nexport interface Post {\n  id: number\n  title: string\n  body: string\n}\n"
  },
  {
    "path": "examples/angular/basic/src/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>TanStack Query Angular basic example</title>\n    <base href=\"/\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <link rel=\"icon\" type=\"image/x-icon\" href=\"favicon.ico\" />\n  </head>\n  <body>\n    <basic-example></basic-example>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/angular/basic/src/main.ts",
    "content": "import { bootstrapApplication } from '@angular/platform-browser'\nimport { appConfig } from './app/app.config'\nimport { BasicExampleComponent } from './app/app.component'\n\nbootstrapApplication(BasicExampleComponent, appConfig).catch((err) =>\n  console.error(err),\n)\n"
  },
  {
    "path": "examples/angular/basic/tsconfig.app.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./out-tsc/app\",\n    \"types\": []\n  },\n  \"files\": [\"src/main.ts\"],\n  \"include\": [\"src/**/*.d.ts\"]\n}\n"
  },
  {
    "path": "examples/angular/basic/tsconfig.json",
    "content": "{\n  \"compileOnSave\": false,\n  \"compilerOptions\": {\n    \"outDir\": \"./dist/out-tsc\",\n    \"forceConsistentCasingInFileNames\": true,\n    \"strict\": true,\n    \"noImplicitOverride\": true,\n    \"noPropertyAccessFromIndexSignature\": true,\n    \"noImplicitReturns\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"skipLibCheck\": true,\n    \"isolatedModules\": true,\n    \"esModuleInterop\": true,\n    \"sourceMap\": true,\n    \"declaration\": false,\n    \"experimentalDecorators\": true,\n    \"moduleResolution\": \"Bundler\",\n    \"importHelpers\": true,\n    \"target\": \"ES2022\",\n    \"module\": \"ES2022\",\n    \"useDefineForClassFields\": false,\n    \"lib\": [\"ES2022\", \"dom\"]\n  },\n  \"angularCompilerOptions\": {\n    \"enableI18nLegacyMessageIdFormat\": false,\n    \"strictInjectionParameters\": true,\n    \"strictInputAccessModifiers\": true,\n    \"strictStandalone\": true,\n    \"strictTemplates\": true\n  }\n}\n"
  },
  {
    "path": "examples/angular/basic-persister/.devcontainer/devcontainer.json",
    "content": "{\n  \"name\": \"Node.js\",\n  \"image\": \"mcr.microsoft.com/devcontainers/javascript-node:22\"\n}\n"
  },
  {
    "path": "examples/angular/basic-persister/.eslintrc.cjs",
    "content": "// @ts-check\n\n/** @type {import('eslint').Linter.Config} */\nconst config = {}\n\nmodule.exports = config\n"
  },
  {
    "path": "examples/angular/basic-persister/README.md",
    "content": "# TanStack Query Angular basic persister example\n\nTo run this example:\n\n- `npm install` or `yarn` or `pnpm i` or `bun i`\n- `npm run start` or `yarn start` or `pnpm start` or `bun start`\n"
  },
  {
    "path": "examples/angular/basic-persister/angular.json",
    "content": "{\n  \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n  \"version\": 1,\n  \"cli\": {\n    \"packageManager\": \"pnpm\",\n    \"analytics\": false,\n    \"cache\": {\n      \"enabled\": false\n    }\n  },\n  \"newProjectRoot\": \"projects\",\n  \"projects\": {\n    \"basic-persister\": {\n      \"projectType\": \"application\",\n      \"schematics\": {\n        \"@schematics/angular:component\": {\n          \"inlineTemplate\": true,\n          \"inlineStyle\": true,\n          \"skipTests\": true\n        },\n        \"@schematics/angular:class\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:directive\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:guard\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:interceptor\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:pipe\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:resolver\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:service\": {\n          \"skipTests\": true\n        }\n      },\n      \"root\": \"\",\n      \"sourceRoot\": \"src\",\n      \"prefix\": \"app\",\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular/build:application\",\n          \"options\": {\n            \"outputPath\": \"dist/basic-persister\",\n            \"index\": \"src/index.html\",\n            \"browser\": \"src/main.ts\",\n            \"polyfills\": [\"zone.js\"],\n            \"tsConfig\": \"tsconfig.app.json\",\n            \"assets\": [\"src/favicon.ico\", \"src/assets\"],\n            \"styles\": [],\n            \"scripts\": []\n          },\n          \"configurations\": {\n            \"production\": {\n              \"budgets\": [\n                {\n                  \"type\": \"initial\",\n                  \"maximumWarning\": \"500kb\",\n                  \"maximumError\": \"1mb\"\n                },\n                {\n                  \"type\": \"anyComponentStyle\",\n                  \"maximumWarning\": \"2kb\",\n                  \"maximumError\": \"4kb\"\n                }\n              ],\n              \"outputHashing\": \"all\"\n            },\n            \"development\": {\n              \"optimization\": false,\n              \"extractLicenses\": false,\n              \"sourceMap\": true\n            }\n          },\n          \"defaultConfiguration\": \"production\"\n        },\n        \"serve\": {\n          \"builder\": \"@angular/build:dev-server\",\n          \"configurations\": {\n            \"production\": {\n              \"buildTarget\": \"basic-persister:build:production\"\n            },\n            \"development\": {\n              \"buildTarget\": \"basic-persister:build:development\"\n            }\n          },\n          \"defaultConfiguration\": \"development\"\n        },\n        \"extract-i18n\": {\n          \"builder\": \"@angular/build:extract-i18n\",\n          \"options\": {\n            \"buildTarget\": \"basic-persister:build\"\n          }\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "examples/angular/basic-persister/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-angular-basic-persister\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"ng\": \"ng\",\n    \"start\": \"ng serve\",\n    \"build\": \"ng build\",\n    \"watch\": \"ng build --watch --configuration development\"\n  },\n  \"private\": true,\n  \"dependencies\": {\n    \"@angular/common\": \"^20.0.0\",\n    \"@angular/compiler\": \"^20.0.0\",\n    \"@angular/core\": \"^20.0.0\",\n    \"@angular/platform-browser\": \"^20.0.0\",\n    \"@tanstack/angular-query-experimental\": \"^5.90.28\",\n    \"@tanstack/angular-query-persist-client\": \"^5.62.32\",\n    \"@tanstack/query-async-storage-persister\": \"^5.90.27\",\n    \"rxjs\": \"^7.8.2\",\n    \"tslib\": \"^2.8.1\",\n    \"zone.js\": \"0.15.0\"\n  },\n  \"devDependencies\": {\n    \"@angular/build\": \"^20.0.0\",\n    \"@angular/cli\": \"^20.0.0\",\n    \"@angular/compiler-cli\": \"^20.0.0\",\n    \"typescript\": \"5.8.3\"\n  }\n}\n"
  },
  {
    "path": "examples/angular/basic-persister/src/app/app.component.html",
    "content": "<p>\n  Try to mock offline behavior with the button in the devtools. You can navigate\n  around as long as there is already data in the cache. You'll get a refetch as\n  soon as you go \"online\" again.\n</p>\n@if (postId() > -1) {\n  <post [postId]=\"postId()\" (setPostId)=\"postId.set($event)\"></post>\n} @else {\n  <posts (setPostId)=\"postId.set($event)\" />\n}\n"
  },
  {
    "path": "examples/angular/basic-persister/src/app/app.component.ts",
    "content": "import { ChangeDetectionStrategy, Component, signal } from '@angular/core'\nimport { PostComponent } from './components/post.component'\nimport { PostsComponent } from './components/posts.component'\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  selector: 'basic-example',\n  templateUrl: './app.component.html',\n  imports: [PostComponent, PostsComponent],\n})\nexport class BasicExampleComponent {\n  postId = signal(-1)\n}\n"
  },
  {
    "path": "examples/angular/basic-persister/src/app/app.config.ts",
    "content": "import { provideHttpClient, withFetch } from '@angular/common/http'\nimport {\n  QueryClient,\n  provideTanStackQuery,\n} from '@tanstack/angular-query-experimental'\nimport { withPersistQueryClient } from '@tanstack/angular-query-persist-client'\nimport { withDevtools } from '@tanstack/angular-query-experimental/devtools'\nimport { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister'\nimport type { ApplicationConfig } from '@angular/core'\n\nconst localStoragePersister = createAsyncStoragePersister({\n  storage: window.localStorage,\n})\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideHttpClient(withFetch()),\n    provideTanStackQuery(\n      new QueryClient({\n        defaultOptions: {\n          queries: {\n            staleTime: 1000 * 60, // 1 minute\n            gcTime: 1000 * 60 * 60 * 24, // 24 hours\n          },\n        },\n      }),\n      withDevtools(),\n      withPersistQueryClient({\n        persistOptions: {\n          persister: localStoragePersister,\n        },\n      }),\n    ),\n  ],\n}\n"
  },
  {
    "path": "examples/angular/basic-persister/src/app/components/post.component.html",
    "content": "<div>\n  <div>\n    <a (click)=\"setPostId.emit(-1)\" href=\"#\"> Back </a>\n  </div>\n  @if (postQuery.isPending()) {\n    Loading...\n  } @else if (postQuery.isError()) {\n    Error: {{ postQuery.error().message }}\n  }\n  @if (postQuery.data(); as post) {\n    <h1>{{ post.title }}</h1>\n    <div>\n      <p>{{ post.body }}</p>\n    </div>\n    @if (postQuery.isFetching()) {\n      Background Updating...\n    }\n  }\n</div>\n"
  },
  {
    "path": "examples/angular/basic-persister/src/app/components/post.component.ts",
    "content": "import {\n  ChangeDetectionStrategy,\n  Component,\n  EventEmitter,\n  Output,\n  inject,\n  input,\n} from '@angular/core'\nimport { QueryClient, injectQuery } from '@tanstack/angular-query-experimental'\nimport { fromEvent, lastValueFrom, takeUntil } from 'rxjs'\nimport { PostsService } from '../services/posts-service'\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  selector: 'post',\n  templateUrl: './post.component.html',\n})\nexport class PostComponent {\n  #postsService = inject(PostsService)\n\n  @Output() setPostId = new EventEmitter<number>()\n\n  postId = input(0)\n\n  postQuery = injectQuery(() => ({\n    enabled: this.postId() > 0,\n    queryKey: ['post', this.postId()],\n    queryFn: async (context) => {\n      // Cancels the request when component is destroyed before the request finishes\n      const abort$ = fromEvent(context.signal, 'abort')\n      return lastValueFrom(\n        this.#postsService.postById$(this.postId()).pipe(takeUntil(abort$)),\n      )\n    },\n  }))\n\n  queryClient = inject(QueryClient)\n}\n"
  },
  {
    "path": "examples/angular/basic-persister/src/app/components/posts.component.html",
    "content": "<div>\n  <h1>Posts</h1>\n  @if (postsQuery.isPending()) {\n    Loading...\n  } @else if (postsQuery.isError()) {\n    Error: {{ postsQuery.error().message }}\n  } @else if (postsQuery.isSuccess()) {\n    <div class=\"todo-container\">\n      @for (post of postsQuery.data(); track post.id) {\n        <p>\n          <!--          We can access the query data here to show bold links for-->\n          <!--          ones that are cached-->\n          <a\n            href=\"#\"\n            (click)=\"setPostId.emit(post.id)\"\n            [style]=\"\n              queryClient.getQueryData(['post', post.id])\n                ? {\n                    fontWeight: 'bold',\n                    color: 'green',\n                  }\n                : {}\n            \"\n            >{{ post.title }}</a\n          >\n        </p>\n      }\n    </div>\n  }\n  <div>\n    @if (postsQuery.isFetching()) {\n      Background Updating...\n    }\n  </div>\n</div>\n"
  },
  {
    "path": "examples/angular/basic-persister/src/app/components/posts.component.ts",
    "content": "import {\n  ChangeDetectionStrategy,\n  Component,\n  EventEmitter,\n  Output,\n  inject,\n} from '@angular/core'\nimport { QueryClient, injectQuery } from '@tanstack/angular-query-experimental'\nimport { lastValueFrom } from 'rxjs'\nimport { PostsService } from '../services/posts-service'\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  selector: 'posts',\n  templateUrl: './posts.component.html',\n})\nexport class PostsComponent {\n  queryClient = inject(QueryClient)\n  #postsService = inject(PostsService)\n\n  @Output() setPostId = new EventEmitter<number>()\n\n  postsQuery = injectQuery(() => ({\n    queryKey: ['posts'],\n    queryFn: () => lastValueFrom(this.#postsService.allPosts$()),\n  }))\n}\n"
  },
  {
    "path": "examples/angular/basic-persister/src/app/services/posts-service.ts",
    "content": "import { HttpClient } from '@angular/common/http'\nimport { Injectable, inject } from '@angular/core'\n\n@Injectable({\n  providedIn: 'root',\n})\nexport class PostsService {\n  #http = inject(HttpClient)\n\n  postById$ = (postId: number) =>\n    this.#http.get<Post>(`https://jsonplaceholder.typicode.com/posts/${postId}`)\n\n  allPosts$ = () =>\n    this.#http.get<Array<Post>>('https://jsonplaceholder.typicode.com/posts')\n}\n\nexport interface Post {\n  id: number\n  title: string\n  body: string\n}\n"
  },
  {
    "path": "examples/angular/basic-persister/src/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>TanStack Query Angular basic persister example</title>\n    <base href=\"/\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <link rel=\"icon\" type=\"image/x-icon\" href=\"favicon.ico\" />\n  </head>\n  <body>\n    <basic-example></basic-example>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/angular/basic-persister/src/main.ts",
    "content": "import { bootstrapApplication } from '@angular/platform-browser'\nimport { appConfig } from './app/app.config'\nimport { BasicExampleComponent } from './app/app.component'\n\nbootstrapApplication(BasicExampleComponent, appConfig).catch((err) =>\n  console.error(err),\n)\n"
  },
  {
    "path": "examples/angular/basic-persister/tsconfig.app.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./out-tsc/app\",\n    \"types\": []\n  },\n  \"files\": [\"src/main.ts\"],\n  \"include\": [\"src/**/*.d.ts\"]\n}\n"
  },
  {
    "path": "examples/angular/basic-persister/tsconfig.json",
    "content": "{\n  \"compileOnSave\": false,\n  \"compilerOptions\": {\n    \"outDir\": \"./dist/out-tsc\",\n    \"forceConsistentCasingInFileNames\": true,\n    \"strict\": true,\n    \"noImplicitOverride\": true,\n    \"noPropertyAccessFromIndexSignature\": true,\n    \"noImplicitReturns\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"skipLibCheck\": true,\n    \"isolatedModules\": true,\n    \"esModuleInterop\": true,\n    \"sourceMap\": true,\n    \"declaration\": false,\n    \"experimentalDecorators\": true,\n    \"moduleResolution\": \"bundler\",\n    \"importHelpers\": true,\n    \"target\": \"ES2022\",\n    \"module\": \"ES2022\",\n    \"useDefineForClassFields\": false,\n    \"lib\": [\"ES2022\", \"dom\"]\n  },\n  \"angularCompilerOptions\": {\n    \"enableI18nLegacyMessageIdFormat\": false,\n    \"strictInjectionParameters\": true,\n    \"strictInputAccessModifiers\": true,\n    \"strictStandalone\": true,\n    \"strictTemplates\": true\n  }\n}\n"
  },
  {
    "path": "examples/angular/devtools-panel/.devcontainer/devcontainer.json",
    "content": "{\n  \"name\": \"Node.js\",\n  \"image\": \"mcr.microsoft.com/devcontainers/javascript-node:22\"\n}\n"
  },
  {
    "path": "examples/angular/devtools-panel/README.md",
    "content": "# TanStack Query Angular devtools panel example\n\nTo run this example:\n\n- `npm install` or `yarn` or `pnpm i` or `bun i`\n- `npm run start` or `yarn start` or `pnpm start` or `bun start`\n"
  },
  {
    "path": "examples/angular/devtools-panel/angular.json",
    "content": "{\n  \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n  \"version\": 1,\n  \"cli\": {\n    \"packageManager\": \"pnpm\",\n    \"analytics\": false,\n    \"cache\": {\n      \"enabled\": false\n    }\n  },\n  \"newProjectRoot\": \"projects\",\n  \"projects\": {\n    \"devtools-panel\": {\n      \"projectType\": \"application\",\n      \"schematics\": {\n        \"@schematics/angular:component\": {\n          \"inlineTemplate\": true,\n          \"inlineStyle\": true,\n          \"skipTests\": true\n        },\n        \"@schematics/angular:class\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:directive\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:guard\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:interceptor\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:pipe\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:resolver\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:service\": {\n          \"skipTests\": true\n        }\n      },\n      \"root\": \"\",\n      \"sourceRoot\": \"src\",\n      \"prefix\": \"app\",\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular/build:application\",\n          \"options\": {\n            \"outputPath\": \"dist/devtools-panel\",\n            \"index\": \"src/index.html\",\n            \"browser\": \"src/main.ts\",\n            \"polyfills\": [\"zone.js\"],\n            \"tsConfig\": \"tsconfig.app.json\",\n            \"scripts\": []\n          },\n          \"configurations\": {\n            \"production\": {\n              \"budgets\": [\n                {\n                  \"type\": \"initial\",\n                  \"maximumWarning\": \"500kb\",\n                  \"maximumError\": \"1mb\"\n                },\n                {\n                  \"type\": \"anyComponentStyle\",\n                  \"maximumWarning\": \"2kb\",\n                  \"maximumError\": \"4kb\"\n                }\n              ],\n              \"outputHashing\": \"all\"\n            },\n            \"development\": {\n              \"optimization\": false,\n              \"extractLicenses\": false,\n              \"sourceMap\": true\n            }\n          },\n          \"defaultConfiguration\": \"production\"\n        },\n        \"serve\": {\n          \"builder\": \"@angular/build:dev-server\",\n          \"configurations\": {\n            \"production\": {\n              \"buildTarget\": \"devtools-panel:build:production\"\n            },\n            \"development\": {\n              \"buildTarget\": \"devtools-panel:build:development\"\n            }\n          },\n          \"defaultConfiguration\": \"development\"\n        },\n        \"extract-i18n\": {\n          \"builder\": \"@angular/build:extract-i18n\",\n          \"options\": {\n            \"buildTarget\": \"devtools-panel:build\"\n          }\n        }\n      }\n    }\n  },\n  \"schematics\": {\n    \"@schematics/angular:component\": {\n      \"type\": \"component\"\n    },\n    \"@schematics/angular:directive\": {\n      \"type\": \"directive\"\n    },\n    \"@schematics/angular:service\": {\n      \"type\": \"service\"\n    },\n    \"@schematics/angular:guard\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:interceptor\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:module\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:pipe\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:resolver\": {\n      \"typeSeparator\": \".\"\n    }\n  }\n}\n"
  },
  {
    "path": "examples/angular/devtools-panel/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-angular-devtools-panel\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"ng\": \"ng\",\n    \"start\": \"ng serve\",\n    \"build\": \"ng build\",\n    \"watch\": \"ng build --watch --configuration development\"\n  },\n  \"private\": true,\n  \"dependencies\": {\n    \"@angular/common\": \"^20.0.0\",\n    \"@angular/compiler\": \"^20.0.0\",\n    \"@angular/core\": \"^20.0.0\",\n    \"@angular/platform-browser\": \"^20.0.0\",\n    \"@angular/router\": \"^20.0.0\",\n    \"@tanstack/angular-query-experimental\": \"^5.90.28\",\n    \"rxjs\": \"^7.8.2\",\n    \"tslib\": \"^2.8.1\",\n    \"zone.js\": \"0.15.0\"\n  },\n  \"devDependencies\": {\n    \"@angular/build\": \"^20.0.0\",\n    \"@angular/cli\": \"^20.0.0\",\n    \"@angular/compiler-cli\": \"^20.0.0\",\n    \"typescript\": \"5.8.3\"\n  }\n}\n"
  },
  {
    "path": "examples/angular/devtools-panel/src/app/app.component.ts",
    "content": "import { ChangeDetectionStrategy, Component } from '@angular/core'\nimport { RouterLink, RouterOutlet } from '@angular/router'\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  selector: 'app-root',\n  template: `\n    <ul>\n      <li>\n        <a routerLink=\"basic\">Basic devtools panel example</a>\n      </li>\n      <li>\n        <a routerLink=\"lazy\">Lazy load devtools panel example</a>\n      </li>\n    </ul>\n\n    <router-outlet />\n  `,\n  imports: [RouterOutlet, RouterLink],\n})\nexport class AppComponent {}\n"
  },
  {
    "path": "examples/angular/devtools-panel/src/app/app.config.ts",
    "content": "import { provideHttpClient, withFetch } from '@angular/common/http'\n\nimport { provideRouter } from '@angular/router'\nimport {\n  QueryClient,\n  provideTanStackQuery,\n} from '@tanstack/angular-query-experimental'\nimport { routes } from './app.routes'\nimport type { ApplicationConfig } from '@angular/core'\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideHttpClient(withFetch()),\n    provideRouter(routes),\n    provideTanStackQuery(new QueryClient()),\n  ],\n}\n"
  },
  {
    "path": "examples/angular/devtools-panel/src/app/app.routes.ts",
    "content": "import type { Route } from '@angular/router'\n\nexport const routes: Array<Route> = [\n  {\n    path: '',\n    redirectTo: 'basic',\n    pathMatch: 'full',\n  },\n  {\n    path: 'basic',\n    loadComponent: () =>\n      import('./components/basic-devtools-panel-example.component'),\n  },\n  {\n    path: 'lazy',\n    loadComponent: () =>\n      import('./components/lazy-load-devtools-panel-example.component'),\n  },\n]\n"
  },
  {
    "path": "examples/angular/devtools-panel/src/app/components/basic-devtools-panel-example.component.ts",
    "content": "import {\n  ChangeDetectionStrategy,\n  Component,\n  signal,\n  viewChild,\n} from '@angular/core'\nimport { injectDevtoolsPanel } from '@tanstack/angular-query-experimental/devtools-panel'\nimport { ExampleQueryComponent } from './example-query.component'\nimport type { ElementRef } from '@angular/core'\n\n@Component({\n  selector: 'basic-devtools-panel-example',\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  template: `\n    <example-query />\n    <h1>Basic devtools panel example</h1>\n    <p>\n      In this example, the devtools panel is loaded programmatically when the\n      button is clicked\n    </p>\n    <button type=\"button\" (click)=\"toggleIsOpen()\">\n      {{ isOpen() ? 'Close' : 'Open' }} the devtools panel\n    </button>\n    @if (isOpen()) {\n      <div #div style=\"height: 500px\"></div>\n    }\n  `,\n  imports: [ExampleQueryComponent],\n})\nexport default class BasicDevtoolsPanelExampleComponent {\n  readonly isOpen = signal(false)\n  readonly divEl = viewChild<ElementRef>('div')\n\n  toggleIsOpen() {\n    this.isOpen.update((prev) => !prev)\n  }\n\n  readonly devtools = injectDevtoolsPanel(() => ({\n    hostElement: this.divEl(),\n  }))\n}\n"
  },
  {
    "path": "examples/angular/devtools-panel/src/app/components/example-query.component.ts",
    "content": "import { ChangeDetectionStrategy, Component, inject } from '@angular/core'\nimport { injectQuery } from '@tanstack/angular-query-experimental'\nimport { HttpClient } from '@angular/common/http'\nimport { lastValueFrom } from 'rxjs'\n\ninterface Response {\n  name: string\n  description: string\n  subscribers_count: number\n  stargazers_count: number\n  forks_count: number\n}\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  selector: 'example-query',\n  template: `\n    <div style=\"padding-bottom: 20px\">\n      @if (query.isPending()) {\n        <div>Loading...</div>\n      }\n      @if (query.isError()) {\n        <div>An error has occurred: {{ query.error().message }}</div>\n      }\n      @if (query.isSuccess()) {\n        @let data = query.data();\n        <h1>{{ data.name }}</h1>\n        <p>{{ data.description }}</p>\n        <strong>👀 {{ data.subscribers_count }}</strong>\n        <strong>✨ {{ data.stargazers_count }}</strong>\n        <strong>🍴 {{ data.forks_count }}</strong>\n      }\n    </div>\n  `,\n})\nexport class ExampleQueryComponent {\n  readonly #http = inject(HttpClient)\n\n  readonly query = injectQuery(() => ({\n    queryKey: ['repoData'],\n    queryFn: () =>\n      lastValueFrom(\n        this.#http.get<Response>('https://api.github.com/repos/tanstack/query'),\n      ),\n  }))\n}\n"
  },
  {
    "path": "examples/angular/devtools-panel/src/app/components/lazy-load-devtools-panel-example.component.ts",
    "content": "import {\n  ChangeDetectionStrategy,\n  Component,\n  Injector,\n  computed,\n  effect,\n  inject,\n  signal,\n  viewChild,\n} from '@angular/core'\nimport { ExampleQueryComponent } from './example-query.component'\nimport type { ElementRef } from '@angular/core'\nimport type { DevtoolsPanelRef } from '@tanstack/angular-query-experimental/devtools-panel'\n\n@Component({\n  selector: 'lazy-load-devtools-panel-example',\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  template: `\n    <example-query />\n    <h1>Lazy load devtools panel example</h1>\n    <p>\n      In this example, the devtools panel is loaded programmatically when the\n      button is clicked. In addition, the code is lazy loaded.\n    </p>\n    <button type=\"button\" (click)=\"toggleIsOpen()\">\n      {{ isOpen() ? 'Close' : 'Open' }} the devtools panel\n    </button>\n    @if (isOpen()) {\n      <div #div style=\"height: 500px\"></div>\n    }\n  `,\n  imports: [ExampleQueryComponent],\n})\nexport default class LazyLoadDevtoolsPanelExampleComponent {\n  readonly isOpen = signal(false)\n  readonly devtools = signal<Promise<DevtoolsPanelRef> | undefined>(undefined)\n  readonly injector = inject(Injector)\n\n  readonly divEl = viewChild<ElementRef>('div')\n  readonly devToolsOptions = computed(() => ({\n    hostElement: this.divEl(),\n  }))\n\n  toggleIsOpen() {\n    this.isOpen.update((prev) => !prev)\n  }\n\n  readonly loadDevtoolsEffect = effect(() => {\n    if (this.devtools()) return\n    if (this.isOpen()) {\n      this.devtools.set(\n        import('@tanstack/angular-query-experimental/devtools-panel').then(\n          ({ injectDevtoolsPanel }) =>\n            injectDevtoolsPanel(this.devToolsOptions, {\n              injector: this.injector,\n            }),\n        ),\n      )\n    }\n  })\n}\n"
  },
  {
    "path": "examples/angular/devtools-panel/src/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>TanStack Query devtools panel example</title>\n    <base href=\"/\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <link rel=\"icon\" type=\"image/x-icon\" href=\"favicon.ico\" />\n  </head>\n  <body>\n    <app-root></app-root>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/angular/devtools-panel/src/main.ts",
    "content": "import { bootstrapApplication } from '@angular/platform-browser'\nimport { appConfig } from './app/app.config'\nimport { AppComponent } from './app/app.component'\n\nbootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err))\n"
  },
  {
    "path": "examples/angular/devtools-panel/tsconfig.app.json",
    "content": "/* To learn more about this file see: https://angular.io/config/tsconfig. */\n{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./out-tsc/app\",\n    \"types\": []\n  },\n  \"files\": [\"src/main.ts\"],\n  \"include\": [\"src/**/*.d.ts\"]\n}\n"
  },
  {
    "path": "examples/angular/devtools-panel/tsconfig.json",
    "content": "{\n  \"compileOnSave\": false,\n  \"compilerOptions\": {\n    \"outDir\": \"./dist/out-tsc\",\n    \"forceConsistentCasingInFileNames\": true,\n    \"strict\": true,\n    \"noImplicitOverride\": true,\n    \"noPropertyAccessFromIndexSignature\": true,\n    \"noImplicitReturns\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"skipLibCheck\": true,\n    \"isolatedModules\": true,\n    \"esModuleInterop\": true,\n    \"sourceMap\": true,\n    \"declaration\": false,\n    \"experimentalDecorators\": true,\n    \"moduleResolution\": \"Bundler\",\n    \"importHelpers\": true,\n    \"target\": \"ES2022\",\n    \"module\": \"ES2022\",\n    \"useDefineForClassFields\": false,\n    \"lib\": [\"ES2022\", \"dom\"]\n  },\n  \"angularCompilerOptions\": {\n    \"enableI18nLegacyMessageIdFormat\": false,\n    \"strictInjectionParameters\": true,\n    \"strictInputAccessModifiers\": true,\n    \"strictStandalone\": true,\n    \"strictTemplates\": true\n  }\n}\n"
  },
  {
    "path": "examples/angular/infinite-query-with-max-pages/.devcontainer/devcontainer.json",
    "content": "{\n  \"name\": \"Node.js\",\n  \"image\": \"mcr.microsoft.com/devcontainers/javascript-node:22\"\n}\n"
  },
  {
    "path": "examples/angular/infinite-query-with-max-pages/.eslintrc.cjs",
    "content": "// @ts-check\n\n/** @type {import('eslint').Linter.Config} */\nconst config = {}\n\nmodule.exports = config\n"
  },
  {
    "path": "examples/angular/infinite-query-with-max-pages/README.md",
    "content": "# TanStack Query Angular infinite query example\n\nTo run this example:\n\n- `npm install` or `yarn` or `pnpm i` or `bun i`\n- `npm run start` or `yarn start` or `pnpm start` or `bun start`\n"
  },
  {
    "path": "examples/angular/infinite-query-with-max-pages/angular.json",
    "content": "{\n  \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n  \"version\": 1,\n  \"cli\": {\n    \"packageManager\": \"pnpm\",\n    \"analytics\": false,\n    \"cache\": {\n      \"enabled\": false\n    }\n  },\n  \"newProjectRoot\": \"projects\",\n  \"projects\": {\n    \"infinite-query-with-max-pages\": {\n      \"projectType\": \"application\",\n      \"schematics\": {\n        \"@schematics/angular:component\": {\n          \"inlineTemplate\": true,\n          \"inlineStyle\": true,\n          \"skipTests\": true\n        },\n        \"@schematics/angular:class\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:directive\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:guard\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:interceptor\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:pipe\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:resolver\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:service\": {\n          \"skipTests\": true\n        }\n      },\n      \"root\": \"\",\n      \"sourceRoot\": \"src\",\n      \"prefix\": \"app\",\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular/build:application\",\n          \"options\": {\n            \"outputPath\": \"dist/infinite-query-with-max-pages\",\n            \"index\": \"src/index.html\",\n            \"browser\": \"src/main.ts\",\n            \"polyfills\": [\"zone.js\"],\n            \"tsConfig\": \"tsconfig.app.json\",\n            \"assets\": [\"src/favicon.ico\", \"src/mockServiceWorker.js\"],\n            \"styles\": [],\n            \"scripts\": []\n          },\n          \"configurations\": {\n            \"production\": {\n              \"budgets\": [\n                {\n                  \"type\": \"initial\",\n                  \"maximumWarning\": \"500kb\",\n                  \"maximumError\": \"1mb\"\n                },\n                {\n                  \"type\": \"anyComponentStyle\",\n                  \"maximumWarning\": \"2kb\",\n                  \"maximumError\": \"4kb\"\n                }\n              ],\n              \"outputHashing\": \"all\"\n            },\n            \"development\": {\n              \"optimization\": false,\n              \"extractLicenses\": false,\n              \"sourceMap\": true\n            }\n          },\n          \"defaultConfiguration\": \"production\"\n        },\n        \"serve\": {\n          \"builder\": \"@angular/build:dev-server\",\n          \"configurations\": {\n            \"production\": {\n              \"buildTarget\": \"infinite-query-with-max-pages:build:production\"\n            },\n            \"development\": {\n              \"buildTarget\": \"infinite-query-with-max-pages:build:development\"\n            }\n          },\n          \"defaultConfiguration\": \"development\"\n        },\n        \"extract-i18n\": {\n          \"builder\": \"@angular/build:extract-i18n\",\n          \"options\": {\n            \"buildTarget\": \"infinite-query-with-max-pages:build\"\n          }\n        }\n      }\n    }\n  },\n  \"schematics\": {\n    \"@schematics/angular:component\": {\n      \"type\": \"component\"\n    },\n    \"@schematics/angular:directive\": {\n      \"type\": \"directive\"\n    },\n    \"@schematics/angular:service\": {\n      \"type\": \"service\"\n    },\n    \"@schematics/angular:guard\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:interceptor\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:module\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:pipe\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:resolver\": {\n      \"typeSeparator\": \".\"\n    }\n  }\n}\n"
  },
  {
    "path": "examples/angular/infinite-query-with-max-pages/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-angular-infinite-query-with-max-pages\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"ng\": \"ng\",\n    \"start\": \"ng serve\",\n    \"build\": \"ng build\",\n    \"watch\": \"ng build --watch --configuration development\"\n  },\n  \"dependencies\": {\n    \"@angular/common\": \"^20.0.0\",\n    \"@angular/compiler\": \"^20.0.0\",\n    \"@angular/core\": \"^20.0.0\",\n    \"@angular/platform-browser\": \"^20.0.0\",\n    \"@tanstack/angular-query-experimental\": \"^5.90.28\",\n    \"rxjs\": \"^7.8.2\",\n    \"tslib\": \"^2.8.1\",\n    \"zone.js\": \"0.15.0\"\n  },\n  \"devDependencies\": {\n    \"@angular/build\": \"^20.0.0\",\n    \"@angular/cli\": \"^20.0.0\",\n    \"@angular/compiler-cli\": \"^20.0.0\",\n    \"typescript\": \"5.8.3\"\n  }\n}\n"
  },
  {
    "path": "examples/angular/infinite-query-with-max-pages/src/app/api/projects-mock.interceptor.ts",
    "content": "import { HttpResponse } from '@angular/common/http'\nimport { delayWhen, of, timer } from 'rxjs'\nimport type { Observable } from 'rxjs'\nimport type { HttpEvent, HttpInterceptorFn } from '@angular/common/http'\n\nexport const projectsMockInterceptor: HttpInterceptorFn = (\n  req,\n  next,\n): Observable<HttpEvent<any>> => {\n  const { url } = req\n\n  if (url.includes('/api/projects')) {\n    const cursor = parseInt(\n      new URLSearchParams(req.url.split('?')[1]).get('cursor') || '0',\n      10,\n    )\n    const pageSize = 4\n\n    const data = Array(pageSize)\n      .fill(0)\n      .map((_, i) => {\n        return {\n          name: 'Project ' + (i + cursor) + ` (server time: ${Date.now()})`,\n          id: i + cursor,\n        }\n      })\n\n    const nextId = cursor < 20 ? data[data.length - 1].id + 1 : null\n    const previousId = cursor > -20 ? data[0].id - pageSize : null\n\n    // Simulate network latency with a random delay between 100ms and 500ms\n    const delayDuration = Math.random() * (500 - 100) + 100\n    return of(\n      new HttpResponse({\n        status: 200,\n        body: {\n          data,\n          nextId,\n          previousId,\n        },\n      }),\n    ).pipe(delayWhen(() => timer(delayDuration)))\n  }\n  return next(req)\n}\n"
  },
  {
    "path": "examples/angular/infinite-query-with-max-pages/src/app/app.component.ts",
    "content": "import { ChangeDetectionStrategy, Component } from '@angular/core'\nimport { ExampleComponent } from './components/example.component'\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  selector: 'app-root',\n  template: `<example />`,\n  imports: [ExampleComponent],\n})\nexport class AppComponent {}\n"
  },
  {
    "path": "examples/angular/infinite-query-with-max-pages/src/app/app.config.ts",
    "content": "import {\n  provideHttpClient,\n  withFetch,\n  withInterceptors,\n} from '@angular/common/http'\nimport {\n  QueryClient,\n  provideTanStackQuery,\n} from '@tanstack/angular-query-experimental'\nimport { withDevtools } from '@tanstack/angular-query-experimental/devtools'\nimport { projectsMockInterceptor } from './api/projects-mock.interceptor'\nimport type { ApplicationConfig } from '@angular/core'\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideHttpClient(withInterceptors([projectsMockInterceptor]), withFetch()),\n    provideTanStackQuery(\n      new QueryClient({\n        defaultOptions: {\n          queries: {\n            gcTime: 1000 * 60 * 60 * 24, // 24 hours\n          },\n        },\n      }),\n      withDevtools(),\n    ),\n  ],\n}\n"
  },
  {
    "path": "examples/angular/infinite-query-with-max-pages/src/app/components/example.component.html",
    "content": "<div>\n  <h1>Infinite Query with max pages</h1>\n  <h3>4 projects per page</h3>\n  <h3>3 pages max</h3>\n  @if (query.isPending()) {\n    <p>Loading...</p>\n  } @else if (query.isError()) {\n    <span>Error: {{ query.error().message }}</span>\n  } @else {\n    <div>\n      <button\n        (click)=\"query.fetchPreviousPage()\"\n        [disabled]=\"previousButtonDisabled()\"\n      >\n        {{ previousButtonText() }}\n      </button>\n    </div>\n    @for (page of query.data().pages; track $index) {\n      @for (project of page.data; track project.id) {\n        <p [projectStyle]=\"project.id\">{{ project.name }} {{ project.id }}</p>\n      }\n    }\n    <div>\n      <button (click)=\"query.fetchNextPage()\" [disabled]=\"nextButtonDisabled()\">\n        {{ nextButtonText() }}\n      </button>\n    </div>\n    <div>\n      {{\n        query.isFetching() && !query.isFetchingNextPage()\n          ? 'Background Updating...'\n          : null\n      }}\n    </div>\n  }\n  <hr />\n</div>\n"
  },
  {
    "path": "examples/angular/infinite-query-with-max-pages/src/app/components/example.component.ts",
    "content": "import {\n  ChangeDetectionStrategy,\n  Component,\n  computed,\n  inject,\n} from '@angular/core'\nimport { injectInfiniteQuery } from '@tanstack/angular-query-experimental'\nimport { lastValueFrom } from 'rxjs'\nimport { ProjectStyleDirective } from '../directives/project-style.directive'\nimport { ProjectsService } from '../services/projects.service'\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  selector: 'example',\n  templateUrl: './example.component.html',\n  imports: [ProjectStyleDirective],\n})\nexport class ExampleComponent {\n  readonly projectsService = inject(ProjectsService)\n\n  readonly query = injectInfiniteQuery(() => ({\n    queryKey: ['projects'],\n    queryFn: ({ pageParam }) => {\n      return lastValueFrom(this.projectsService.getProjects(pageParam))\n    },\n    initialPageParam: 0,\n    getPreviousPageParam: (firstPage) => firstPage.previousId ?? undefined,\n    getNextPageParam: (lastPage) => lastPage.nextId ?? undefined,\n    maxPages: 3,\n  }))\n\n  readonly nextButtonDisabled = computed(\n    () => !this.#hasNextPage() || this.#isFetchingNextPage(),\n  )\n\n  readonly nextButtonText = computed(() =>\n    this.#isFetchingNextPage()\n      ? 'Loading more...'\n      : this.#hasNextPage()\n        ? 'Load newer'\n        : 'Nothing more to load',\n  )\n\n  readonly previousButtonDisabled = computed(\n    () => !this.#hasPreviousPage() || this.#isFetchingNextPage(),\n  )\n  readonly previousButtonText = computed(() =>\n    this.#isFetchingPreviousPage()\n      ? 'Loading more...'\n      : this.#hasPreviousPage()\n        ? 'Load Older'\n        : 'Nothing more to load',\n  )\n\n  readonly #hasPreviousPage = this.query.hasPreviousPage\n  readonly #hasNextPage = this.query.hasNextPage\n  readonly #isFetchingPreviousPage = this.query.isFetchingPreviousPage\n  readonly #isFetchingNextPage = this.query.isFetchingNextPage\n}\n"
  },
  {
    "path": "examples/angular/infinite-query-with-max-pages/src/app/directives/project-style.directive.ts",
    "content": "import { Directive, computed, input } from '@angular/core'\n\n@Directive({\n  selector: '[projectStyle]',\n  host: {\n    '[style]': 'style()',\n  },\n})\nexport class ProjectStyleDirective {\n  readonly projectStyle = input.required<number>()\n\n  readonly style = computed(\n    () =>\n      `\n      border: 1px solid gray;\n      border-radius: 5px;\n      padding: 8px;\n      font-size: 14px;\n      background: hsla(${this.projectStyle() * 30}, 60%, 80%, 1);\n    `,\n  )\n}\n"
  },
  {
    "path": "examples/angular/infinite-query-with-max-pages/src/app/services/projects.service.ts",
    "content": "import { HttpClient } from '@angular/common/http'\nimport { Injectable, inject } from '@angular/core'\n\ninterface Project {\n  id: number\n  name: string\n}\n\ninterface ProjectResponse {\n  data: Array<Project>\n  nextId: number | undefined\n  previousId: number | undefined\n}\n\n@Injectable({\n  providedIn: 'root',\n})\nexport class ProjectsService {\n  readonly #http = inject(HttpClient)\n  getProjects = (page: number) =>\n    this.#http.get<ProjectResponse>(`/api/projects?cursor=${page}`)\n}\n"
  },
  {
    "path": "examples/angular/infinite-query-with-max-pages/src/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>TanStack Query Angular infinite query example</title>\n    <base href=\"/\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <link rel=\"icon\" type=\"image/x-icon\" href=\"favicon.ico\" />\n  </head>\n  <body>\n    <app-root></app-root>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/angular/infinite-query-with-max-pages/src/main.ts",
    "content": "import { bootstrapApplication } from '@angular/platform-browser'\nimport { appConfig } from './app/app.config'\nimport { AppComponent } from './app/app.component'\n\nbootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err))\n"
  },
  {
    "path": "examples/angular/infinite-query-with-max-pages/tsconfig.app.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./out-tsc/app\",\n    \"types\": []\n  },\n  \"files\": [\"src/main.ts\"],\n  \"include\": [\"src/**/*.d.ts\"]\n}\n"
  },
  {
    "path": "examples/angular/infinite-query-with-max-pages/tsconfig.json",
    "content": "{\n  \"compileOnSave\": false,\n  \"compilerOptions\": {\n    \"outDir\": \"./dist/out-tsc\",\n    \"forceConsistentCasingInFileNames\": true,\n    \"strict\": true,\n    \"noImplicitOverride\": true,\n    \"noPropertyAccessFromIndexSignature\": true,\n    \"noImplicitReturns\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"skipLibCheck\": true,\n    \"isolatedModules\": true,\n    \"esModuleInterop\": true,\n    \"sourceMap\": true,\n    \"declaration\": false,\n    \"experimentalDecorators\": true,\n    \"moduleResolution\": \"Bundler\",\n    \"importHelpers\": true,\n    \"target\": \"ES2022\",\n    \"module\": \"ES2022\",\n    \"useDefineForClassFields\": false,\n    \"lib\": [\"ES2022\", \"dom\"]\n  },\n  \"angularCompilerOptions\": {\n    \"enableI18nLegacyMessageIdFormat\": false,\n    \"strictInjectionParameters\": true,\n    \"strictInputAccessModifiers\": true,\n    \"strictStandalone\": true,\n    \"strictTemplates\": true\n  }\n}\n"
  },
  {
    "path": "examples/angular/optimistic-updates/.devcontainer/devcontainer.json",
    "content": "{\n  \"name\": \"Node.js\",\n  \"image\": \"mcr.microsoft.com/devcontainers/javascript-node:22\"\n}\n"
  },
  {
    "path": "examples/angular/optimistic-updates/.eslintrc.cjs",
    "content": "// @ts-check\n\n/** @type {import('eslint').Linter.Config} */\nconst config = {}\n\nmodule.exports = config\n"
  },
  {
    "path": "examples/angular/optimistic-updates/README.md",
    "content": "# TanStack Query Angular optimistic-updates example\n\nTo run this example:\n\n- `npm install` or `yarn` or `pnpm i` or `bun i`\n- `npm run start` or `yarn start` or `pnpm start` or `bun start`\n"
  },
  {
    "path": "examples/angular/optimistic-updates/angular.json",
    "content": "{\n  \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n  \"version\": 1,\n  \"cli\": {\n    \"packageManager\": \"pnpm\",\n    \"analytics\": false,\n    \"cache\": {\n      \"enabled\": false\n    }\n  },\n  \"newProjectRoot\": \"projects\",\n  \"projects\": {\n    \"optimistic-updates\": {\n      \"projectType\": \"application\",\n      \"schematics\": {\n        \"@schematics/angular:component\": {\n          \"inlineTemplate\": true,\n          \"inlineStyle\": true,\n          \"skipTests\": true\n        },\n        \"@schematics/angular:class\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:directive\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:guard\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:interceptor\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:pipe\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:resolver\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:service\": {\n          \"skipTests\": true\n        }\n      },\n      \"root\": \"\",\n      \"sourceRoot\": \"src\",\n      \"prefix\": \"app\",\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular/build:application\",\n          \"options\": {\n            \"outputPath\": \"dist/optimistic-updates\",\n            \"index\": \"src/index.html\",\n            \"browser\": \"src/main.ts\",\n            \"polyfills\": [\"zone.js\"],\n            \"tsConfig\": \"tsconfig.app.json\",\n            \"assets\": [\"src/favicon.ico\", \"src/assets\"],\n            \"styles\": [],\n            \"scripts\": []\n          },\n          \"configurations\": {\n            \"production\": {\n              \"budgets\": [\n                {\n                  \"type\": \"initial\",\n                  \"maximumWarning\": \"500kb\",\n                  \"maximumError\": \"1mb\"\n                },\n                {\n                  \"type\": \"anyComponentStyle\",\n                  \"maximumWarning\": \"2kb\",\n                  \"maximumError\": \"4kb\"\n                }\n              ],\n              \"outputHashing\": \"all\"\n            },\n            \"development\": {\n              \"optimization\": false,\n              \"extractLicenses\": false,\n              \"sourceMap\": true\n            }\n          },\n          \"defaultConfiguration\": \"production\"\n        },\n        \"serve\": {\n          \"builder\": \"@angular/build:dev-server\",\n          \"configurations\": {\n            \"production\": {\n              \"buildTarget\": \"optimistic-updates:build:production\"\n            },\n            \"development\": {\n              \"buildTarget\": \"optimistic-updates:build:development\"\n            }\n          },\n          \"defaultConfiguration\": \"development\"\n        },\n        \"extract-i18n\": {\n          \"builder\": \"@angular/build:extract-i18n\",\n          \"options\": {\n            \"buildTarget\": \"optimistic-updates:build\"\n          }\n        }\n      }\n    }\n  },\n  \"schematics\": {\n    \"@schematics/angular:component\": {\n      \"type\": \"component\"\n    },\n    \"@schematics/angular:directive\": {\n      \"type\": \"directive\"\n    },\n    \"@schematics/angular:service\": {\n      \"type\": \"service\"\n    },\n    \"@schematics/angular:guard\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:interceptor\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:module\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:pipe\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:resolver\": {\n      \"typeSeparator\": \".\"\n    }\n  }\n}\n"
  },
  {
    "path": "examples/angular/optimistic-updates/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-angular-optimistic-updates\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"ng\": \"ng\",\n    \"start\": \"ng serve\",\n    \"build\": \"ng build\",\n    \"watch\": \"ng build --watch --configuration development\"\n  },\n  \"private\": true,\n  \"dependencies\": {\n    \"@angular/common\": \"^20.0.0\",\n    \"@angular/compiler\": \"^20.0.0\",\n    \"@angular/core\": \"^20.0.0\",\n    \"@angular/forms\": \"^20.0.0\",\n    \"@angular/platform-browser\": \"^20.0.0\",\n    \"@tanstack/angular-query-experimental\": \"^5.90.28\",\n    \"rxjs\": \"^7.8.2\",\n    \"tslib\": \"^2.8.1\",\n    \"zone.js\": \"0.15.0\"\n  },\n  \"devDependencies\": {\n    \"@angular/build\": \"^20.0.0\",\n    \"@angular/cli\": \"^20.0.0\",\n    \"@angular/compiler-cli\": \"^20.0.0\",\n    \"typescript\": \"5.8.3\"\n  }\n}\n"
  },
  {
    "path": "examples/angular/optimistic-updates/src/app/app.component.ts",
    "content": "import { ChangeDetectionStrategy, Component } from '@angular/core'\nimport { OptimisticUpdatesComponent } from './components/optimistic-updates.component'\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  selector: 'app-root',\n  template: `<optimistic-updates />`,\n  imports: [OptimisticUpdatesComponent],\n})\nexport class AppComponent {}\n"
  },
  {
    "path": "examples/angular/optimistic-updates/src/app/app.config.ts",
    "content": "import {\n  provideHttpClient,\n  withFetch,\n  withInterceptors,\n} from '@angular/common/http'\nimport {\n  QueryClient,\n  provideTanStackQuery,\n} from '@tanstack/angular-query-experimental'\nimport { withDevtools } from '@tanstack/angular-query-experimental/devtools'\nimport { mockInterceptor } from './interceptor/mock-api.interceptor'\nimport type { ApplicationConfig } from '@angular/core'\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideHttpClient(withFetch(), withInterceptors([mockInterceptor])),\n    provideTanStackQuery(\n      new QueryClient({\n        defaultOptions: {\n          queries: {\n            gcTime: 1000 * 60 * 60 * 24, // 24 hours\n          },\n        },\n      }),\n      withDevtools(),\n    ),\n  ],\n}\n"
  },
  {
    "path": "examples/angular/optimistic-updates/src/app/components/optimistic-updates.component.ts",
    "content": "import { ChangeDetectionStrategy, Component, inject } from '@angular/core'\nimport {\n  injectMutation,\n  injectQuery,\n} from '@tanstack/angular-query-experimental'\nimport { FormsModule } from '@angular/forms'\nimport { DatePipe } from '@angular/common'\nimport { TasksService } from '../services/tasks.service'\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  selector: 'optimistic-updates',\n  imports: [FormsModule, DatePipe],\n  template: `\n    <p>\n      In this example, new items can be created using a mutation. The new item\n      will be optimistically added to the list in hopes that the server accepts\n      the item. If it does, the list is refetched with the true items from the\n      list. Every now and then, the mutation may fail though. When that happens,\n      the previous list of items is restored and the list is again refetched\n      from the server.\n    </p>\n\n    <hr />\n    @if (tasks.isLoading()) {\n      <p>Loading...</p>\n    }\n\n    <div class=\"container\">\n      <label>\n        <input type=\"checkbox\" [(ngModel)]=\"failMutation\" />\n        Fail Mutation\n      </label>\n\n      <div class=\"input-container\">\n        <input type=\"text\" [(ngModel)]=\"newItem\" placeholder=\"Enter text\" />\n        <button (click)=\"addItem()\">Create</button>\n        <ul>\n          @for (task of tasks.data(); track task) {\n            <li>{{ task }}</li>\n          }\n        </ul>\n\n        <div>\n          Updated At: {{ tasks.dataUpdatedAt() | date: 'MMMM d, h:mm:ss a ' }}\n        </div>\n      </div>\n      @if (!tasks.isLoading() && tasks.isFetching()) {\n        <p>Fetching in background</p>\n      }\n    </div>\n  `,\n})\nexport class OptimisticUpdatesComponent {\n  #tasksService = inject(TasksService)\n\n  tasks = injectQuery(() => this.#tasksService.allTasks())\n  clearMutation = injectMutation(() => this.#tasksService.addTask())\n  addMutation = injectMutation(() => this.#tasksService.addTask())\n\n  newItem = ''\n  failMutation = false\n\n  addItem() {\n    if (!this.newItem) return\n\n    this.addMutation.mutate({\n      task: this.newItem,\n      failMutation: this.failMutation,\n    })\n    this.newItem = ''\n  }\n}\n"
  },
  {
    "path": "examples/angular/optimistic-updates/src/app/interceptor/mock-api.interceptor.ts",
    "content": "/**\n * MockApiInterceptor is used to simulate API responses for `/api/tasks` endpoints.\n * It handles the following operations:\n * - GET: Fetches all tasks from sessionStorage.\n * - POST: Adds a new task to sessionStorage.\n * Simulated responses include a delay to mimic network latency.\n */\nimport { HttpResponse } from '@angular/common/http'\nimport { delay, of } from 'rxjs'\nimport type {\n  HttpEvent,\n  HttpHandlerFn,\n  HttpInterceptorFn,\n  HttpRequest,\n} from '@angular/common/http'\nimport type { Observable } from 'rxjs'\n\nexport const mockInterceptor: HttpInterceptorFn = (\n  req: HttpRequest<unknown>,\n  next: HttpHandlerFn,\n): Observable<HttpEvent<any>> => {\n  const respondWith = (status: number, body: any) =>\n    of(new HttpResponse({ status, body })).pipe(delay(1000))\n  if (req.url === '/api/tasks') {\n    switch (req.method) {\n      case 'GET':\n        return respondWith(\n          200,\n          JSON.parse(\n            sessionStorage.getItem('optimistic-updates-tasks') || '[]',\n          ),\n        )\n      case 'POST':\n        const tasks = JSON.parse(\n          sessionStorage.getItem('optimistic-updates-tasks') || '[]',\n        )\n        tasks.push(req.body)\n        sessionStorage.setItem(\n          'optimistic-updates-tasks',\n          JSON.stringify(tasks),\n        )\n        return respondWith(201, {\n          status: 'success',\n          task: req.body,\n        })\n    }\n  }\n  if (req.url === '/api/tasks-wrong-url') {\n    return respondWith(500, {\n      status: 'error',\n    })\n  }\n\n  return next(req)\n}\n"
  },
  {
    "path": "examples/angular/optimistic-updates/src/app/services/tasks.service.ts",
    "content": "import { HttpClient } from '@angular/common/http'\nimport { Injectable, inject } from '@angular/core'\nimport {\n  QueryClient,\n  mutationOptions,\n  queryOptions,\n} from '@tanstack/angular-query-experimental'\n\nimport { lastValueFrom } from 'rxjs'\n\n@Injectable({\n  providedIn: 'root',\n})\nexport class TasksService {\n  #queryClient = inject(QueryClient) // Manages query state and caching\n  #http = inject(HttpClient) // Handles HTTP requests\n\n  /**\n   * Fetches all tasks from the API.\n   * Returns an observable containing an array of task strings.\n   */\n  allTasks = () =>\n    queryOptions({\n      queryKey: ['tasks'],\n      queryFn: () => {\n        return lastValueFrom(this.#http.get<Array<string>>('/api/tasks'))\n      },\n    })\n\n  /**\n   * Creates a mutation for adding a task.\n   * On success, invalidates and refetches the \"tasks\" query cache to update the task list.\n   */\n  addTask() {\n    return mutationOptions({\n      mutationFn: ({\n        task,\n        failMutation = false,\n      }: {\n        task: string\n        failMutation: boolean\n      }) =>\n        lastValueFrom(\n          this.#http.post(\n            `/api/tasks${failMutation ? '-wrong-url' : ''}`,\n            task,\n          ),\n        ),\n      mutationKey: ['tasks'],\n      onSuccess: () => {\n        this.#queryClient.invalidateQueries({ queryKey: ['tasks'] })\n      },\n      onMutate: async ({ task }) => {\n        // Cancel any outgoing refetches\n        // (so they don't overwrite our optimistic update)\n        await this.#queryClient.cancelQueries({ queryKey: ['tasks'] })\n\n        // Snapshot the previous value\n        const previousTodos = this.#queryClient.getQueryData<Array<string>>([\n          'tasks',\n        ])\n\n        // Optimistically update to the new value\n        if (previousTodos) {\n          this.#queryClient.setQueryData<Array<string>>(\n            ['tasks'],\n            [...previousTodos, task],\n          )\n        }\n\n        return previousTodos\n      },\n      onError: (err, variables, context) => {\n        if (context) {\n          this.#queryClient.setQueryData<Array<string>>(['tasks'], context)\n        }\n      },\n      // Always refetch after error or success:\n      onSettled: () => {\n        this.#queryClient.invalidateQueries({ queryKey: ['tasks'] })\n      },\n    })\n  }\n}\n"
  },
  {
    "path": "examples/angular/optimistic-updates/src/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>TanStack Query Angular Optimistic Updates Example</title>\n    <base href=\"/\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <link rel=\"icon\" type=\"image/x-icon\" href=\"favicon.ico\" />\n  </head>\n  <body>\n    <app-root></app-root>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/angular/optimistic-updates/src/main.ts",
    "content": "import { bootstrapApplication } from '@angular/platform-browser'\nimport { appConfig } from './app/app.config'\nimport { AppComponent } from './app/app.component'\n\nbootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err))\n"
  },
  {
    "path": "examples/angular/optimistic-updates/tsconfig.app.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./out-tsc/app\",\n    \"types\": []\n  },\n  \"files\": [\"src/main.ts\"],\n  \"include\": [\"src/**/*.d.ts\"]\n}\n"
  },
  {
    "path": "examples/angular/optimistic-updates/tsconfig.json",
    "content": "{\n  \"compileOnSave\": false,\n  \"compilerOptions\": {\n    \"outDir\": \"./dist/out-tsc\",\n    \"forceConsistentCasingInFileNames\": true,\n    \"strict\": true,\n    \"noImplicitOverride\": true,\n    \"noPropertyAccessFromIndexSignature\": true,\n    \"noImplicitReturns\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"skipLibCheck\": true,\n    \"isolatedModules\": true,\n    \"esModuleInterop\": true,\n    \"sourceMap\": true,\n    \"declaration\": false,\n    \"experimentalDecorators\": true,\n    \"moduleResolution\": \"Bundler\",\n    \"importHelpers\": true,\n    \"target\": \"ES2022\",\n    \"module\": \"ES2022\",\n    \"useDefineForClassFields\": false,\n    \"lib\": [\"ES2022\", \"dom\"]\n  },\n  \"angularCompilerOptions\": {\n    \"enableI18nLegacyMessageIdFormat\": false,\n    \"strictInjectionParameters\": true,\n    \"strictInputAccessModifiers\": true,\n    \"strictStandalone\": true,\n    \"strictTemplates\": true\n  }\n}\n"
  },
  {
    "path": "examples/angular/pagination/.devcontainer/devcontainer.json",
    "content": "{\n  \"name\": \"Node.js\",\n  \"image\": \"mcr.microsoft.com/devcontainers/javascript-node:22\"\n}\n"
  },
  {
    "path": "examples/angular/pagination/README.md",
    "content": "# TanStack Query Angular pagination example\n\nTo run this example:\n\n- `npm install` or `yarn` or `pnpm i` or `bun i`\n- `npm run start` or `yarn start` or `pnpm start` or `bun start`\n"
  },
  {
    "path": "examples/angular/pagination/angular.json",
    "content": "{\n  \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n  \"version\": 1,\n  \"cli\": {\n    \"packageManager\": \"pnpm\",\n    \"analytics\": false,\n    \"cache\": {\n      \"enabled\": false\n    }\n  },\n  \"newProjectRoot\": \"projects\",\n  \"projects\": {\n    \"pagination\": {\n      \"projectType\": \"application\",\n      \"schematics\": {\n        \"@schematics/angular:component\": {\n          \"inlineTemplate\": true,\n          \"inlineStyle\": true,\n          \"skipTests\": true\n        },\n        \"@schematics/angular:class\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:directive\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:guard\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:interceptor\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:pipe\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:resolver\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:service\": {\n          \"skipTests\": true\n        }\n      },\n      \"root\": \"\",\n      \"sourceRoot\": \"src\",\n      \"prefix\": \"app\",\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular/build:application\",\n          \"options\": {\n            \"outputPath\": \"dist/pagination\",\n            \"index\": \"src/index.html\",\n            \"browser\": \"src/main.ts\",\n            \"polyfills\": [\"zone.js\"],\n            \"tsConfig\": \"tsconfig.app.json\",\n            \"assets\": [\"src/favicon.ico\"],\n            \"styles\": [],\n            \"scripts\": []\n          },\n          \"configurations\": {\n            \"production\": {\n              \"budgets\": [\n                {\n                  \"type\": \"initial\",\n                  \"maximumWarning\": \"500kb\",\n                  \"maximumError\": \"1mb\"\n                },\n                {\n                  \"type\": \"anyComponentStyle\",\n                  \"maximumWarning\": \"2kb\",\n                  \"maximumError\": \"4kb\"\n                }\n              ],\n              \"outputHashing\": \"all\"\n            },\n            \"development\": {\n              \"optimization\": false,\n              \"extractLicenses\": false,\n              \"sourceMap\": true\n            }\n          },\n          \"defaultConfiguration\": \"production\"\n        },\n        \"serve\": {\n          \"builder\": \"@angular/build:dev-server\",\n          \"configurations\": {\n            \"production\": {\n              \"buildTarget\": \"pagination:build:production\"\n            },\n            \"development\": {\n              \"buildTarget\": \"pagination:build:development\"\n            }\n          },\n          \"defaultConfiguration\": \"development\"\n        },\n        \"extract-i18n\": {\n          \"builder\": \"@angular/build:extract-i18n\",\n          \"options\": {\n            \"buildTarget\": \"pagination:build\"\n          }\n        }\n      }\n    }\n  },\n  \"schematics\": {\n    \"@schematics/angular:component\": {\n      \"type\": \"component\"\n    },\n    \"@schematics/angular:directive\": {\n      \"type\": \"directive\"\n    },\n    \"@schematics/angular:service\": {\n      \"type\": \"service\"\n    },\n    \"@schematics/angular:guard\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:interceptor\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:module\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:pipe\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:resolver\": {\n      \"typeSeparator\": \".\"\n    }\n  }\n}\n"
  },
  {
    "path": "examples/angular/pagination/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-angular-pagination\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"ng\": \"ng\",\n    \"start\": \"ng serve\",\n    \"build\": \"ng build\",\n    \"watch\": \"ng build --watch --configuration development\"\n  },\n  \"dependencies\": {\n    \"@angular/common\": \"^20.0.0\",\n    \"@angular/compiler\": \"^20.0.0\",\n    \"@angular/core\": \"^20.0.0\",\n    \"@angular/platform-browser\": \"^20.0.0\",\n    \"@tanstack/angular-query-experimental\": \"^5.90.28\",\n    \"rxjs\": \"^7.8.2\",\n    \"tslib\": \"^2.8.1\",\n    \"zone.js\": \"0.15.0\"\n  },\n  \"devDependencies\": {\n    \"@angular/build\": \"^20.0.0\",\n    \"@angular/cli\": \"^20.0.0\",\n    \"@angular/compiler-cli\": \"^20.0.0\",\n    \"typescript\": \"5.8.3\"\n  }\n}\n"
  },
  {
    "path": "examples/angular/pagination/src/app/api/projects-mock.interceptor.ts",
    "content": "import { HttpResponse } from '@angular/common/http'\nimport { delay, of } from 'rxjs'\nimport type { Observable } from 'rxjs'\nimport type { HttpEvent, HttpInterceptorFn } from '@angular/common/http'\n\nexport const projectsMockInterceptor: HttpInterceptorFn = (\n  req,\n  next,\n): Observable<HttpEvent<any>> => {\n  const { url } = req\n\n  if (url.includes('/api/projects')) {\n    const page = parseInt(\n      new URLSearchParams(req.url.split('?')[1]).get('page') || '0',\n      10,\n    )\n    const pageSize = 10\n\n    const projects = Array(pageSize)\n      .fill(0)\n      .map((_, i) => {\n        const id = page * pageSize + (i + 1)\n        return {\n          name: 'Project ' + id,\n          id,\n        }\n      })\n\n    return of(\n      new HttpResponse({\n        status: 200,\n        body: {\n          projects,\n          hasMore: page < 9,\n        },\n      }),\n    ).pipe(delay(1000))\n  }\n  return next(req)\n}\n"
  },
  {
    "path": "examples/angular/pagination/src/app/app.component.ts",
    "content": "import { ChangeDetectionStrategy, Component } from '@angular/core'\nimport { ExampleComponent } from './components/example.component'\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  selector: 'app-root',\n  template: `<example />`,\n  imports: [ExampleComponent],\n})\nexport class AppComponent {}\n"
  },
  {
    "path": "examples/angular/pagination/src/app/app.config.ts",
    "content": "import {\n  provideHttpClient,\n  withFetch,\n  withInterceptors,\n} from '@angular/common/http'\nimport {\n  QueryClient,\n  provideTanStackQuery,\n} from '@tanstack/angular-query-experimental'\nimport { withDevtools } from '@tanstack/angular-query-experimental/devtools'\nimport { projectsMockInterceptor } from './api/projects-mock.interceptor'\nimport type { ApplicationConfig } from '@angular/core'\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideHttpClient(withInterceptors([projectsMockInterceptor]), withFetch()),\n    provideTanStackQuery(new QueryClient(), withDevtools()),\n  ],\n}\n"
  },
  {
    "path": "examples/angular/pagination/src/app/components/example.component.html",
    "content": "<div>\n  <p>\n    In this example, each page of data remains visible as the next page is\n    fetched. The buttons and capability to proceed to the next page are also\n    supressed until the next page cursor is known. Each page is cached as a\n    normal query too, so when going to previous pages, you'll see them\n    instantaneously while they are also refetched invisibly in the background.\n  </p>\n\n  @if (query.isPending()) {\n    <div>Loading...</div>\n  } @else if (query.isError()) {\n    <div>Error: {{ query.error().message }}</div>\n  } @else if (query.isSuccess()) {\n    <div>\n      @for (project of query.data().projects; track project.id) {\n        <p>{{ project.name }}</p>\n      }\n    </div>\n  }\n\n  <div>Current Page: {{ page() + 1 }}</div>\n\n  <button (click)=\"previousPage()\" [disabled]=\"page() === 0\">\n    Previous Page\n  </button>\n  <button\n    (click)=\"nextPage()\"\n    [disabled]=\"query.isPlaceholderData() || !query.data()?.hasMore\"\n  >\n    Next Page\n  </button>\n  <!-- Since the last page's data potentially sticks around between page requests, -->\n  <!-- we can use `isFetching` to show a background loading -->\n  <!-- indicator since our `status === 'pending'` state won't be triggered -->\n  @if (query.isFetching()) {\n    <span>Loading...</span>\n  }\n</div>\n"
  },
  {
    "path": "examples/angular/pagination/src/app/components/example.component.ts",
    "content": "import {\n  ChangeDetectionStrategy,\n  Component,\n  effect,\n  inject,\n  signal,\n  untracked,\n} from '@angular/core'\nimport {\n  QueryClient,\n  injectQuery,\n  keepPreviousData,\n} from '@tanstack/angular-query-experimental'\nimport { lastValueFrom } from 'rxjs'\nimport { ProjectsService } from '../services/projects.service'\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  selector: 'example',\n  templateUrl: './example.component.html',\n})\nexport class ExampleComponent {\n  readonly queryClient = inject(QueryClient)\n  readonly projectsService = inject(ProjectsService)\n  readonly page = signal(0)\n\n  readonly query = injectQuery(() => ({\n    queryKey: ['projects', this.page()],\n    queryFn: () => {\n      return lastValueFrom(this.projectsService.getProjects(this.page()))\n    },\n    placeholderData: keepPreviousData,\n    staleTime: 5000,\n  }))\n\n  readonly prefetchEffect = effect(() => {\n    const data = this.query.data()\n    const isPlaceholderData = this.query.isPlaceholderData()\n    const newPage = this.page() + 1\n\n    untracked(() => {\n      if (!isPlaceholderData && data?.hasMore) {\n        void this.queryClient.prefetchQuery({\n          queryKey: ['projects', newPage],\n          queryFn: () =>\n            lastValueFrom(this.projectsService.getProjects(newPage)),\n        })\n      }\n    })\n  })\n\n  previousPage() {\n    this.page.update((currentPage) => {\n      return Math.max(currentPage - 1, 0)\n    })\n  }\n\n  nextPage() {\n    this.page.update((currentPage) => {\n      return this.query.data()?.hasMore ? currentPage + 1 : currentPage\n    })\n  }\n}\n"
  },
  {
    "path": "examples/angular/pagination/src/app/services/projects.service.ts",
    "content": "import { HttpClient } from '@angular/common/http'\nimport { Injectable, inject } from '@angular/core'\n\ninterface Project {\n  id: number\n  name: string\n}\n\ninterface ProjectResponse {\n  projects: Array<Project>\n  hasMore: boolean\n}\n\n@Injectable({\n  providedIn: 'root',\n})\nexport class ProjectsService {\n  readonly #http = inject(HttpClient)\n\n  getProjects(page: number) {\n    return this.#http.get<ProjectResponse>(`/api/projects?page=${page}`)\n  }\n}\n"
  },
  {
    "path": "examples/angular/pagination/src/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>TanStack Query Angular pagination example</title>\n    <base href=\"/\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <link rel=\"icon\" type=\"image/x-icon\" href=\"favicon.ico\" />\n  </head>\n  <body>\n    <app-root></app-root>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/angular/pagination/src/main.ts",
    "content": "import { bootstrapApplication } from '@angular/platform-browser'\nimport { appConfig } from './app/app.config'\nimport { AppComponent } from './app/app.component'\n\nbootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err))\n"
  },
  {
    "path": "examples/angular/pagination/tsconfig.app.json",
    "content": "/* To learn more about this file see: https://angular.io/config/tsconfig. */\n{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./out-tsc/app\",\n    \"types\": []\n  },\n  \"files\": [\"src/main.ts\"],\n  \"include\": [\"src/**/*.d.ts\"]\n}\n"
  },
  {
    "path": "examples/angular/pagination/tsconfig.json",
    "content": "{\n  \"compileOnSave\": false,\n  \"compilerOptions\": {\n    \"outDir\": \"./dist/out-tsc\",\n    \"forceConsistentCasingInFileNames\": true,\n    \"strict\": true,\n    \"noImplicitOverride\": true,\n    \"noPropertyAccessFromIndexSignature\": true,\n    \"noImplicitReturns\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"skipLibCheck\": true,\n    \"isolatedModules\": true,\n    \"esModuleInterop\": true,\n    \"sourceMap\": true,\n    \"declaration\": false,\n    \"experimentalDecorators\": true,\n    \"moduleResolution\": \"Bundler\",\n    \"importHelpers\": true,\n    \"target\": \"ES2022\",\n    \"module\": \"ES2022\",\n    \"useDefineForClassFields\": false,\n    \"lib\": [\"ES2022\", \"dom\"]\n  },\n  \"angularCompilerOptions\": {\n    \"enableI18nLegacyMessageIdFormat\": false,\n    \"strictInjectionParameters\": true,\n    \"strictInputAccessModifiers\": true,\n    \"strictStandalone\": true,\n    \"strictTemplates\": true\n  }\n}\n"
  },
  {
    "path": "examples/angular/query-options-from-a-service/.devcontainer/devcontainer.json",
    "content": "{\n  \"name\": \"Node.js\",\n  \"image\": \"mcr.microsoft.com/devcontainers/javascript-node:22\"\n}\n"
  },
  {
    "path": "examples/angular/query-options-from-a-service/.eslintrc.cjs",
    "content": "// @ts-check\n\n/** @type {import('eslint').Linter.Config} */\nconst config = {}\n\nmodule.exports = config\n"
  },
  {
    "path": "examples/angular/query-options-from-a-service/README.md",
    "content": "# TanStack Query Angular query options from a service example\n\nTo run this example:\n\n- `npm install` or `yarn` or `pnpm i` or `bun i`\n- `npm run start` or `yarn start` or `pnpm start` or `bun start`\n"
  },
  {
    "path": "examples/angular/query-options-from-a-service/angular.json",
    "content": "{\n  \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n  \"version\": 1,\n  \"cli\": {\n    \"packageManager\": \"pnpm\",\n    \"analytics\": false,\n    \"cache\": {\n      \"enabled\": false\n    }\n  },\n  \"newProjectRoot\": \"projects\",\n  \"projects\": {\n    \"query-options-from-a-service\": {\n      \"projectType\": \"application\",\n      \"schematics\": {\n        \"@schematics/angular:component\": {\n          \"inlineTemplate\": true,\n          \"inlineStyle\": true,\n          \"skipTests\": true\n        },\n        \"@schematics/angular:class\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:directive\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:guard\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:interceptor\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:pipe\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:resolver\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:service\": {\n          \"skipTests\": true\n        }\n      },\n      \"root\": \"\",\n      \"sourceRoot\": \"src\",\n      \"prefix\": \"app\",\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular/build:application\",\n          \"options\": {\n            \"outputPath\": \"dist/query-options-from-a-service\",\n            \"index\": \"src/index.html\",\n            \"browser\": \"src/main.ts\",\n            \"polyfills\": [\"zone.js\"],\n            \"tsConfig\": \"tsconfig.app.json\",\n            \"assets\": [\"src/favicon.ico\", \"src/assets\"],\n            \"styles\": [],\n            \"scripts\": []\n          },\n          \"configurations\": {\n            \"production\": {\n              \"budgets\": [\n                {\n                  \"type\": \"initial\",\n                  \"maximumWarning\": \"500kb\",\n                  \"maximumError\": \"1mb\"\n                },\n                {\n                  \"type\": \"anyComponentStyle\",\n                  \"maximumWarning\": \"2kb\",\n                  \"maximumError\": \"4kb\"\n                }\n              ],\n              \"outputHashing\": \"all\"\n            },\n            \"development\": {\n              \"optimization\": false,\n              \"extractLicenses\": false,\n              \"sourceMap\": true\n            }\n          },\n          \"defaultConfiguration\": \"production\"\n        },\n        \"serve\": {\n          \"builder\": \"@angular/build:dev-server\",\n          \"configurations\": {\n            \"production\": {\n              \"buildTarget\": \"query-options-from-a-service:build:production\"\n            },\n            \"development\": {\n              \"buildTarget\": \"query-options-from-a-service:build:development\"\n            }\n          },\n          \"defaultConfiguration\": \"development\"\n        },\n        \"extract-i18n\": {\n          \"builder\": \"@angular/build:extract-i18n\",\n          \"options\": {\n            \"buildTarget\": \"query-options-from-a-service:build\"\n          }\n        }\n      }\n    }\n  },\n  \"schematics\": {\n    \"@schematics/angular:component\": {\n      \"type\": \"component\"\n    },\n    \"@schematics/angular:directive\": {\n      \"type\": \"directive\"\n    },\n    \"@schematics/angular:service\": {\n      \"type\": \"service\"\n    },\n    \"@schematics/angular:guard\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:interceptor\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:module\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:pipe\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:resolver\": {\n      \"typeSeparator\": \".\"\n    }\n  }\n}\n"
  },
  {
    "path": "examples/angular/query-options-from-a-service/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-angular-query-options-from-a-service\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"ng\": \"ng\",\n    \"start\": \"ng serve\",\n    \"build\": \"ng build\",\n    \"watch\": \"ng build --watch --configuration development\"\n  },\n  \"private\": true,\n  \"dependencies\": {\n    \"@angular/common\": \"^20.0.0\",\n    \"@angular/compiler\": \"^20.0.0\",\n    \"@angular/core\": \"^20.0.0\",\n    \"@angular/platform-browser\": \"^20.0.0\",\n    \"@angular/router\": \"^20.0.0\",\n    \"@tanstack/angular-query-experimental\": \"^5.90.28\",\n    \"rxjs\": \"^7.8.2\",\n    \"tslib\": \"^2.8.1\",\n    \"zone.js\": \"0.15.0\"\n  },\n  \"devDependencies\": {\n    \"@angular/build\": \"^20.0.0\",\n    \"@angular/cli\": \"^20.0.0\",\n    \"@angular/compiler-cli\": \"^20.0.0\",\n    \"typescript\": \"5.8.3\"\n  }\n}\n"
  },
  {
    "path": "examples/angular/query-options-from-a-service/src/app/app.component.html",
    "content": "<p>\n  As you visit the posts below, you will notice them in a loading state the\n  first time you load them. However, after you return to this list and click on\n  any posts you have already visited again, you will see them load instantly and\n  background refresh right before your eyes!\n  <strong>\n    (You may need to throttle your network speed to simulate longer loading\n    sequences)\n  </strong>\n</p>\n<router-outlet />\n"
  },
  {
    "path": "examples/angular/query-options-from-a-service/src/app/app.component.ts",
    "content": "import { Component } from '@angular/core'\nimport { RouterOutlet } from '@angular/router'\n\n@Component({\n  selector: 'app-root',\n  imports: [RouterOutlet],\n  templateUrl: './app.component.html',\n})\nexport class AppComponent {}\n"
  },
  {
    "path": "examples/angular/query-options-from-a-service/src/app/app.config.ts",
    "content": "import { provideHttpClient, withFetch } from '@angular/common/http'\nimport { provideRouter, withComponentInputBinding } from '@angular/router'\nimport {\n  QueryClient,\n  provideTanStackQuery,\n} from '@tanstack/angular-query-experimental'\n\nimport { withDevtools } from '@tanstack/angular-query-experimental/devtools'\nimport { routes } from './app.routes'\nimport type { ApplicationConfig } from '@angular/core'\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideHttpClient(withFetch()),\n    provideRouter(routes, withComponentInputBinding()),\n    provideTanStackQuery(new QueryClient(), withDevtools()),\n  ],\n}\n"
  },
  {
    "path": "examples/angular/query-options-from-a-service/src/app/app.routes.ts",
    "content": "import type { Route } from '@angular/router'\n\n// loadComponent lazily loads the component\n// when the component is the default export, there is no need to handle the promise\n\nexport const routes: Array<Route> = [\n  {\n    path: '',\n    loadComponent: () => import('./components/posts.component'),\n  },\n  {\n    path: 'post/:postId',\n    loadComponent: () => import('./components/post.component'),\n  },\n]\n"
  },
  {
    "path": "examples/angular/query-options-from-a-service/src/app/components/post.component.html",
    "content": "<div>\n  <div>\n    <a routerLink=\"/\" href=\"#\">Back</a>\n  </div>\n  @if (postQuery.isPending()) {\n    Loading...\n  } @else if (postQuery.isError()) {\n    Error: {{ postQuery.error().message }}\n  }\n  @if (postQuery.isSuccess()) {\n    @let post = postQuery.data();\n    <h1>{{ post.title }}</h1>\n    <div>\n      <p>{{ post.body }}</p>\n    </div>\n    @if (postQuery.isFetching()) {\n      Background Updating...\n    }\n  }\n</div>\n"
  },
  {
    "path": "examples/angular/query-options-from-a-service/src/app/components/post.component.ts",
    "content": "import {\n  ChangeDetectionStrategy,\n  Component,\n  inject,\n  input,\n  numberAttribute,\n} from '@angular/core'\nimport { RouterLink } from '@angular/router'\nimport { injectQuery } from '@tanstack/angular-query-experimental'\nimport { QueriesService } from '../services/queries-service'\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  selector: 'post',\n  templateUrl: './post.component.html',\n  imports: [RouterLink],\n})\nexport default class PostComponent {\n  private readonly queries = inject(QueriesService)\n\n  readonly postId = input.required({\n    transform: numberAttribute,\n  })\n\n  readonly postQuery = injectQuery(() => this.queries.post(this.postId()))\n}\n"
  },
  {
    "path": "examples/angular/query-options-from-a-service/src/app/components/posts.component.html",
    "content": "<div>\n  <h1>Posts</h1>\n  @if (postsQuery.isPending()) {\n    Loading...\n  } @else if (postsQuery.isError()) {\n    Error: {{ postsQuery.error().message }}\n  } @else if (postsQuery.isSuccess()) {\n    <div class=\"todo-container\">\n      @for (post of postsQuery.data(); track post.id) {\n        <p>\n          <!--          We can access the query data here to show bold links for-->\n          <!--          ones that are cached-->\n          <a\n            routerLink=\"post/{{ post.id }}\"\n            [style]=\"\n              queryClient.getQueryData(['post', post.id])\n                ? {\n                    fontWeight: 'bold',\n                    color: 'green',\n                  }\n                : {}\n            \"\n            >{{ post.title }}</a\n          >\n        </p>\n      }\n    </div>\n  }\n  <div>\n    @if (postsQuery.isFetching()) {\n      Background Updating...\n    }\n  </div>\n</div>\n"
  },
  {
    "path": "examples/angular/query-options-from-a-service/src/app/components/posts.component.ts",
    "content": "import { ChangeDetectionStrategy, Component, inject } from '@angular/core'\nimport { RouterLink } from '@angular/router'\nimport { QueryClient, injectQuery } from '@tanstack/angular-query-experimental'\nimport { QueriesService } from '../services/queries-service'\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  selector: 'posts',\n  templateUrl: './posts.component.html',\n  imports: [RouterLink],\n})\nexport default class PostsComponent {\n  private readonly queries = inject(QueriesService)\n  readonly postsQuery = injectQuery(() => this.queries.posts())\n  readonly queryClient = inject(QueryClient)\n}\n"
  },
  {
    "path": "examples/angular/query-options-from-a-service/src/app/services/queries-service.ts",
    "content": "import { Injectable, inject } from '@angular/core'\nimport { lastValueFrom } from 'rxjs'\nimport { queryOptions } from '@tanstack/angular-query-experimental'\nimport { HttpClient } from '@angular/common/http'\n\nexport interface Post {\n  id: number\n  title: string\n  body: string\n}\n\n@Injectable({\n  providedIn: 'root',\n})\nexport class QueriesService {\n  private readonly http = inject(HttpClient)\n\n  post(postId: number) {\n    return queryOptions({\n      queryKey: ['post', postId],\n      queryFn: () => {\n        return lastValueFrom(\n          this.http.get<Post>(\n            `https://jsonplaceholder.typicode.com/posts/${postId}`,\n          ),\n        )\n      },\n    })\n  }\n\n  posts() {\n    return queryOptions({\n      queryKey: ['posts'],\n      queryFn: () =>\n        lastValueFrom(\n          this.http.get<Array<Post>>(\n            'https://jsonplaceholder.typicode.com/posts',\n          ),\n        ),\n    })\n  }\n}\n"
  },
  {
    "path": "examples/angular/query-options-from-a-service/src/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>TanStack Query Angular query options from a service example</title>\n    <base href=\"/\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <link rel=\"icon\" type=\"image/x-icon\" href=\"favicon.ico\" />\n  </head>\n  <body>\n    <app-root></app-root>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/angular/query-options-from-a-service/src/main.ts",
    "content": "import { bootstrapApplication } from '@angular/platform-browser'\nimport { appConfig } from './app/app.config'\nimport { AppComponent } from './app/app.component'\n\nbootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err))\n"
  },
  {
    "path": "examples/angular/query-options-from-a-service/tsconfig.app.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./out-tsc/app\",\n    \"types\": []\n  },\n  \"files\": [\"src/main.ts\"],\n  \"include\": [\"src/**/*.d.ts\"]\n}\n"
  },
  {
    "path": "examples/angular/query-options-from-a-service/tsconfig.json",
    "content": "{\n  \"compileOnSave\": false,\n  \"compilerOptions\": {\n    \"outDir\": \"./dist/out-tsc\",\n    \"forceConsistentCasingInFileNames\": true,\n    \"strict\": true,\n    \"noImplicitOverride\": true,\n    \"noPropertyAccessFromIndexSignature\": true,\n    \"noImplicitReturns\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"skipLibCheck\": true,\n    \"isolatedModules\": true,\n    \"esModuleInterop\": true,\n    \"sourceMap\": true,\n    \"declaration\": false,\n    \"experimentalDecorators\": true,\n    \"moduleResolution\": \"Bundler\",\n    \"importHelpers\": true,\n    \"target\": \"ES2022\",\n    \"module\": \"ES2022\",\n    \"useDefineForClassFields\": false,\n    \"lib\": [\"ES2022\", \"dom\"]\n  },\n  \"angularCompilerOptions\": {\n    \"enableI18nLegacyMessageIdFormat\": false,\n    \"strictInjectionParameters\": true,\n    \"strictInputAccessModifiers\": true,\n    \"strictStandalone\": true,\n    \"strictTemplates\": true\n  }\n}\n"
  },
  {
    "path": "examples/angular/router/.devcontainer/devcontainer.json",
    "content": "{\n  \"name\": \"Node.js\",\n  \"image\": \"mcr.microsoft.com/devcontainers/javascript-node:22\"\n}\n"
  },
  {
    "path": "examples/angular/router/.eslintrc.cjs",
    "content": "// @ts-check\n\n/** @type {import('eslint').Linter.Config} */\nconst config = {}\n\nmodule.exports = config\n"
  },
  {
    "path": "examples/angular/router/README.md",
    "content": "# TanStack Query Angular router example\n\nTo run this example:\n\n- `npm install` or `yarn` or `pnpm i` or `bun i`\n- `npm run start` or `yarn start` or `pnpm start` or `bun start`\n"
  },
  {
    "path": "examples/angular/router/angular.json",
    "content": "{\n  \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n  \"version\": 1,\n  \"cli\": {\n    \"packageManager\": \"pnpm\",\n    \"analytics\": false,\n    \"cache\": {\n      \"enabled\": false\n    }\n  },\n  \"newProjectRoot\": \"projects\",\n  \"projects\": {\n    \"router\": {\n      \"projectType\": \"application\",\n      \"schematics\": {\n        \"@schematics/angular:component\": {\n          \"inlineTemplate\": true,\n          \"inlineStyle\": true,\n          \"skipTests\": true\n        },\n        \"@schematics/angular:class\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:directive\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:guard\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:interceptor\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:pipe\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:resolver\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:service\": {\n          \"skipTests\": true\n        }\n      },\n      \"root\": \"\",\n      \"sourceRoot\": \"src\",\n      \"prefix\": \"app\",\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular/build:application\",\n          \"options\": {\n            \"outputPath\": \"dist/router\",\n            \"index\": \"src/index.html\",\n            \"browser\": \"src/main.ts\",\n            \"polyfills\": [\"zone.js\"],\n            \"tsConfig\": \"tsconfig.app.json\",\n            \"assets\": [\"src/favicon.ico\", \"src/assets\"],\n            \"styles\": [],\n            \"scripts\": []\n          },\n          \"configurations\": {\n            \"production\": {\n              \"budgets\": [\n                {\n                  \"type\": \"initial\",\n                  \"maximumWarning\": \"500kb\",\n                  \"maximumError\": \"1mb\"\n                },\n                {\n                  \"type\": \"anyComponentStyle\",\n                  \"maximumWarning\": \"2kb\",\n                  \"maximumError\": \"4kb\"\n                }\n              ],\n              \"outputHashing\": \"all\"\n            },\n            \"development\": {\n              \"optimization\": false,\n              \"extractLicenses\": false,\n              \"sourceMap\": true\n            }\n          },\n          \"defaultConfiguration\": \"production\"\n        },\n        \"serve\": {\n          \"builder\": \"@angular/build:dev-server\",\n          \"configurations\": {\n            \"production\": {\n              \"buildTarget\": \"router:build:production\"\n            },\n            \"development\": {\n              \"buildTarget\": \"router:build:development\"\n            }\n          },\n          \"defaultConfiguration\": \"development\"\n        },\n        \"extract-i18n\": {\n          \"builder\": \"@angular/build:extract-i18n\",\n          \"options\": {\n            \"buildTarget\": \"router:build\"\n          }\n        }\n      }\n    }\n  },\n  \"schematics\": {\n    \"@schematics/angular:component\": {\n      \"type\": \"component\"\n    },\n    \"@schematics/angular:directive\": {\n      \"type\": \"directive\"\n    },\n    \"@schematics/angular:service\": {\n      \"type\": \"service\"\n    },\n    \"@schematics/angular:guard\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:interceptor\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:module\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:pipe\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:resolver\": {\n      \"typeSeparator\": \".\"\n    }\n  }\n}\n"
  },
  {
    "path": "examples/angular/router/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-angular-router\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"ng\": \"ng\",\n    \"start\": \"ng serve\",\n    \"build\": \"ng build\",\n    \"watch\": \"ng build --watch --configuration development\"\n  },\n  \"private\": true,\n  \"dependencies\": {\n    \"@angular/common\": \"^20.0.0\",\n    \"@angular/compiler\": \"^20.0.0\",\n    \"@angular/core\": \"^20.0.0\",\n    \"@angular/platform-browser\": \"^20.0.0\",\n    \"@angular/router\": \"^20.0.0\",\n    \"@tanstack/angular-query-experimental\": \"^5.90.28\",\n    \"rxjs\": \"^7.8.2\",\n    \"tslib\": \"^2.8.1\",\n    \"zone.js\": \"0.15.0\"\n  },\n  \"devDependencies\": {\n    \"@angular/build\": \"^20.0.0\",\n    \"@angular/cli\": \"^20.0.0\",\n    \"@angular/compiler-cli\": \"^20.0.0\",\n    \"typescript\": \"5.8.3\"\n  }\n}\n"
  },
  {
    "path": "examples/angular/router/src/app/app.component.html",
    "content": "<p>\n  As you visit the posts below, you will notice them in a loading state the\n  first time you load them. However, after you return to this list and click on\n  any posts you have already visited again, you will see them load instantly and\n  background refresh right before your eyes!\n  <strong>\n    (You may need to throttle your network speed to simulate longer loading\n    sequences)\n  </strong>\n</p>\n<router-outlet />\n"
  },
  {
    "path": "examples/angular/router/src/app/app.component.ts",
    "content": "import { ChangeDetectionStrategy, Component } from '@angular/core'\nimport { RouterOutlet } from '@angular/router'\n\n@Component({\n  selector: 'app-root',\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  imports: [RouterOutlet],\n  templateUrl: './app.component.html',\n})\nexport class AppComponent {}\n"
  },
  {
    "path": "examples/angular/router/src/app/app.config.ts",
    "content": "import { provideHttpClient, withFetch } from '@angular/common/http'\nimport { provideRouter, withComponentInputBinding } from '@angular/router'\nimport {\n  QueryClient,\n  provideTanStackQuery,\n} from '@tanstack/angular-query-experimental'\n\nimport { withDevtools } from '@tanstack/angular-query-experimental/devtools'\nimport { routes } from './app.routes'\nimport type { ApplicationConfig } from '@angular/core'\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideHttpClient(withFetch()),\n    provideTanStackQuery(new QueryClient(), withDevtools()),\n    provideRouter(routes, withComponentInputBinding()),\n  ],\n}\n"
  },
  {
    "path": "examples/angular/router/src/app/app.routes.ts",
    "content": "import type { Route } from '@angular/router'\n\n// loadComponent lazily loads the component\n// when the component is the default export, there is no need to handle the promise\n\nexport const routes: Array<Route> = [\n  {\n    path: '',\n    loadComponent: () => import('./components/posts.component'),\n  },\n  {\n    path: 'post/:postId',\n    loadComponent: () => import('./components/post.component'),\n  },\n]\n"
  },
  {
    "path": "examples/angular/router/src/app/components/post.component.html",
    "content": "<div>\n  <div>\n    <a routerLink=\"/\" href=\"#\">Back</a>\n  </div>\n  @if (postQuery.isPending()) {\n    Loading...\n  } @else if (postQuery.isError()) {\n    Error: {{ postQuery.error().message }}\n  }\n  @if (postQuery.isSuccess()) {\n    @let post = postQuery.data();\n    <h1>{{ post.title }}</h1>\n    <div>\n      <p>{{ post.body }}</p>\n    </div>\n    @if (postQuery.isFetching()) {\n      Background Updating...\n    }\n  }\n</div>\n"
  },
  {
    "path": "examples/angular/router/src/app/components/post.component.ts",
    "content": "import {\n  ChangeDetectionStrategy,\n  Component,\n  inject,\n  input,\n  numberAttribute,\n} from '@angular/core'\nimport { RouterLink } from '@angular/router'\nimport { injectQuery } from '@tanstack/angular-query-experimental'\nimport { lastValueFrom } from 'rxjs'\nimport { PostsService } from '../services/posts-service'\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  selector: 'post',\n  templateUrl: './post.component.html',\n  imports: [RouterLink],\n})\nexport default class PostComponent {\n  readonly #postsService = inject(PostsService)\n\n  // The Angular router will automatically bind postId\n  // as `withComponentInputBinding` is added to `provideRouter`.\n  // See https://angular.dev/api/router/withComponentInputBinding\n  readonly postId = input.required({\n    transform: numberAttribute,\n  })\n\n  readonly postQuery = injectQuery(() => ({\n    queryKey: ['post', this.postId()],\n    queryFn: () => {\n      return lastValueFrom(this.#postsService.postById$(this.postId()))\n    },\n  }))\n}\n"
  },
  {
    "path": "examples/angular/router/src/app/components/posts.component.html",
    "content": "<div>\n  <h1>Posts</h1>\n  @if (postsQuery.isPending()) {\n    Loading...\n  } @else if (postsQuery.isError()) {\n    Error: {{ postsQuery.error().message }}\n  } @else if (postsQuery.isSuccess()) {\n    <div class=\"todo-container\">\n      @for (post of postsQuery.data(); track post.id) {\n        <p>\n          <!--          We can access the query data here to show bold links for-->\n          <!--          ones that are cached-->\n          <a\n            routerLink=\"post/{{ post.id }}\"\n            [style]=\"\n              queryClient.getQueryData(['post', post.id])\n                ? {\n                    fontWeight: 'bold',\n                    color: 'green',\n                  }\n                : {}\n            \"\n            >{{ post.title }}</a\n          >\n        </p>\n      }\n    </div>\n  }\n  <div>\n    @if (postsQuery.isFetching()) {\n      Background Updating...\n    }\n  </div>\n</div>\n"
  },
  {
    "path": "examples/angular/router/src/app/components/posts.component.ts",
    "content": "import { ChangeDetectionStrategy, Component, inject } from '@angular/core'\nimport { RouterLink } from '@angular/router'\nimport { QueryClient, injectQuery } from '@tanstack/angular-query-experimental'\nimport { lastValueFrom } from 'rxjs'\nimport { PostsService } from '../services/posts-service'\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  selector: 'posts',\n  templateUrl: './posts.component.html',\n  imports: [RouterLink],\n})\nexport default class PostsComponent {\n  readonly #postsService = inject(PostsService)\n\n  readonly postsQuery = injectQuery(() => ({\n    queryKey: ['posts'],\n    queryFn: () => lastValueFrom(this.#postsService.allPosts$()),\n  }))\n\n  readonly queryClient = inject(QueryClient)\n}\n"
  },
  {
    "path": "examples/angular/router/src/app/services/posts-service.ts",
    "content": "import { HttpClient } from '@angular/common/http'\nimport { Injectable, inject } from '@angular/core'\n\n@Injectable({\n  providedIn: 'root',\n})\nexport class PostsService {\n  readonly #http = inject(HttpClient)\n\n  postById$ = (postId: number) =>\n    this.#http.get<Post>(`https://jsonplaceholder.typicode.com/posts/${postId}`)\n\n  allPosts$ = () =>\n    this.#http.get<Array<Post>>('https://jsonplaceholder.typicode.com/posts')\n}\n\nexport interface Post {\n  id: number\n  title: string\n  body: string\n}\n"
  },
  {
    "path": "examples/angular/router/src/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>TanStack Query Angular router example</title>\n    <base href=\"/\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <link rel=\"icon\" type=\"image/x-icon\" href=\"favicon.ico\" />\n  </head>\n  <body>\n    <app-root></app-root>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/angular/router/src/main.ts",
    "content": "import { bootstrapApplication } from '@angular/platform-browser'\nimport { appConfig } from './app/app.config'\nimport { AppComponent } from './app/app.component'\n\nbootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err))\n"
  },
  {
    "path": "examples/angular/router/tsconfig.app.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./out-tsc/app\",\n    \"types\": []\n  },\n  \"files\": [\"src/main.ts\"],\n  \"include\": [\"src/**/*.d.ts\"]\n}\n"
  },
  {
    "path": "examples/angular/router/tsconfig.json",
    "content": "{\n  \"compileOnSave\": false,\n  \"compilerOptions\": {\n    \"outDir\": \"./dist/out-tsc\",\n    \"forceConsistentCasingInFileNames\": true,\n    \"strict\": true,\n    \"noImplicitOverride\": true,\n    \"noPropertyAccessFromIndexSignature\": true,\n    \"noImplicitReturns\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"skipLibCheck\": true,\n    \"isolatedModules\": true,\n    \"esModuleInterop\": true,\n    \"sourceMap\": true,\n    \"declaration\": false,\n    \"experimentalDecorators\": true,\n    \"moduleResolution\": \"Bundler\",\n    \"importHelpers\": true,\n    \"target\": \"ES2022\",\n    \"module\": \"ES2022\",\n    \"useDefineForClassFields\": false,\n    \"lib\": [\"ES2022\", \"dom\"]\n  },\n  \"angularCompilerOptions\": {\n    \"enableI18nLegacyMessageIdFormat\": false,\n    \"strictInjectionParameters\": true,\n    \"strictInputAccessModifiers\": true,\n    \"strictStandalone\": true,\n    \"strictTemplates\": true\n  }\n}\n"
  },
  {
    "path": "examples/angular/rxjs/.devcontainer/devcontainer.json",
    "content": "{\n  \"name\": \"Node.js\",\n  \"image\": \"mcr.microsoft.com/devcontainers/javascript-node:22\"\n}\n"
  },
  {
    "path": "examples/angular/rxjs/.eslintrc.cjs",
    "content": "// @ts-check\n\n/** @type {import('eslint').Linter.Config} */\nconst config = {}\n\nmodule.exports = config\n"
  },
  {
    "path": "examples/angular/rxjs/README.md",
    "content": "# TanStack Query Angular RxJS Example\n\nTo run this example:\n\n- `npm install` or `yarn` or `pnpm i` or `bun i`\n- `npm run start` or `yarn start` or `pnpm start` or `bun start`\n"
  },
  {
    "path": "examples/angular/rxjs/angular.json",
    "content": "{\n  \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n  \"version\": 1,\n  \"cli\": {\n    \"packageManager\": \"pnpm\",\n    \"analytics\": false,\n    \"cache\": {\n      \"enabled\": false\n    }\n  },\n  \"newProjectRoot\": \"projects\",\n  \"projects\": {\n    \"rxjs\": {\n      \"projectType\": \"application\",\n      \"schematics\": {\n        \"@schematics/angular:component\": {\n          \"inlineTemplate\": true,\n          \"inlineStyle\": true,\n          \"skipTests\": true\n        },\n        \"@schematics/angular:class\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:directive\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:guard\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:interceptor\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:pipe\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:resolver\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:service\": {\n          \"skipTests\": true\n        }\n      },\n      \"root\": \"\",\n      \"sourceRoot\": \"src\",\n      \"prefix\": \"app\",\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular/build:application\",\n          \"options\": {\n            \"outputPath\": \"dist/rxjs\",\n            \"index\": \"src/index.html\",\n            \"browser\": \"src/main.ts\",\n            \"polyfills\": [\"zone.js\"],\n            \"tsConfig\": \"tsconfig.app.json\",\n            \"assets\": [\"src/favicon.ico\", \"src/mockServiceWorker.js\"],\n            \"styles\": [],\n            \"scripts\": []\n          },\n          \"configurations\": {\n            \"production\": {\n              \"budgets\": [\n                {\n                  \"type\": \"initial\",\n                  \"maximumWarning\": \"500kb\",\n                  \"maximumError\": \"1mb\"\n                },\n                {\n                  \"type\": \"anyComponentStyle\",\n                  \"maximumWarning\": \"2kb\",\n                  \"maximumError\": \"4kb\"\n                }\n              ],\n              \"outputHashing\": \"all\"\n            },\n            \"development\": {\n              \"optimization\": false,\n              \"extractLicenses\": false,\n              \"sourceMap\": true\n            }\n          },\n          \"defaultConfiguration\": \"production\"\n        },\n        \"serve\": {\n          \"builder\": \"@angular/build:dev-server\",\n          \"configurations\": {\n            \"production\": {\n              \"buildTarget\": \"rxjs:build:production\"\n            },\n            \"development\": {\n              \"buildTarget\": \"rxjs:build:development\"\n            }\n          },\n          \"defaultConfiguration\": \"development\"\n        },\n        \"extract-i18n\": {\n          \"builder\": \"@angular/build:extract-i18n\",\n          \"options\": {\n            \"buildTarget\": \"rxjs:build\"\n          }\n        }\n      }\n    }\n  },\n  \"schematics\": {\n    \"@schematics/angular:component\": {\n      \"type\": \"component\"\n    },\n    \"@schematics/angular:directive\": {\n      \"type\": \"directive\"\n    },\n    \"@schematics/angular:service\": {\n      \"type\": \"service\"\n    },\n    \"@schematics/angular:guard\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:interceptor\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:module\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:pipe\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:resolver\": {\n      \"typeSeparator\": \".\"\n    }\n  }\n}\n"
  },
  {
    "path": "examples/angular/rxjs/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-angular-rxjs\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"ng\": \"ng\",\n    \"start\": \"ng serve\",\n    \"build\": \"ng build\",\n    \"watch\": \"ng build --watch --configuration development\"\n  },\n  \"dependencies\": {\n    \"@angular/common\": \"^20.0.0\",\n    \"@angular/compiler\": \"^20.0.0\",\n    \"@angular/core\": \"^20.0.0\",\n    \"@angular/forms\": \"^20.0.0\",\n    \"@angular/platform-browser\": \"^20.0.0\",\n    \"@tanstack/angular-query-experimental\": \"^5.90.28\",\n    \"rxjs\": \"^7.8.2\",\n    \"tslib\": \"^2.8.1\",\n    \"zone.js\": \"0.15.0\"\n  },\n  \"devDependencies\": {\n    \"@angular/build\": \"^20.0.0\",\n    \"@angular/cli\": \"^20.0.0\",\n    \"@angular/compiler-cli\": \"^20.0.0\",\n    \"typescript\": \"5.8.3\"\n  }\n}\n"
  },
  {
    "path": "examples/angular/rxjs/src/app/api/autocomplete-mock.interceptor.ts",
    "content": "import { HttpResponse } from '@angular/common/http'\nimport { delayWhen, of, timer } from 'rxjs'\nimport type { Observable } from 'rxjs'\nimport type { HttpEvent, HttpInterceptorFn } from '@angular/common/http'\n\nexport const autocompleteMockInterceptor: HttpInterceptorFn = (\n  req,\n  next,\n): Observable<HttpEvent<any>> => {\n  const { url } = req\n\n  if (url.includes('/api/autocomplete')) {\n    const term = new URLSearchParams(req.url.split('?')[1]).get('term') || ''\n\n    const data = [\n      'C#',\n      'C++',\n      'Go',\n      'Java',\n      'JavaScript',\n      'Kotlin',\n      'Lisp',\n      'Objective-C',\n      'PHP',\n      'Perl',\n      'Python',\n      'R',\n      'Ruby',\n      'Rust',\n      'SQL',\n      'Scala',\n      'Shell',\n      'Swift',\n      'TypeScript',\n    ]\n\n    // Simulate network latency with a random delay between 100ms and 500ms\n    const delayDuration = Math.random() * (500 - 100) + 100\n    return of(\n      new HttpResponse({\n        status: 200,\n        body: {\n          suggestions: data.filter((item) =>\n            item.toLowerCase().startsWith(term.toLowerCase()),\n          ),\n        },\n      }),\n    ).pipe(delayWhen(() => timer(delayDuration)))\n  }\n  return next(req)\n}\n"
  },
  {
    "path": "examples/angular/rxjs/src/app/app.component.ts",
    "content": "import { ChangeDetectionStrategy, Component } from '@angular/core'\nimport { ExampleComponent } from './components/example.component'\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  selector: 'app-root',\n  template: `<example />`,\n  imports: [ExampleComponent],\n})\nexport class AppComponent {}\n"
  },
  {
    "path": "examples/angular/rxjs/src/app/app.config.ts",
    "content": "import {\n  provideHttpClient,\n  withFetch,\n  withInterceptors,\n} from '@angular/common/http'\nimport {\n  QueryClient,\n  provideTanStackQuery,\n} from '@tanstack/angular-query-experimental'\nimport { withDevtools } from '@tanstack/angular-query-experimental/devtools'\nimport { autocompleteMockInterceptor } from './api/autocomplete-mock.interceptor'\nimport type { ApplicationConfig } from '@angular/core'\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideHttpClient(\n      withFetch(),\n      withInterceptors([autocompleteMockInterceptor]),\n    ),\n    provideTanStackQuery(\n      new QueryClient({\n        defaultOptions: {\n          queries: {\n            gcTime: 1000 * 60 * 60 * 24, // 24 hours\n          },\n        },\n      }),\n      withDevtools(),\n    ),\n  ],\n}\n"
  },
  {
    "path": "examples/angular/rxjs/src/app/components/example.component.html",
    "content": "<h1>Search for a programming language</h1>\n\n<form [formGroup]=\"form\">\n  <input type=\"text\" formControlName=\"term\" />\n\n  @if (query.isSuccess() && query.data().suggestions.length) {\n    <ul>\n      @for (suggestion of query.data().suggestions; track suggestion) {\n        <li>{{ suggestion }}</li>\n      }\n    </ul>\n  }\n</form>\n"
  },
  {
    "path": "examples/angular/rxjs/src/app/components/example.component.ts",
    "content": "import { ChangeDetectionStrategy, Component, inject } from '@angular/core'\nimport { toSignal } from '@angular/core/rxjs-interop'\nimport { NonNullableFormBuilder, ReactiveFormsModule } from '@angular/forms'\nimport {\n  injectQuery,\n  keepPreviousData,\n} from '@tanstack/angular-query-experimental'\nimport { debounceTime, distinctUntilChanged, lastValueFrom } from 'rxjs'\nimport { AutocompleteService } from '../services/autocomplete-service'\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  selector: 'example',\n  templateUrl: './example.component.html',\n  imports: [ReactiveFormsModule],\n})\nexport class ExampleComponent {\n  readonly #autocompleteService = inject(AutocompleteService)\n  readonly #fb = inject(NonNullableFormBuilder)\n\n  readonly form = this.#fb.group({\n    term: '',\n  })\n\n  readonly term = toSignal(\n    this.form.controls.term.valueChanges.pipe(\n      debounceTime(300),\n      distinctUntilChanged(),\n    ),\n    { initialValue: '' },\n  )\n\n  readonly query = injectQuery(() => ({\n    queryKey: ['suggestions', this.term()],\n    queryFn: () => {\n      return lastValueFrom(\n        this.#autocompleteService.getSuggestions(this.term()),\n      )\n    },\n    placeholderData: keepPreviousData,\n    staleTime: 1000 * 60 * 5, // 5 minutes\n  }))\n}\n"
  },
  {
    "path": "examples/angular/rxjs/src/app/services/autocomplete-service.ts",
    "content": "import { HttpClient } from '@angular/common/http'\nimport { Injectable, inject } from '@angular/core'\nimport { of } from 'rxjs'\n\ninterface Response {\n  suggestions: Array<string>\n}\n\n@Injectable({\n  providedIn: 'root',\n})\nexport class AutocompleteService {\n  readonly #http = inject(HttpClient)\n\n  getSuggestions = (term: string = '') =>\n    term.trim() === ''\n      ? of({ suggestions: [] })\n      : this.#http.get<Response>(\n          `/api/autocomplete?term=${encodeURIComponent(term)}`,\n        )\n}\n"
  },
  {
    "path": "examples/angular/rxjs/src/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>TanStack Query Angular RxJS example</title>\n    <base href=\"/\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <link rel=\"icon\" type=\"image/x-icon\" href=\"favicon.ico\" />\n  </head>\n  <body>\n    <app-root></app-root>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/angular/rxjs/src/main.ts",
    "content": "import { bootstrapApplication } from '@angular/platform-browser'\nimport { appConfig } from './app/app.config'\nimport { AppComponent } from './app/app.component'\n\nbootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err))\n"
  },
  {
    "path": "examples/angular/rxjs/tsconfig.app.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./out-tsc/app\",\n    \"types\": []\n  },\n  \"files\": [\"src/main.ts\"],\n  \"include\": [\"src/**/*.d.ts\"]\n}\n"
  },
  {
    "path": "examples/angular/rxjs/tsconfig.json",
    "content": "{\n  \"compileOnSave\": false,\n  \"compilerOptions\": {\n    \"outDir\": \"./dist/out-tsc\",\n    \"forceConsistentCasingInFileNames\": true,\n    \"strict\": true,\n    \"noImplicitOverride\": true,\n    \"noPropertyAccessFromIndexSignature\": true,\n    \"noImplicitReturns\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"skipLibCheck\": true,\n    \"isolatedModules\": true,\n    \"esModuleInterop\": true,\n    \"sourceMap\": true,\n    \"declaration\": false,\n    \"experimentalDecorators\": true,\n    \"moduleResolution\": \"Bundler\",\n    \"importHelpers\": true,\n    \"target\": \"ES2022\",\n    \"module\": \"ES2022\",\n    \"useDefineForClassFields\": false,\n    \"lib\": [\"ES2022\", \"dom\"]\n  },\n  \"angularCompilerOptions\": {\n    \"enableI18nLegacyMessageIdFormat\": false,\n    \"strictInjectionParameters\": true,\n    \"strictInputAccessModifiers\": true,\n    \"strictStandalone\": true,\n    \"strictTemplates\": true\n  }\n}\n"
  },
  {
    "path": "examples/angular/simple/.devcontainer/devcontainer.json",
    "content": "{\n  \"name\": \"Node.js\",\n  \"image\": \"mcr.microsoft.com/devcontainers/javascript-node:22\"\n}\n"
  },
  {
    "path": "examples/angular/simple/.eslintrc.cjs",
    "content": "// @ts-check\n\n/** @type {import('eslint').Linter.Config} */\nconst config = {}\n\nmodule.exports = config\n"
  },
  {
    "path": "examples/angular/simple/README.md",
    "content": "# TanStack Query Angular simple example\n\nTo run this example:\n\n- `npm install` or `yarn` or `pnpm i` or `bun i`\n- `npm run start` or `yarn start` or `pnpm start` or `bun start`\n"
  },
  {
    "path": "examples/angular/simple/angular.json",
    "content": "{\n  \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n  \"version\": 1,\n  \"cli\": {\n    \"packageManager\": \"pnpm\",\n    \"analytics\": false,\n    \"cache\": {\n      \"enabled\": false\n    }\n  },\n  \"newProjectRoot\": \"projects\",\n  \"projects\": {\n    \"simple\": {\n      \"projectType\": \"application\",\n      \"schematics\": {\n        \"@schematics/angular:component\": {\n          \"inlineTemplate\": true,\n          \"inlineStyle\": true,\n          \"skipTests\": true\n        },\n        \"@schematics/angular:class\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:directive\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:guard\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:interceptor\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:pipe\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:resolver\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:service\": {\n          \"skipTests\": true\n        }\n      },\n      \"root\": \"\",\n      \"sourceRoot\": \"src\",\n      \"prefix\": \"app\",\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular/build:application\",\n          \"options\": {\n            \"outputPath\": \"dist/simple\",\n            \"index\": \"src/index.html\",\n            \"browser\": \"src/main.ts\",\n            \"polyfills\": [\"zone.js\"],\n            \"tsConfig\": \"tsconfig.app.json\",\n            \"assets\": [\"src/favicon.ico\", \"src/assets\"],\n            \"styles\": [\"src/styles.css\"],\n            \"scripts\": []\n          },\n          \"configurations\": {\n            \"production\": {\n              \"budgets\": [\n                {\n                  \"type\": \"initial\",\n                  \"maximumWarning\": \"500kb\",\n                  \"maximumError\": \"1mb\"\n                },\n                {\n                  \"type\": \"anyComponentStyle\",\n                  \"maximumWarning\": \"2kb\",\n                  \"maximumError\": \"4kb\"\n                }\n              ],\n              \"outputHashing\": \"all\"\n            },\n            \"development\": {\n              \"optimization\": false,\n              \"extractLicenses\": false,\n              \"sourceMap\": true\n            }\n          },\n          \"defaultConfiguration\": \"production\"\n        },\n        \"serve\": {\n          \"builder\": \"@angular/build:dev-server\",\n          \"configurations\": {\n            \"production\": {\n              \"buildTarget\": \"simple:build:production\"\n            },\n            \"development\": {\n              \"buildTarget\": \"simple:build:development\"\n            }\n          },\n          \"defaultConfiguration\": \"development\"\n        },\n        \"extract-i18n\": {\n          \"builder\": \"@angular/build:extract-i18n\",\n          \"options\": {\n            \"buildTarget\": \"simple:build\"\n          }\n        }\n      }\n    }\n  },\n  \"schematics\": {\n    \"@schematics/angular:component\": {\n      \"type\": \"component\"\n    },\n    \"@schematics/angular:directive\": {\n      \"type\": \"directive\"\n    },\n    \"@schematics/angular:service\": {\n      \"type\": \"service\"\n    },\n    \"@schematics/angular:guard\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:interceptor\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:module\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:pipe\": {\n      \"typeSeparator\": \".\"\n    },\n    \"@schematics/angular:resolver\": {\n      \"typeSeparator\": \".\"\n    }\n  }\n}\n"
  },
  {
    "path": "examples/angular/simple/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-angular-simple\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"ng\": \"ng\",\n    \"start\": \"ng serve\",\n    \"build\": \"ng build\",\n    \"watch\": \"ng build --watch --configuration development\"\n  },\n  \"private\": true,\n  \"dependencies\": {\n    \"@angular/common\": \"^20.0.0\",\n    \"@angular/compiler\": \"^20.0.0\",\n    \"@angular/core\": \"^20.0.0\",\n    \"@angular/platform-browser\": \"^20.0.0\",\n    \"@tanstack/angular-query-experimental\": \"^5.90.28\",\n    \"rxjs\": \"^7.8.2\",\n    \"tslib\": \"^2.8.1\",\n    \"zone.js\": \"0.15.0\"\n  },\n  \"devDependencies\": {\n    \"@angular/build\": \"^20.0.0\",\n    \"@angular/cli\": \"^20.0.0\",\n    \"@angular/compiler-cli\": \"^20.0.0\",\n    \"typescript\": \"5.8.3\"\n  }\n}\n"
  },
  {
    "path": "examples/angular/simple/src/app/app.component.ts",
    "content": "import { ChangeDetectionStrategy, Component } from '@angular/core'\nimport { SimpleExampleComponent } from './components/simple-example.component'\n\n@Component({\n  selector: 'app-root',\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  imports: [SimpleExampleComponent],\n  template: `<simple-example />`,\n})\nexport class AppComponent {}\n"
  },
  {
    "path": "examples/angular/simple/src/app/app.config.ts",
    "content": "import { provideHttpClient, withFetch } from '@angular/common/http'\nimport {\n  QueryClient,\n  provideTanStackQuery,\n} from '@tanstack/angular-query-experimental'\nimport { withDevtools } from '@tanstack/angular-query-experimental/devtools'\nimport type { ApplicationConfig } from '@angular/core'\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideHttpClient(withFetch()),\n    provideTanStackQuery(new QueryClient(), withDevtools()),\n  ],\n}\n"
  },
  {
    "path": "examples/angular/simple/src/app/components/simple-example.component.html",
    "content": "@if (query.isPending()) {\n  <div>Loading...</div>\n}\n@if (query.isError()) {\n  <div>An error has occurred: {{ query.error().message }}</div>\n}\n@if (query.data(); as data) {\n  <h1>{{ data.name }}</h1>\n  <p>{{ data.description }}</p>\n  <strong>👀 {{ data.subscribers_count }}</strong>\n  <strong>✨ {{ data.stargazers_count }}</strong>\n  <strong>🍴 {{ data.forks_count }}</strong>\n}\n"
  },
  {
    "path": "examples/angular/simple/src/app/components/simple-example.component.ts",
    "content": "import { ChangeDetectionStrategy, Component, inject } from '@angular/core'\nimport { injectQuery } from '@tanstack/angular-query-experimental'\nimport { HttpClient } from '@angular/common/http'\nimport { lastValueFrom } from 'rxjs'\n\ninterface Response {\n  name: string\n  description: string\n  subscribers_count: number\n  stargazers_count: number\n  forks_count: number\n}\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  selector: 'simple-example',\n  templateUrl: './simple-example.component.html',\n})\nexport class SimpleExampleComponent {\n  readonly #http = inject(HttpClient)\n\n  readonly query = injectQuery(() => ({\n    queryKey: ['repoData'],\n    queryFn: () =>\n      lastValueFrom(\n        this.#http.get<Response>('https://api.github.com/repos/tanstack/query'),\n      ),\n  }))\n}\n"
  },
  {
    "path": "examples/angular/simple/src/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>TanStack Query Angular simple example</title>\n    <base href=\"/\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <link rel=\"icon\" type=\"image/x-icon\" href=\"favicon.ico\" />\n  </head>\n  <body>\n    <app-root></app-root>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/angular/simple/src/main.ts",
    "content": "import { bootstrapApplication } from '@angular/platform-browser'\nimport { appConfig } from './app/app.config'\nimport { AppComponent } from './app/app.component'\n\nbootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err))\n"
  },
  {
    "path": "examples/angular/simple/src/styles.css",
    "content": "/* You can add global styles to this file, and also import other style files */\n"
  },
  {
    "path": "examples/angular/simple/tsconfig.app.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./out-tsc/app\",\n    \"types\": []\n  },\n  \"files\": [\"src/main.ts\"],\n  \"include\": [\"src/**/*.d.ts\"]\n}\n"
  },
  {
    "path": "examples/angular/simple/tsconfig.json",
    "content": "{\n  \"compileOnSave\": false,\n  \"compilerOptions\": {\n    \"outDir\": \"./dist/out-tsc\",\n    \"forceConsistentCasingInFileNames\": true,\n    \"strict\": true,\n    \"noImplicitOverride\": true,\n    \"noPropertyAccessFromIndexSignature\": true,\n    \"noImplicitReturns\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"skipLibCheck\": true,\n    \"isolatedModules\": true,\n    \"esModuleInterop\": true,\n    \"sourceMap\": true,\n    \"declaration\": false,\n    \"experimentalDecorators\": true,\n    \"moduleResolution\": \"Bundler\",\n    \"importHelpers\": true,\n    \"target\": \"ES2022\",\n    \"module\": \"ES2022\",\n    \"useDefineForClassFields\": false,\n    \"lib\": [\"ES2022\", \"dom\"]\n  },\n  \"angularCompilerOptions\": {\n    \"enableI18nLegacyMessageIdFormat\": false,\n    \"strictInjectionParameters\": true,\n    \"strictInputAccessModifiers\": true,\n    \"strictStandalone\": true,\n    \"strictTemplates\": true\n  }\n}\n"
  },
  {
    "path": "examples/preact/simple/.gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "examples/preact/simple/README.md",
    "content": "# `create-preact`\n\n<h2 align=\"center\">\n  <img height=\"256\" width=\"256\" src=\"./src/assets/preact.svg\">\n</h2>\n\n<h3 align=\"center\">Get started using Preact and Vite!</h3>\n\n## Getting Started\n\n- `pnpm dev` - Starts a dev server at http://localhost:5173/\n\n- `pnpm build` - Builds for production, emitting to `dist/`\n\n- `pnpm preview` - Starts a server at http://localhost:4173/ to test production build locally\n"
  },
  {
    "path": "examples/preact/simple/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/vite.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <meta name=\"color-scheme\" content=\"light dark\" />\n    <title>Vite + Preact</title>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/src/index.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/preact/simple/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-preact-simple\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/preact-query\": \"workspace:^\",\n    \"preact\": \"^10.28.0\"\n  },\n  \"devDependencies\": {\n    \"@preact/preset-vite\": \"^2.10.2\",\n    \"eslint\": \"^9.36.0\",\n    \"eslint-config-preact\": \"^2.0.0\",\n    \"typescript\": \"^5.9.3\",\n    \"vite\": \"^6.4.1\"\n  },\n  \"eslintConfig\": {\n    \"extends\": \"preact\"\n  }\n}\n"
  },
  {
    "path": "examples/preact/simple/src/index.tsx",
    "content": "import { render } from 'preact'\nimport {\n  QueryClient,\n  QueryClientProvider,\n  useQuery,\n} from '@tanstack/preact-query'\n\nconst queryClient = new QueryClient()\n\nexport function App() {\n  return (\n    <QueryClientProvider client={queryClient}>\n      <Example />\n    </QueryClientProvider>\n  )\n}\n\nconst Example = () => {\n  const { isPending, error, data, isFetching } = useQuery({\n    queryKey: ['repoData'],\n    queryFn: async () => {\n      const response = await fetch(\n        'https://api.github.com/repos/TanStack/query',\n      )\n      return await response.json()\n    },\n  })\n\n  if (isPending) return 'Loading...'\n\n  if (error !== null) return 'An error has occurred: ' + error.message\n\n  return (\n    <div>\n      <h1>{data.full_name}</h1>\n      <p>{data.description}</p>\n      <strong>👀 {data.subscribers_count}</strong>{' '}\n      <strong>✨ {data.stargazers_count}</strong>{' '}\n      <strong>🍴 {data.forks_count}</strong>\n      <div>{isFetching ? 'Updating...' : ''}</div>\n    </div>\n  )\n}\n\nconst app = document.getElementById('app')\nif (!app) throw new Error('Missing #app element')\n\nrender(<App />, app)\n"
  },
  {
    "path": "examples/preact/simple/src/style.css",
    "content": ":root {\n  font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;\n  line-height: 1.5;\n  font-weight: 400;\n\n  color: #222;\n  background-color: #ffffff;\n\n  font-synthesis: none;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-text-size-adjust: 100%;\n}\n\nbody {\n  margin: 0;\n  display: flex;\n  align-items: center;\n  min-height: 100vh;\n}\n\n#app {\n  max-width: 1280px;\n  margin: 0 auto;\n  text-align: center;\n}\n\nimg {\n  margin-bottom: 1.5rem;\n}\n\nimg:hover {\n  filter: drop-shadow(0 0 2em #673ab8aa);\n}\n\nsection {\n  margin-top: 5rem;\n  display: grid;\n  grid-template-columns: repeat(3, 1fr);\n  column-gap: 1.5rem;\n}\n\n.resource {\n  padding: 0.75rem 1.5rem;\n  border-radius: 0.5rem;\n  text-align: left;\n  text-decoration: none;\n  color: #222;\n  background-color: #f1f1f1;\n  border: 1px solid transparent;\n}\n\n.resource:hover {\n  border: 1px solid #000;\n  box-shadow: 0 25px 50px -12px #673ab888;\n}\n\n@media (max-width: 639px) {\n  #app {\n    margin: 2rem;\n  }\n  section {\n    margin-top: 5rem;\n    grid-template-columns: 1fr;\n    row-gap: 1rem;\n  }\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n    color: #ccc;\n    background-color: #1a1a1a;\n  }\n  .resource {\n    color: #ccc;\n    background-color: #161616;\n  }\n  .resource:hover {\n    border: 1px solid #bbb;\n  }\n}\n"
  },
  {
    "path": "examples/preact/simple/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"noEmit\": true,\n    \"allowJs\": true,\n    \"checkJs\": true,\n\n    /* Preact Config */\n    \"jsx\": \"react-jsx\",\n    \"jsxImportSource\": \"preact\",\n    \"skipLibCheck\": true,\n    \"paths\": {\n      \"react\": [\"./node_modules/preact/compat/\"],\n      \"react-dom\": [\"./node_modules/preact/compat/\"]\n    }\n  },\n  \"include\": [\"node_modules/vite/client.d.ts\", \"**/*\"]\n}\n"
  },
  {
    "path": "examples/preact/simple/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport preact from '@preact/preset-vite'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n  plugins: [preact()],\n})\n"
  },
  {
    "path": "examples/react/algolia/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\npnpm-lock.yaml\nyarn.lock\npackage-lock.json\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "examples/react/algolia/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `npm install`\n- `npm run dev`\n"
  },
  {
    "path": "examples/react/algolia/eslint.config.js",
    "content": "import { tanstackConfig } from '@tanstack/eslint-config'\nimport pluginQuery from '@tanstack/eslint-plugin-query'\nimport pluginReact from '@eslint-react/eslint-plugin'\n\nexport default [\n  ...tanstackConfig,\n  ...pluginQuery.configs['flat/recommended'],\n  pluginReact.configs.recommended,\n]\n"
  },
  {
    "path": "examples/react/algolia/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"shortcut icon\" type=\"image/svg+xml\" href=\"/emblem-light.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <meta name=\"theme-color\" content=\"#000000\" />\n\n    <title>TanStack Query React Algolia example App</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/index.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/react/algolia/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-react-algolia\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@algolia/client-search\": \"5.2.1\",\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\"\n  },\n  \"devDependencies\": {\n    \"@tanstack/eslint-plugin-query\": \"^5.91.5\",\n    \"@types/react\": \"^18.2.79\",\n    \"@types/react-dom\": \"^18.2.25\",\n    \"@vitejs/plugin-react\": \"^4.3.4\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "examples/react/algolia/src/App.tsx",
    "content": "import { QueryClient, QueryClientProvider } from '@tanstack/react-query'\n\nimport './styles.css'\nimport Search from './Search'\n\nconst queryClient = new QueryClient()\n\nexport default function App() {\n  return (\n    <QueryClientProvider client={queryClient}>\n      <div className=\"App\">\n        <h1>TanStack Query with Algolia</h1>\n        <Search />\n      </div>\n    </QueryClientProvider>\n  )\n}\n"
  },
  {
    "path": "examples/react/algolia/src/Search.tsx",
    "content": "import * as React from 'react'\n\nimport SearchResults from './SearchResults'\n\nexport default function Search() {\n  const [query, setQuery] = React.useState('')\n\n  const handleOnChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n    event.preventDefault()\n    // It is recommended to debounce this event in prod\n    setQuery(event.target.value)\n  }\n\n  return (\n    <div>\n      <input\n        onChange={handleOnChange}\n        value={query}\n        placeholder=\"Search products\"\n      />\n      <SearchResults query={query} />\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/react/algolia/src/SearchResults.tsx",
    "content": "import useAlgolia from './useAlgolia'\n\ntype Product = {\n  name: string\n  shortDescription: string\n  salePrice: number\n}\n\ntype SearchResultsProps = {\n  query: string\n}\n\nexport default function SearchResults({ query = '' }: SearchResultsProps) {\n  const {\n    hits,\n    isLoading,\n    isFetching,\n    status,\n    hasNextPage,\n    isFetchingNextPage,\n    fetchNextPage,\n  } = useAlgolia<Product>({\n    indexName: 'bestbuy',\n    query,\n    hitsPerPage: 5,\n    staleTime: 1000 * 30, // 30s\n    gcTime: 1000 * 60 * 15, // 15m\n  })\n\n  if (!query) return null\n\n  if (isLoading) return <div className=\"loading\">Loading...</div>\n\n  return (\n    <div>\n      <div className=\"search-status\">\n        Status: {status} {isFetching && <span>fetching...</span>}\n      </div>\n      <div>\n        <div className=\"search-result\">\n          {hits && hits.length > 0 ? (\n            hits.map((product) => (\n              <li key={product.objectID} className=\"product\">\n                <span className=\"product-name\">{product.name}</span>\n                {product.shortDescription && (\n                  <>\n                    <br />\n                    <span className=\"product-description\">\n                      {product.shortDescription}\n                    </span>\n                  </>\n                )}\n                <br />\n                <span className=\"product-price\">${product.salePrice}</span>\n              </li>\n            ))\n          ) : (\n            <h3>No products found!</h3>\n          )}\n        </div>\n        {hasNextPage && (\n          <div className=\"search-more\" onClick={() => fetchNextPage()}>\n            more\n          </div>\n        )}\n        {isFetchingNextPage && (\n          <div className=\"search-status\">Fetching next page...</div>\n        )}\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/react/algolia/src/algolia.ts",
    "content": "import { searchClient } from '@algolia/client-search'\nimport type { Hit } from '@algolia/client-search'\n\n// From Algolia example\n// https://github.com/algolia/react-instantsearch\nconst ALGOLIA_APP_ID = 'latency'\nconst ALGOLIA_SEARCH_API_KEY = '6be0576ff61c053d5f9a3225e2a90f76'\n\ntype SearchOptions = {\n  indexName: string\n  query: string\n  pageParam: number\n  hitsPerPage: number\n}\n\nexport async function search<TData>({\n  indexName,\n  query,\n  pageParam,\n  hitsPerPage = 10,\n}: SearchOptions): Promise<{\n  hits: Array<Hit<TData>>\n  nextPage: number | undefined\n}> {\n  const client = searchClient(ALGOLIA_APP_ID, ALGOLIA_SEARCH_API_KEY)\n\n  console.log('algolia:search', { indexName, query, pageParam, hitsPerPage })\n\n  const { hits, page, nbPages } = await client.searchSingleIndex<TData>({\n    indexName,\n    searchParams: { query, page: pageParam, hitsPerPage },\n  })\n\n  const nextPage = page + 1 < nbPages ? page + 1 : undefined\n\n  return { hits, nextPage }\n}\n"
  },
  {
    "path": "examples/react/algolia/src/index.tsx",
    "content": "import ReactDOM from 'react-dom/client'\n\nimport App from './App'\n\nconst rootElement = document.getElementById('root') as HTMLElement\nReactDOM.createRoot(rootElement).render(<App />)\n"
  },
  {
    "path": "examples/react/algolia/src/styles.css",
    "content": ".App {\n  font-family: sans-serif;\n  font-size: 14px;\n  padding: 20px;\n}\n\n.loading {\n  padding-top: 20px;\n  padding-left: 20px;\n  color: darkmagenta;\n}\n\n.search-status {\n  padding-top: 20px;\n  padding-left: 20px;\n  color: gray;\n}\n\n.search-result {\n  padding-left: 20px;\n  padding-top: 20px;\n}\n\n.search-more {\n  color: blue;\n  padding-left: 20px;\n  padding-top: 20px;\n  cursor: pointer;\n  font-weight: bold;\n  text-transform: uppercase;\n}\n\n.product {\n  padding-bottom: 5px;\n}\n\n.product-name {\n  font-weight: bold;\n  font-size: 12px;\n}\n\n.product-description {\n  font-size: 12px;\n}\n\n.product-price {\n  font-size: 12px;\n  font-weight: bold;\n}\n"
  },
  {
    "path": "examples/react/algolia/src/useAlgolia.ts",
    "content": "import { skipToken, useInfiniteQuery } from '@tanstack/react-query'\nimport { search } from './algolia'\n\nexport type UseAlgoliaOptions = {\n  indexName: string\n  query: string\n  hitsPerPage?: number\n  staleTime?: number\n  gcTime?: number\n}\n\nexport default function useAlgolia<TData>({\n  indexName,\n  query,\n  hitsPerPage = 10,\n  staleTime,\n  gcTime,\n}: UseAlgoliaOptions) {\n  const queryInfo = useInfiniteQuery({\n    queryKey: ['algolia', indexName, query, hitsPerPage],\n    queryFn: query\n      ? ({ pageParam }) =>\n          search<TData>({ indexName, query, pageParam, hitsPerPage })\n      : skipToken,\n    initialPageParam: 0,\n    getNextPageParam: (lastPage) => lastPage.nextPage,\n    staleTime,\n    gcTime,\n  })\n\n  const hits = queryInfo.data?.pages.map((page) => page.hits).flat()\n\n  return { ...queryInfo, hits }\n}\n"
  },
  {
    "path": "examples/react/algolia/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "examples/react/algolia/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\n\nexport default defineConfig({\n  plugins: [react()],\n})\n"
  },
  {
    "path": "examples/react/auto-refetching/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\npnpm-lock.yaml\nyarn.lock\npackage-lock.json\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "examples/react/auto-refetching/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `npm install`\n- `npm run dev`\n"
  },
  {
    "path": "examples/react/auto-refetching/next.config.js",
    "content": "// @ts-check\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {\n  eslint: {\n    ignoreDuringBuilds: true,\n  },\n  typescript: {\n    ignoreBuildErrors: true,\n  },\n}\n\nexport default nextConfig\n"
  },
  {
    "path": "examples/react/auto-refetching/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-react-auto-refetching\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"next\",\n    \"build\": \"next build\",\n    \"start\": \"next start\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"next\": \"^16.0.7\",\n    \"react\": \"^19.2.1\",\n    \"react-dom\": \"^19.2.1\"\n  },\n  \"devDependencies\": {\n    \"@types/react\": \"^19.2.7\",\n    \"@types/react-dom\": \"^19.2.3\",\n    \"typescript\": \"5.8.3\"\n  }\n}\n"
  },
  {
    "path": "examples/react/auto-refetching/src/pages/api/data.ts",
    "content": "import type { NextApiRequest, NextApiResponse } from 'next'\n\n// an simple endpoint for getting current list\nlet list = ['Item 1', 'Item 2', 'Item 3']\n\nexport default async (\n  req: NextApiRequest,\n  res: NextApiResponse<typeof list>,\n) => {\n  if (req.query.add) {\n    if (!list.includes(req.query.add)) {\n      list.push(req.query.add)\n    }\n  } else if (req.query.clear) {\n    list = []\n  }\n\n  await new Promise((r) => setTimeout(r, 100))\n\n  res.json(list)\n}\n"
  },
  {
    "path": "examples/react/auto-refetching/src/pages/index.tsx",
    "content": "import React from 'react'\n\nimport {\n  QueryClient,\n  QueryClientProvider,\n  useMutation,\n  useQuery,\n  useQueryClient,\n} from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\n\nconst queryClient = new QueryClient()\n\nexport default function App() {\n  return (\n    <QueryClientProvider client={queryClient}>\n      <Example />\n    </QueryClientProvider>\n  )\n}\n\nfunction Example() {\n  const queryClient = useQueryClient()\n  const [intervalMs, setIntervalMs] = React.useState(1000)\n  const [value, setValue] = React.useState('')\n\n  const { status, data, error, isFetching } = useQuery({\n    queryKey: ['todos'],\n    queryFn: async (): Promise<Array<string>> => {\n      const response = await fetch('/api/data')\n      return await response.json()\n    },\n    // Refetch the data every second\n    refetchInterval: intervalMs,\n  })\n\n  const addMutation = useMutation({\n    mutationFn: (add: string) => fetch(`/api/data?add=${add}`),\n    onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),\n  })\n\n  const clearMutation = useMutation({\n    mutationFn: () => fetch(`/api/data?clear=1`),\n    onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),\n  })\n\n  if (status === 'pending') return <h1>Loading...</h1>\n  if (status === 'error') return <span>Error: {error.message}</span>\n\n  return (\n    <div>\n      <h1>Auto Refetch with stale-time set to {intervalMs}ms</h1>\n      <p>\n        This example is best experienced on your own machine, where you can open\n        multiple tabs to the same localhost server and see your changes\n        propagate between the two.\n      </p>\n      <label>\n        Query Interval speed (ms):{' '}\n        <input\n          value={intervalMs}\n          onChange={(ev) => setIntervalMs(Number(ev.target.value))}\n          type=\"number\"\n          step=\"100\"\n        />{' '}\n        <span\n          style={{\n            display: 'inline-block',\n            marginLeft: '.5rem',\n            width: 10,\n            height: 10,\n            background: isFetching ? 'green' : 'transparent',\n            transition: !isFetching ? 'all .3s ease' : 'none',\n            borderRadius: '100%',\n            transform: 'scale(2)',\n          }}\n        />\n      </label>\n      <h2>Todo List</h2>\n      <form\n        onSubmit={(event) => {\n          event.preventDefault()\n          addMutation.mutate(value, {\n            onSuccess: () => {\n              setValue('')\n            },\n          })\n        }}\n      >\n        <input\n          placeholder=\"enter something\"\n          value={value}\n          onChange={(ev) => setValue(ev.target.value)}\n        />\n      </form>\n      <ul>\n        {data.map((item) => (\n          <li key={item}>{item}</li>\n        ))}\n      </ul>\n      <div>\n        <button\n          onClick={() => {\n            clearMutation.mutate()\n          }}\n        >\n          Clear All\n        </button>\n      </div>\n      <ReactQueryDevtools initialIsOpen />\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/react/auto-refetching/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"jsx\": \"react-jsx\",\n    \"incremental\": true,\n    \"target\": \"ES2017\"\n  },\n  \"include\": [\"next-env.d.ts\", \"**/*.ts\", \"**/*.tsx\"],\n  \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "examples/react/basic/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\npnpm-lock.yaml\nyarn.lock\npackage-lock.json\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "examples/react/basic/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `npm install`\n- `npm run dev`\n"
  },
  {
    "path": "examples/react/basic/eslint.config.js",
    "content": "import { tanstackConfig } from '@tanstack/eslint-config'\nimport pluginQuery from '@tanstack/eslint-plugin-query'\nimport pluginReact from '@eslint-react/eslint-plugin'\n\nexport default [\n  ...tanstackConfig,\n  ...pluginQuery.configs['flat/recommended'],\n  pluginReact.configs.recommended,\n]\n"
  },
  {
    "path": "examples/react/basic/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"shortcut icon\" type=\"image/svg+xml\" href=\"/emblem-light.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <meta name=\"theme-color\" content=\"#000000\" />\n\n    <title>TanStack Query React Basic Example App</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/index.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/react/basic/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-react-basic\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\",\n    \"test:eslint\": \"eslint ./src\"\n  },\n  \"dependencies\": {\n    \"@tanstack/query-async-storage-persister\": \"^5.90.27\",\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"@tanstack/react-query-persist-client\": \"^5.90.27\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\"\n  },\n  \"devDependencies\": {\n    \"@tanstack/eslint-plugin-query\": \"^5.91.5\",\n    \"@types/react\": \"^18.2.79\",\n    \"@types/react-dom\": \"^18.2.25\",\n    \"@vitejs/plugin-react\": \"^4.3.4\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  },\n  \"nx\": {\n    \"targets\": {\n      \"test:eslint\": {\n        \"dependsOn\": [\n          \"^build\"\n        ]\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "examples/react/basic/src/index.tsx",
    "content": "import * as React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { QueryClient, useQuery, useQueryClient } from '@tanstack/react-query'\nimport { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'\nimport { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\n\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      gcTime: 1000 * 60 * 60 * 24, // 24 hours\n    },\n  },\n})\n\nconst persister = createAsyncStoragePersister({\n  storage: window.localStorage,\n})\n\ntype Post = {\n  id: number\n  title: string\n  body: string\n}\n\nfunction usePosts() {\n  return useQuery({\n    queryKey: ['posts'],\n    queryFn: async (): Promise<Array<Post>> => {\n      const response = await fetch('https://jsonplaceholder.typicode.com/posts')\n      return await response.json()\n    },\n  })\n}\n\nfunction Posts({\n  setPostId,\n}: {\n  setPostId: React.Dispatch<React.SetStateAction<number>>\n}) {\n  const queryClient = useQueryClient()\n  const { status, data, error, isFetching } = usePosts()\n\n  return (\n    <div>\n      <h1>Posts</h1>\n      <div>\n        {status === 'pending' ? (\n          'Loading...'\n        ) : status === 'error' ? (\n          <span>Error: {error.message}</span>\n        ) : (\n          <>\n            <div>\n              {data.map((post) => (\n                <p key={post.id}>\n                  <a\n                    onClick={() => setPostId(post.id)}\n                    href=\"#\"\n                    style={\n                      // We can access the query data here to show bold links for\n                      // ones that are cached\n                      queryClient.getQueryData(['post', post.id])\n                        ? {\n                            fontWeight: 'bold',\n                            color: 'green',\n                          }\n                        : {}\n                    }\n                  >\n                    {post.title}\n                  </a>\n                </p>\n              ))}\n            </div>\n            <div>{isFetching ? 'Background Updating...' : ' '}</div>\n          </>\n        )}\n      </div>\n    </div>\n  )\n}\n\nconst getPostById = async (id: number): Promise<Post> => {\n  const response = await fetch(\n    `https://jsonplaceholder.typicode.com/posts/${id}`,\n  )\n  return await response.json()\n}\n\nfunction usePost(postId: number) {\n  return useQuery({\n    queryKey: ['post', postId],\n    queryFn: () => getPostById(postId),\n    enabled: !!postId,\n  })\n}\n\nfunction Post({\n  postId,\n  setPostId,\n}: {\n  postId: number\n  setPostId: React.Dispatch<React.SetStateAction<number>>\n}) {\n  const { status, data, error, isFetching } = usePost(postId)\n\n  return (\n    <div>\n      <div>\n        <a onClick={() => setPostId(-1)} href=\"#\">\n          Back\n        </a>\n      </div>\n      {!postId || status === 'pending' ? (\n        'Loading...'\n      ) : status === 'error' ? (\n        <span>Error: {error.message}</span>\n      ) : (\n        <>\n          <h1>{data.title}</h1>\n          <div>\n            <p>{data.body}</p>\n          </div>\n          <div>{isFetching ? 'Background Updating...' : ' '}</div>\n        </>\n      )}\n    </div>\n  )\n}\n\nfunction App() {\n  const [postId, setPostId] = React.useState(-1)\n\n  return (\n    <PersistQueryClientProvider\n      client={queryClient}\n      persistOptions={{ persister }}\n    >\n      <p>\n        As you visit the posts below, you will notice them in a loading state\n        the first time you load them. However, after you return to this list and\n        click on any posts you have already visited again, you will see them\n        load instantly and background refresh right before your eyes!{' '}\n        <strong>\n          (You may need to throttle your network speed to simulate longer\n          loading sequences)\n        </strong>\n      </p>\n      {postId > -1 ? (\n        <Post postId={postId} setPostId={setPostId} />\n      ) : (\n        <Posts setPostId={setPostId} />\n      )}\n      <ReactQueryDevtools initialIsOpen />\n    </PersistQueryClientProvider>\n  )\n}\n\nconst rootElement = document.getElementById('root')\nif (!rootElement) throw new Error('Missing #root element')\nReactDOM.createRoot(rootElement).render(<App />)\n"
  },
  {
    "path": "examples/react/basic/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src\", \"eslint.config.js\"]\n}\n"
  },
  {
    "path": "examples/react/basic/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\n\nexport default defineConfig({\n  plugins: [react()],\n})\n"
  },
  {
    "path": "examples/react/basic-graphql-request/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\npnpm-lock.yaml\nyarn.lock\npackage-lock.json\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "examples/react/basic-graphql-request/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `npm install`\n- `npm run dev`\n"
  },
  {
    "path": "examples/react/basic-graphql-request/eslint.config.js",
    "content": "import { tanstackConfig } from '@tanstack/eslint-config'\nimport pluginQuery from '@tanstack/eslint-plugin-query'\nimport pluginReact from '@eslint-react/eslint-plugin'\n\nexport default [\n  ...tanstackConfig,\n  ...pluginQuery.configs['flat/recommended'],\n  pluginReact.configs.recommended,\n]\n"
  },
  {
    "path": "examples/react/basic-graphql-request/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"shortcut icon\" type=\"image/svg+xml\" href=\"/emblem-light.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <meta name=\"theme-color\" content=\"#000000\" />\n\n    <title>TanStack Query React Basic GraphQl Request Example App</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/index.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/react/basic-graphql-request/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-react-basic-graphql-request\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"graphql\": \"^16.9.0\",\n    \"graphql-request\": \"^7.1.2\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\"\n  },\n  \"devDependencies\": {\n    \"@vitejs/plugin-react\": \"^4.3.4\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "examples/react/basic-graphql-request/src/index.tsx",
    "content": "import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport {\n  QueryClient,\n  QueryClientProvider,\n  useQuery,\n  useQueryClient,\n} from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\nimport { gql, request } from 'graphql-request'\n\nconst endpoint = 'https://graphqlzero.almansi.me/api'\n\nconst queryClient = new QueryClient()\n\ntype Post = {\n  id: number\n  title: string\n  body: string\n}\n\nfunction App() {\n  const [postId, setPostId] = React.useState(-1)\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      <p>\n        As you visit the posts below, you will notice them in a loading state\n        the first time you load them. However, after you return to this list and\n        click on any posts you have already visited again, you will see them\n        load instantly and background refresh right before your eyes!{' '}\n        <strong>\n          (You may need to throttle your network speed to simulate longer\n          loading sequences)\n        </strong>\n      </p>\n      {postId > -1 ? (\n        <Post postId={postId} setPostId={setPostId} />\n      ) : (\n        <Posts setPostId={setPostId} />\n      )}\n      <ReactQueryDevtools initialIsOpen />\n    </QueryClientProvider>\n  )\n}\n\nfunction usePosts() {\n  return useQuery({\n    queryKey: ['posts'],\n    queryFn: async () => {\n      const {\n        posts: { data },\n      } = await request<{ posts: { data: Array<Post> } }>(\n        endpoint,\n        gql`\n          query {\n            posts {\n              data {\n                id\n                title\n              }\n            }\n          }\n        `,\n      )\n      return data\n    },\n  })\n}\n\nfunction Posts({\n  setPostId,\n}: {\n  setPostId: React.Dispatch<React.SetStateAction<number>>\n}) {\n  const queryClient = useQueryClient()\n  const { status, data, error, isFetching } = usePosts()\n\n  return (\n    <div>\n      <h1>Posts</h1>\n      <div>\n        {status === 'pending' ? (\n          'Loading...'\n        ) : status === 'error' ? (\n          <span>Error: {error.message}</span>\n        ) : (\n          <>\n            <div>\n              {data.map((post) => (\n                <p key={post.id}>\n                  <a\n                    onClick={() => setPostId(post.id)}\n                    href=\"#\"\n                    style={\n                      // We can find the existing query data here to show bold links for\n                      // ones that are cached\n                      queryClient.getQueryData(['post', post.id])\n                        ? {\n                            fontWeight: 'bold',\n                            color: 'green',\n                          }\n                        : {}\n                    }\n                  >\n                    {post.title}\n                  </a>\n                </p>\n              ))}\n            </div>\n            <div>{isFetching ? 'Background Updating...' : ' '}</div>\n          </>\n        )}\n      </div>\n    </div>\n  )\n}\n\nfunction usePost(postId: number) {\n  return useQuery({\n    queryKey: ['post', postId],\n    queryFn: async () => {\n      const { post } = await request<{ post: Post }>(\n        endpoint,\n        gql`\n        query {\n          post(id: ${postId}) {\n            id\n            title\n            body\n          }\n        }\n        `,\n      )\n\n      return post\n    },\n    enabled: !!postId,\n  })\n}\n\nfunction Post({\n  postId,\n  setPostId,\n}: {\n  postId: number\n  setPostId: React.Dispatch<React.SetStateAction<number>>\n}) {\n  const { status, data, error, isFetching } = usePost(postId)\n\n  return (\n    <div>\n      <div>\n        <a onClick={() => setPostId(-1)} href=\"#\">\n          Back\n        </a>\n      </div>\n      {!postId || status === 'pending' ? (\n        'Loading...'\n      ) : status === 'error' ? (\n        <span>Error: {error.message}</span>\n      ) : (\n        <>\n          <h1>{data.title}</h1>\n          <div>\n            <p>{data.body}</p>\n          </div>\n          <div>{isFetching ? 'Background Updating...' : ' '}</div>\n        </>\n      )}\n    </div>\n  )\n}\n\nconst rootElement = document.getElementById('root') as HTMLElement\nReactDOM.createRoot(rootElement).render(<App />)\n"
  },
  {
    "path": "examples/react/basic-graphql-request/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src\", \"eslint.config.js\"]\n}\n"
  },
  {
    "path": "examples/react/chat/.eslintrc",
    "content": "{\n  \"extends\": [\"plugin:react/jsx-runtime\", \"plugin:react-hooks/recommended\"]\n}\n"
  },
  {
    "path": "examples/react/chat/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\npnpm-lock.yaml\nyarn.lock\npackage-lock.json\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "examples/react/chat/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `npm install`\n- `npm run dev`\n"
  },
  {
    "path": "examples/react/chat/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/emblem-light.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <meta name=\"theme-color\" content=\"#000000\" />\n\n    <title>TanStack Query React Simple Example App</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/index.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/react/chat/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-chat\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\"\n  },\n  \"devDependencies\": {\n    \"@tailwindcss/vite\": \"^4.0.14\",\n    \"@vitejs/plugin-react\": \"^4.3.4\",\n    \"tailwindcss\": \"^4.0.14\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "examples/react/chat/src/chat.ts",
    "content": "import {\n  queryOptions,\n  experimental_streamedQuery as streamedQuery,\n} from '@tanstack/react-query'\n\nconst answers = [\n  \"I'm just an example chat, I can't really answer any questions :(\".split(' '),\n  'TanStack is great. Would you like to know more?'.split(' '),\n]\n\nfunction chatAnswer(_question: string) {\n  return {\n    async *[Symbol.asyncIterator]() {\n      const answer = answers[Math.floor(Math.random() * answers.length)]\n      let index = 0\n      while (index < answer.length) {\n        await new Promise((resolve) =>\n          setTimeout(resolve, 100 + Math.random() * 300),\n        )\n        yield answer[index++]\n      }\n    },\n  }\n}\n\nexport const chatQueryOptions = (question: string) =>\n  queryOptions({\n    queryKey: ['chat', question],\n    queryFn: streamedQuery({\n      streamFn: () => chatAnswer(question),\n    }),\n    staleTime: Infinity,\n  })\n"
  },
  {
    "path": "examples/react/chat/src/index.tsx",
    "content": "import ReactDOM from 'react-dom/client'\nimport {\n  QueryClient,\n  QueryClientProvider,\n  useQuery,\n} from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\n\nimport './style.css'\nimport { useState } from 'react'\nimport { chatQueryOptions } from './chat'\nimport { Message } from './message'\n\nconst queryClient = new QueryClient()\n\nexport default function App() {\n  return (\n    <QueryClientProvider client={queryClient}>\n      <ReactQueryDevtools />\n      <Example />\n    </QueryClientProvider>\n  )\n}\n\nfunction ChatMessage({ question }: { question: string }) {\n  const { error, data = [], isFetching } = useQuery(chatQueryOptions(question))\n\n  if (error) return 'An error has occurred: ' + error.message\n\n  return (\n    <div>\n      <Message message={{ content: question, isQuestion: true }} />\n      <Message\n        inProgress={isFetching}\n        message={{ content: data.join(' '), isQuestion: false }}\n      />\n    </div>\n  )\n}\n\nfunction Example() {\n  const [questions, setQuestions] = useState<Array<string>>([])\n  const [currentQuestion, setCurrentQuestion] = useState('')\n\n  const submitMessage = () => {\n    setQuestions([...questions, currentQuestion])\n    setCurrentQuestion('')\n  }\n\n  return (\n    <div className=\"flex flex-col h-screen max-w-3xl mx-auto p-4\">\n      <h1 className=\"text-3xl font-bold text-gray-800\">\n        TanStack Chat Example\n      </h1>\n      <div className=\"overflow-y-auto mb-4 space-y-4\">\n        {questions.map((question) => (\n          <ChatMessage key={question} question={question} />\n        ))}\n      </div>\n\n      <div className=\"flex items-center space-x-2\">\n        <input\n          className=\"flex-1 p-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 focus:ring-offset-gray-100\"\n          value={currentQuestion}\n          onChange={(e) => setCurrentQuestion(e.target.value)}\n          onKeyDown={(e) => {\n            if (e.key === 'Enter') {\n              submitMessage()\n            }\n          }}\n          placeholder=\"Type your message...\"\n        />\n        <button\n          onClick={submitMessage}\n          disabled={!currentQuestion.trim()}\n          className=\"flex items-center gap-2 bg-blue-600 hover:bg-blue-700 text-white font-semibold px-4 py-2 rounded-2xl shadow-md transition\"\n        >\n          <span>Send</span>\n          <svg\n            xmlns=\"http://www.w3.org/2000/svg\"\n            width=\"24\"\n            height=\"24\"\n            viewBox=\"0 0 24 24\"\n            fill=\"none\"\n            stroke=\"currentColor\"\n            stroke-width=\"2\"\n            stroke-linecap=\"round\"\n            stroke-linejoin=\"round\"\n          >\n            <path d=\"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z\" />\n            <path d=\"m21.854 2.147-10.94 10.939\" />\n          </svg>\n        </button>\n      </div>\n    </div>\n  )\n}\n\nconst rootElement = document.getElementById('root') as HTMLElement\nReactDOM.createRoot(rootElement).render(<App />)\n"
  },
  {
    "path": "examples/react/chat/src/message.tsx",
    "content": "export function Message({\n  inProgress,\n  message,\n}: {\n  inProgress?: boolean\n  message: { content: string; isQuestion: boolean }\n}) {\n  return (\n    <div\n      className={`flex ${message.isQuestion ? 'justify-end' : 'justify-start'}`}\n    >\n      <div\n        className={`max-w-[80%] rounded-lg p-3 ${\n          message.isQuestion\n            ? 'bg-blue-500 text-white'\n            : 'bg-gray-200 text-gray-800'\n        }`}\n      >\n        {message.content}\n        {inProgress ? '...' : null}\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/react/chat/src/style.css",
    "content": "@import 'tailwindcss';\n"
  },
  {
    "path": "examples/react/chat/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src\", \"eslint.config.js\"]\n}\n"
  },
  {
    "path": "examples/react/chat/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\nimport tailwindcss from '@tailwindcss/vite'\n\nexport default defineConfig({\n  plugins: [tailwindcss(), react()],\n})\n"
  },
  {
    "path": "examples/react/default-query-function/.eslintrc",
    "content": "{\n  \"extends\": [\"plugin:react/jsx-runtime\", \"plugin:react-hooks/recommended\"]\n}\n"
  },
  {
    "path": "examples/react/default-query-function/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\npnpm-lock.yaml\nyarn.lock\npackage-lock.json\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "examples/react/default-query-function/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `npm install`\n- `npm run dev`\n"
  },
  {
    "path": "examples/react/default-query-function/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"shortcut icon\" type=\"image/svg+xml\" href=\"/emblem-light.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <meta name=\"theme-color\" content=\"#000000\" />\n\n    <title>TanStack Query React Default Query Function Example App</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/index.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/react/default-query-function/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-react-default-query-function\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\"\n  },\n  \"devDependencies\": {\n    \"@vitejs/plugin-react\": \"^4.3.4\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "examples/react/default-query-function/src/index.tsx",
    "content": "import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport {\n  QueryClient,\n  QueryClientProvider,\n  useQuery,\n  useQueryClient,\n} from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\nimport type { QueryKey } from '@tanstack/react-query'\n\ntype Post = {\n  id: number\n  title: string\n  body: string\n}\n\n// Define a default query function that will receive the query key\nconst defaultQueryFn = async ({ queryKey }: { queryKey: QueryKey }) => {\n  const response = await fetch(\n    `https://jsonplaceholder.typicode.com${queryKey[0]}`,\n  )\n  return await response.json()\n}\n\n// provide the default query function to your app via the query client\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      queryFn: defaultQueryFn,\n    },\n  },\n})\n\nfunction App() {\n  const [postId, setPostId] = React.useState(-1)\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      <p>\n        As you visit the posts below, you will notice them in a loading state\n        the first time you load them. However, after you return to this list and\n        click on any posts you have already visited again, you will see them\n        load instantly and background refresh right before your eyes!{' '}\n        <strong>\n          (You may need to throttle your network speed to simulate longer\n          loading sequences)\n        </strong>\n      </p>\n      {postId > -1 ? (\n        <Post postId={postId} setPostId={setPostId} />\n      ) : (\n        <Posts setPostId={setPostId} />\n      )}\n      <ReactQueryDevtools initialIsOpen />\n    </QueryClientProvider>\n  )\n}\n\nfunction Posts({\n  setPostId,\n}: {\n  setPostId: React.Dispatch<React.SetStateAction<number>>\n}) {\n  const queryClient = useQueryClient()\n\n  // All you have to do now is pass a key!\n  const { status, data, error, isFetching } = useQuery<Array<Post>>({\n    queryKey: ['/posts'],\n  })\n\n  return (\n    <div>\n      <h1>Posts</h1>\n      <div>\n        {status === 'pending' ? (\n          'Loading...'\n        ) : status === 'error' ? (\n          <span>Error: {error.message}</span>\n        ) : (\n          <>\n            <div>\n              {data.map((post) => (\n                <p key={post.id}>\n                  <a\n                    onClick={() => setPostId(post.id)}\n                    href=\"#\"\n                    style={\n                      // We can use the queryCache here to show bold links for\n                      // ones that are cached\n                      queryClient.getQueryData([`/posts/${post.id}`])\n                        ? {\n                            fontWeight: 'bold',\n                            color: 'green',\n                          }\n                        : {}\n                    }\n                  >\n                    {post.title}\n                  </a>\n                </p>\n              ))}\n            </div>\n            <div>{isFetching ? 'Background Updating...' : ' '}</div>\n          </>\n        )}\n      </div>\n    </div>\n  )\n}\n\nfunction Post({\n  postId,\n  setPostId,\n}: {\n  postId: number\n  setPostId: React.Dispatch<React.SetStateAction<number>>\n}) {\n  // You can even leave out the queryFn and just go straight into options\n  const { status, data, error, isFetching } = useQuery<Post>({\n    queryKey: [`/posts/${postId}`],\n    enabled: !!postId,\n  })\n\n  return (\n    <div>\n      <div>\n        <a onClick={() => setPostId(-1)} href=\"#\">\n          Back\n        </a>\n      </div>\n      {!postId || status === 'pending' ? (\n        'Loading...'\n      ) : status === 'error' ? (\n        <span>Error: {error.message}</span>\n      ) : (\n        <>\n          <h1>{data.title}</h1>\n          <div>\n            <p>{data.body}</p>\n          </div>\n          <div>{isFetching ? 'Background Updating...' : ' '}</div>\n        </>\n      )}\n    </div>\n  )\n}\n\nconst rootElement = document.getElementById('root') as HTMLElement\nReactDOM.createRoot(rootElement).render(<App />)\n"
  },
  {
    "path": "examples/react/default-query-function/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src\", \"eslint.config.js\"]\n}\n"
  },
  {
    "path": "examples/react/default-query-function/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\n\nexport default defineConfig({\n  plugins: [react()],\n})\n"
  },
  {
    "path": "examples/react/devtools-panel/.eslintrc",
    "content": "{\n  \"extends\": [\"plugin:react/jsx-runtime\", \"plugin:react-hooks/recommended\"]\n}\n"
  },
  {
    "path": "examples/react/devtools-panel/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\npnpm-lock.yaml\nyarn.lock\npackage-lock.json\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "examples/react/devtools-panel/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `npm install`\n- `npm run dev`\n"
  },
  {
    "path": "examples/react/devtools-panel/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/emblem-light.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <meta name=\"theme-color\" content=\"#000000\" />\n\n    <title>TanStack Query React Devtools Panel Example App</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/index.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/react/devtools-panel/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-react-devtools-panel\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\"\n  },\n  \"devDependencies\": {\n    \"@vitejs/plugin-react\": \"^4.3.4\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "examples/react/devtools-panel/src/index.tsx",
    "content": "import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport {\n  QueryClient,\n  QueryClientProvider,\n  useQuery,\n} from '@tanstack/react-query'\nimport { ReactQueryDevtoolsPanel } from '@tanstack/react-query-devtools'\n\nconst queryClient = new QueryClient()\n\nexport default function App() {\n  const [isOpen, setIsOpen] = React.useState(false)\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      <Example />\n      <button\n        onClick={() => setIsOpen(!isOpen)}\n      >{`${isOpen ? 'Close' : 'Open'} the devtools panel`}</button>\n      {isOpen && <ReactQueryDevtoolsPanel onClose={() => setIsOpen(false)} />}\n    </QueryClientProvider>\n  )\n}\n\nfunction Example() {\n  const { isPending, error, data, isFetching } = useQuery({\n    queryKey: ['repoData'],\n    queryFn: async () => {\n      const response = await fetch(\n        'https://api.github.com/repos/TanStack/query',\n      )\n      return await response.json()\n    },\n  })\n\n  if (isPending) return 'Loading...'\n\n  if (error) return 'An error has occurred: ' + error.message\n\n  return (\n    <div\n      style={{\n        paddingBottom: 20,\n      }}\n    >\n      <h1>{data.full_name}</h1>\n      <p>{data.description}</p>\n      <strong>👀 {data.subscribers_count}</strong>{' '}\n      <strong>✨ {data.stargazers_count}</strong>{' '}\n      <strong>🍴 {data.forks_count}</strong>\n      <div>{isFetching ? 'Updating...' : ''}</div>\n    </div>\n  )\n}\n\nconst rootElement = document.getElementById('root') as HTMLElement\nReactDOM.createRoot(rootElement).render(<App />)\n"
  },
  {
    "path": "examples/react/devtools-panel/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src\", \"eslint.config.js\"]\n}\n"
  },
  {
    "path": "examples/react/devtools-panel/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\n\nexport default defineConfig({\n  plugins: [react()],\n})\n"
  },
  {
    "path": "examples/react/eslint-legacy/.eslintrc",
    "content": "{\n  \"parser\": \"@typescript-eslint/parser\",\n  \"plugins\": [\"@typescript-eslint\"],\n  \"extends\": [\"plugin:@tanstack/query/recommended\"]\n}\n"
  },
  {
    "path": "examples/react/eslint-legacy/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\npnpm-lock.yaml\nyarn.lock\npackage-lock.json\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "examples/react/eslint-legacy/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `npm install`\n- `npm run dev`\n"
  },
  {
    "path": "examples/react/eslint-legacy/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"shortcut icon\" type=\"image/svg+xml\" href=\"/emblem-light.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <meta name=\"theme-color\" content=\"#000000\" />\n\n    <title>TanStack Query React Basic Example App</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/index.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/react/eslint-legacy/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-eslint-legacy\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\",\n    \"test:eslint\": \"ESLINT_USE_FLAT_CONFIG=false eslint ./src/**/*.tsx\"\n  },\n  \"dependencies\": {\n    \"@tanstack/query-async-storage-persister\": \"^5.90.27\",\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"@tanstack/react-query-persist-client\": \"^5.90.27\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\"\n  },\n  \"devDependencies\": {\n    \"@tanstack/eslint-plugin-query\": \"^5.91.5\",\n    \"@types/react\": \"^18.2.79\",\n    \"@types/react-dom\": \"^18.2.25\",\n    \"@vitejs/plugin-react\": \"^4.3.4\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  },\n  \"nx\": {\n    \"targets\": {\n      \"test:eslint\": {\n        \"dependsOn\": [\n          \"^build\"\n        ]\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "examples/react/eslint-legacy/src/index.tsx",
    "content": "import * as React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { QueryClient, useQuery, useQueryClient } from '@tanstack/react-query'\nimport { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'\nimport { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\n\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      gcTime: 1000 * 60 * 60 * 24, // 24 hours\n    },\n  },\n})\n\nconst persister = createAsyncStoragePersister({\n  storage: window.localStorage,\n})\n\ntype Post = {\n  id: number\n  title: string\n  body: string\n}\n\nfunction usePosts() {\n  return useQuery({\n    queryKey: ['posts'],\n    queryFn: async (): Promise<Array<Post>> => {\n      const response = await fetch('https://jsonplaceholder.typicode.com/posts')\n      return await response.json()\n    },\n  })\n}\n\nfunction Posts({\n  setPostId,\n}: {\n  setPostId: React.Dispatch<React.SetStateAction<number>>\n}) {\n  const queryClient = useQueryClient()\n  const { status, data, error, isFetching } = usePosts()\n\n  return (\n    <div>\n      <h1>Posts</h1>\n      <div>\n        {status === 'pending' ? (\n          'Loading...'\n        ) : status === 'error' ? (\n          <span>Error: {error.message}</span>\n        ) : (\n          <>\n            <div>\n              {data.map((post) => (\n                <p key={post.id}>\n                  <a\n                    onClick={() => setPostId(post.id)}\n                    href=\"#\"\n                    style={\n                      // We can access the query data here to show bold links for\n                      // ones that are cached\n                      queryClient.getQueryData(['post', post.id])\n                        ? {\n                            fontWeight: 'bold',\n                            color: 'green',\n                          }\n                        : {}\n                    }\n                  >\n                    {post.title}\n                  </a>\n                </p>\n              ))}\n            </div>\n            <div>{isFetching ? 'Background Updating...' : ' '}</div>\n          </>\n        )}\n      </div>\n    </div>\n  )\n}\n\nconst getPostById = async (id: number): Promise<Post> => {\n  const response = await fetch(\n    `https://jsonplaceholder.typicode.com/posts/${id}`,\n  )\n  return await response.json()\n}\n\nfunction usePost(postId: number) {\n  return useQuery({\n    queryKey: ['post', postId],\n    queryFn: () => getPostById(postId),\n    enabled: !!postId,\n  })\n}\n\nfunction Post({\n  postId,\n  setPostId,\n}: {\n  postId: number\n  setPostId: React.Dispatch<React.SetStateAction<number>>\n}) {\n  const { status, data, error, isFetching } = usePost(postId)\n\n  return (\n    <div>\n      <div>\n        <a onClick={() => setPostId(-1)} href=\"#\">\n          Back\n        </a>\n      </div>\n      {!postId || status === 'pending' ? (\n        'Loading...'\n      ) : status === 'error' ? (\n        <span>Error: {error.message}</span>\n      ) : (\n        <>\n          <h1>{data.title}</h1>\n          <div>\n            <p>{data.body}</p>\n          </div>\n          <div>{isFetching ? 'Background Updating...' : ' '}</div>\n        </>\n      )}\n    </div>\n  )\n}\n\nfunction App() {\n  const [postId, setPostId] = React.useState(-1)\n\n  return (\n    <PersistQueryClientProvider\n      client={queryClient}\n      persistOptions={{ persister }}\n    >\n      <p>\n        As you visit the posts below, you will notice them in a loading state\n        the first time you load them. However, after you return to this list and\n        click on any posts you have already visited again, you will see them\n        load instantly and background refresh right before your eyes!{' '}\n        <strong>\n          (You may need to throttle your network speed to simulate longer\n          loading sequences)\n        </strong>\n      </p>\n      {postId > -1 ? (\n        <Post postId={postId} setPostId={setPostId} />\n      ) : (\n        <Posts setPostId={setPostId} />\n      )}\n      <ReactQueryDevtools initialIsOpen />\n    </PersistQueryClientProvider>\n  )\n}\n\nconst rootElement = document.getElementById('root') as HTMLElement\nReactDOM.createRoot(rootElement).render(<App />)\n"
  },
  {
    "path": "examples/react/eslint-legacy/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "examples/react/eslint-legacy/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\n\nexport default defineConfig({\n  plugins: [react()],\n})\n"
  },
  {
    "path": "examples/react/infinite-query-with-max-pages/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\npnpm-lock.yaml\nyarn.lock\npackage-lock.json\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "examples/react/infinite-query-with-max-pages/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `npm install`\n- `npm run dev`\n"
  },
  {
    "path": "examples/react/infinite-query-with-max-pages/next.config.js",
    "content": "// @ts-check\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {\n  eslint: {\n    ignoreDuringBuilds: true,\n  },\n  typescript: {\n    ignoreBuildErrors: true,\n  },\n}\n\nexport default nextConfig\n"
  },
  {
    "path": "examples/react/infinite-query-with-max-pages/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-react-infinite-query-with-max-pages\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"next\",\n    \"build\": \"next build\",\n    \"start\": \"next start\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"next\": \"^16.0.7\",\n    \"react\": \"^19.2.1\",\n    \"react-dom\": \"^19.2.1\"\n  },\n  \"devDependencies\": {\n    \"@types/react\": \"^19.2.7\",\n    \"@types/react-dom\": \"^19.2.3\",\n    \"typescript\": \"5.8.3\"\n  }\n}\n"
  },
  {
    "path": "examples/react/infinite-query-with-max-pages/src/pages/api/projects.ts",
    "content": "import type { NextApiRequest, NextApiResponse } from 'next'\n\nexport default (req: NextApiRequest, res: NextApiResponse) => {\n  const cursor = parseInt(req.query.cursor) || 0\n  const pageSize = 4\n\n  const data = Array(pageSize)\n    .fill(0)\n    .map((_, i) => {\n      return {\n        name: 'Project ' + (i + cursor) + ` (server time: ${Date.now()})`,\n        id: i + cursor,\n      }\n    })\n\n  const nextId = cursor < 20 ? data[data.length - 1].id + 1 : null\n  const previousId = cursor > -20 ? data[0].id - pageSize : null\n\n  setTimeout(() => res.json({ data, nextId, previousId }), 300)\n}\n"
  },
  {
    "path": "examples/react/infinite-query-with-max-pages/src/pages/index.tsx",
    "content": "import React from 'react'\nimport {\n  QueryClient,\n  QueryClientProvider,\n  useInfiniteQuery,\n} from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\n\nconst queryClient = new QueryClient()\n\nexport default function App() {\n  return (\n    <QueryClientProvider client={queryClient}>\n      <Example />\n    </QueryClientProvider>\n  )\n}\n\nfunction Example() {\n  const {\n    status,\n    data,\n    error,\n    isFetching,\n    isFetchingNextPage,\n    isFetchingPreviousPage,\n    fetchNextPage,\n    fetchPreviousPage,\n    hasNextPage,\n    hasPreviousPage,\n  } = useInfiniteQuery({\n    queryKey: ['projects'],\n    queryFn: async ({ pageParam }) => {\n      const response = await fetch(`/api/projects?cursor=${pageParam}`)\n      return await response.json()\n    },\n    initialPageParam: 0,\n    getPreviousPageParam: (firstPage) => firstPage.previousId ?? undefined,\n    getNextPageParam: (lastPage) => lastPage.nextId ?? undefined,\n    maxPages: 3,\n  })\n\n  return (\n    <div>\n      <h1>Infinite Query with max pages</h1>\n      <h3>4 projects per page</h3>\n      <h3>3 pages max</h3>\n      {status === 'pending' ? (\n        <p>Loading...</p>\n      ) : status === 'error' ? (\n        <span>Error: {error.message}</span>\n      ) : (\n        <>\n          <div>\n            <button\n              onClick={() => fetchPreviousPage()}\n              disabled={!hasPreviousPage || isFetchingPreviousPage}\n            >\n              {isFetchingPreviousPage\n                ? 'Loading more...'\n                : hasPreviousPage\n                  ? 'Load Older'\n                  : 'Nothing more to load'}\n            </button>\n          </div>\n          {data.pages.map((page) => (\n            <React.Fragment key={page.nextId}>\n              {page.data.map((project) => (\n                <p\n                  style={{\n                    border: '1px solid gray',\n                    borderRadius: '5px',\n                    padding: '8px',\n                    fontSize: '14px',\n                    background: `hsla(${project.id * 30}, 60%, 80%, 1)`,\n                  }}\n                  key={project.id}\n                >\n                  {project.name}\n                </p>\n              ))}\n            </React.Fragment>\n          ))}\n          <div>\n            <button\n              onClick={() => fetchNextPage()}\n              disabled={!hasNextPage || isFetchingNextPage}\n            >\n              {isFetchingNextPage\n                ? 'Loading more...'\n                : hasNextPage\n                  ? 'Load Newer'\n                  : 'Nothing more to load'}\n            </button>\n          </div>\n          <div>\n            {isFetching && !isFetchingNextPage\n              ? 'Background Updating...'\n              : null}\n          </div>\n        </>\n      )}\n      <hr />\n      <ReactQueryDevtools initialIsOpen />\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/react/infinite-query-with-max-pages/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"jsx\": \"react-jsx\",\n    \"incremental\": true,\n    \"target\": \"ES2017\"\n  },\n  \"include\": [\"next-env.d.ts\", \"**/*.ts\", \"**/*.tsx\"],\n  \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "examples/react/load-more-infinite-scroll/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\npnpm-lock.yaml\nyarn.lock\npackage-lock.json\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "examples/react/load-more-infinite-scroll/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `npm install`\n- `npm run dev`\n"
  },
  {
    "path": "examples/react/load-more-infinite-scroll/next.config.js",
    "content": "// @ts-check\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {\n  eslint: {\n    ignoreDuringBuilds: true,\n  },\n  typescript: {\n    ignoreBuildErrors: true,\n  },\n}\n\nexport default nextConfig\n"
  },
  {
    "path": "examples/react/load-more-infinite-scroll/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-react-load-more-infinite-scroll\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"next\",\n    \"build\": \"next build\",\n    \"start\": \"next start\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"next\": \"^16.0.7\",\n    \"react\": \"^19.2.1\",\n    \"react-dom\": \"^19.2.1\",\n    \"react-intersection-observer\": \"^9.16.0\"\n  },\n  \"devDependencies\": {\n    \"@types/react\": \"^19.2.7\",\n    \"@types/react-dom\": \"^19.2.3\",\n    \"typescript\": \"5.8.3\"\n  }\n}\n"
  },
  {
    "path": "examples/react/load-more-infinite-scroll/src/pages/about.tsx",
    "content": "export default () => {\n  return (\n    <a\n      href=\"\"\n      onClick={(e) => {\n        window.history.back()\n        e.preventDefault()\n      }}\n    >\n      Back\n    </a>\n  )\n}\n"
  },
  {
    "path": "examples/react/load-more-infinite-scroll/src/pages/api/projects.ts",
    "content": "import type { NextApiRequest, NextApiResponse } from 'next'\n\nexport default (req: NextApiRequest, res: NextApiResponse) => {\n  const cursor = parseInt(req.query.cursor) || 0\n  const pageSize = 5\n\n  const data = Array(pageSize)\n    .fill(0)\n    .map((_, i) => {\n      return {\n        name: 'Project ' + (i + cursor) + ` (server time: ${Date.now()})`,\n        id: i + cursor,\n      }\n    })\n\n  const nextId = cursor < 10 ? data[data.length - 1].id + 1 : null\n  const previousId = cursor > -10 ? data[0].id - pageSize : null\n\n  setTimeout(() => res.json({ data, nextId, previousId }), 1000)\n}\n"
  },
  {
    "path": "examples/react/load-more-infinite-scroll/src/pages/index.tsx",
    "content": "import React from 'react'\nimport Link from 'next/link'\nimport { useInView } from 'react-intersection-observer'\nimport {\n  useInfiniteQuery,\n  QueryClient,\n  QueryClientProvider,\n} from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\n\nconst queryClient = new QueryClient()\n\nexport default function App() {\n  return (\n    <QueryClientProvider client={queryClient}>\n      <Example />\n    </QueryClientProvider>\n  )\n}\n\nfunction Example() {\n  const { ref, inView } = useInView()\n\n  const {\n    status,\n    data,\n    error,\n    isFetching,\n    isFetchingNextPage,\n    isFetchingPreviousPage,\n    fetchNextPage,\n    fetchPreviousPage,\n    hasNextPage,\n    hasPreviousPage,\n  } = useInfiniteQuery({\n    queryKey: ['projects'],\n    queryFn: async ({\n      pageParam,\n    }): Promise<{\n      data: Array<{ name: string; id: number }>\n      previousId: number\n      nextId: number\n    }> => {\n      const response = await fetch(`/api/projects?cursor=${pageParam}`)\n      return await response.json()\n    },\n    initialPageParam: 0,\n    getPreviousPageParam: (firstPage) => firstPage.previousId,\n    getNextPageParam: (lastPage) => lastPage.nextId,\n  })\n\n  React.useEffect(() => {\n    if (inView && hasNextPage && !isFetchingNextPage) {\n      fetchNextPage()\n    }\n  }, [inView, hasNextPage, isFetchingNextPage, fetchNextPage])\n\n  return (\n    <div>\n      <h1>Infinite Loading</h1>\n      {status === 'pending' ? (\n        <p>Loading...</p>\n      ) : status === 'error' ? (\n        <span>Error: {error.message}</span>\n      ) : (\n        <>\n          <div>\n            <button\n              onClick={() => fetchPreviousPage()}\n              disabled={!hasPreviousPage || isFetchingPreviousPage}\n            >\n              {isFetchingPreviousPage\n                ? 'Loading more...'\n                : hasPreviousPage\n                  ? 'Load Older'\n                  : 'Nothing more to load'}\n            </button>\n          </div>\n          {data.pages.map((page) => (\n            <React.Fragment key={page.nextId}>\n              {page.data.map((project) => (\n                <p\n                  style={{\n                    border: '1px solid gray',\n                    borderRadius: '5px',\n                    padding: '10rem 1rem',\n                    background: `hsla(${project.id * 30}, 60%, 80%, 1)`,\n                  }}\n                  key={project.id}\n                >\n                  {project.name}\n                </p>\n              ))}\n            </React.Fragment>\n          ))}\n          <div>\n            <button\n              ref={ref}\n              onClick={() => fetchNextPage()}\n              disabled={!hasNextPage || isFetchingNextPage}\n            >\n              {isFetchingNextPage\n                ? 'Loading more...'\n                : hasNextPage\n                  ? 'Load Newer'\n                  : 'Nothing more to load'}\n            </button>\n          </div>\n          <div>\n            {isFetching && !isFetchingNextPage\n              ? 'Background Updating...'\n              : null}\n          </div>\n        </>\n      )}\n      <hr />\n      <Link href=\"/about\">Go to another page</Link>\n      <ReactQueryDevtools initialIsOpen />\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/react/load-more-infinite-scroll/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"jsx\": \"react-jsx\",\n    \"incremental\": true,\n    \"target\": \"ES2017\"\n  },\n  \"include\": [\"next-env.d.ts\", \"**/*.ts\", \"**/*.tsx\"],\n  \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "examples/react/nextjs/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# next.js\n/.next/\n/out/\n\n# production\n/build\n\n# misc\n.DS_Store\n*.pem\n\n# debug\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "examples/react/nextjs/README.md",
    "content": "# Example\n\nIn this simple example, we integrate React-Query seamlessly with Next.js data fetching methods to fetch queries in the server and hydrate them in the browser.\n\nIn addition to fetching and mutating data, React-Query analyzes your queries and their results to construct a client-side cache of your data, which is kept up to date as further queries and mutations are run.\n\nTo run this example:\n\n- `npm install`\n- `npm run dev`\n"
  },
  {
    "path": "examples/react/nextjs/next.config.js",
    "content": "// @ts-check\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {\n  eslint: {\n    ignoreDuringBuilds: true,\n  },\n  typescript: {\n    ignoreBuildErrors: true,\n  },\n}\n\nexport default nextConfig\n"
  },
  {
    "path": "examples/react/nextjs/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-react-nextjs\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"next\",\n    \"build\": \"next build\",\n    \"start\": \"next start\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"next\": \"^16.0.7\",\n    \"react\": \"^19.2.1\",\n    \"react-dom\": \"^19.2.1\"\n  },\n  \"devDependencies\": {\n    \"@types/react\": \"^19.2.7\",\n    \"@types/react-dom\": \"^19.2.3\",\n    \"typescript\": \"5.8.3\"\n  }\n}\n"
  },
  {
    "path": "examples/react/nextjs/src/components/Header.tsx",
    "content": "import React from 'react'\nimport { useRouter } from 'next/router'\nimport Link from 'next/link'\n\nexport const Header = () => {\n  const { pathname } = useRouter()\n\n  return (\n    <header>\n      <Link href=\"/\" className={pathname === '/' ? 'is-active' : ''}>\n        Home\n      </Link>\n      <Link\n        href=\"/client-only\"\n        className={pathname === '/client-only' ? 'is-active' : ''}\n      >\n        Client-Only\n      </Link>\n      <style jsx>{`\n        header {\n          margin-bottom: 25px;\n        }\n        a {\n          font-size: 14px;\n          margin-right: 15px;\n          text-decoration: none;\n        }\n        .is-active {\n          text-decoration: underline;\n        }\n      `}</style>\n    </header>\n  )\n}\n"
  },
  {
    "path": "examples/react/nextjs/src/components/InfoBox.tsx",
    "content": "import React from 'react'\n\nconst InfoBox = ({ children }: { children: React.ReactNode }) => (\n  <div className=\"info\">\n    <style jsx>{`\n      .info {\n        margin-top: 20px;\n        margin-bottom: 20px;\n        padding-top: 20px;\n        padding-bottom: 20px;\n        border-top: 1px solid #ececec;\n        border-bottom: 1px solid #ececec;\n      }\n    `}</style>\n    {children}\n  </div>\n)\n\nexport { InfoBox }\n"
  },
  {
    "path": "examples/react/nextjs/src/components/Layout.tsx",
    "content": "import React from 'react'\n\nexport const Layout = ({ children }: { children: React.ReactNode }) => {\n  return (\n    <main>\n      {children}\n      <style jsx global>{`\n        * {\n          font-family:\n            Menlo, Monaco, 'Lucida Console', 'Liberation Mono',\n            'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New',\n            monospace, serif;\n        }\n        body {\n          margin: 0;\n          padding: 25px 50px;\n        }\n        a {\n          color: #22bad9;\n        }\n        p {\n          font-size: 14px;\n          line-height: 24px;\n        }\n        article {\n          margin: 0 auto;\n          max-width: 650px;\n        }\n        button {\n          align-items: center;\n          background-color: #22bad9;\n          border: 0;\n          color: white;\n          display: flex;\n          padding: 5px 7px;\n          transition: background-color 0.3s;\n        }\n        button:active {\n          background-color: #1b9db7;\n        }\n        button:disabled {\n          background-color: #b5bebf;\n        }\n        button:focus {\n          outline: none;\n        }\n      `}</style>\n    </main>\n  )\n}\n"
  },
  {
    "path": "examples/react/nextjs/src/components/PostList.tsx",
    "content": "import React, { useState } from 'react'\nimport { usePosts } from '../hooks/usePosts'\n\nexport const PostList = () => {\n  const [postCount, setPostCount] = useState(10)\n  const { data, isPending, isFetching } = usePosts(postCount)\n\n  if (isPending) return <div>Loading</div>\n\n  return (\n    <section>\n      <ul>\n        {data?.map((post, index) => (\n          <li key={post.id}>\n            {index + 1}. {post.title}\n          </li>\n        ))}\n      </ul>\n      {postCount <= 90 && (\n        <button\n          onClick={() => setPostCount(postCount + 10)}\n          disabled={isFetching}\n        >\n          {isFetching ? 'Loading...' : 'Show More'}\n        </button>\n      )}\n      <style jsx>{`\n        section {\n          padding-bottom: 20px;\n        }\n        li {\n          display: block;\n          margin-bottom: 10px;\n        }\n        div {\n          align-items: center;\n          display: flex;\n        }\n        a {\n          font-size: 14px;\n          margin-right: 10px;\n          text-decoration: none;\n          padding-bottom: 0;\n          border: 0;\n        }\n        span {\n          font-size: 14px;\n          margin-right: 5px;\n        }\n        ul {\n          margin: 0;\n          padding: 0;\n        }\n        button:before {\n          align-self: center;\n          border-style: solid;\n          border-width: 6px 4px 0 4px;\n          border-color: #ffffff transparent transparent transparent;\n          content: '';\n          height: 0;\n          margin-right: 5px;\n          width: 0;\n        }\n      `}</style>\n    </section>\n  )\n}\n"
  },
  {
    "path": "examples/react/nextjs/src/components/index.ts",
    "content": "export * from './Header'\nexport * from './InfoBox'\nexport * from './Layout'\nexport * from './PostList'\n"
  },
  {
    "path": "examples/react/nextjs/src/hooks/usePosts.ts",
    "content": "import { useQuery } from '@tanstack/react-query'\n\ntype Post = {\n  id: number\n  title: string\n  body: string\n}\n\nconst fetchPosts = async (limit = 10): Promise<Array<Post>> => {\n  const response = await fetch('https://jsonplaceholder.typicode.com/posts')\n  const data = await response.json()\n  return data.filter((x: Post) => x.id <= limit)\n}\n\nconst usePosts = (limit: number) => {\n  return useQuery({\n    queryKey: ['posts', limit],\n    queryFn: () => fetchPosts(limit),\n  })\n}\n\nexport { usePosts, fetchPosts }\n"
  },
  {
    "path": "examples/react/nextjs/src/pages/_app.tsx",
    "content": "import React from 'react'\nimport {\n  HydrationBoundary,\n  QueryClient,\n  QueryClientProvider,\n} from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\nimport type { AppProps } from 'next/app'\n\nexport default function MyApp({ Component, pageProps }: AppProps) {\n  const [queryClient] = React.useState(() => new QueryClient())\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      <HydrationBoundary state={pageProps.dehydratedState}>\n        <Component {...pageProps} />\n      </HydrationBoundary>\n      <ReactQueryDevtools />\n    </QueryClientProvider>\n  )\n}\n"
  },
  {
    "path": "examples/react/nextjs/src/pages/client-only.tsx",
    "content": "import React from 'react'\nimport { Header, InfoBox, Layout, PostList } from '../components'\n\nconst ClientOnly = () => {\n  return (\n    <Layout>\n      <Header />\n      <InfoBox>ℹ️ This data is loaded on client and not prefetched</InfoBox>\n      <PostList />\n    </Layout>\n  )\n}\n\nexport default ClientOnly\n"
  },
  {
    "path": "examples/react/nextjs/src/pages/index.tsx",
    "content": "import React from 'react'\nimport { QueryClient, dehydrate } from '@tanstack/react-query'\nimport { Header, InfoBox, Layout, PostList } from '../components'\nimport { fetchPosts } from '../hooks/usePosts'\n\nconst Home = () => {\n  return (\n    <Layout>\n      <Header />\n      <InfoBox>ℹ️ This page shows how to use SSG with React-Query.</InfoBox>\n      <PostList />\n    </Layout>\n  )\n}\n\nexport async function getStaticProps() {\n  const queryClient = new QueryClient()\n\n  await queryClient.prefetchQuery({\n    queryKey: ['posts', 10],\n    queryFn: () => fetchPosts(10),\n  })\n\n  return {\n    props: {\n      dehydratedState: dehydrate(queryClient),\n    },\n  }\n}\n\nexport default Home\n"
  },
  {
    "path": "examples/react/nextjs/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"jsx\": \"react-jsx\",\n    \"incremental\": true,\n    \"target\": \"ES2017\"\n  },\n  \"include\": [\"next-env.d.ts\", \"**/*.ts\", \"**/*.tsx\"],\n  \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "examples/react/nextjs-app-prefetching/.eslintrc.cjs",
    "content": "/** @type {import('eslint').Linter.Config} */\nmodule.exports = {\n  extends: ['plugin:react/jsx-runtime', 'plugin:react-hooks/recommended'],\n  settings: {\n    react: {\n      version: 'detect',\n    },\n  },\n}\n"
  },
  {
    "path": "examples/react/nextjs-app-prefetching/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# next.js\n/.next/\n/out/\n\n# production\n/build\n\n# misc\n.DS_Store\n*.pem\n\n# debug\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# local env files\n.env*.local\n\n# vercel\n.vercel\n\n# typescript\n*.tsbuildinfo\n"
  },
  {
    "path": "examples/react/nextjs-app-prefetching/README.md",
    "content": "This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).\n\n## Getting Started\n\nFirst, run the development server:\n\n```bash\nnpm run dev\n# or\nyarn dev\n# or\npnpm dev\n```\n\nOpen [http://localhost:3000](http://localhost:3000) with your browser to see the result.\n\nYou can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.\n\nThis project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.\n\n## Learn More\n\nTo learn more about Next.js, take a look at the following resources:\n\n- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.\n- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.\n\nYou can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!\n\n## Deploy on Vercel\n\nThe easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.\n\nCheck out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.\n"
  },
  {
    "path": "examples/react/nextjs-app-prefetching/app/get-query-client.ts",
    "content": "import {\n  QueryClient,\n  defaultShouldDehydrateQuery,\n  isServer,\n} from '@tanstack/react-query'\n\nfunction makeQueryClient() {\n  return new QueryClient({\n    defaultOptions: {\n      queries: {\n        staleTime: 60 * 1000,\n      },\n      dehydrate: {\n        // include pending queries in dehydration\n        shouldDehydrateQuery: (query) =>\n          defaultShouldDehydrateQuery(query) ||\n          query.state.status === 'pending',\n      },\n    },\n  })\n}\n\nlet browserQueryClient: QueryClient | undefined = undefined\n\nexport function getQueryClient() {\n  if (isServer) {\n    // Server: always make a new query client\n    return makeQueryClient()\n  } else {\n    // Browser: make a new query client if we don't already have one\n    // This is very important, so we don't re-make a new client if React\n    // suspends during the initial render. This may not be needed if we\n    // have a suspense boundary BELOW the creation of the query client\n    if (!browserQueryClient) browserQueryClient = makeQueryClient()\n    return browserQueryClient\n  }\n}\n"
  },
  {
    "path": "examples/react/nextjs-app-prefetching/app/layout.tsx",
    "content": "import Providers from './providers'\nimport type React from 'react'\nimport type { Metadata } from 'next'\n\nexport const metadata: Metadata = {\n  title: 'Create Next App',\n  description: 'Generated by create next app',\n}\n\nexport default function RootLayout({\n  children,\n}: {\n  children: React.ReactNode\n}) {\n  return (\n    <html lang=\"en\">\n      <body>\n        <Providers>{children}</Providers>\n      </body>\n    </html>\n  )\n}\n"
  },
  {
    "path": "examples/react/nextjs-app-prefetching/app/page.tsx",
    "content": "import React from 'react'\nimport { HydrationBoundary, dehydrate } from '@tanstack/react-query'\nimport { pokemonOptions } from '@/app/pokemon'\nimport { getQueryClient } from '@/app/get-query-client'\nimport { PokemonInfo } from './pokemon-info'\n\nexport default function Home() {\n  const queryClient = getQueryClient()\n\n  void queryClient.prefetchQuery(pokemonOptions)\n\n  return (\n    <main>\n      <h1>Pokemon Info</h1>\n      <HydrationBoundary state={dehydrate(queryClient)}>\n        <PokemonInfo />\n      </HydrationBoundary>\n    </main>\n  )\n}\n"
  },
  {
    "path": "examples/react/nextjs-app-prefetching/app/pokemon-info.tsx",
    "content": "'use client'\n\nimport React from 'react'\nimport { useSuspenseQuery } from '@tanstack/react-query'\nimport { pokemonOptions } from '@/app/pokemon'\n\nexport function PokemonInfo() {\n  const { data } = useSuspenseQuery(pokemonOptions)\n\n  return (\n    <div>\n      <figure>\n        <img src={data.sprites.front_shiny} height={200} alt={data.name} />\n        <h2>I'm {data.name}</h2>\n      </figure>\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/react/nextjs-app-prefetching/app/pokemon.ts",
    "content": "import { queryOptions } from '@tanstack/react-query'\n\nexport const pokemonOptions = queryOptions({\n  queryKey: ['pokemon'],\n  queryFn: async () => {\n    const response = await fetch('https://pokeapi.co/api/v2/pokemon/25')\n\n    return response.json()\n  },\n})\n"
  },
  {
    "path": "examples/react/nextjs-app-prefetching/app/providers.tsx",
    "content": "'use client'\nimport { QueryClientProvider } from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\nimport { getQueryClient } from '@/app/get-query-client'\nimport type * as React from 'react'\n\nexport default function Providers({ children }: { children: React.ReactNode }) {\n  const queryClient = getQueryClient()\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      {children}\n      <ReactQueryDevtools />\n    </QueryClientProvider>\n  )\n}\n"
  },
  {
    "path": "examples/react/nextjs-app-prefetching/next.config.js",
    "content": "// @ts-check\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {\n  eslint: {\n    ignoreDuringBuilds: true,\n  },\n  typescript: {\n    ignoreBuildErrors: true,\n  },\n}\n\nexport default nextConfig\n"
  },
  {
    "path": "examples/react/nextjs-app-prefetching/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-react-nextjs-app-prefetching\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"next dev\",\n    \"build\": \"next build\",\n    \"start\": \"next start\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"next\": \"^16.0.7\",\n    \"react\": \"^19.2.1\",\n    \"react-dom\": \"^19.2.1\"\n  },\n  \"devDependencies\": {\n    \"@types/react\": \"^19.2.7\",\n    \"@types/react-dom\": \"^19.2.3\",\n    \"typescript\": \"5.8.3\"\n  }\n}\n"
  },
  {
    "path": "examples/react/nextjs-app-prefetching/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES5\",\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"jsx\": \"react-jsx\",\n    \"incremental\": true,\n    \"plugins\": [\n      {\n        \"name\": \"next\"\n      }\n    ],\n    \"paths\": {\n      \"@/*\": [\"./*\"]\n    }\n  },\n  \"include\": [\n    \"next-env.d.ts\",\n    \"**/*.ts\",\n    \"**/*.tsx\",\n    \".next/types/**/*.ts\",\n    \".eslintrc.cjs\",\n    \".next/dev/types/**/*.ts\"\n  ],\n  \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "examples/react/nextjs-suspense-streaming/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# next.js\n/.next/\n/out/\n\n# production\n/build\n\n# misc\n.DS_Store\n*.pem\n\n# debug\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# local env files\n.env*.local\n\n# vercel\n.vercel\n\n# typescript\n*.tsbuildinfo\n"
  },
  {
    "path": "examples/react/nextjs-suspense-streaming/next.config.js",
    "content": "// @ts-check\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {\n  typescript: {\n    ignoreBuildErrors: true,\n  },\n  webpack: (config) => {\n    if (config.name === 'server') config.optimization.concatenateModules = false\n\n    return config\n  },\n}\n\nexport default nextConfig\n"
  },
  {
    "path": "examples/react/nextjs-suspense-streaming/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-nextjs-suspense-streaming\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"next dev --webpack\",\n    \"build\": \"next build --webpack\",\n    \"start\": \"next start\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"@tanstack/react-query-next-experimental\": \"^5.91.0\",\n    \"next\": \"^16.0.7\",\n    \"react\": \"^19.2.1\",\n    \"react-dom\": \"^19.2.1\"\n  },\n  \"devDependencies\": {\n    \"@types/react\": \"^19.2.7\",\n    \"@types/react-dom\": \"^19.2.3\",\n    \"typescript\": \"5.8.3\"\n  }\n}\n"
  },
  {
    "path": "examples/react/nextjs-suspense-streaming/src/app/api/wait/route.ts",
    "content": "import { NextResponse } from 'next/server'\n\nexport async function GET(request: Request) {\n  const { searchParams } = new URL(request.url)\n  const wait = Number(searchParams.get('wait'))\n\n  await new Promise((resolve) => setTimeout(resolve, wait))\n\n  return NextResponse.json(`waited ${wait}ms`)\n}\n"
  },
  {
    "path": "examples/react/nextjs-suspense-streaming/src/app/layout.tsx",
    "content": "import { Providers } from './providers'\n\nexport const metadata = {\n  title: 'Next.js',\n  description: 'Generated by Next.js',\n}\n\nexport default function RootLayout({\n  children,\n}: {\n  children: React.ReactNode\n}) {\n  return (\n    <html lang=\"en\">\n      <body>\n        <Providers>{children}</Providers>\n      </body>\n    </html>\n  )\n}\n"
  },
  {
    "path": "examples/react/nextjs-suspense-streaming/src/app/page.tsx",
    "content": "'use client'\nimport { isServer, useSuspenseQuery } from '@tanstack/react-query'\nimport { Suspense } from 'react'\n\nexport const runtime = 'edge' // 'nodejs' (default) | 'edge'\n\nfunction getBaseURL() {\n  if (!isServer) {\n    return ''\n  }\n  if (process.env.VERCEL_URL) {\n    return `https://${process.env.VERCEL_URL}`\n  }\n  return 'http://localhost:3000'\n}\nconst baseUrl = getBaseURL()\nfunction useWaitQuery(props: { wait: number }) {\n  const query = useSuspenseQuery({\n    queryKey: ['wait', props.wait],\n    queryFn: async () => {\n      const path = `/api/wait?wait=${props.wait}`\n      const url = baseUrl + path\n\n      const res: string = await (\n        await fetch(url, {\n          cache: 'no-store',\n        })\n      ).json()\n      return res\n    },\n  })\n\n  return [query.data as string, query] as const\n}\n\nfunction MyComponent(props: { wait: number }) {\n  const [data] = useWaitQuery(props)\n\n  return <div>result: {data}</div>\n}\n\nexport default function MyPage() {\n  return (\n    <>\n      <Suspense fallback={<div>waiting 100....</div>}>\n        <MyComponent wait={100} />\n      </Suspense>\n      <Suspense fallback={<div>waiting 200....</div>}>\n        <MyComponent wait={200} />\n      </Suspense>\n      <Suspense fallback={<div>waiting 300....</div>}>\n        <MyComponent wait={300} />\n      </Suspense>\n      <Suspense fallback={<div>waiting 400....</div>}>\n        <MyComponent wait={400} />\n      </Suspense>\n      <Suspense fallback={<div>waiting 500....</div>}>\n        <MyComponent wait={500} />\n      </Suspense>\n      <Suspense fallback={<div>waiting 600....</div>}>\n        <MyComponent wait={600} />\n      </Suspense>\n      <Suspense fallback={<div>waiting 700....</div>}>\n        <MyComponent wait={700} />\n      </Suspense>\n\n      <fieldset>\n        <legend>\n          combined <code>Suspense</code>-container\n        </legend>\n        <Suspense\n          fallback={\n            <>\n              <div>waiting 800....</div>\n              <div>waiting 900....</div>\n              <div>waiting 1000....</div>\n            </>\n          }\n        >\n          <MyComponent wait={800} />\n          <MyComponent wait={900} />\n          <MyComponent wait={1000} />\n        </Suspense>\n      </fieldset>\n    </>\n  )\n}\n"
  },
  {
    "path": "examples/react/nextjs-suspense-streaming/src/app/providers.tsx",
    "content": "'use client'\n\nimport {\n  QueryClient,\n  QueryClientProvider,\n  isServer,\n} from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\nimport * as React from 'react'\nimport { ReactQueryStreamedHydration } from '@tanstack/react-query-next-experimental'\n\nfunction makeQueryClient() {\n  return new QueryClient({\n    defaultOptions: {\n      queries: {\n        staleTime: 60 * 1000,\n      },\n    },\n  })\n}\n\nlet browserQueryClient: QueryClient | undefined = undefined\n\nfunction getQueryClient() {\n  if (isServer) {\n    return makeQueryClient()\n  } else {\n    if (!browserQueryClient) browserQueryClient = makeQueryClient()\n    return browserQueryClient\n  }\n}\n\nexport function Providers(props: { children: React.ReactNode }) {\n  const queryClient = getQueryClient()\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      <ReactQueryStreamedHydration>\n        {props.children}\n      </ReactQueryStreamedHydration>\n      <ReactQueryDevtools initialIsOpen={false} />\n    </QueryClientProvider>\n  )\n}\n"
  },
  {
    "path": "examples/react/nextjs-suspense-streaming/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES5\",\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"jsx\": \"react-jsx\",\n    \"incremental\": true,\n    \"plugins\": [\n      {\n        \"name\": \"next\"\n      }\n    ]\n  },\n  \"include\": [\n    \"next-env.d.ts\",\n    \"**/*.ts\",\n    \"**/*.tsx\",\n    \".next/types/**/*.ts\",\n    \".next/dev/types/**/*.ts\"\n  ],\n  \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "examples/react/offline/.eslintrc",
    "content": "{\n  \"extends\": [\"plugin:react/jsx-runtime\", \"plugin:react-hooks/recommended\"]\n}\n"
  },
  {
    "path": "examples/react/offline/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\npnpm-lock.yaml\nyarn.lock\npackage-lock.json\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "examples/react/offline/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `npm install`\n- `npm run dev`\n"
  },
  {
    "path": "examples/react/offline/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"shortcut icon\" type=\"image/svg+xml\" href=\"/emblem-light.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <meta name=\"theme-color\" content=\"#000000\" />\n\n    <title>TanStack Query React Offline Example App</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/index.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/react/offline/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-react-offline\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/query-async-storage-persister\": \"^5.90.27\",\n    \"@tanstack/react-location\": \"^3.7.4\",\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"@tanstack/react-query-persist-client\": \"^5.90.27\",\n    \"msw\": \"^2.6.6\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\",\n    \"react-hot-toast\": \"^2.5.2\"\n  },\n  \"devDependencies\": {\n    \"@vitejs/plugin-react\": \"^4.3.4\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  },\n  \"msw\": {\n    \"workerDirectory\": [\n      \"public\"\n    ]\n  }\n}\n"
  },
  {
    "path": "examples/react/offline/public/mockServiceWorker.js",
    "content": "/* eslint-disable */\n\n/**\n * Mock Service Worker (2.1.7).\n * @see https://github.com/mswjs/msw\n * - Please do NOT modify this file.\n * - Please do NOT serve this file on production.\n */\n\nconst INTEGRITY_CHECKSUM = '223d191a56023cd36aa88c802961b911'\nconst IS_MOCKED_RESPONSE = Symbol('isMockedResponse')\nconst activeClientIds = new Set()\n\nself.addEventListener('install', function () {\n  self.skipWaiting()\n})\n\nself.addEventListener('activate', function (event) {\n  event.waitUntil(self.clients.claim())\n})\n\nself.addEventListener('message', async function (event) {\n  const clientId = event.source.id\n\n  if (!clientId || !self.clients) {\n    return\n  }\n\n  const client = await self.clients.get(clientId)\n\n  if (!client) {\n    return\n  }\n\n  const allClients = await self.clients.matchAll({\n    type: 'window',\n  })\n\n  switch (event.data) {\n    case 'KEEPALIVE_REQUEST': {\n      sendToClient(client, {\n        type: 'KEEPALIVE_RESPONSE',\n      })\n      break\n    }\n\n    case 'INTEGRITY_CHECK_REQUEST': {\n      sendToClient(client, {\n        type: 'INTEGRITY_CHECK_RESPONSE',\n        payload: INTEGRITY_CHECKSUM,\n      })\n      break\n    }\n\n    case 'MOCK_ACTIVATE': {\n      activeClientIds.add(clientId)\n\n      sendToClient(client, {\n        type: 'MOCKING_ENABLED',\n        payload: true,\n      })\n      break\n    }\n\n    case 'MOCK_DEACTIVATE': {\n      activeClientIds.delete(clientId)\n      break\n    }\n\n    case 'CLIENT_CLOSED': {\n      activeClientIds.delete(clientId)\n\n      const remainingClients = allClients.filter((client) => {\n        return client.id !== clientId\n      })\n\n      // Unregister itself when there are no more clients\n      if (remainingClients.length === 0) {\n        self.registration.unregister()\n      }\n\n      break\n    }\n  }\n})\n\nself.addEventListener('fetch', function (event) {\n  const { request } = event\n\n  // Bypass navigation requests.\n  if (request.mode === 'navigate') {\n    return\n  }\n\n  // Opening the DevTools triggers the \"only-if-cached\" request\n  // that cannot be handled by the worker. Bypass such requests.\n  if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') {\n    return\n  }\n\n  // Bypass all requests when there are no active clients.\n  // Prevents the self-unregistered worked from handling requests\n  // after it's been deleted (still remains active until the next reload).\n  if (activeClientIds.size === 0) {\n    return\n  }\n\n  // Generate unique request ID.\n  const requestId = crypto.randomUUID()\n  event.respondWith(handleRequest(event, requestId))\n})\n\nasync function handleRequest(event, requestId) {\n  const client = await resolveMainClient(event)\n  const response = await getResponse(event, client, requestId)\n\n  // Send back the response clone for the \"response:*\" life-cycle events.\n  // Ensure MSW is active and ready to handle the message, otherwise\n  // this message will pend indefinitely.\n  if (client && activeClientIds.has(client.id)) {\n    ;(async function () {\n      const responseClone = response.clone()\n\n      sendToClient(\n        client,\n        {\n          type: 'RESPONSE',\n          payload: {\n            requestId,\n            isMockedResponse: IS_MOCKED_RESPONSE in response,\n            type: responseClone.type,\n            status: responseClone.status,\n            statusText: responseClone.statusText,\n            body: responseClone.body,\n            headers: Object.fromEntries(responseClone.headers.entries()),\n          },\n        },\n        [responseClone.body],\n      )\n    })()\n  }\n\n  return response\n}\n\n// Resolve the main client for the given event.\n// Client that issues a request doesn't necessarily equal the client\n// that registered the worker. It's with the latter the worker should\n// communicate with during the response resolving phase.\nasync function resolveMainClient(event) {\n  const client = await self.clients.get(event.clientId)\n\n  if (client?.frameType === 'top-level') {\n    return client\n  }\n\n  const allClients = await self.clients.matchAll({\n    type: 'window',\n  })\n\n  return allClients\n    .filter((client) => {\n      // Get only those clients that are currently visible.\n      return client.visibilityState === 'visible'\n    })\n    .find((client) => {\n      // Find the client ID that's recorded in the\n      // set of clients that have registered the worker.\n      return activeClientIds.has(client.id)\n    })\n}\n\nasync function getResponse(event, client, requestId) {\n  const { request } = event\n\n  // Clone the request because it might've been already used\n  // (i.e. its body has been read and sent to the client).\n  const requestClone = request.clone()\n\n  function passthrough() {\n    const headers = Object.fromEntries(requestClone.headers.entries())\n\n    // Remove internal MSW request header so the passthrough request\n    // complies with any potential CORS preflight checks on the server.\n    // Some servers forbid unknown request headers.\n    delete headers['x-msw-intention']\n\n    return fetch(requestClone, { headers })\n  }\n\n  // Bypass mocking when the client is not active.\n  if (!client) {\n    return passthrough()\n  }\n\n  // Bypass initial page load requests (i.e. static assets).\n  // The absence of the immediate/parent client in the map of the active clients\n  // means that MSW hasn't dispatched the \"MOCK_ACTIVATE\" event yet\n  // and is not ready to handle requests.\n  if (!activeClientIds.has(client.id)) {\n    return passthrough()\n  }\n\n  // Bypass requests with the explicit bypass header.\n  // Such requests can be issued by \"ctx.fetch()\".\n  const mswIntention = request.headers.get('x-msw-intention')\n  if (['bypass', 'passthrough'].includes(mswIntention)) {\n    return passthrough()\n  }\n\n  // Notify the client that a request has been intercepted.\n  const requestBuffer = await request.arrayBuffer()\n  const clientMessage = await sendToClient(\n    client,\n    {\n      type: 'REQUEST',\n      payload: {\n        id: requestId,\n        url: request.url,\n        mode: request.mode,\n        method: request.method,\n        headers: Object.fromEntries(request.headers.entries()),\n        cache: request.cache,\n        credentials: request.credentials,\n        destination: request.destination,\n        integrity: request.integrity,\n        redirect: request.redirect,\n        referrer: request.referrer,\n        referrerPolicy: request.referrerPolicy,\n        body: requestBuffer,\n        keepalive: request.keepalive,\n      },\n    },\n    [requestBuffer],\n  )\n\n  switch (clientMessage.type) {\n    case 'MOCK_RESPONSE': {\n      return respondWithMock(clientMessage.data)\n    }\n\n    case 'MOCK_NOT_FOUND': {\n      return passthrough()\n    }\n  }\n\n  return passthrough()\n}\n\nfunction sendToClient(client, message, transferrables = []) {\n  return new Promise((resolve, reject) => {\n    const channel = new MessageChannel()\n\n    channel.port1.onmessage = (event) => {\n      if (event.data && event.data.error) {\n        return reject(event.data.error)\n      }\n\n      resolve(event.data)\n    }\n\n    client.postMessage(\n      message,\n      [channel.port2].concat(transferrables.filter(Boolean)),\n    )\n  })\n}\n\nasync function respondWithMock(response) {\n  // Setting response status code to 0 is a no-op.\n  // However, when responding with a \"Response.error()\", the produced Response\n  // instance will have status code set to 0. Since it's not possible to create\n  // a Response instance with status code 0, handle that use-case separately.\n  if (response.status === 0) {\n    return Response.error()\n  }\n\n  const mockedResponse = new Response(response.body, response)\n\n  Reflect.defineProperty(mockedResponse, IS_MOCKED_RESPONSE, {\n    value: true,\n    enumerable: true,\n  })\n\n  return mockedResponse\n}\n"
  },
  {
    "path": "examples/react/offline/src/App.tsx",
    "content": "import * as React from 'react'\nimport {\n  MutationCache,\n  QueryClient,\n  onlineManager,\n  useIsRestoring,\n  useQuery,\n} from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\nimport { Toaster, toast } from 'react-hot-toast'\nimport { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'\nimport { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister'\nimport {\n  Link,\n  Outlet,\n  ReactLocation,\n  Router,\n  useMatch,\n} from '@tanstack/react-location'\n\nimport * as api from './api'\nimport { movieKeys, useMovie } from './movies'\n\nconst persister = createAsyncStoragePersister({\n  storage: window.localStorage,\n})\n\nconst location = new ReactLocation()\n\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      gcTime: 1000 * 60 * 60 * 24, // 24 hours\n      staleTime: 2000,\n      retry: 0,\n    },\n  },\n  // configure global cache callbacks to show toast notifications\n  mutationCache: new MutationCache({\n    onSuccess: (data) => {\n      toast.success(data.message)\n    },\n    onError: (error) => {\n      toast.error(error.message)\n    },\n  }),\n})\n\n// we need a default mutation function so that paused mutations can resume after a page reload\nqueryClient.setMutationDefaults(movieKeys.all(), {\n  mutationFn: async ({ id, comment }) => {\n    // to avoid clashes with our optimistic update when an offline mutation continues\n    await queryClient.cancelQueries({ queryKey: movieKeys.detail(id) })\n    return api.updateMovie(id, comment)\n  },\n})\n\nexport default function App() {\n  return (\n    <PersistQueryClientProvider\n      client={queryClient}\n      persistOptions={{ persister }}\n      onSuccess={() => {\n        // resume mutations after initial restore from localStorage was successful\n        queryClient.resumePausedMutations().then(() => {\n          queryClient.invalidateQueries()\n        })\n      }}\n    >\n      <Movies />\n      <ReactQueryDevtools initialIsOpen />\n    </PersistQueryClientProvider>\n  )\n}\n\nfunction Movies() {\n  const isRestoring = useIsRestoring()\n  return (\n    <Router\n      location={location}\n      routes={[\n        {\n          path: '/',\n          element: <List />,\n        },\n        {\n          path: ':movieId',\n          element: <Detail />,\n          errorElement: <MovieError />,\n          loader: ({ params: { movieId } }) =>\n            queryClient.getQueryData(movieKeys.detail(movieId)) ??\n            // do not load if we are offline or hydrating because it returns a promise that is pending until we go online again\n            // we just let the Detail component handle it\n            (onlineManager.isOnline() && !isRestoring\n              ? queryClient.fetchQuery({\n                  queryKey: movieKeys.detail(movieId),\n                  queryFn: () => api.fetchMovie(movieId),\n                })\n              : undefined),\n        },\n      ]}\n    >\n      <Outlet />\n      <Toaster />\n    </Router>\n  )\n}\n\nfunction List() {\n  const moviesQuery = useQuery({\n    queryKey: movieKeys.list(),\n    queryFn: api.fetchMovies,\n  })\n\n  if (moviesQuery.isLoading) {\n    return 'Loading...'\n  }\n\n  if (moviesQuery.data) {\n    return (\n      <div>\n        <h1>Movies</h1>\n        <p>\n          Try to mock offline behaviour with the button in the devtools. You can\n          navigate around as long as there is already data in the cache. You'll\n          get a refetch as soon as you go online again.\n        </p>\n        <ul>\n          {moviesQuery.data.movies.map((movie) => (\n            <li key={movie.id}>\n              <Link to={`./${movie.id}`} preload>\n                {movie.title}\n              </Link>\n            </li>\n          ))}\n        </ul>\n        <div>\n          Updated at: {new Date(moviesQuery.data.ts).toLocaleTimeString()}\n        </div>\n        <div>{moviesQuery.isFetching && 'fetching...'}</div>\n      </div>\n    )\n  }\n\n  // query will be in 'idle' fetchStatus while restoring from localStorage\n  return null\n}\n\nfunction MovieError() {\n  const { error } = useMatch()\n\n  return (\n    <div>\n      <Link to=\"..\">Back</Link>\n      <h1>Couldn't load movie!</h1>\n      <div>{error.message}</div>\n    </div>\n  )\n}\n\nfunction Detail() {\n  const {\n    params: { movieId },\n  } = useMatch()\n  const { comment, setComment, updateMovie, movieQuery } = useMovie(movieId)\n\n  if (movieQuery.isLoading) {\n    return 'Loading...'\n  }\n\n  function submitForm(event: any) {\n    event.preventDefault()\n\n    updateMovie.mutate({\n      id: movieId,\n      comment,\n    })\n  }\n\n  if (movieQuery.data) {\n    return (\n      <form onSubmit={submitForm}>\n        <Link to=\"..\">Back</Link>\n        <h1>Movie: {movieQuery.data.movie.title}</h1>\n        <p>\n          Try to mock offline behaviour with the button in the devtools, then\n          update the comment. The optimistic update will succeed, but the actual\n          mutation will be paused and resumed once you go online again.\n        </p>\n        <p>\n          You can also reload the page, which will make the persisted mutation\n          resume, as you will be online again when you \"come back\".\n        </p>\n        <p>\n          <label>\n            Comment: <br />\n            <textarea\n              name=\"comment\"\n              value={comment}\n              onChange={(event) => setComment(event.target.value)}\n            />\n          </label>\n        </p>\n        <button type=\"submit\">Submit</button>\n        <div>\n          Updated at: {new Date(movieQuery.data.ts).toLocaleTimeString()}\n        </div>\n        <div>{movieQuery.isFetching && 'fetching...'}</div>\n        <div>\n          {updateMovie.isPaused\n            ? 'mutation paused - offline'\n            : updateMovie.isPending && 'updating...'}\n        </div>\n      </form>\n    )\n  }\n\n  if (movieQuery.isPaused) {\n    return \"We're offline and have no data to show :(\"\n  }\n\n  return null\n}\n"
  },
  {
    "path": "examples/react/offline/src/api.ts",
    "content": "import { HttpResponse, delay, http, passthrough } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst movies = [\n  {\n    id: '1',\n    title: 'Guardians of the Galaxy',\n    comment: '',\n  },\n  {\n    id: '2',\n    title: 'Wall-E',\n    comment: '',\n  },\n]\n\nexport const fetchMovie = async (\n  id: string,\n): Promise<{\n  ts: number\n  movie: { comment: string; id: string; title: string }\n}> => {\n  const response = await fetch(`/movies/${id}`)\n  return await response.json()\n}\n\nexport const fetchMovies = async (): Promise<{\n  ts: number\n  movies: typeof movies\n}> => {\n  const response = await fetch('/movies')\n  return await response.json()\n}\n\nexport const updateMovie = async (id: string, comment: string) => {\n  const response = await fetch(`/movies/${id}`, {\n    method: 'POST',\n    body: JSON.stringify({ comment }),\n    headers: { 'Content-Type': 'application/json' },\n  })\n  return await response.json()\n}\n\nexport const worker = setupWorker(\n  http.get('/movies', async () => {\n    await delay(500)\n    return HttpResponse.json({\n      ts: Date.now(),\n      movies: movies.map(({ id, title }) => ({ id, title })),\n    })\n  }),\n\n  http.get('/movies/:id', async ({ params }) => {\n    const { id } = params\n\n    const movie = movies.find((movie) => movie.id === id)\n\n    if (!movie) {\n      return new HttpResponse(`Movie with id ${id} not found`, {\n        status: 404,\n      })\n    }\n\n    await delay(500)\n    return HttpResponse.json({ ts: Date.now(), movie })\n  }),\n\n  http.post('/movies/:id', async ({ request, params }) => {\n    const { id } = params\n    const body = await request.json()\n    const { comment } = body\n\n    movies.forEach((movie) => {\n      if (movie.id === id) {\n        movie.comment = comment.toUpperCase()\n      }\n    })\n\n    await delay(500)\n    return HttpResponse.json({ message: `Successfully updated movie ${id}` })\n  }),\n  http.get('*.js', () => passthrough()),\n  http.get('*.svg', () => passthrough()),\n)\n"
  },
  {
    "path": "examples/react/offline/src/index.tsx",
    "content": "import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport App from './App'\nimport { worker } from './api'\n\nworker.start()\n\nconst rootElement = document.getElementById('root') as HTMLElement\nReactDOM.createRoot(rootElement).render(\n  <div style={{ padding: '16px' }}>\n    <App />\n  </div>,\n)\n"
  },
  {
    "path": "examples/react/offline/src/movies.ts",
    "content": "import * as React from 'react'\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport * as api from './api'\n\nexport const movieKeys = {\n  all: () => ['movies'],\n  list: () => [...movieKeys.all(), 'list'],\n  details: () => [...movieKeys.all(), 'detail'],\n  detail: (id: string) => [...movieKeys.details(), id],\n}\n\nexport const useMovie = (movieId: string) => {\n  const queryClient = useQueryClient()\n\n  const movieQuery = useQuery({\n    queryKey: movieKeys.detail(movieId),\n    queryFn: () => api.fetchMovie(movieId),\n  })\n\n  const [comment, setComment] = React.useState<string | undefined>()\n\n  const updateMovie = useMutation({\n    mutationKey: movieKeys.detail(movieId),\n    onMutate: async () => {\n      await queryClient.cancelQueries({ queryKey: movieKeys.detail(movieId) })\n      const previousData = queryClient.getQueryData(movieKeys.detail(movieId))\n\n      // remove local state so that server state is taken instead\n      setComment(undefined)\n\n      queryClient.setQueryData(movieKeys.detail(movieId), {\n        ...previousData,\n        movie: {\n          ...previousData.movie,\n          comment,\n        },\n      })\n\n      return { previousData }\n    },\n    onError: (_, __, context) => {\n      queryClient.setQueryData(movieKeys.detail(movieId), context.previousData)\n    },\n    onSettled: () => {\n      queryClient.invalidateQueries({ queryKey: movieKeys.detail(movieId) })\n    },\n  })\n\n  return {\n    comment: comment ?? movieQuery.data?.movie.comment,\n    setComment,\n    updateMovie,\n    movieQuery,\n  }\n}\n"
  },
  {
    "path": "examples/react/offline/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src\", \"eslint.config.js\"]\n}\n"
  },
  {
    "path": "examples/react/offline/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\n\nexport default defineConfig({\n  plugins: [react()],\n})\n"
  },
  {
    "path": "examples/react/optimistic-updates-cache/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\npnpm-lock.yaml\nyarn.lock\npackage-lock.json\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "examples/react/optimistic-updates-cache/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `npm install`\n- `npm run dev`\n"
  },
  {
    "path": "examples/react/optimistic-updates-cache/next.config.js",
    "content": "// @ts-check\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {\n  eslint: {\n    ignoreDuringBuilds: true,\n  },\n  typescript: {\n    ignoreBuildErrors: true,\n  },\n}\n\nexport default nextConfig\n"
  },
  {
    "path": "examples/react/optimistic-updates-cache/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-react-optimistic-updates-cache\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"next\",\n    \"build\": \"next build\",\n    \"start\": \"next start\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"next\": \"^16.0.7\",\n    \"react\": \"^19.2.1\",\n    \"react-dom\": \"^19.2.1\"\n  },\n  \"devDependencies\": {\n    \"@types/react\": \"^19.2.7\",\n    \"@types/react-dom\": \"^19.2.3\",\n    \"typescript\": \"5.8.3\"\n  }\n}\n"
  },
  {
    "path": "examples/react/optimistic-updates-cache/src/pages/api/data.ts",
    "content": "import type { NextApiRequest, NextApiResponse } from 'next'\n\ntype Todo = { id: string; text: string }\n\nconst items: Array<Todo> = []\n\nexport default async (req: NextApiRequest, res: NextApiResponse) => {\n  await new Promise((r) => setTimeout(r, 1000))\n\n  if (req.method === 'POST') {\n    const text: string = req.body.text\n\n    // sometimes it will fail, this will cause a regression on the UI\n\n    if (Math.random() > 0.7) {\n      res.status(500)\n      res.json({ message: 'Could not add item!' })\n      return\n    }\n\n    const newTodo = { id: Math.random().toString(), text: text.toUpperCase() }\n    items.push(newTodo)\n    res.json(newTodo)\n    return\n  } else {\n    res.json({\n      ts: Date.now(),\n      items,\n    })\n  }\n}\n"
  },
  {
    "path": "examples/react/optimistic-updates-cache/src/pages/index.tsx",
    "content": "import * as React from 'react'\n\nimport {\n  QueryClient,\n  QueryClientProvider,\n  queryOptions,\n  useMutation,\n  useQuery,\n  useQueryClient,\n} from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\n\nconst client = new QueryClient()\n\ntype Todos = {\n  items: ReadonlyArray<{\n    id: string\n    text: string\n  }>\n  ts: number\n}\n\nasync function fetchTodos({ signal }: { signal: AbortSignal }): Promise<Todos> {\n  const response = await fetch('/api/data', { signal })\n  return await response.json()\n}\n\nconst todoListOptions = queryOptions({\n  queryKey: ['todos'],\n  queryFn: fetchTodos,\n})\n\nfunction Example() {\n  const queryClient = useQueryClient()\n  const [text, setText] = React.useState('')\n  const { isFetching, ...queryInfo } = useQuery(todoListOptions)\n\n  const addTodoMutation = useMutation({\n    mutationFn: async (newTodo: string) => {\n      const response = await fetch('/api/data', {\n        method: 'POST',\n        body: JSON.stringify({ text: newTodo }),\n        headers: { 'Content-Type': 'application/json' },\n      })\n      return await response.json()\n    },\n    // When mutate is called:\n    onMutate: async (newTodo, context) => {\n      setText('')\n      // Cancel any outgoing refetch\n      // (so they don't overwrite our optimistic update)\n      await context.client.cancelQueries(todoListOptions)\n\n      // Snapshot the previous value\n      const previousTodos = context.client.getQueryData(\n        todoListOptions.queryKey,\n      )\n\n      // Optimistically update to the new value\n      if (previousTodos) {\n        context.client.setQueryData(todoListOptions.queryKey, {\n          ...previousTodos,\n          items: [\n            ...previousTodos.items,\n            { id: Math.random().toString(), text: newTodo },\n          ],\n        })\n      }\n\n      return { previousTodos }\n    },\n    // If the mutation fails,\n    // use the result returned from onMutate to roll back\n    onError: (err, variables, onMutateResult, context) => {\n      if (onMutateResult?.previousTodos) {\n        context.client.setQueryData<Todos>(\n          ['todos'],\n          onMutateResult.previousTodos,\n        )\n      }\n    },\n    // Always refetch after error or success:\n    onSettled: (data, error, variables, onMutateResult, context) =>\n      context.client.invalidateQueries({ queryKey: ['todos'] }),\n  })\n\n  return (\n    <div>\n      <p>\n        In this example, new items can be created using a mutation. The new item\n        will be optimistically added to the list in hopes that the server\n        accepts the item. If it does, the list is refetched with the true items\n        from the list. Every now and then, the mutation may fail though. When\n        that happens, the previous list of items is restored and the list is\n        again refetched from the server.\n      </p>\n      <form\n        onSubmit={(e) => {\n          e.preventDefault()\n          addTodoMutation.mutate(text)\n        }}\n      >\n        <input\n          type=\"text\"\n          onChange={(event) => setText(event.target.value)}\n          value={text}\n        />\n        <button disabled={addTodoMutation.isPending}>Create</button>\n      </form>\n      <br />\n      {queryInfo.isSuccess && (\n        <>\n          <div>\n            {/* The type of queryInfo.data will be narrowed because we check for isSuccess first */}\n            Updated At: {new Date(queryInfo.data.ts).toLocaleTimeString()}\n          </div>\n          <ul>\n            {queryInfo.data.items.map((todo) => (\n              <li key={todo.id}>{todo.text}</li>\n            ))}\n          </ul>\n          {isFetching && <div>Updating in background...</div>}\n        </>\n      )}\n      {queryInfo.isLoading && 'Loading'}\n      {queryInfo.error instanceof Error && queryInfo.error.message}\n    </div>\n  )\n}\n\nexport default function App() {\n  return (\n    <QueryClientProvider client={client}>\n      <Example />\n      <ReactQueryDevtools initialIsOpen />\n    </QueryClientProvider>\n  )\n}\n"
  },
  {
    "path": "examples/react/optimistic-updates-cache/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"lib\": [\"DOM\", \"ES2015\"],\n    \"jsx\": \"react-jsx\",\n    \"target\": \"ES5\",\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"noEmit\": true,\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"incremental\": true\n  },\n  \"include\": [\"src\"],\n  \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "examples/react/optimistic-updates-ui/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\npnpm-lock.yaml\nyarn.lock\npackage-lock.json\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "examples/react/optimistic-updates-ui/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `npm install`\n- `npm run dev`\n"
  },
  {
    "path": "examples/react/optimistic-updates-ui/next.config.js",
    "content": "// @ts-check\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {\n  eslint: {\n    ignoreDuringBuilds: true,\n  },\n  typescript: {\n    ignoreBuildErrors: true,\n  },\n}\n\nexport default nextConfig\n"
  },
  {
    "path": "examples/react/optimistic-updates-ui/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-react-optimistic-updates-ui\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"next\",\n    \"build\": \"next build\",\n    \"start\": \"next start\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"next\": \"^16.0.7\",\n    \"react\": \"^19.2.1\",\n    \"react-dom\": \"^19.2.1\"\n  },\n  \"devDependencies\": {\n    \"@types/react\": \"^19.2.7\",\n    \"@types/react-dom\": \"^19.2.3\",\n    \"typescript\": \"5.8.3\"\n  }\n}\n"
  },
  {
    "path": "examples/react/optimistic-updates-ui/src/pages/api/data.ts",
    "content": "import type { NextApiRequest, NextApiResponse } from 'next'\n\ntype Todo = { id: string; text: string }\n\nconst items: Array<Todo> = []\n\nexport default async (req: NextApiRequest, res: NextApiResponse) => {\n  await new Promise((r) => setTimeout(r, 1000))\n\n  if (req.method === 'POST') {\n    const text: string = req.body.text\n\n    // sometimes it will fail, this will cause a regression on the UI\n\n    if (Math.random() > 0.7) {\n      res.status(500)\n      res.json({ message: 'Could not add item!' })\n      return\n    }\n\n    const newTodo = { id: Math.random().toString(), text: text.toUpperCase() }\n    items.push(newTodo)\n    res.json(newTodo)\n    return\n  } else {\n    res.json({\n      ts: Date.now(),\n      items,\n    })\n  }\n}\n"
  },
  {
    "path": "examples/react/optimistic-updates-ui/src/pages/index.tsx",
    "content": "import * as React from 'react'\nimport {\n  QueryClient,\n  QueryClientProvider,\n  useMutation,\n  useQuery,\n  useQueryClient,\n} from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\n\nconst client = new QueryClient()\n\ntype Todos = {\n  items: ReadonlyArray<{\n    id: string\n    text: string\n  }>\n  ts: number\n}\n\nasync function fetchTodos(): Promise<Todos> {\n  const response = await fetch('/api/data')\n  return await response.json()\n}\n\nfunction useTodos() {\n  return useQuery({ queryKey: ['todos'], queryFn: fetchTodos })\n}\n\nfunction Example() {\n  const queryClient = useQueryClient()\n  const [text, setText] = React.useState('')\n  const todoQuery = useTodos()\n\n  const addTodoMutation = useMutation({\n    mutationFn: async (newTodo: string) => {\n      const response = await fetch('/api/data', {\n        method: 'POST',\n        body: JSON.stringify({ text: newTodo }),\n        headers: { 'Content-Type': 'application/json' },\n      })\n      if (!response.ok) {\n        throw new Error('Something went wrong.')\n      }\n      return await response.json()\n    },\n    onSettled: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),\n  })\n\n  return (\n    <div>\n      <p>\n        In this example, new items can be created using a mutation. The new item\n        will be optimistically added to the list in hopes that the server\n        accepts the item. If it does, the list is refetched with the true items\n        from the list. Every now and then, the mutation may fail though. When\n        that happens, the previous list of items is restored and the list is\n        again refetched from the server.\n      </p>\n      <form\n        onSubmit={(e) => {\n          e.preventDefault()\n          setText('')\n          addTodoMutation.mutate(text)\n        }}\n      >\n        <input\n          type=\"text\"\n          onChange={(event) => setText(event.target.value)}\n          value={text}\n        />\n        <button disabled={addTodoMutation.isPending}>Create</button>\n      </form>\n      <br />\n      {todoQuery.isSuccess && (\n        <>\n          <div>\n            {/* The type of queryInfo.data will be narrowed because we check for isSuccess first */}\n            Updated At: {new Date(todoQuery.data.ts).toLocaleTimeString()}\n          </div>\n          <ul>\n            {todoQuery.data.items.map((todo) => (\n              <li key={todo.id}>{todo.text}</li>\n            ))}\n            {addTodoMutation.isPending && (\n              <li style={{ opacity: 0.5 }}>{addTodoMutation.variables}</li>\n            )}\n            {addTodoMutation.isError && (\n              <li style={{ color: 'red' }}>\n                {addTodoMutation.variables}\n                <button\n                  onClick={() =>\n                    addTodoMutation.mutate(addTodoMutation.variables)\n                  }\n                >\n                  Retry\n                </button>\n              </li>\n            )}\n          </ul>\n          {todoQuery.isFetching && <div>Updating in background...</div>}\n        </>\n      )}\n      {todoQuery.isPending && 'Loading'}\n      {todoQuery.error instanceof Error && todoQuery.error.message}\n    </div>\n  )\n}\n\nexport default function App() {\n  return (\n    <QueryClientProvider client={client}>\n      <Example />\n      <ReactQueryDevtools initialIsOpen />\n    </QueryClientProvider>\n  )\n}\n"
  },
  {
    "path": "examples/react/optimistic-updates-ui/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"lib\": [\"dom\", \"es2015\"],\n    \"jsx\": \"react-jsx\",\n    \"target\": \"ES5\",\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"noEmit\": true,\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"incremental\": true\n  },\n  \"include\": [\"src\"],\n  \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "examples/react/pagination/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\npnpm-lock.yaml\nyarn.lock\npackage-lock.json\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "examples/react/pagination/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `npm install`\n- `npm run dev`\n"
  },
  {
    "path": "examples/react/pagination/next.config.js",
    "content": "// @ts-check\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {\n  eslint: {\n    ignoreDuringBuilds: true,\n  },\n  typescript: {\n    ignoreBuildErrors: true,\n  },\n}\n\nexport default nextConfig\n"
  },
  {
    "path": "examples/react/pagination/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-react-pagination\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"next\",\n    \"build\": \"next build\",\n    \"start\": \"next start\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"next\": \"^16.0.7\",\n    \"react\": \"^19.2.1\",\n    \"react-dom\": \"^19.2.1\"\n  },\n  \"devDependencies\": {\n    \"@types/react\": \"^19.2.7\",\n    \"@types/react-dom\": \"^19.2.3\",\n    \"typescript\": \"5.8.3\"\n  }\n}\n"
  },
  {
    "path": "examples/react/pagination/src/pages/api/projects.ts",
    "content": "import type { NextApiRequest, NextApiResponse } from 'next'\n\nexport default async (req: NextApiRequest, res: NextApiResponse) => {\n  const page = parseInt(req.query.page) || 0\n\n  const pageSize = 10\n\n  const projects = Array(pageSize)\n    .fill(0)\n    .map((_, i) => {\n      const id = page * pageSize + (i + 1)\n      return {\n        name: 'Project ' + id,\n        id,\n      }\n    })\n\n  await new Promise((r) => setTimeout(r, 1000))\n\n  res.json({ projects, hasMore: page < 9 })\n}\n"
  },
  {
    "path": "examples/react/pagination/src/pages/index.tsx",
    "content": "import React from 'react'\nimport {\n  QueryClient,\n  QueryClientProvider,\n  keepPreviousData,\n  useQuery,\n  useQueryClient,\n} from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\n\nconst queryClient = new QueryClient()\n\nexport default function App() {\n  return (\n    <QueryClientProvider client={queryClient}>\n      <Example />\n    </QueryClientProvider>\n  )\n}\n\nconst fetchProjects = async (\n  page = 0,\n): Promise<{\n  projects: Array<{ name: string; id: number }>\n  hasMore: boolean\n}> => {\n  const response = await fetch(`/api/projects?page=${page}`)\n  return await response.json()\n}\n\nfunction Example() {\n  const queryClient = useQueryClient()\n  const [page, setPage] = React.useState(0)\n\n  const { status, data, error, isFetching, isPlaceholderData } = useQuery({\n    queryKey: ['projects', page],\n    queryFn: () => fetchProjects(page),\n    placeholderData: keepPreviousData,\n    staleTime: 5000,\n  })\n\n  // Prefetch the next page!\n  React.useEffect(() => {\n    if (!isPlaceholderData && data?.hasMore) {\n      queryClient.prefetchQuery({\n        queryKey: ['projects', page + 1],\n        queryFn: () => fetchProjects(page + 1),\n      })\n    }\n  }, [data, isPlaceholderData, page, queryClient])\n\n  return (\n    <div>\n      <p>\n        In this example, each page of data remains visible as the next page is\n        fetched. The buttons and capability to proceed to the next page are also\n        supressed until the next page cursor is known. Each page is cached as a\n        normal query too, so when going to previous pages, you'll see them\n        instantaneously while they are also refetched invisibly in the\n        background.\n      </p>\n      {status === 'pending' ? (\n        <div>Loading...</div>\n      ) : status === 'error' ? (\n        <div>Error: {error.message}</div>\n      ) : (\n        // `data` will either resolve to the latest page's data\n        // or if fetching a new page, the last successful page's data\n        <div>\n          {data.projects.map((project) => (\n            <p key={project.id}>{project.name}</p>\n          ))}\n        </div>\n      )}\n      <div>Current Page: {page + 1}</div>\n      <button\n        onClick={() => setPage((old) => Math.max(old - 1, 0))}\n        disabled={page === 0}\n      >\n        Previous Page\n      </button>{' '}\n      <button\n        onClick={() => {\n          setPage((old) => (data?.hasMore ? old + 1 : old))\n        }}\n        disabled={isPlaceholderData || !data?.hasMore}\n      >\n        Next Page\n      </button>\n      {\n        // Since the last page's data potentially sticks around between page requests,\n        // we can use `isFetching` to show a background loading\n        // indicator since our `status === 'pending'` state won't be triggered\n        isFetching ? <span> Loading...</span> : null\n      }{' '}\n      <ReactQueryDevtools initialIsOpen />\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/react/pagination/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"jsx\": \"react-jsx\",\n    \"incremental\": true,\n    \"target\": \"ES2017\"\n  },\n  \"include\": [\"next-env.d.ts\", \"**/*.ts\", \"**/*.tsx\"],\n  \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "examples/react/playground/.eslintrc",
    "content": "{\n  \"extends\": [\"plugin:react/jsx-runtime\", \"plugin:react-hooks/recommended\"]\n}\n"
  },
  {
    "path": "examples/react/playground/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\npnpm-lock.yaml\nyarn.lock\npackage-lock.json\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "examples/react/playground/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `npm install`\n- `npm run dev`\n"
  },
  {
    "path": "examples/react/playground/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"shortcut icon\" type=\"image/svg+xml\" href=\"/emblem-light.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <meta name=\"theme-color\" content=\"#000000\" />\n\n    <title>TanStack Query React Playgorund Example App</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/index.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/react/playground/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-react-playground\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\"\n  },\n  \"devDependencies\": {\n    \"@vitejs/plugin-react\": \"^4.3.4\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "examples/react/playground/src/index.tsx",
    "content": "import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport {\n  QueryClient,\n  QueryClientProvider,\n  useMutation,\n  useQuery,\n  useQueryClient,\n} from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\nimport './styles.css'\n\nlet id = 0\nlet list = [\n  'apple',\n  'banana',\n  'pineapple',\n  'grapefruit',\n  'dragonfruit',\n  'grapes',\n].map((d) => ({ id: id++, name: d, notes: 'These are some notes' }))\n\ntype Todos = typeof list\ntype Todo = Todos[0]\n\nlet errorRate = 0.05\nlet queryTimeMin = 1000\nlet queryTimeMax = 2000\n\nconst queryClient = new QueryClient()\n\nfunction Root() {\n  const [staleTime, setStaleTime] = React.useState(1000)\n  const [gcTime, setGcTime] = React.useState(3000)\n  const [localErrorRate, setErrorRate] = React.useState(errorRate)\n  const [localFetchTimeMin, setLocalFetchTimeMin] = React.useState(queryTimeMin)\n  const [localFetchTimeMax, setLocalFetchTimeMax] = React.useState(queryTimeMax)\n\n  React.useEffect(() => {\n    errorRate = localErrorRate\n    queryTimeMin = localFetchTimeMin\n    queryTimeMax = localFetchTimeMax\n  }, [localErrorRate, localFetchTimeMax, localFetchTimeMin])\n\n  React.useEffect(() => {\n    queryClient.setDefaultOptions({\n      queries: {\n        staleTime,\n        gcTime,\n      },\n    })\n  }, [gcTime, staleTime])\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      <p>\n        The \"staleTime\" and \"gcTime\" durations have been altered in this example\n        to show how query stale-ness and query caching work on a granular level\n      </p>\n      <div>\n        Stale Time:{' '}\n        <input\n          type=\"number\"\n          min=\"0\"\n          step=\"1000\"\n          value={staleTime}\n          onChange={(e) => setStaleTime(parseFloat(e.target.value))}\n          style={{ width: '100px' }}\n        />\n      </div>\n      <div>\n        Garbage collection Time:{' '}\n        <input\n          type=\"number\"\n          min=\"0\"\n          step=\"1000\"\n          value={gcTime}\n          onChange={(e) => setGcTime(parseFloat(e.target.value))}\n          style={{ width: '100px' }}\n        />\n      </div>\n      <br />\n      <div>\n        Error Rate:{' '}\n        <input\n          type=\"number\"\n          min=\"0\"\n          max=\"1\"\n          step=\".05\"\n          value={localErrorRate}\n          onChange={(e) => setErrorRate(parseFloat(e.target.value))}\n          style={{ width: '100px' }}\n        />\n      </div>\n      <div>\n        Fetch Time Min:{' '}\n        <input\n          type=\"number\"\n          min=\"1\"\n          step=\"500\"\n          value={localFetchTimeMin}\n          onChange={(e) => setLocalFetchTimeMin(parseFloat(e.target.value))}\n          style={{ width: '60px' }}\n        />{' '}\n      </div>\n      <div>\n        Fetch Time Max:{' '}\n        <input\n          type=\"number\"\n          min=\"1\"\n          step=\"500\"\n          value={localFetchTimeMax}\n          onChange={(e) => setLocalFetchTimeMax(parseFloat(e.target.value))}\n          style={{ width: '60px' }}\n        />\n      </div>\n      <br />\n      <App />\n      <br />\n      <ReactQueryDevtools initialIsOpen />\n    </QueryClientProvider>\n  )\n}\n\nfunction App() {\n  const queryClient = useQueryClient()\n  const [editingIndex, setEditingIndex] = React.useState<number | null>(null)\n  const [views, setViews] = React.useState(['', 'fruit', 'grape'])\n  // const [views, setViews] = React.useState([\"\"]);\n\n  return (\n    <div className=\"App\">\n      <div>\n        <button onClick={() => queryClient.invalidateQueries()}>\n          Force Refetch All\n        </button>\n      </div>\n      <br />\n      <hr />\n      {views.map((view, index) => (\n        <div key={index}>\n          <Todos\n            initialFilter={view}\n            setEditingIndex={setEditingIndex}\n            onRemove={() => {\n              setViews((old) => [...old, ''])\n            }}\n          />\n          <br />\n        </div>\n      ))}\n      <button\n        onClick={() => {\n          setViews((old) => [...old, ''])\n        }}\n      >\n        Add Filter List\n      </button>\n      <hr />\n      {editingIndex !== null ? (\n        <>\n          <EditTodo\n            editingIndex={editingIndex}\n            setEditingIndex={setEditingIndex}\n          />\n          <hr />\n        </>\n      ) : null}\n      <AddTodo />\n    </div>\n  )\n}\n\nfunction Todos({\n  initialFilter = '',\n  setEditingIndex,\n}: {\n  initialFilter: string\n  setEditingIndex: React.Dispatch<React.SetStateAction<number | null>>\n}) {\n  const [filter, setFilter] = React.useState(initialFilter)\n\n  const { status, data, isFetching, error, failureCount, refetch } = useQuery({\n    queryKey: ['todos', { filter }],\n    queryFn: fetchTodos,\n  })\n\n  return (\n    <div>\n      <div>\n        <label>\n          Filter:{' '}\n          <input value={filter} onChange={(e) => setFilter(e.target.value)} />\n        </label>\n      </div>\n      {status === 'pending' ? (\n        <span>Loading... (Attempt: {failureCount + 1})</span>\n      ) : status === 'error' ? (\n        <span>\n          Error: {error.message}\n          <br />\n          <button onClick={() => refetch()}>Retry</button>\n        </span>\n      ) : (\n        <>\n          <ul>\n            {data\n              ? data.map((todo) => (\n                  <li key={todo.id}>\n                    {todo.name}{' '}\n                    <button onClick={() => setEditingIndex(todo.id)}>\n                      Edit\n                    </button>\n                  </li>\n                ))\n              : null}\n          </ul>\n          <div>\n            {isFetching ? (\n              <span>\n                Background Refreshing... (Attempt: {failureCount + 1})\n              </span>\n            ) : (\n              <span>&nbsp;</span>\n            )}\n          </div>\n        </>\n      )}\n    </div>\n  )\n}\n\nfunction EditTodo({\n  editingIndex,\n  setEditingIndex,\n}: {\n  editingIndex: number\n  setEditingIndex: React.Dispatch<React.SetStateAction<number | null>>\n}) {\n  const queryClient = useQueryClient()\n\n  // Don't attempt to query until editingIndex is truthy\n  const { status, data, isFetching, error, failureCount, refetch } = useQuery({\n    queryKey: ['todo', { id: editingIndex }],\n    queryFn: () => fetchTodoById({ id: editingIndex }),\n  })\n\n  const [todo, setTodo] = React.useState(data || {})\n\n  React.useEffect(() => {\n    if (editingIndex !== null && data) {\n      setTodo(data)\n    } else {\n      setTodo({})\n    }\n  }, [data, editingIndex])\n\n  const saveMutation = useMutation({\n    mutationFn: patchTodo,\n    onSuccess: (data) => {\n      // Update `todos` and the individual todo queries when this mutation succeeds\n      queryClient.invalidateQueries({ queryKey: ['todos'] })\n      queryClient.setQueryData(['todo', { id: editingIndex }], data)\n    },\n  })\n\n  const onSave = () => {\n    saveMutation.mutate(todo)\n  }\n\n  const disableEditSave =\n    status === 'pending' || saveMutation.status === 'pending'\n\n  return (\n    <div>\n      <div>\n        {data ? (\n          <>\n            <button onClick={() => setEditingIndex(null)}>Back</button> Editing\n            Todo \"{data.name}\" (#\n            {editingIndex})\n          </>\n        ) : null}\n      </div>\n      {status === 'pending' ? (\n        <span>Loading... (Attempt: {failureCount + 1})</span>\n      ) : error ? (\n        <span>\n          Error! <button onClick={() => refetch()}>Retry</button>\n        </span>\n      ) : (\n        <>\n          <label>\n            Name:{' '}\n            <input\n              value={todo.name}\n              onChange={(e) =>\n                e.persist() ||\n                setTodo((old) => ({ ...old, name: e.target.value }))\n              }\n              disabled={disableEditSave}\n            />\n          </label>\n          <label>\n            Notes:{' '}\n            <input\n              value={todo.notes}\n              onChange={(e) =>\n                e.persist() ||\n                setTodo((old) => ({ ...old, notes: e.target.value }))\n              }\n              disabled={disableEditSave}\n            />\n          </label>\n          <div>\n            <button onClick={onSave} disabled={disableEditSave}>\n              Save\n            </button>\n          </div>\n          <div>\n            {saveMutation.status === 'pending'\n              ? 'Saving...'\n              : saveMutation.status === 'error'\n                ? saveMutation.error.message\n                : 'Saved!'}\n          </div>\n          <div>\n            {isFetching ? (\n              <span>\n                Background Refreshing... (Attempt: {failureCount + 1})\n              </span>\n            ) : (\n              <span>&nbsp;</span>\n            )}\n          </div>\n        </>\n      )}\n    </div>\n  )\n}\n\nfunction AddTodo() {\n  const queryClient = useQueryClient()\n  const [name, setName] = React.useState('')\n\n  const addMutation = useMutation({\n    mutationFn: postTodo,\n    onSuccess: () => {\n      queryClient.invalidateQueries({ queryKey: ['todos'] })\n    },\n  })\n\n  return (\n    <div>\n      <input\n        value={name}\n        onChange={(e) => setName(e.target.value)}\n        disabled={addMutation.status === 'pending'}\n      />\n      <button\n        onClick={() => {\n          addMutation.mutate({ name, notes: 'These are some notes' })\n        }}\n        disabled={addMutation.status === 'pending' || !name}\n      >\n        Add Todo\n      </button>\n      <div>\n        {addMutation.status === 'pending'\n          ? 'Saving...'\n          : addMutation.status === 'error'\n            ? addMutation.error.message\n            : 'Saved!'}\n      </div>\n    </div>\n  )\n}\n\nfunction fetchTodos({ signal, queryKey: [, { filter }] }): Promise<Todos> {\n  console.info('fetchTodos', { filter })\n\n  if (signal) {\n    signal.addEventListener('abort', () => {\n      console.info('cancelled', filter)\n    })\n  }\n\n  return new Promise((resolve, reject) => {\n    setTimeout(\n      () => {\n        if (Math.random() < errorRate) {\n          return reject(\n            new Error(JSON.stringify({ fetchTodos: { filter } }, null, 2)),\n          )\n        }\n        resolve(list.filter((d) => d.name.includes(filter)))\n      },\n      queryTimeMin + Math.random() * (queryTimeMax - queryTimeMin),\n    )\n  })\n}\n\nfunction fetchTodoById({ id }: { id: number }): Promise<Todo> {\n  console.info('fetchTodoById', { id })\n  return new Promise((resolve, reject) => {\n    setTimeout(\n      () => {\n        if (Math.random() < errorRate) {\n          return reject(\n            new Error(JSON.stringify({ fetchTodoById: { id } }, null, 2)),\n          )\n        }\n        resolve(list.find((d) => d.id === id))\n      },\n      queryTimeMin + Math.random() * (queryTimeMax - queryTimeMin),\n    )\n  })\n}\n\nfunction postTodo({ name, notes }: Omit<Todo, 'id'>) {\n  console.info('postTodo', { name, notes })\n  return new Promise((resolve, reject) => {\n    setTimeout(\n      () => {\n        if (Math.random() < errorRate) {\n          return reject(\n            new Error(JSON.stringify({ postTodo: { name, notes } }, null, 2)),\n          )\n        }\n        const todo = { name, notes, id: id++ }\n        list = [...list, todo]\n        resolve(todo)\n      },\n      queryTimeMin + Math.random() * (queryTimeMax - queryTimeMin),\n    )\n  })\n}\n\nfunction patchTodo(todo?: Todo): Promise<Todo> {\n  console.info('patchTodo', todo)\n  return new Promise((resolve, reject) => {\n    setTimeout(\n      () => {\n        if (Math.random() < errorRate) {\n          return reject(new Error(JSON.stringify({ patchTodo: todo }, null, 2)))\n        }\n        list = list.map((d) => {\n          if (d.id === todo.id) {\n            return todo\n          }\n          return d\n        })\n        resolve(todo)\n      },\n      queryTimeMin + Math.random() * (queryTimeMax - queryTimeMin),\n    )\n  })\n}\n\nconst rootElement = document.getElementById('root') as HTMLElement\nReactDOM.createRoot(rootElement).render(<Root />)\n"
  },
  {
    "path": "examples/react/playground/src/styles.css",
    "content": "body {\n  margin: 0;\n  padding: 1rem;\n  font-family:\n    -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu',\n    'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  color: white;\n  background: #0b1521;\n}\n"
  },
  {
    "path": "examples/react/playground/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src\", \"eslint.config.js\"]\n}\n"
  },
  {
    "path": "examples/react/playground/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\n\nexport default defineConfig({\n  plugins: [react()],\n})\n"
  },
  {
    "path": "examples/react/prefetching/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\npnpm-lock.yaml\nyarn.lock\npackage-lock.json\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "examples/react/prefetching/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `npm install`\n- `npm run dev`\n"
  },
  {
    "path": "examples/react/prefetching/next.config.js",
    "content": "// @ts-check\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {\n  eslint: {\n    ignoreDuringBuilds: true,\n  },\n  typescript: {\n    ignoreBuildErrors: true,\n  },\n}\n\nexport default nextConfig\n"
  },
  {
    "path": "examples/react/prefetching/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-react-prefetching\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"next\",\n    \"build\": \"next build\",\n    \"start\": \"next start\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"next\": \"^16.0.7\",\n    \"react\": \"^19.2.1\",\n    \"react-dom\": \"^19.2.1\"\n  },\n  \"devDependencies\": {\n    \"@types/react\": \"^19.2.7\",\n    \"@types/react-dom\": \"^19.2.3\",\n    \"typescript\": \"5.8.3\"\n  }\n}\n"
  },
  {
    "path": "examples/react/prefetching/src/pages/[user]/[repo].tsx",
    "content": "import React from 'react'\nimport Link from 'next/link'\nimport { useQuery } from '@tanstack/react-query'\nimport { usePathname } from 'next/navigation'\n\nasync function fetchProject(id: string): Promise<{\n  forks_count: number\n  stargazers_count: number\n  watchers_count: number\n}> {\n  console.info('Fetching project:', id)\n\n  const response = await fetch(`https://api.github.com/repos/${id}`)\n  await new Promise((r) => setTimeout(r, 1000))\n  return await response.json()\n}\n\nexport default function Repo() {\n  const id = usePathname()\n\n  const { status, data, error, isFetching } = useQuery({\n    queryKey: ['team', id],\n    queryFn: () => fetchProject(id),\n  })\n\n  return (\n    <div style={{ textAlign: 'center' }}>\n      <h1>{id}</h1>\n      {status === 'pending' ? (\n        'Loading...'\n      ) : status === 'error' ? (\n        <span>Error: {error.message}</span>\n      ) : (\n        <>\n          <div>\n            <p>forks: {data.forks_count}</p>\n            <p>stars: {data.stargazers_count}</p>\n            <p>watchers: {data.watchers_count}</p>\n          </div>\n          <div>{isFetching ? 'Background Updating...' : ' '}</div>\n        </>\n      )}\n      <br />\n      <br />\n      <Link href=\"/\">Back</Link>\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/react/prefetching/src/pages/_app.tsx",
    "content": "import React from 'react'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport type { AppProps } from 'next/app'\n\nexport default function MyApp({ Component, pageProps }: AppProps) {\n  const [queryClient] = React.useState(() => new QueryClient())\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      <Component {...pageProps} />\n    </QueryClientProvider>\n  )\n}\n"
  },
  {
    "path": "examples/react/prefetching/src/pages/index.tsx",
    "content": "import React from 'react'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\n\nconst getCharacters = async (): Promise<{\n  results: Array<{ id: number; name: string }>\n}> => {\n  await new Promise((r) => setTimeout(r, 500))\n  const response = await fetch('https://rickandmortyapi.com/api/character/')\n  return await response.json()\n}\n\nconst getCharacter = async (selectedChar: number) => {\n  await new Promise((r) => setTimeout(r, 500))\n  const response = await fetch(\n    `https://rickandmortyapi.com/api/character/${selectedChar}`,\n  )\n  return await response.json()\n}\n\nexport default function Example() {\n  const queryClient = useQueryClient()\n  const rerender = React.useState(0)[1]\n  const [selectedChar, setSelectedChar] = React.useState(1)\n\n  const charactersQuery = useQuery({\n    queryKey: ['characters'],\n    queryFn: getCharacters,\n  })\n\n  const characterQuery = useQuery({\n    queryKey: ['character', selectedChar],\n    queryFn: () => getCharacter(selectedChar),\n  })\n\n  return (\n    <div className=\"App\">\n      <p>\n        Hovering over a character will prefetch it, and when it's been\n        prefetched it will turn <strong>bold</strong>. Clicking on a prefetched\n        character will show their stats below immediately.\n      </p>\n      <h2>Characters</h2>\n      {charactersQuery.isPending ? (\n        'Loading...'\n      ) : (\n        <>\n          <ul>\n            {charactersQuery.data?.results.map((char) => (\n              <li\n                key={char.id}\n                onClick={() => {\n                  setSelectedChar(char.id)\n                }}\n                onMouseEnter={async () => {\n                  await queryClient.prefetchQuery({\n                    queryKey: ['character', char.id],\n                    queryFn: () => getCharacter(char.id),\n                    staleTime: 10 * 1000, // only prefetch if older than 10 seconds\n                  })\n\n                  setTimeout(() => {\n                    rerender({})\n                  }, 1)\n                }}\n              >\n                <div\n                  style={\n                    queryClient.getQueryData(['character', char.id])\n                      ? {\n                          fontWeight: 'bold',\n                        }\n                      : {}\n                  }\n                >\n                  {char.id} - {char.name}\n                </div>\n              </li>\n            ))}\n          </ul>\n\n          <h3>Selected Character</h3>\n          {characterQuery.isPending ? (\n            'Loading...'\n          ) : (\n            <>\n              <pre>{JSON.stringify(characterQuery.data, null, 2)}</pre>\n            </>\n          )}\n          <ReactQueryDevtools initialIsOpen />\n        </>\n      )}\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/react/prefetching/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"jsx\": \"react-jsx\",\n    \"incremental\": true,\n    \"target\": \"ES2017\"\n  },\n  \"include\": [\"next-env.d.ts\", \"**/*.ts\", \"**/*.tsx\"],\n  \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "examples/react/react-native/.eslintrc",
    "content": "{\n  \"root\": true,\n  \"extends\": \"@callstack\",\n  \"rules\": {\n    \"react-native/no-raw-text\": 0,\n    \"promise/prefer-await-to-then\": 0\n  },\n  \"settings\": {\n    \"import/resolver\": {\n      \"alias\": {\n        \"map\": [[\"@app\", \"./src\"]],\n        \"extensions\": [\".ts\", \".tsx\", \".js\", \".jsx\", \".json\"]\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "examples/react/react-native/.gitignore",
    "content": "node_modules/**/*\n.expo/*\nnpm-debug.*\n*.jks\n*.p8\n*.p12\n*.key\n*.mobileprovision\n*.orig.*\nweb-build/\ncoverage/\n\n# macOS\n.DS_Store\n\n.vscode/*\n\ndb_data\n\n# @generated expo-cli sync-ba457486f18e0afcb8f6494641422f0a1150e3a9\n# The following patterns were generated by expo-cli\n\n# OSX\n#\n.DS_Store\n\n# Xcode\n#\nbuild/\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspectivev3\n!default.perspectivev3\nxcuserdata\n*.xccheckout\n*.moved-aside\nDerivedData\n*.hmap\n*.ipa\n*.xcuserstate\nproject.xcworkspace\n\n# Android/IntelliJ\n#\nbuild/\n.idea\n.gradle\nlocal.properties\n*.iml\n*.hprof\n\n# node.js\n#\nnode_modules/\nnpm-debug.log\nyarn-error.log\n\n# BUCK\nbuck-out/\n\\.buckd/\n*.keystore\n!debug.keystore\n\n# fastlane\n#\n# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the\n# screenshots whenever they are needed.\n# For more information about the recommended setup visit:\n# https://docs.fastlane.tools/best-practices/source-control/\n\n*/fastlane/report.xml\n*/fastlane/Preview.html\n*/fastlane/screenshots\n\n# Bundle artifacts\n*.jsbundle\n\n# CocoaPods\n/ios/Pods/\n\n# Expo\n.expo/*\nweb-build/\n\n# @end expo-cli\n\n!lib\n"
  },
  {
    "path": "examples/react/react-native/App.tsx",
    "content": "import * as React from 'react'\nimport { AppStateStatus, Platform } from 'react-native'\nimport { NavigationContainer } from '@react-navigation/native'\nimport {\n  QueryClient,\n  QueryClientProvider,\n  focusManager,\n} from '@tanstack/react-query'\n\nimport { useAppState } from './src/hooks/useAppState'\nimport { MoviesStack } from './src/navigation/MoviesStack'\nimport { useOnlineManager } from './src/hooks/useOnlineManager'\n\nfunction onAppStateChange(status: AppStateStatus) {\n  // React Query already supports in web browser refetch on window focus by default\n  if (Platform.OS !== 'web') {\n    focusManager.setFocused(status === 'active')\n  }\n}\n\nconst queryClient = new QueryClient({\n  defaultOptions: { queries: { retry: 2 } },\n})\n\nexport default function App() {\n  useOnlineManager()\n\n  useAppState(onAppStateChange)\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      <NavigationContainer>\n        <MoviesStack />\n      </NavigationContainer>\n    </QueryClientProvider>\n  )\n}\n"
  },
  {
    "path": "examples/react/react-native/README.md",
    "content": "# Example\n\nTo run this example:\n\n- Install expo CLI if needed `npm install --global expo-cli`\n- `pnpm install`\n- `pnpm start`\n"
  },
  {
    "path": "examples/react/react-native/app.json",
    "content": "{\n  \"expo\": {\n    \"name\": \"react-query-basic-example\",\n    \"slug\": \"react-query-basic-example\",\n    \"version\": \"1.0.0\",\n    \"orientation\": \"portrait\",\n    \"icon\": \"./assets/icon.png\",\n    \"splash\": {\n      \"image\": \"./assets/splash.png\",\n      \"resizeMode\": \"contain\",\n      \"backgroundColor\": \"#ffffff\"\n    },\n    \"updates\": {\n      \"fallbackToCacheTimeout\": 0\n    },\n    \"assetBundlePatterns\": [\"**/*\"],\n    \"ios\": {\n      \"supportsTablet\": true\n    },\n    \"android\": {\n      \"adaptiveIcon\": {\n        \"foregroundImage\": \"./assets/adaptive-icon.png\",\n        \"backgroundColor\": \"#FFFFFF\"\n      }\n    },\n    \"web\": {\n      \"favicon\": \"./assets/favicon.png\"\n    },\n    \"description\": \"React Query basic example\"\n  }\n}\n"
  },
  {
    "path": "examples/react/react-native/babel.config.js",
    "content": "module.exports = function (api) {\n  api.cache(true)\n  return {\n    presets: ['babel-preset-expo'],\n  }\n}\n"
  },
  {
    "path": "examples/react/react-native/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-react-react-native\",\n  \"private\": true,\n  \"main\": \"node_modules/expo/AppEntry.js\",\n  \"scripts\": {\n    \"start\": \"expo start\",\n    \"android\": \"expo start --android\",\n    \"ios\": \"expo start --ios\",\n    \"web\": \"expo start --web\",\n    \"eject\": \"expo eject\",\n    \"type:check\": \"tsc --noEmit\"\n  },\n  \"dependencies\": {\n    \"@react-native-community/netinfo\": \"^11.4.1\",\n    \"@react-navigation/native\": \"^6.1.18\",\n    \"@react-navigation/stack\": \"^6.4.1\",\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"expo\": \"^52.0.11\",\n    \"expo-constants\": \"^17.0.3\",\n    \"expo-status-bar\": \"^2.0.0\",\n    \"react\": \"^19.0.0\",\n    \"react-native\": \"^0.76.3\",\n    \"react-native-gesture-handler\": \"^2.20.2\",\n    \"react-native-paper\": \"^5.12.5\",\n    \"react-native-reanimated\": \"^3.16.2\",\n    \"react-native-safe-area-context\": \"^4.12.0\",\n    \"react-native-screens\": \"^4.1.0\",\n    \"react-native-web\": \"^0.19.13\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.24.9\",\n    \"@expo/config\": \"^10.0.5\",\n    \"typescript\": \"5.8.3\"\n  }\n}\n"
  },
  {
    "path": "examples/react/react-native/src/components/Divider.tsx",
    "content": "import * as React from 'react'\nimport { StyleSheet } from 'react-native'\nimport { Divider as PaperDivider } from 'react-native-paper'\n\nexport function Divider() {\n  return <PaperDivider style={styles.divider} />\n}\n\nconst styles = StyleSheet.create({\n  divider: {\n    marginLeft: 10,\n  },\n})\n"
  },
  {
    "path": "examples/react/react-native/src/components/ErrorMessage.tsx",
    "content": "import * as React from 'react'\nimport { StyleSheet, Text, View } from 'react-native'\n\ntype Props = {\n  message: string\n}\n\nexport function ErrorMessage({ message }: Props) {\n  return (\n    <View style={styles.fill}>\n      <Text>{message}</Text>\n    </View>\n  )\n}\n\nconst styles = StyleSheet.create({\n  fill: {\n    flex: 1,\n    justifyContent: 'center',\n    alignItems: 'center',\n  },\n})\n"
  },
  {
    "path": "examples/react/react-native/src/components/ListItem.tsx",
    "content": "import * as React from 'react'\nimport { StyleSheet, View } from 'react-native'\nimport { Paragraph, TouchableRipple } from 'react-native-paper'\nimport type { MovieDetails } from '../lib/api'\n\ntype Props = {\n  item: MovieDetails\n  onPress: (item: MovieDetails) => void\n}\n\nexport function ListItem({ item, onPress }: Props) {\n  return (\n    <TouchableRipple onPress={() => onPress(item)} accessibilityRole=\"button\">\n      <View style={styles.item}>\n        <View style={styles.firstRow}>\n          <Paragraph style={styles.title}>{item.title}</Paragraph>\n        </View>\n        <View style={styles.secondRow}>\n          <Paragraph>{item.year}</Paragraph>\n        </View>\n      </View>\n    </TouchableRipple>\n  )\n}\n\nconst styles = StyleSheet.create({\n  item: {\n    paddingRight: 10,\n    paddingLeft: 30,\n    paddingTop: 20,\n    paddingBottom: 10,\n    marginBottom: 10,\n  },\n  firstRow: {\n    marginTop: 5,\n    marginBottom: 5,\n  },\n  secondRow: {\n    marginBottom: 10,\n  },\n  title: { fontWeight: 'bold' },\n})\n"
  },
  {
    "path": "examples/react/react-native/src/components/LoadingIndicator.tsx",
    "content": "import * as React from 'react'\nimport { ActivityIndicator, StyleSheet, View } from 'react-native'\n\nexport function LoadingIndicator() {\n  return (\n    <View style={styles.fill}>\n      <ActivityIndicator size=\"large\" />\n    </View>\n  )\n}\n\nconst styles = StyleSheet.create({\n  fill: {\n    flex: 1,\n    justifyContent: 'center',\n    alignItems: 'center',\n  },\n})\n"
  },
  {
    "path": "examples/react/react-native/src/data/movies.json",
    "content": "[\n  {\n    \"year\": 2013,\n    \"title\": \"Rush\",\n    \"info\": {\n      \"directors\": [\"Ron Howard\"],\n      \"release_date\": \"2013-09-02T00:00:00Z\",\n      \"rating\": 8.3,\n      \"genres\": [\"Action\", \"Biography\", \"Drama\", \"Sport\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTQyMDE0MTY0OV5BMl5BanBnXkFtZTcwMjI2OTI0OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A re-creation of the merciless 1970s rivalry between Formula One rivals James Hunt and Niki Lauda.\",\n      \"rank\": 2,\n      \"running_time_secs\": 7380,\n      \"actors\": [\"Daniel Bruhl\", \"Chris Hemsworth\", \"Olivia Wilde\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Prisoners\",\n    \"info\": {\n      \"directors\": [\"Denis Villeneuve\"],\n      \"release_date\": \"2013-08-30T00:00:00Z\",\n      \"rating\": 8.2,\n      \"genres\": [\"Crime\", \"Drama\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTg0NTIzMjQ1NV5BMl5BanBnXkFtZTcwNDc3MzM5OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"When Keller Dover's daughter and her friend go missing, he takes matters into his own hands as the police pursue multiple leads and the pressure mounts. But just how far will this desperate father go to protect his family?\",\n      \"rank\": 3,\n      \"running_time_secs\": 9180,\n      \"actors\": [\"Hugh Jackman\", \"Jake Gyllenhaal\", \"Viola Davis\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Hunger Games: Catching Fire\",\n    \"info\": {\n      \"directors\": [\"Francis Lawrence\"],\n      \"release_date\": \"2013-11-11T00:00:00Z\",\n      \"genres\": [\"Action\", \"Adventure\", \"Sci-Fi\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTAyMjQ3OTAxMzNeQTJeQWpwZ15BbWU4MDU0NzA1MzAx._V1_SX400_.jpg\",\n      \"plot\": \"Katniss Everdeen and Peeta Mellark become targets of the Capitol after their victory in the 74th Hunger Games sparks a rebellion in the Districts of Panem.\",\n      \"rank\": 4,\n      \"running_time_secs\": 8760,\n      \"actors\": [\"Jennifer Lawrence\", \"Josh Hutcherson\", \"Liam Hemsworth\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Thor: The Dark World\",\n    \"info\": {\n      \"directors\": [\"Alan Taylor\"],\n      \"release_date\": \"2013-10-30T00:00:00Z\",\n      \"genres\": [\"Action\", \"Adventure\", \"Fantasy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTQyNzAwOTUxOF5BMl5BanBnXkFtZTcwMTE0OTc5OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Faced with an enemy that even Odin and Asgard cannot withstand, Thor must embark on his most perilous and personal journey yet, one that will reunite him with Jane Foster and force him to sacrifice everything to save us all.\",\n      \"rank\": 5,\n      \"actors\": [\"Chris Hemsworth\", \"Natalie Portman\", \"Tom Hiddleston\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"This Is the End\",\n    \"info\": {\n      \"directors\": [\"Evan Goldberg\", \"Seth Rogen\"],\n      \"release_date\": \"2013-06-03T00:00:00Z\",\n      \"rating\": 7.2,\n      \"genres\": [\"Comedy\", \"Fantasy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTQxODE3NjM1Ml5BMl5BanBnXkFtZTcwMzkzNjc4OA@@._V1_SX400_.jpg\",\n      \"plot\": \"While attending a party at James Franco's house, Seth Rogen, Jay Baruchel and many other celebrities are faced with the apocalypse.\",\n      \"rank\": 6,\n      \"running_time_secs\": 6420,\n      \"actors\": [\"James Franco\", \"Jonah Hill\", \"Seth Rogen\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Insidious: Chapter 2\",\n    \"info\": {\n      \"directors\": [\"James Wan\"],\n      \"release_date\": \"2013-09-13T00:00:00Z\",\n      \"rating\": 7.1,\n      \"genres\": [\"Horror\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTg0OTA5ODIxNF5BMl5BanBnXkFtZTcwNTUzNDg4OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"The haunted Lambert family seeks to uncover the mysterious childhood secret that has left them dangerously connected to the spirit world.\",\n      \"rank\": 7,\n      \"running_time_secs\": 6360,\n      \"actors\": [\"Patrick Wilson\", \"Rose Byrne\", \"Barbara Hershey\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"World War Z\",\n    \"info\": {\n      \"directors\": [\"Marc Forster\"],\n      \"release_date\": \"2013-06-02T00:00:00Z\",\n      \"rating\": 7.1,\n      \"genres\": [\"Action\", \"Adventure\", \"Horror\", \"Sci-Fi\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTg0NTgxMjIxOF5BMl5BanBnXkFtZTcwMDM0MDY1OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"United Nations employee Gerry Lane traverses the world in a race against time to stop the Zombie pandemic that is toppling armies and governments, and threatening to destroy humanity itself.\",\n      \"rank\": 8,\n      \"running_time_secs\": 6960,\n      \"actors\": [\"Brad Pitt\", \"Mireille Enos\", \"Daniella Kertesz\"]\n    }\n  },\n  {\n    \"year\": 2014,\n    \"title\": \"X-Men: Days of Future Past\",\n    \"info\": {\n      \"directors\": [\"Bryan Singer\"],\n      \"release_date\": \"2014-05-21T00:00:00Z\",\n      \"genres\": [\"Action\", \"Adventure\", \"Fantasy\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTQ0NzIwNTA1MV5BMl5BanBnXkFtZTgwNjY2OTcwMDE@._V1_SX400_.jpg\",\n      \"plot\": \"The X-Men send Wolverine to the past to change a major historical event that could globally impact man and mutant kind.\",\n      \"rank\": 9,\n      \"actors\": [\"Jennifer Lawrence\", \"Hugh Jackman\", \"Michael Fassbender\"]\n    }\n  },\n  {\n    \"year\": 2014,\n    \"title\": \"Transformers: Age of Extinction\",\n    \"info\": {\n      \"directors\": [\"Michael Bay\"],\n      \"release_date\": \"2014-06-25T00:00:00Z\",\n      \"genres\": [\"Action\", \"Adventure\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTQyMDA5Nzg0Nl5BMl5BanBnXkFtZTgwNzA4NDcxMDE@._V1_SX400_.jpg\",\n      \"plot\": \"A mechanic and his daughter make a discovery that brings down Autobots and Decepticons - and a paranoid government official - on them.\",\n      \"rank\": 10,\n      \"actors\": [\"Mark Wahlberg\", \"Nicola Peltz\", \"Jack Reynor\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Now You See Me\",\n    \"info\": {\n      \"directors\": [\"Louis Leterrier\"],\n      \"release_date\": \"2013-05-21T00:00:00Z\",\n      \"rating\": 7.3,\n      \"genres\": [\"Crime\", \"Mystery\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTY0NDY3MDMxN15BMl5BanBnXkFtZTcwOTM5NzMzOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"An FBI agent and an Interpol detective track a team of illusionists who pull off bank heists during their performances and reward their audiences with the money.\",\n      \"rank\": 11,\n      \"running_time_secs\": 6900,\n      \"actors\": [\"Jesse Eisenberg\", \"Common\", \"Mark Ruffalo\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Gravity\",\n    \"info\": {\n      \"directors\": [\"Alfonso Cuaron\"],\n      \"release_date\": \"2013-08-28T00:00:00Z\",\n      \"rating\": 8.2,\n      \"genres\": [\"Drama\", \"Sci-Fi\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BNjE5MzYwMzYxMF5BMl5BanBnXkFtZTcwOTk4MTk0OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A medical engineer and an astronaut work together to survive after an accident leaves them adrift in space.\",\n      \"rank\": 12,\n      \"running_time_secs\": 5400,\n      \"actors\": [\"Sandra Bullock\", \"George Clooney\", \"Ed Harris\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"We're the Millers\",\n    \"info\": {\n      \"directors\": [\"Rawson Marshall Thurber\"],\n      \"release_date\": \"2013-08-03T00:00:00Z\",\n      \"rating\": 7.2,\n      \"genres\": [\"Comedy\", \"Crime\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjA5Njc0NDUxNV5BMl5BanBnXkFtZTcwMjYzNzU1OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A veteran pot dealer creates a fake family as part of his plan to move a huge shipment of weed into the U.S. from Mexico.\",\n      \"rank\": 13,\n      \"running_time_secs\": 6600,\n      \"actors\": [\"Jason Sudeikis\", \"Jennifer Aniston\", \"Emma Roberts\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Riddick\",\n    \"info\": {\n      \"directors\": [\"David Twohy\"],\n      \"release_date\": \"2013-09-04T00:00:00Z\",\n      \"rating\": 6.8,\n      \"genres\": [\"Action\", \"Sci-Fi\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTk5NzYwMzQ4MV5BMl5BanBnXkFtZTcwMjE5MTI1OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Left for dead on a sun-scorched planet, Riddick finds himself up against an alien race of predators. Activating an emergency beacon alerts two ships: one carrying a new breed of mercenary, the other captained by a man from Riddick's past.\",\n      \"rank\": 14,\n      \"running_time_secs\": 7140,\n      \"actors\": [\"Vin Diesel\", \"Karl Urban\", \"Katee Sackhoff\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Family\",\n    \"info\": {\n      \"directors\": [\"Luc Besson\"],\n      \"release_date\": \"2013-09-10T00:00:00Z\",\n      \"rating\": 6.5,\n      \"genres\": [\"Action\", \"Comedy\", \"Crime\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjE2MzI0MzkyNV5BMl5BanBnXkFtZTcwMjQ2MDM2OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"The Manzoni family, a notorious mafia clan, is relocated to Normandy, France under the witness protection program, where fitting in soon becomes challenging as their old habits die hard.\",\n      \"rank\": 15,\n      \"running_time_secs\": 6660,\n      \"actors\": [\"Robert De Niro\", \"Michelle Pfeiffer\", \"Dianna Agron\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Star Trek Into Darkness\",\n    \"info\": {\n      \"directors\": [\"J.J. Abrams\"],\n      \"release_date\": \"2013-05-02T00:00:00Z\",\n      \"rating\": 7.9,\n      \"genres\": [\"Action\", \"Adventure\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTk2NzczOTgxNF5BMl5BanBnXkFtZTcwODQ5ODczOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"After the crew of the Enterprise find an unstoppable force of terror from within their own organization, Captain Kirk leads a manhunt to a war-zone world to capture a one man weapon of mass destruction.\",\n      \"rank\": 16,\n      \"running_time_secs\": 7920,\n      \"actors\": [\"Chris Pine\", \"Zachary Quinto\", \"Zoe Saldana\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"After Earth\",\n    \"info\": {\n      \"directors\": [\"M. Night Shyamalan\"],\n      \"release_date\": \"2013-05-01T00:00:00Z\",\n      \"rating\": 4.9,\n      \"genres\": [\"Action\", \"Adventure\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTY3MzQyMjkwMl5BMl5BanBnXkFtZTcwMDk2OTE0OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A crash landing leaves Kitai Raige and his father Cypher stranded on Earth, a millennium after events forced humanity's escape. With Cypher injured, Kitai must embark on a perilous journey to signal for help.\",\n      \"rank\": 17,\n      \"running_time_secs\": 6000,\n      \"actors\": [\"Jaden Smith\", \"David Denman\", \"Will Smith\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Great Gatsby\",\n    \"info\": {\n      \"directors\": [\"Baz Luhrmann\"],\n      \"release_date\": \"2013-05-01T00:00:00Z\",\n      \"rating\": 7.3,\n      \"genres\": [\"Drama\", \"Romance\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTkxNTk1ODcxNl5BMl5BanBnXkFtZTcwMDI1OTMzOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A Midwestern war veteran finds himself drawn to the past and lifestyle of his millionaire neighbor.\",\n      \"rank\": 18,\n      \"running_time_secs\": 8580,\n      \"actors\": [\"Leonardo DiCaprio\", \"Carey Mulligan\", \"Joel Edgerton\"]\n    }\n  },\n  {\n    \"year\": 2014,\n    \"title\": \"Divergent\",\n    \"info\": {\n      \"directors\": [\"Neil Burger\"],\n      \"release_date\": \"2014-03-20T00:00:00Z\",\n      \"genres\": [\"Action\", \"Adventure\", \"Romance\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjIyOTEyODQ4OV5BMl5BanBnXkFtZTgwMDIwNzEzMDE@._V1_SX400_.jpg\",\n      \"plot\": \"Beatrice Prior, a teenager with a special mind, finds her life threatened when an authoritarian leader seeks to exterminate her kind in her effort to seize control of their divided society.\",\n      \"rank\": 20,\n      \"actors\": [\"Shailene Woodley\", \"Kate Winslet\", \"Zoe Kravitz\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"We Are What We Are\",\n    \"info\": {\n      \"directors\": [\"Jim Mickle\"],\n      \"release_date\": \"2013-01-18T00:00:00Z\",\n      \"rating\": 6.2,\n      \"genres\": [\"Drama\", \"Horror\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjI3NjI3NjAyN15BMl5BanBnXkFtZTgwODE3NzMxMDE@._V1_SX400_.jpg\",\n      \"plot\": \"The Parkers, a reclusive family who follow ancient customs, find their secret existence threatened as a torrential downpour moves into their area, forcing daughters Iris and Rose to assume responsibilities beyond those of a typical family.\",\n      \"rank\": 21,\n      \"running_time_secs\": 6300,\n      \"actors\": [\"Bill Sage\", \"Ambyr Childers\", \"Julia Garner\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Iron Man 3\",\n    \"info\": {\n      \"directors\": [\"Shane Black\"],\n      \"release_date\": \"2013-04-18T00:00:00Z\",\n      \"rating\": 7.4,\n      \"genres\": [\"Action\", \"Adventure\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjIzMzAzMjQyM15BMl5BanBnXkFtZTcwNzM2NjcyOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"When Tony Stark's world is torn apart by a formidable terrorist called the Mandarin, he starts an odyssey of rebuilding and retribution.\",\n      \"rank\": 22,\n      \"running_time_secs\": 7800,\n      \"actors\": [\"Robert Downey Jr.\", \"Guy Pearce\", \"Gwyneth Paltrow\"]\n    }\n  },\n  {\n    \"year\": 2014,\n    \"title\": \"The Amazing Spider-Man 2\",\n    \"info\": {\n      \"directors\": [\"Marc Webb\"],\n      \"release_date\": \"2014-04-17T00:00:00Z\",\n      \"genres\": [\"Action\", \"Adventure\", \"Fantasy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjE0MDAwNTUzNF5BMl5BanBnXkFtZTcwNDQ4NDYxOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Spider-Man squares off against the Rhino and the powerful Electro while struggling to keep his promise to leave Gwen Stacey out of his dangerous life.\",\n      \"rank\": 23,\n      \"actors\": [\"Andrew Garfield\", \"Emma Stone\", \"Jamie Foxx\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Curse of Chucky\",\n    \"info\": {\n      \"directors\": [\"Don Mancini\"],\n      \"release_date\": \"2013-08-02T00:00:00Z\",\n      \"rating\": 5.7,\n      \"genres\": [\"Horror\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjkxMjM0MDE3OF5BMl5BanBnXkFtZTcwMDQ3NzI4OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"After her mother's mysterious death, Nica begins to suspect that the talking, red-haired doll her visiting niece has been playing with may be the key to recent bloodshed and chaos.\",\n      \"rank\": 24,\n      \"running_time_secs\": 5820,\n      \"actors\": [\"Chantal Quesnelle\", \"Fiona Dourif\", \"Danielle Bisutti\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Conjuring\",\n    \"info\": {\n      \"directors\": [\"James Wan\"],\n      \"release_date\": \"2013-06-08T00:00:00Z\",\n      \"rating\": 7.7,\n      \"genres\": [\"Horror\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTM3NjA1NDMyMV5BMl5BanBnXkFtZTcwMDQzNDMzOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Paranormal investigators Ed and Lorraine Warren work to help a family terrorized by a dark presence in their farmhouse.\",\n      \"rank\": 25,\n      \"running_time_secs\": 6720,\n      \"actors\": [\"Patrick Wilson\", \"Vera Farmiga\", \"Ron Livingston\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Oldboy\",\n    \"info\": {\n      \"directors\": [\"Spike Lee\"],\n      \"release_date\": \"2013-10-10T00:00:00Z\",\n      \"genres\": [\"Action\", \"Drama\", \"Mystery\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTk5NTEwMzI5OV5BMl5BanBnXkFtZTgwMDQ4ODUwMDE@._V1_SX400_.jpg\",\n      \"plot\": \"Obsessed with vengeance, a man sets out to find out why he was kidnapped and locked up into solitary confinement for 20 years without reason.\",\n      \"rank\": 26,\n      \"actors\": [\"Josh Brolin\", \"Elizabeth Olsen\", \"Samuel L. Jackson\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Escape Plan\",\n    \"info\": {\n      \"directors\": [\"Mikael Hafstrom\"],\n      \"release_date\": \"2013-07-18T00:00:00Z\",\n      \"rating\": 7.6,\n      \"genres\": [\"Action\", \"Mystery\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTk3OTcxMTEyNl5BMl5BanBnXkFtZTcwMDQ4MjQ2OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"When a structural-security authority finds himself incarcerated in a prison he designed, he has to put his skills to escape and find out who framed him.\",\n      \"rank\": 27,\n      \"running_time_secs\": 6960,\n      \"actors\": [\"Sylvester Stallone\", \"Arnold Schwarzenegger\", \"50 Cent\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Elysium\",\n    \"info\": {\n      \"directors\": [\"Neill Blomkamp\"],\n      \"release_date\": \"2013-08-07T00:00:00Z\",\n      \"rating\": 7,\n      \"genres\": [\"Action\", \"Drama\", \"Sci-Fi\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BNDc2NjU0MTcwNV5BMl5BanBnXkFtZTcwMjg4MDg2OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Set in the year 2154, where the very wealthy live on a man-made space station while the rest of the population resides on a ruined Earth, a man takes on a mission that could bring equality to the polarized worlds.\",\n      \"rank\": 28,\n      \"running_time_secs\": 6540,\n      \"actors\": [\"Matt Damon\", \"Jodie Foster\", \"Sharlto Copley\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Cloudy with a Chance of Meatballs 2\",\n    \"info\": {\n      \"directors\": [\"Cody Cameron\", \"Kris Pearn\"],\n      \"release_date\": \"2013-09-26T00:00:00Z\",\n      \"rating\": 6.7,\n      \"genres\": [\"Animation\", \"Comedy\", \"Family\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTYzNDM0MDI1NF5BMl5BanBnXkFtZTcwNzQ5NzYxOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Flint Lockwood now works at The Live Corp Company for his idol Chester V. But he's forced to leave his post when he learns that his most infamous machine is still operational and is churning out menacing food-animal hybrids.\",\n      \"rank\": 29,\n      \"running_time_secs\": 5700,\n      \"actors\": [\"Bill Hader\", \"Anna Faris\", \"Will Forte\"]\n    }\n  },\n  {\n    \"year\": 2014,\n    \"title\": \"RoboCop\",\n    \"info\": {\n      \"directors\": [\"Jose Padilha\"],\n      \"release_date\": \"2014-01-30T00:00:00Z\",\n      \"genres\": [\"Action\", \"Crime\", \"Sci-Fi\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjMwNzQ2MDkyOV5BMl5BanBnXkFtZTgwMjE5MjMyMDE@._V1_SX400_.jpg\",\n      \"plot\": \"In 2028 Detroit, when Alex Murphy (Joel Kinnaman) - a loving husband, father and good cop - is critically injured in the line of duty, the multinational conglomerate OmniCorp sees their chance for a part-man, part-robot police officer.\",\n      \"rank\": 30,\n      \"actors\": [\"Joel Kinnaman\", \"Douglas Urbanski\", \"Abbie Cornish\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Carrie\",\n    \"info\": {\n      \"directors\": [\"Kimberly Peirce\"],\n      \"release_date\": \"2013-10-07T00:00:00Z\",\n      \"genres\": [\"Drama\", \"Horror\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTc1MDIyOTkxN15BMl5BanBnXkFtZTgwMTU1NzEzMDE@._V1_SX400_.jpg\",\n      \"plot\": \"A reimagining of the classic horror tale about Carrie White, a shy girl outcast by her peers and sheltered by her deeply religious mother, who unleashes telekinetic terror on her small town after being pushed too far at her senior prom.\",\n      \"rank\": 31,\n      \"actors\": [\"Chloe Grace Moretz\", \"Julianne Moore\", \"Judy Greer\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Mortal Instruments: City of Bones\",\n    \"info\": {\n      \"directors\": [\"Harald Zwart\"],\n      \"release_date\": \"2013-08-12T00:00:00Z\",\n      \"rating\": 6.6,\n      \"genres\": [\n        \"Action\",\n        \"Adventure\",\n        \"Drama\",\n        \"Fantasy\",\n        \"Mystery\",\n        \"Romance\"\n      ],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTc5NzAyOTQyNF5BMl5BanBnXkFtZTcwNzQ1MDc4OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"When her mother disappears, Clary Fray learns that she descends from a line of warriors who protect our world from demons. She joins forces with others like her and heads into a dangerous alternate New York called Downworld.\",\n      \"rank\": 32,\n      \"running_time_secs\": 7800,\n      \"actors\": [\"Lily Collins\", \"Jamie Campbell Bower\", \"Robert Sheehan\"]\n    }\n  },\n  {\n    \"year\": 2014,\n    \"title\": \"Captain America: The Winter Soldier\",\n    \"info\": {\n      \"directors\": [\"Anthony Russo\", \"Joe Russo\"],\n      \"release_date\": \"2014-04-02T00:00:00Z\",\n      \"genres\": [\"Action\", \"Adventure\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjAzMTg3MDcxM15BMl5BanBnXkFtZTcwNDQzNzI4OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Steve Rogers struggles to embrace his role in the modern world and teams up with Natasha Romanoff, aka Black Widow, to battle a powerful yet shadowy enemy in present-day Washington, D.C.\",\n      \"rank\": 33,\n      \"actors\": [\"Chris Evans\", \"Frank Grillo\", \"Sebastian Stan\"]\n    }\n  },\n  {\n    \"year\": 2014,\n    \"title\": \"Need for Speed\",\n    \"info\": {\n      \"directors\": [\"Scott Waugh\"],\n      \"release_date\": \"2014-03-13T00:00:00Z\",\n      \"genres\": [\"Action\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjU2MTM3OTA3N15BMl5BanBnXkFtZTgwMjQ5MDYyMDE@._V1_SX400_.jpg\",\n      \"plot\": \"Fresh from prison, a street racer who was framed by a wealthy business associate joins a cross country race with revenge in mind. His ex-partner, learning of the plan, places a massive bounty on his head as the race begins.\",\n      \"rank\": 34,\n      \"actors\": [\"Aaron Paul\", \"Chillie Mo\", \"Dominic Cooper\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Runner Runner\",\n    \"info\": {\n      \"directors\": [\"Brad Furman\"],\n      \"release_date\": \"2013-09-25T00:00:00Z\",\n      \"rating\": 5.4,\n      \"genres\": [\"Crime\", \"Drama\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTU5OTA0MjI4Ml5BMl5BanBnXkFtZTgwMTgxOTQwMDE@._V1_SX400_.jpg\",\n      \"plot\": \"When a poor college student who cracks an online poker game goes bust, he arranges a face-to-face with the man he thinks cheated him, a sly offshore entrepreneur.\",\n      \"rank\": 35,\n      \"running_time_secs\": 5460,\n      \"actors\": [\"Ben Affleck\", \"Justin Timberlake\", \"Gemma Arterton\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"I Spit on Your Grave 2\",\n    \"info\": {\n      \"directors\": [\"Steven R. Monroe\"],\n      \"release_date\": \"2013-08-25T00:00:00Z\",\n      \"rating\": 5.5,\n      \"genres\": [\"Crime\", \"Horror\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTc1Nzk3NjM0M15BMl5BanBnXkFtZTgwMjM5MzYyMDE@._V1_SX400_.jpg\",\n      \"rank\": 36,\n      \"running_time_secs\": 6360,\n      \"actors\": [\"Jemma Dallender\", \"Yavor Baharov\", \"Joe Absolom\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Battle of the Year\",\n    \"info\": {\n      \"directors\": [\"Benson Lee\"],\n      \"release_date\": \"2013-09-19T00:00:00Z\",\n      \"rating\": 3.5,\n      \"genres\": [\"Music\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BOTY2OTcyNzM3NF5BMl5BanBnXkFtZTgwNzgxMjkxMDE@._V1_SX400_.jpg\",\n      \"plot\": \"Battle of the Year attracts all the best teams from around the world, but the Americans haven't won in fifteen years. Dante enlists Blake to assemble a team of the best dancers and bring the Trophy back to America where it started.\",\n      \"rank\": 37,\n      \"running_time_secs\": 6600,\n      \"actors\": [\"Josh Holloway\", \"Laz Alonso\", \"Josh Peck\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Behind the Candelabra\",\n    \"info\": {\n      \"directors\": [\"Steven Soderbergh\"],\n      \"release_date\": \"2013-05-21T00:00:00Z\",\n      \"rating\": 7,\n      \"genres\": [\"Biography\", \"Drama\", \"Romance\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTg0OTY2OTM0OF5BMl5BanBnXkFtZTcwMTk4OTQ1OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Based on the autobiographical novel, the tempestuous 6-year relationship between Liberace and his (much younger) lover, Scott Thorson, is recounted.\",\n      \"rank\": 38,\n      \"running_time_secs\": 7080,\n      \"actors\": [\"Matt Damon\", \"Scott Bakula\", \"Eric Zuckerman\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"No se Aceptan Devoluciones\",\n    \"info\": {\n      \"directors\": [\"Eugenio Derbez\"],\n      \"release_date\": \"2013-08-30T00:00:00Z\",\n      \"rating\": 6.9,\n      \"genres\": [\"Comedy\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTUyNjI3ODI0N15BMl5BanBnXkFtZTcwMTQ1NTY5OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A man who has made a new life for himself and the daughter left on his doorstep 6 years ago finds his family threatened when the birth mother resurfaces.\",\n      \"rank\": 39,\n      \"running_time_secs\": 6900,\n      \"actors\": [\"Eugenio Derbez\", \"Karla Souza\", \"Jessica Lindsey\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Bling Ring\",\n    \"info\": {\n      \"directors\": [\"Sofia Coppola\"],\n      \"release_date\": \"2013-05-16T00:00:00Z\",\n      \"rating\": 5.8,\n      \"genres\": [\"Crime\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTQzMTgwMzQxN15BMl5BanBnXkFtZTcwOTcwNTY0OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Inspired by actual events, a group of fame-obsessed teenagers use the internet to track celebrities' whereabouts in order to rob their homes.\",\n      \"rank\": 41,\n      \"running_time_secs\": 5400,\n      \"actors\": [\"Katie Chang\", \"Israel Broussard\", \"Emma Watson\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Furious 6\",\n    \"info\": {\n      \"directors\": [\"Justin Lin\"],\n      \"release_date\": \"2013-05-07T00:00:00Z\",\n      \"rating\": 7.2,\n      \"genres\": [\"Action\", \"Crime\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTM3NTg2NDQzOF5BMl5BanBnXkFtZTcwNjc2NzQzOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Hobbs has Dom and Brian reassemble their crew in order to take down a mastermind who commands an organization of mercenary drivers across 12 countries. Payment? Full pardons for them all.\",\n      \"rank\": 42,\n      \"running_time_secs\": 7800,\n      \"actors\": [\"Vin Diesel\", \"Paul Walker\", \"Dwayne Johnson\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Machete Kills\",\n    \"info\": {\n      \"directors\": [\"Robert Rodriguez\"],\n      \"release_date\": \"2013-09-19T00:00:00Z\",\n      \"rating\": 6.3,\n      \"genres\": [\"Action\", \"Crime\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjA2MzUxMTM3M15BMl5BanBnXkFtZTgwMzA2NzkxMDE@._V1_SX400_.jpg\",\n      \"plot\": \"The U.S. government recruits Machete to battle his way through Mexico in order to take down an arms dealer who looks to launch a weapon into space.\",\n      \"rank\": 43,\n      \"running_time_secs\": 6420,\n      \"actors\": [\"Danny Trejo\", \"Alexa Vega\", \"Mel Gibson\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"12 Years a Slave\",\n    \"info\": {\n      \"directors\": [\"Steve McQueen\"],\n      \"release_date\": \"2013-08-30T00:00:00Z\",\n      \"rating\": 7.7,\n      \"genres\": [\"Biography\", \"Drama\", \"History\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjExMTEzODkyN15BMl5BanBnXkFtZTcwNTU4NTc4OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"In the antebellum United States, Solomon Northup, a free black man from upstate New York, is abducted and sold into slavery.\",\n      \"rank\": 44,\n      \"running_time_secs\": 7980,\n      \"actors\": [\n        \"Chiwetel Ejiofor\",\n        \"Michael K. Williams\",\n        \"Michael Fassbender\"\n      ]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The World's End\",\n    \"info\": {\n      \"directors\": [\"Edgar Wright\"],\n      \"release_date\": \"2013-07-18T00:00:00Z\",\n      \"rating\": 7.5,\n      \"genres\": [\"Action\", \"Comedy\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BNzA1MTk1MzY0OV5BMl5BanBnXkFtZTgwNjkzNTUwMDE@._V1_SX400_.jpg\",\n      \"plot\": \"Five friends who reunite in an attempt to top their epic pub crawl from 20 years earlier unwittingly become humankind's only hope for survival.\",\n      \"rank\": 45,\n      \"running_time_secs\": 6540,\n      \"actors\": [\"Simon Pegg\", \"Nick Frost\", \"Martin Freeman\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"Pitch Perfect\",\n    \"info\": {\n      \"directors\": [\"Jason Moore\"],\n      \"release_date\": \"2012-09-28T00:00:00Z\",\n      \"rating\": 7.1,\n      \"genres\": [\"Comedy\", \"Music\", \"Romance\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTcyMTMzNzE5N15BMl5BanBnXkFtZTcwNzg5NjM5Nw@@._V1_SX400_.jpg\",\n      \"plot\": \"Beca, a freshman at Barden University, is cajoled into joining The Bellas, her school's all-girls singing group. Injecting some much needed energy into their repertoire, The Bellas take on their male rivals in a campus competition.\",\n      \"rank\": 46,\n      \"running_time_secs\": 6720,\n      \"actors\": [\"Anna Kendrick\", \"Brittany Snow\", \"Rebel Wilson\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Epic\",\n    \"info\": {\n      \"directors\": [\"Chris Wedge\"],\n      \"release_date\": \"2013-05-15T00:00:00Z\",\n      \"rating\": 6.6,\n      \"genres\": [\"Animation\", \"Adventure\", \"Family\", \"Fantasy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTgyNDYwNzE5NV5BMl5BanBnXkFtZTcwMzUyODM5OA@@._V1_SX400_.jpg\",\n      \"plot\": \"A teenager finds herself transported to a deep forest setting where a battle between the forces of good and the forces of evil is taking place. She bands together with a rag-tag group characters in order to save their world -- and ours.\",\n      \"rank\": 47,\n      \"running_time_secs\": 6120,\n      \"actors\": [\"Amanda Seyfried\", \"Josh Hutcherson\", \"Beyonce Knowles\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"The Avengers\",\n    \"info\": {\n      \"directors\": [\"Joss Whedon\"],\n      \"release_date\": \"2012-04-11T00:00:00Z\",\n      \"rating\": 8.2,\n      \"genres\": [\"Action\", \"Fantasy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTk2NTI1MTU4N15BMl5BanBnXkFtZTcwODg0OTY0Nw@@._V1_SX400_.jpg\",\n      \"plot\": \"Nick Fury of S.H.I.E.L.D. assembles a team of superhumans to save the planet from Loki and his army.\",\n      \"rank\": 48,\n      \"running_time_secs\": 8580,\n      \"actors\": [\"Robert Downey Jr.\", \"Chris Evans\", \"Scarlett Johansson\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Metallica Through the Never\",\n    \"info\": {\n      \"directors\": [\"Nimrod Antal\"],\n      \"release_date\": \"2013-09-09T00:00:00Z\",\n      \"rating\": 7.8,\n      \"genres\": [\"Action\", \"Music\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjQwNjk5MTk4Ml5BMl5BanBnXkFtZTcwNTgwNDA5OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Trip, a young roadie for Metallica, is sent on an urgent mission during the band's show. But what seems like a simple assignment turns into a surreal adventure.\",\n      \"rank\": 49,\n      \"running_time_secs\": 5640,\n      \"actors\": [\"Dane DeHaan\", \"James Hetfield\", \"Lars Ulrich\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Oblivion\",\n    \"info\": {\n      \"directors\": [\"Joseph Kosinski\"],\n      \"release_date\": \"2013-04-10T00:00:00Z\",\n      \"rating\": 7,\n      \"genres\": [\"Action\", \"Adventure\", \"Mystery\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTQwMDY0MTA4MF5BMl5BanBnXkFtZTcwNzI3MDgxOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A veteran assigned to extract Earth's remaining resources begins to question what he knows about his mission and himself.\",\n      \"rank\": 50,\n      \"running_time_secs\": 7440,\n      \"actors\": [\"Tom Cruise\", \"Morgan Freeman\", \"Andrea Riseborough\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Dom Hemingway\",\n    \"info\": {\n      \"directors\": [\"Richard Shepard\"],\n      \"release_date\": \"2013-09-08T00:00:00Z\",\n      \"rating\": 6.9,\n      \"genres\": [\"Comedy\", \"Crime\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTczMDYzOTAwM15BMl5BanBnXkFtZTgwMDg5OTgwMDE@._V1_SX400_.jpg\",\n      \"plot\": \"After spending 12 years in prison for keeping his mouth shut, notorious safe-cracker Dom Hemingway is back on the streets of London looking to collect what he's owed.\",\n      \"rank\": 51,\n      \"running_time_secs\": 5580,\n      \"actors\": [\"Jude Law\", \"Richard E. Grant\", \"Demian Bichir\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Hangover Part III\",\n    \"info\": {\n      \"directors\": [\"Todd Phillips\"],\n      \"release_date\": \"2013-05-20T00:00:00Z\",\n      \"rating\": 5.9,\n      \"genres\": [\"Comedy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTA0NjE1MzMzODheQTJeQWpwZ15BbWU3MDY4MTQ3Mzk@._V1_SX400_.jpg\",\n      \"plot\": \"When one of their own is kidnapped by an angry gangster, the Wolf Pack must track down Mr. Chow, who has escaped from prison and is on the lam.\",\n      \"rank\": 52,\n      \"running_time_secs\": 6000,\n      \"actors\": [\"Bradley Cooper\", \"Zach Galifianakis\", \"Ed Helms\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Despicable Me 2\",\n    \"info\": {\n      \"directors\": [\"Pierre Coffin\", \"Chris Renaud\"],\n      \"release_date\": \"2013-06-16T00:00:00Z\",\n      \"rating\": 7.7,\n      \"genres\": [\n        \"Animation\",\n        \"Adventure\",\n        \"Comedy\",\n        \"Crime\",\n        \"Family\",\n        \"Sci-Fi\"\n      ],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BOTg4NTk2OTg5N15BMl5BanBnXkFtZTcwMDk1MzI2OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Gru is recruited by the Anti-Villain League to help deal with a powerful new super criminal.\",\n      \"rank\": 55,\n      \"running_time_secs\": 5880,\n      \"actors\": [\"Steve Carell\", \"Kristen Wiig\", \"Benjamin Bratt\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Butler\",\n    \"info\": {\n      \"directors\": [\"Lee Daniels\"],\n      \"release_date\": \"2013-08-05T00:00:00Z\",\n      \"rating\": 6.6,\n      \"genres\": [\"Biography\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjM2NDY3MjkyMF5BMl5BanBnXkFtZTcwMDM5Nzg5OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"As Cecil Gaines serves eight presidents during his tenure as a butler at the White House, the civil rights movement, Vietnam, and other major events affect this man's life, family, and American society.\",\n      \"rank\": 56,\n      \"running_time_secs\": 7920,\n      \"actors\": [\"Forest Whitaker\", \"Oprah Winfrey\", \"John Cusack\"]\n    }\n  },\n  {\n    \"year\": 2014,\n    \"title\": \"Dumb and Dumber To\",\n    \"info\": {\n      \"directors\": [\"Bobby Farrelly\", \"Peter Farrelly\"],\n      \"release_date\": \"2014-01-01T00:00:00Z\",\n      \"genres\": [\"Comedy\"],\n      \"plot\": \"20 years after the dimwits set out on their first adventure, they head out in search of one of their long lost children in the hope of gaining a new kidney.\",\n      \"rank\": 57,\n      \"actors\": [\"Jennifer Lawrence\", \"Jim Carrey\", \"Jeff Daniels\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Blue Jasmine\",\n    \"info\": {\n      \"directors\": [\"Woody Allen\"],\n      \"release_date\": \"2013-07-26T00:00:00Z\",\n      \"rating\": 7.8,\n      \"genres\": [\"Comedy\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTc0ODk5MzEyMV5BMl5BanBnXkFtZTcwMzI0MDY1OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A New York socialite, deeply troubled and in denial, arrives in San Francisco to impose upon her sister. She looks a million, but isn't bringing money, peace, or love...\",\n      \"rank\": 58,\n      \"running_time_secs\": 5880,\n      \"actors\": [\"Cate Blanchett\", \"Alec Baldwin\", \"Peter Sarsgaard\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Ender's Game\",\n    \"info\": {\n      \"directors\": [\"Gavin Hood\"],\n      \"release_date\": \"2013-10-24T00:00:00Z\",\n      \"genres\": [\"Action\", \"Adventure\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjAzMzI5OTgzMl5BMl5BanBnXkFtZTgwMTU5MTAwMDE@._V1_SX400_.jpg\",\n      \"plot\": \"70 years after a horrific alien war, an unusually gifted child is sent to an advanced military school in space to prepare for a future invasion.\",\n      \"rank\": 59,\n      \"running_time_secs\": 6840,\n      \"actors\": [\"Harrison Ford\", \"Asa Butterfield\", \"Hailee Steinfeld\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"White House Down\",\n    \"info\": {\n      \"directors\": [\"Roland Emmerich\"],\n      \"release_date\": \"2013-06-26T00:00:00Z\",\n      \"rating\": 6.4,\n      \"genres\": [\"Action\", \"Drama\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTAyNzQyNTcwNjVeQTJeQWpwZ15BbWU3MDAwOTQ4Nzk@._V1_SX400_.jpg\",\n      \"plot\": \"While on a tour of the White House with his young daughter, a Capitol policeman springs into action to save his child and protect the president from a heavily armed group of paramilitary invaders.\",\n      \"rank\": 60,\n      \"running_time_secs\": 7860,\n      \"actors\": [\"Channing Tatum\", \"Jamie Foxx\", \"Maggie Gyllenhaal\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Pain & Gain\",\n    \"info\": {\n      \"directors\": [\"Michael Bay\"],\n      \"release_date\": \"2013-04-11T00:00:00Z\",\n      \"rating\": 6.5,\n      \"genres\": [\"Comedy\", \"Crime\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTU0NDE5NTU0OV5BMl5BanBnXkFtZTcwMzI1OTMzOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A trio of bodybuilders in Florida get caught up in an extortion ring and a kidnapping scheme that goes terribly wrong.\",\n      \"rank\": 61,\n      \"running_time_secs\": 7740,\n      \"actors\": [\"Mark Wahlberg\", \"Dwayne Johnson\", \"Anthony Mackie\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"2 Guns\",\n    \"info\": {\n      \"directors\": [\"Baltasar Kormakur\"],\n      \"release_date\": \"2013-07-30T00:00:00Z\",\n      \"rating\": 7,\n      \"genres\": [\"Action\", \"Comedy\", \"Crime\", \"Drama\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BNTQ5MTgzNDg4OF5BMl5BanBnXkFtZTcwMjAyODEzOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A DEA agent and a naval intelligence officer find themselves on the run after a botched attempt to infiltrate a drug cartel. While fleeing, they learn the secret of their shaky alliance: Neither knew that the other was an undercover agent.\",\n      \"rank\": 62,\n      \"running_time_secs\": 6540,\n      \"actors\": [\"Denzel Washington\", \"Mark Wahlberg\", \"Paula Patton\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"The Dark Knight Rises\",\n    \"info\": {\n      \"directors\": [\"Christopher Nolan\"],\n      \"release_date\": \"2012-07-16T00:00:00Z\",\n      \"rating\": 8.6,\n      \"genres\": [\"Action\", \"Crime\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTk4ODQzNDY3Ml5BMl5BanBnXkFtZTcwODA0NTM4Nw@@._V1_SX400_.jpg\",\n      \"plot\": \"Eight years on, a new evil rises from where the Batman and Commissioner Gordon tried to bury it, causing the Batman to resurface and fight to protect Gotham City... the very city which brands him an enemy.\",\n      \"rank\": 63,\n      \"running_time_secs\": 9900,\n      \"actors\": [\"Christian Bale\", \"Tom Hardy\", \"Anne Hathaway\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"The Place Beyond the Pines\",\n    \"info\": {\n      \"directors\": [\"Derek Cianfrance\"],\n      \"release_date\": \"2012-09-07T00:00:00Z\",\n      \"rating\": 7.4,\n      \"genres\": [\"Crime\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjc1OTEwNjU4N15BMl5BanBnXkFtZTcwNzUzNDIwOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A motorcycle stunt rider turns to robbing banks as a way to provide for his lover and their newborn child, a decision that puts him on a collision course with an ambitious rookie cop navigating a department ruled by a corrupt detective.\",\n      \"rank\": 64,\n      \"running_time_secs\": 8400,\n      \"actors\": [\"Ryan Gosling\", \"Bradley Cooper\", \"Eva Mendes\"]\n    }\n  },\n  {\n    \"year\": 2014,\n    \"title\": \"Fast & Furious 7\",\n    \"info\": {\n      \"directors\": [\"James Wan\"],\n      \"release_date\": \"2014-07-10T00:00:00Z\",\n      \"genres\": [\"Action\", \"Crime\", \"Thriller\"],\n      \"plot\": \"After Dominic Toretto and his crew helped take down Owen Shaw, his brother Ian Shaw now wants revenge.\",\n      \"rank\": 65,\n      \"actors\": [\"Vin Diesel\", \"Paul Walker\", \"Dwayne Johnson\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"jOBS\",\n    \"info\": {\n      \"directors\": [\"Joshua Michael Stern\"],\n      \"release_date\": \"2013-01-25T00:00:00Z\",\n      \"rating\": 5.6,\n      \"genres\": [\"Biography\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTM5NTQ3MTYxN15BMl5BanBnXkFtZTcwODE2Nzk3OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"The story of Steve Jobs' ascension from college dropout into one of the most revered creative entrepreneurs of the 20th century.\",\n      \"rank\": 66,\n      \"running_time_secs\": 7680,\n      \"actors\": [\"Ashton Kutcher\", \"Dermot Mulroney\", \"Josh Gad\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"Disconnect\",\n    \"info\": {\n      \"directors\": [\"Henry Alex Rubin\"],\n      \"release_date\": \"2012-09-11T00:00:00Z\",\n      \"rating\": 7.5,\n      \"genres\": [\"Drama\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjA2MTEzMDkyOF5BMl5BanBnXkFtZTcwNzc4NTgxOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A drama centered on a group of people searching for human connections in today's wired world.\",\n      \"rank\": 67,\n      \"running_time_secs\": 6900,\n      \"actors\": [\"Jason Bateman\", \"Jonah Bobo\", \"Haley Ramm\"]\n    }\n  },\n  {\n    \"year\": 2011,\n    \"title\": \"Bridesmaids\",\n    \"info\": {\n      \"directors\": [\"Paul Feig\"],\n      \"release_date\": \"2011-04-28T00:00:00Z\",\n      \"rating\": 6.8,\n      \"genres\": [\"Comedy\", \"Romance\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjAyOTMyMzUxNl5BMl5BanBnXkFtZTcwODI4MzE0NA@@._V1_SX400_.jpg\",\n      \"plot\": \"Competition between the maid of honor and a bridesmaid, over who is the bride's best friend, threatens to upend the life of an out-of-work pastry chef.\",\n      \"rank\": 68,\n      \"running_time_secs\": 7500,\n      \"actors\": [\"Kristen Wiig\", \"Maya Rudolph\", \"Rose Byrne\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Man of Steel\",\n    \"info\": {\n      \"directors\": [\"Zack Snyder\"],\n      \"release_date\": \"2013-06-10T00:00:00Z\",\n      \"rating\": 7.6,\n      \"genres\": [\"Action\", \"Adventure\", \"Fantasy\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjI5OTYzNjI0Ml5BMl5BanBnXkFtZTcwMzM1NDA1OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A young itinerant worker is forced to confront his secret extraterrestrial heritage when Earth is invaded by members of his race.\",\n      \"rank\": 69,\n      \"running_time_secs\": 8580,\n      \"actors\": [\"Henry Cavill\", \"Amy Adams\", \"Michael Shannon\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Ghost Team One\",\n    \"info\": {\n      \"directors\": [\"Ben Peyser\", \"Scott Rutherford\"],\n      \"release_date\": \"2013-01-20T00:00:00Z\",\n      \"rating\": 4.3,\n      \"genres\": [\"Comedy\", \"Horror\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BOTYwODQ3NzUyOV5BMl5BanBnXkFtZTgwNjAxNDcyMDE@._V1_SX400_.jpg\",\n      \"plot\": \"Two roommates deathly afraid of ghosts both fall in love with a girl who believes their home is haunted.\",\n      \"rank\": 70,\n      \"running_time_secs\": 6420,\n      \"actors\": [\"Carlos Santos\", \"J.R. Villarreal\", \"Tony Cavalero\"]\n    }\n  },\n  {\n    \"year\": 2010,\n    \"title\": \"Insidious\",\n    \"info\": {\n      \"directors\": [\"James Wan\"],\n      \"release_date\": \"2010-09-14T00:00:00Z\",\n      \"rating\": 6.7,\n      \"genres\": [\"Horror\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTYyOTAxMDA0OF5BMl5BanBnXkFtZTcwNzgwNTc1NA@@._V1_SX400_.jpg\",\n      \"plot\": \"A family looks to prevent evil spirits from trapping their comatose child in a realm called The Further.\",\n      \"rank\": 71,\n      \"running_time_secs\": 6180,\n      \"actors\": [\"Patrick Wilson\", \"Rose Byrne\", \"Ty Simpkins\"]\n    }\n  },\n  {\n    \"year\": 2014,\n    \"title\": \"Godzilla\",\n    \"info\": {\n      \"directors\": [\"Gareth Edwards\"],\n      \"release_date\": \"2014-05-14T00:00:00Z\",\n      \"genres\": [\"Action\", \"Adventure\", \"Fantasy\", \"Sci-Fi\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTk5MTUwNTY2Nl5BMl5BanBnXkFtZTcwMDk0MTk4OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A giant radioactive monster called Godzilla awakens from its slumber to wreak destruction on its creators.\",\n      \"rank\": 72,\n      \"actors\": [\"Aaron Taylor-Johnson\", \"Elizabeth Olsen\", \"Bryan Cranston\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"Wreck-It Ralph\",\n    \"info\": {\n      \"directors\": [\"Rich Moore\"],\n      \"release_date\": \"2012-11-01T00:00:00Z\",\n      \"rating\": 7.8,\n      \"genres\": [\"Animation\", \"Adventure\", \"Comedy\", \"Family\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BNzMxNTExOTkyMF5BMl5BanBnXkFtZTcwMzEyNDc0OA@@._V1_SX400_.jpg\",\n      \"plot\": \"A video game villain wants to be a hero and sets out to fulfill his dream, but his quest brings havoc to the whole arcade where he lives.\",\n      \"rank\": 73,\n      \"running_time_secs\": 6480,\n      \"actors\": [\"John C. Reilly\", \"Jack McBrayer\", \"Jane Lynch\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Hobbit: The Desolation of Smaug\",\n    \"info\": {\n      \"directors\": [\"Peter Jackson\"],\n      \"release_date\": \"2013-12-11T00:00:00Z\",\n      \"genres\": [\"Adventure\", \"Drama\", \"Fantasy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjAxMjMzMzAxOV5BMl5BanBnXkFtZTcwNTU3NzU2OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"The Dwarves, Bilbo and Gandalf have successfully escaped the Misty Mountains, and Bilbo has gained the One Ring. They all continue their journey to get their gold back from the Dragon, Smaug.\",\n      \"rank\": 74,\n      \"actors\": [\"Martin Freeman\", \"Ian McKellen\", \"Richard Armitage\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Frozen\",\n    \"info\": {\n      \"directors\": [\"Chris Buck\", \"Jennifer Lee\"],\n      \"release_date\": \"2013-11-20T00:00:00Z\",\n      \"genres\": [\n        \"Animation\",\n        \"Action\",\n        \"Adventure\",\n        \"Comedy\",\n        \"Family\",\n        \"Fantasy\",\n        \"Musical\",\n        \"Mystery\",\n        \"Romance\",\n        \"Thriller\"\n      ],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTQ1MjQwMTE5OF5BMl5BanBnXkFtZTgwNjk3MTcyMDE@._V1_SX400_.jpg\",\n      \"plot\": \"Fearless optimist Anna teams up with Kristoff in an epic journey, encountering Everest-like conditions, and a hilarious snowman named Olaf in a race to find Anna's sister Elsa, whose icy powers have trapped the kingdom in eternal winter.\",\n      \"rank\": 75,\n      \"actors\": [\"Kristen Bell\", \"Josh Gad\", \"Idina Menzel\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"Spring Breakers\",\n    \"info\": {\n      \"directors\": [\"Harmony Korine\"],\n      \"release_date\": \"2012-09-05T00:00:00Z\",\n      \"rating\": 5.5,\n      \"genres\": [\"Crime\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BNDE3MDQzMDA5OF5BMl5BanBnXkFtZTcwMTUxNTgxOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Four college girls who land in jail after robbing a restaurant in order to fund their spring break vacation find themselves bailed out by a drug and arms dealer who wants them to do some dirty work.\",\n      \"rank\": 76,\n      \"running_time_secs\": 5640,\n      \"actors\": [\"Vanessa Hudgens\", \"Selena Gomez\", \"Ashley Benson\"]\n    }\n  },\n  {\n    \"year\": 2014,\n    \"title\": \"Fifty Shades of Grey\",\n    \"info\": {\n      \"directors\": [\"Sam Taylor-Johnson\"],\n      \"release_date\": \"2014-08-01T00:00:00Z\",\n      \"genres\": [\"Drama\", \"Romance\"],\n      \"plot\": \"A literature student Anastasia Steele meets a handsome, yet tormented, billionaire named Christian Grey.\",\n      \"rank\": 77,\n      \"actors\": [\"Charlie Hunnam\", \"Dakota Johnson\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"Silver Linings Playbook\",\n    \"info\": {\n      \"directors\": [\"David O. Russell\"],\n      \"release_date\": \"2012-09-08T00:00:00Z\",\n      \"rating\": 7.9,\n      \"genres\": [\"Comedy\", \"Drama\", \"Romance\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTM2MTI5NzA3MF5BMl5BanBnXkFtZTcwODExNTc0OA@@._V1_SX400_.jpg\",\n      \"plot\": \"After a stint in a mental institution, former teacher Pat Solitano moves back in with his parents and tries to reconcile with his ex-wife. Things get more challenging when Pat meets Tiffany, a mysterious girl with problems of her own.\",\n      \"rank\": 78,\n      \"running_time_secs\": 7320,\n      \"actors\": [\"Bradley Cooper\", \"Jennifer Lawrence\", \"Robert De Niro\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"R.I.P.D.\",\n    \"info\": {\n      \"directors\": [\"Robert Schwentke\"],\n      \"release_date\": \"2013-07-17T00:00:00Z\",\n      \"rating\": 5.4,\n      \"genres\": [\"Action\", \"Comedy\", \"Crime\", \"Fantasy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTM5OTYxNzE5N15BMl5BanBnXkFtZTcwMDU1MTQ4OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A recently slain cop joins a team of undead police officers working for the Rest in Peace Department and tries to find the man who murdered him.\",\n      \"rank\": 79,\n      \"running_time_secs\": 5760,\n      \"actors\": [\"Ryan Reynolds\", \"Jeff Bridges\", \"Mary-Louise Parker\"]\n    }\n  },\n  {\n    \"year\": 1994,\n    \"title\": \"The Shawshank Redemption\",\n    \"info\": {\n      \"directors\": [\"Frank Darabont\"],\n      \"release_date\": \"1994-09-10T00:00:00Z\",\n      \"rating\": 9.3,\n      \"genres\": [\"Crime\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BODU4MjU4NjIwNl5BMl5BanBnXkFtZTgwMDU2MjEyMDE@._V1_SX400_.jpg\",\n      \"plot\": \"Two imprisoned men bond over a number of years, finding solace and eventual redemption through acts of common decency.\",\n      \"rank\": 80,\n      \"running_time_secs\": 8520,\n      \"actors\": [\"Tim Robbins\", \"Morgan Freeman\", \"Bob Gunton\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Pacific Rim\",\n    \"info\": {\n      \"directors\": [\"Guillermo del Toro\"],\n      \"release_date\": \"2013-07-02T00:00:00Z\",\n      \"rating\": 7.5,\n      \"genres\": [\"Action\", \"Adventure\", \"Fantasy\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTY3MTI5NjQ4Nl5BMl5BanBnXkFtZTcwOTU1OTU0OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"As a war between humankind and monstrous sea creatures wages on, a former pilot and a trainee are paired up to drive a seemingly obsolete special weapon in a desperate effort to save the world from the apocalypse.\",\n      \"rank\": 81,\n      \"running_time_secs\": 7860,\n      \"actors\": [\"Idris Elba\", \"Charlie Hunnam\", \"Rinko Kikuchi\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"The Hunger Games\",\n    \"info\": {\n      \"directors\": [\"Gary Ross\"],\n      \"release_date\": \"2012-03-12T00:00:00Z\",\n      \"rating\": 7.2,\n      \"genres\": [\"Adventure\", \"Sci-Fi\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjA4NDg3NzYxMF5BMl5BanBnXkFtZTcwNTgyNzkyNw@@._V1_SX400_.jpg\",\n      \"plot\": \"Katniss Everdeen voluntarily takes her younger sister's place in the Hunger Games, a televised fight to the death in which two teenagers from each of the twelve Districts of Panem are chosen at random to compete.\",\n      \"rank\": 82,\n      \"running_time_secs\": 8520,\n      \"actors\": [\"Jennifer Lawrence\", \"Josh Hutcherson\", \"Liam Hemsworth\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Last Days on Mars\",\n    \"info\": {\n      \"directors\": [\"Ruairi Robinson\"],\n      \"release_date\": \"2013-05-20T00:00:00Z\",\n      \"rating\": 7.4,\n      \"genres\": [\"Sci-Fi\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTk4ODgxMDU0M15BMl5BanBnXkFtZTgwOTg0NzcyMDE@._V1_SX400_.jpg\",\n      \"plot\": \"A group of astronaut explorers succumb one by one to a mysterious and terrifying force while collecting specimens on Mars.\",\n      \"rank\": 83,\n      \"running_time_secs\": 5880,\n      \"actors\": [\"Liev Schreiber\", \"Romola Garai\", \"Elias Koteas\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Baggage Claim\",\n    \"info\": {\n      \"directors\": [\"David E. Talbert\"],\n      \"release_date\": \"2013-09-27T00:00:00Z\",\n      \"rating\": 4.1,\n      \"genres\": [\"Comedy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjIyNDU4NTY3M15BMl5BanBnXkFtZTcwOTA3MDA1OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Pledging to keep herself from being the oldest and the only woman in her entire family never to wed, Montana embarks on a thirty-day, thirty-thousand-mile expedition to charm a potential suitor into becoming her fiance.\",\n      \"rank\": 84,\n      \"running_time_secs\": 5760,\n      \"actors\": [\"Paula Patton\", \"Taye Diggs\", \"Jill Scott\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Percy Jackson: Sea of Monsters\",\n    \"info\": {\n      \"directors\": [\"Thor Freudenthal\"],\n      \"release_date\": \"2013-08-07T00:00:00Z\",\n      \"rating\": 6.5,\n      \"genres\": [\"Adventure\", \"Family\", \"Fantasy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTUwODUyODI0Nl5BMl5BanBnXkFtZTcwNzAxODY2OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"In order to restore their dying safe haven, the son of Poseidon and his friends embark on a quest to the Sea of Monsters to find the mythical Golden Fleece while trying to stop an ancient evil from rising.\",\n      \"rank\": 85,\n      \"running_time_secs\": 6360,\n      \"actors\": [\"Logan Lerman\", \"Alexandra Daddario\", \"Brandon T. Jackson\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"Byzantium\",\n    \"info\": {\n      \"directors\": [\"Neil Jordan\"],\n      \"release_date\": \"2012-09-09T00:00:00Z\",\n      \"rating\": 6.5,\n      \"genres\": [\"Drama\", \"Fantasy\", \"Horror\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTk2Nzc0NDQwMV5BMl5BanBnXkFtZTcwNjI2MjY3OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Residents of a coastal town learn, with deathly consequences, the secret shared by the two mysterious women who have sought shelter at a local resort.\",\n      \"rank\": 86,\n      \"running_time_secs\": 7080,\n      \"actors\": [\"Saoirse Ronan\", \"Gemma Arterton\", \"Sam Riley\"]\n    }\n  },\n  {\n    \"year\": 2011,\n    \"title\": \"X-Men: First Class\",\n    \"info\": {\n      \"directors\": [\"Matthew Vaughn\"],\n      \"release_date\": \"2011-05-25T00:00:00Z\",\n      \"rating\": 7.8,\n      \"genres\": [\"Action\", \"Adventure\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTg5OTMxNzk4Nl5BMl5BanBnXkFtZTcwOTk1MjAwNQ@@._V1_SX400_.jpg\",\n      \"plot\": \"In 1962, the United States government enlists the help of Mutants with superhuman abilities to stop a malicious dictator who is determined to start world war III.\",\n      \"rank\": 87,\n      \"running_time_secs\": 7920,\n      \"actors\": [\"James McAvoy\", \"Michael Fassbender\", \"Jennifer Lawrence\"]\n    }\n  },\n  {\n    \"year\": 1993,\n    \"title\": \"Hocus Pocus\",\n    \"info\": {\n      \"directors\": [\"Kenny Ortega\"],\n      \"release_date\": \"1993-07-16T00:00:00Z\",\n      \"rating\": 6.2,\n      \"genres\": [\"Comedy\", \"Family\", \"Fantasy\", \"Horror\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTI3MDI2NDc3Ml5BMl5BanBnXkFtZTcwNDQ2MzQyMQ@@._V1_SX400_.jpg\",\n      \"plot\": \"After 300 years, three sister witches are resurrected in Salem Massachusetts on Halloween night, and it us up to two teenagers, a young girl, and an immortal cat to put an end to the witches reign of terror once and for all.\",\n      \"rank\": 88,\n      \"running_time_secs\": 5760,\n      \"actors\": [\"Bette Midler\", \"Sarah Jessica Parker\", \"Kathy Najimy\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The East\",\n    \"info\": {\n      \"directors\": [\"Zal Batmanglij\"],\n      \"release_date\": \"2013-01-20T00:00:00Z\",\n      \"rating\": 6.9,\n      \"genres\": [\"Crime\", \"Drama\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjEyNjQzMzg5Nl5BMl5BanBnXkFtZTcwMjExNzU1OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"An operative for an elite private intelligence firm finds her priorities changing dramatically after she is tasked with infiltrating an anarchist group known for executing covert attacks upon major corporations.\",\n      \"rank\": 89,\n      \"running_time_secs\": 6960,\n      \"actors\": [\"Brit Marling\", \"Alexander Skarsgard\", \"Ellen Page\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"V/H/S/2\",\n    \"info\": {\n      \"directors\": [\"Simon Barrett\", \"Jason Eisener\", \"Gareth Evans\"],\n      \"release_date\": \"2013-01-19T00:00:00Z\",\n      \"rating\": 6.2,\n      \"genres\": [\"Horror\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BODg4OTMxNDAxMV5BMl5BanBnXkFtZTcwMjM4ODQ0OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Searching for a missing student, two private investigators break into his house and find collection of VHS tapes. Viewing the horrific contents of each cassette, they realize there may be dark motives behind the student's disappearance.\",\n      \"rank\": 90,\n      \"running_time_secs\": 5760,\n      \"actors\": [\"Lawrence Michael Levine\", \"Kelsy Abbott\", \"Adam Wingard\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Croods\",\n    \"info\": {\n      \"directors\": [\"Kirk De Micco\", \"Chris Sanders\"],\n      \"release_date\": \"2013-02-15T00:00:00Z\",\n      \"rating\": 7.3,\n      \"genres\": [\"Animation\", \"Adventure\", \"Comedy\", \"Family\", \"Fantasy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTcyOTc2OTA1Ml5BMl5BanBnXkFtZTcwOTI1MjkzOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"After their cave is destroyed, a caveman family must trek through an unfamiliar fantastical world with the help of an inventive boy.\",\n      \"rank\": 91,\n      \"running_time_secs\": 5880,\n      \"actors\": [\"Nicolas Cage\", \"Ryan Reynolds\", \"Emma Stone\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Olympus Has Fallen\",\n    \"info\": {\n      \"directors\": [\"Antoine Fuqua\"],\n      \"release_date\": \"2013-03-20T00:00:00Z\",\n      \"rating\": 6.4,\n      \"genres\": [\"Action\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTkxNjIyNjE5OF5BMl5BanBnXkFtZTcwMTI3NzkxOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Disgraced former Presidential guard Mike Banning finds himself trapped inside the White House in the wake of a terrorist attack; using his inside knowledge, Banning works with national security to rescue the President from his kidnappers.\",\n      \"rank\": 92,\n      \"running_time_secs\": 7200,\n      \"actors\": [\"Gerard Butler\", \"Aaron Eckhart\", \"Morgan Freeman\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Hummingbird\",\n    \"info\": {\n      \"directors\": [\"Steven Knight\"],\n      \"release_date\": \"2013-05-09T00:00:00Z\",\n      \"rating\": 6.2,\n      \"genres\": [\"Action\", \"Crime\", \"Drama\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjI0ODc3NjI4NV5BMl5BanBnXkFtZTcwOTc3MzI1OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Homeless and on the run from a military court martial, a damaged ex-special forces soldier navigating London's criminal underworld seizes an opportunity to assume another man's identity -- transforming into an avenging angel in the process.\",\n      \"rank\": 93,\n      \"running_time_secs\": 6000,\n      \"actors\": [\"Jason Statham\", \"Agata Buzek\", \"Vicky McClure\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"About Time\",\n    \"info\": {\n      \"directors\": [\"Richard Curtis\"],\n      \"release_date\": \"2013-06-27T00:00:00Z\",\n      \"rating\": 7.6,\n      \"genres\": [\"Comedy\", \"Drama\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTA1ODUzMDA3NzFeQTJeQWpwZ15BbWU3MDgxMTYxNTk@._V1_SX400_.jpg\",\n      \"plot\": \"At the age of 21, Tim discovers he can travel in time and change what happens and has happened in his own life. His decision to make his world a better place by getting a girlfriend turns out not to be as easy as you might think.\",\n      \"rank\": 94,\n      \"running_time_secs\": 7380,\n      \"actors\": [\"Domhnall Gleeson\", \"Rachel McAdams\", \"Bill Nighy\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"Mud\",\n    \"info\": {\n      \"directors\": [\"Jeff Nichols\"],\n      \"release_date\": \"2012-05-26T00:00:00Z\",\n      \"rating\": 7.5,\n      \"genres\": [\"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTU2MzcyODgyNV5BMl5BanBnXkFtZTcwNTc4MDYwOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Two young boys encounter a fugitive and form a pact to help him evade the bounty hunters on his trail and to reunite him with his true love.\",\n      \"rank\": 95,\n      \"running_time_secs\": 7800,\n      \"actors\": [\"Matthew McConaughey\", \"Tye Sheridan\", \"Jacob Lofland\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"Argo\",\n    \"info\": {\n      \"directors\": [\"Ben Affleck\"],\n      \"release_date\": \"2012-08-31T00:00:00Z\",\n      \"rating\": 7.9,\n      \"genres\": [\"Biography\", \"Drama\", \"History\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTc3MjI0MjM0NF5BMl5BanBnXkFtZTcwMTYxMTQ1OA@@._V1_SX400_.jpg\",\n      \"plot\": \"Acting under the cover of a Hollywood producer scouting a location for a science fiction film, a CIA agent launches a dangerous operation to rescue six Americans in Tehran during the U.S. hostage crisis in Iran in 1980.\",\n      \"rank\": 96,\n      \"running_time_secs\": 7200,\n      \"actors\": [\"Ben Affleck\", \"Bryan Cranston\", \"John Goodman\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"Django Unchained\",\n    \"info\": {\n      \"directors\": [\"Quentin Tarantino\"],\n      \"release_date\": \"2012-12-25T00:00:00Z\",\n      \"rating\": 8.5,\n      \"genres\": [\"Adventure\", \"Drama\", \"Western\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjIyNTQ5NjQ1OV5BMl5BanBnXkFtZTcwODg1MDU4OA@@._V1_SX400_.jpg\",\n      \"plot\": \"With the help of a German bounty hunter, a freed slave sets out to rescue his wife from a brutal Mississippi plantation owner.\",\n      \"rank\": 97,\n      \"running_time_secs\": 9900,\n      \"actors\": [\"Jamie Foxx\", \"Christoph Waltz\", \"Leonardo DiCaprio\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Grown Ups 2\",\n    \"info\": {\n      \"directors\": [\"Dennis Dugan\"],\n      \"release_date\": \"2013-07-11T00:00:00Z\",\n      \"rating\": 5.2,\n      \"genres\": [\"Comedy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTgwNTI2MDI0OF5BMl5BanBnXkFtZTcwMTk5MDg0OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"After moving his family back to his hometown to be with his friends and their kids, Lenny finds out that between old bullies, new bullies, schizo bus drivers, drunk cops on skis, and 400 costumed party crashers sometimes crazy follows you.\",\n      \"rank\": 98,\n      \"running_time_secs\": 6060,\n      \"actors\": [\"Adam Sandler\", \"Kevin James\", \"Chris Rock\"]\n    }\n  },\n  {\n    \"year\": 2008,\n    \"title\": \"The Dark Knight\",\n    \"info\": {\n      \"directors\": [\"Christopher Nolan\"],\n      \"release_date\": \"2008-07-14T00:00:00Z\",\n      \"rating\": 9,\n      \"genres\": [\"Action\", \"Crime\", \"Drama\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTMxNTMwODM0NF5BMl5BanBnXkFtZTcwODAyMTk2Mw@@._V1_SX400_.jpg\",\n      \"plot\": \"When Batman, Gordon and Harvey Dent launch an assault on the mob, they let the clown out of the box, the Joker, bent on turning Gotham on itself and bringing any heroes down to his level.\",\n      \"rank\": 99,\n      \"running_time_secs\": 9120,\n      \"actors\": [\"Christian Bale\", \"Heath Ledger\", \"Aaron Eckhart\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Planes\",\n    \"info\": {\n      \"directors\": [\"Klay Hall\"],\n      \"release_date\": \"2013-08-05T00:00:00Z\",\n      \"rating\": 5.2,\n      \"genres\": [\"Animation\", \"Adventure\", \"Comedy\", \"Family\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjAwODc5NzYzOF5BMl5BanBnXkFtZTcwNTk4MjEzOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A cropdusting plane with a fear of heights lives his dream of competing in a famous around-the-world aerial race.\",\n      \"rank\": 100,\n      \"running_time_secs\": 5460,\n      \"actors\": [\"Carlos Alazraqui\", \"Dane Cook\", \"Stacy Keach\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Captain Phillips\",\n    \"info\": {\n      \"directors\": [\"Paul Greengrass\"],\n      \"release_date\": \"2013-09-27T00:00:00Z\",\n      \"rating\": 6.7,\n      \"genres\": [\"Action\", \"Biography\", \"Drama\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTQzNzExMDg3Ml5BMl5BanBnXkFtZTgwODU1NzEzMDE@._V1_SX400_.jpg\",\n      \"plot\": \"The true story of Captain Richard Phillips and the 2009 hijacking by Somali pirates of the US-flagged MV Maersk Alabama, the first American cargo ship to be hijacked in two hundred years.\",\n      \"rank\": 101,\n      \"running_time_secs\": 8040,\n      \"actors\": [\"Tom Hanks\", \"Barkhad Abdi\", \"Barkhad Abdirahman\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"The Hobbit: An Unexpected Journey\",\n    \"info\": {\n      \"directors\": [\"Peter Jackson\"],\n      \"release_date\": \"2012-11-28T00:00:00Z\",\n      \"rating\": 8.1,\n      \"genres\": [\"Adventure\", \"Fantasy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTcwNTE4MTUxMl5BMl5BanBnXkFtZTcwMDIyODM4OA@@._V1_SX400_.jpg\",\n      \"plot\": \"A younger and more reluctant Hobbit, Bilbo Baggins, sets out on an \\\"unexpected journey\\\" to the Lonely Mountain with a spirited group of Dwarves to reclaim their stolen mountain home from a dragon named Smaug.\",\n      \"rank\": 103,\n      \"running_time_secs\": 10140,\n      \"actors\": [\"Martin Freeman\", \"Ian McKellen\", \"Richard Armitage\"]\n    }\n  },\n  {\n    \"year\": 2014,\n    \"title\": \"Guardians of the Galaxy\",\n    \"info\": {\n      \"directors\": [\"James Gunn\"],\n      \"release_date\": \"2014-07-31T00:00:00Z\",\n      \"genres\": [\"Action\", \"Adventure\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTg3NDI5Mjg5MF5BMl5BanBnXkFtZTgwNzI2OTIzMDE@._V1_SX400_.jpg\",\n      \"plot\": \"A jet pilot gets stranded in space, and must unite a diverse team of aliens to form a squad capable of defeating cosmic threats.\",\n      \"rank\": 104,\n      \"actors\": [\"Vin Diesel\", \"Zoe Saldana\", \"Bradley Cooper\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"Les Miserables\",\n    \"info\": {\n      \"directors\": [\"Tom Hooper\"],\n      \"release_date\": \"2012-12-05T00:00:00Z\",\n      \"rating\": 7.6,\n      \"genres\": [\"Drama\", \"Musical\", \"Romance\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTQ4NDI3NDg4M15BMl5BanBnXkFtZTcwMjY5OTI1OA@@._V1_SX400_.jpg\",\n      \"plot\": \"In 19th-century France, Jean Valjean, who for decades has been hunted by the ruthless policeman Javert after he breaks parole, agrees to care for factory worker Fantine's daughter, Cosette. The fateful decision changes their lives forever.\",\n      \"rank\": 106,\n      \"running_time_secs\": 9480,\n      \"actors\": [\"Hugh Jackman\", \"Russell Crowe\", \"Anne Hathaway\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Kings of Summer\",\n    \"info\": {\n      \"directors\": [\"Jordan Vogt-Roberts\"],\n      \"release_date\": \"2013-01-19T00:00:00Z\",\n      \"rating\": 7.1,\n      \"genres\": [\"Comedy\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTc3ODA1NTI0MV5BMl5BanBnXkFtZTcwOTE4OTUzOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Three teenage friends, in the ultimate act of independence, decide to spend their summer building a house in the woods and living off the land.\",\n      \"rank\": 107,\n      \"running_time_secs\": 5700,\n      \"actors\": [\"Nick Robinson\", \"Gabriel Basso\", \"Moises Arias\"]\n    }\n  },\n  {\n    \"year\": 2009,\n    \"title\": \"Mr. Nobody\",\n    \"info\": {\n      \"directors\": [\"Jaco Van Dormael\"],\n      \"release_date\": \"2009-09-12T00:00:00Z\",\n      \"rating\": 7.8,\n      \"genres\": [\"Drama\", \"Fantasy\", \"Romance\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTg4ODkzMDQ3Nl5BMl5BanBnXkFtZTgwNTEwMTkxMDE@._V1_SX400_.jpg\",\n      \"plot\": \"A boy stands on a station platform as a train is about to leave. Should he go with his mother or stay with his father? An infinity of possibilities rise from this decision. As long as he doesn't choose, anything is possible.\",\n      \"rank\": 108,\n      \"running_time_secs\": 8460,\n      \"actors\": [\"Jared Leto\", \"Sarah Polley\", \"Diane Kruger\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Fifth Estate\",\n    \"info\": {\n      \"directors\": [\"Bill Condon\"],\n      \"release_date\": \"2013-09-05T00:00:00Z\",\n      \"rating\": 6.4,\n      \"genres\": [\"Biography\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjY1MTY5NTg3M15BMl5BanBnXkFtZTgwMDQyMjgwMDE@._V1_SX400_.jpg\",\n      \"plot\": \"A dramatic thriller based on real events, THE FIFTH ESTATE reveals the quest to expose the deceptions and corruptions of power that turned an Internet upstart into the 21st century's most fiercely debated organization.\",\n      \"rank\": 110,\n      \"running_time_secs\": 7680,\n      \"actors\": [\"Benedict Cumberbatch\", \"Daniel Bruhl\", \"Carice van Houten\"]\n    }\n  },\n  {\n    \"year\": 1997,\n    \"title\": \"Titanic\",\n    \"info\": {\n      \"directors\": [\"James Cameron\"],\n      \"release_date\": \"1997-11-01T00:00:00Z\",\n      \"rating\": 7.6,\n      \"genres\": [\"Drama\", \"Romance\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjExNzM0NDM0N15BMl5BanBnXkFtZTcwMzkxOTUwNw@@._V1_SX400_.jpg\",\n      \"plot\": \"A seventeen-year-old aristocrat, expecting to be married to a rich claimant by her mother, falls in love with a kind but poor artist aboard the luxurious, ill-fated R.M.S. Titanic.\",\n      \"rank\": 111,\n      \"running_time_secs\": 11640,\n      \"actors\": [\"Leonardo DiCaprio\", \"Kate Winslet\", \"Billy Zane\"]\n    }\n  },\n  {\n    \"year\": 2004,\n    \"title\": \"The Incredibles\",\n    \"info\": {\n      \"directors\": [\"Brad Bird\"],\n      \"release_date\": \"2004-10-27T00:00:00Z\",\n      \"rating\": 8,\n      \"genres\": [\"Animation\", \"Action\", \"Adventure\", \"Family\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTY5OTU0OTc2NV5BMl5BanBnXkFtZTcwMzU4MDcyMQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A family of undercover superheroes, while trying to live the quiet suburban life, are forced into action to save the world.\",\n      \"rank\": 112,\n      \"running_time_secs\": 6900,\n      \"actors\": [\"Craig T. Nelson\", \"Samuel L. Jackson\", \"Holly Hunter\"]\n    }\n  },\n  {\n    \"year\": 2014,\n    \"title\": \"Into the Woods\",\n    \"info\": {\n      \"directors\": [\"Rob Marshall\"],\n      \"release_date\": \"2014-12-25T00:00:00Z\",\n      \"genres\": [\"Comedy\", \"Fantasy\", \"Musical\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTY4OTE5NDYzOV5BMl5BanBnXkFtZTgwODcwMzMzMDE@._V1_SX400_.jpg\",\n      \"plot\": \"A witch conspires to teach important lessons to various characters of popular children's stories including Little Red Riding Hood, Cinderella, Jack and the Beanstalk and Rapunzel.\",\n      \"rank\": 113,\n      \"actors\": [\"Anna Kendrick\", \"Johnny Depp\", \"Chris Pine\"]\n    }\n  },\n  {\n    \"year\": 1994,\n    \"title\": \"Pulp Fiction\",\n    \"info\": {\n      \"directors\": [\"Quentin Tarantino\"],\n      \"release_date\": \"1994-05-12T00:00:00Z\",\n      \"rating\": 9,\n      \"genres\": [\"Crime\", \"Drama\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjE0ODk2NjczOV5BMl5BanBnXkFtZTYwNDQ0NDg4._V1_SX400_.jpg\",\n      \"plot\": \"The lives of two mob hit men, a boxer, a gangster's wife, and a pair of diner bandits intertwine in four tales of violence and redemption.\",\n      \"rank\": 114,\n      \"running_time_secs\": 9240,\n      \"actors\": [\"John Travolta\", \"Uma Thurman\", \"Samuel L. Jackson\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Call\",\n    \"info\": {\n      \"directors\": [\"Brad Anderson\"],\n      \"release_date\": \"2013-03-14T00:00:00Z\",\n      \"rating\": 6.6,\n      \"genres\": [\"Crime\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjExNDkzNjAwOV5BMl5BanBnXkFtZTcwMDMzMzQwOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"When a veteran 911 operator takes a life-altering call from a teenage girl who has just been abducted, she realizes that she must confront a killer from her past in order to save the girl's life.\",\n      \"rank\": 115,\n      \"running_time_secs\": 5640,\n      \"actors\": [\"Halle Berry\", \"Evie Thompson\", \"Abigail Breslin\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Side Effects\",\n    \"info\": {\n      \"directors\": [\"Steven Soderbergh\"],\n      \"release_date\": \"2013-02-08T00:00:00Z\",\n      \"rating\": 7.1,\n      \"genres\": [\"Crime\", \"Drama\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTc2MzY0NDAwOF5BMl5BanBnXkFtZTcwMTE1Mzc4OA@@._V1_SX400_.jpg\",\n      \"plot\": \"A young woman's world unravels when a drug prescribed by her psychiatrist has unexpected side effects.\",\n      \"rank\": 116,\n      \"running_time_secs\": 6360,\n      \"actors\": [\"Rooney Mara\", \"Channing Tatum\", \"Jude Law\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"The Iceman\",\n    \"info\": {\n      \"directors\": [\"Ariel Vromen\"],\n      \"release_date\": \"2012-08-30T00:00:00Z\",\n      \"rating\": 6.9,\n      \"genres\": [\"Biography\", \"Crime\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTc3NjY3NzUyOF5BMl5BanBnXkFtZTcwMTA5NzAyOA@@._V1_SX400_.jpg\",\n      \"plot\": \"The true story of Richard Kuklinski, the notorious contract killer and family man. When finally arrested in 1986, neither his wife nor daughters have any clue about his real profession.\",\n      \"rank\": 117,\n      \"running_time_secs\": 6300,\n      \"actors\": [\"Michael Shannon\", \"Chris Evans\", \"James Franco\"]\n    }\n  },\n  {\n    \"year\": 1939,\n    \"title\": \"The Wizard of Oz\",\n    \"info\": {\n      \"directors\": [\"Victor Fleming\", \"George Cukor\", \"Mervyn LeRoy\"],\n      \"release_date\": \"1939-08-12T00:00:00Z\",\n      \"rating\": 8.2,\n      \"genres\": [\"Adventure\", \"Family\", \"Fantasy\", \"Musical\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTU0MTA2OTIwNF5BMl5BanBnXkFtZTcwMzA0Njk3OA@@._V1_SX400_.jpg\",\n      \"plot\": \"Dorothy Gale is swept away to a magical land in a tornado and embarks on a quest to see the Wizard who can help her return home.\",\n      \"rank\": 118,\n      \"running_time_secs\": 6060,\n      \"actors\": [\"Judy Garland\", \"Frank Morgan\", \"Ray Bolger\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Big Sur\",\n    \"info\": {\n      \"directors\": [\"Michael Polish\"],\n      \"release_date\": \"2013-01-23T00:00:00Z\",\n      \"rating\": 6.3,\n      \"genres\": [\"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjI3MDU0MDY2MF5BMl5BanBnXkFtZTgwNDY3NjUzMDE@._V1_SX400_.jpg\",\n      \"plot\": \"A recounting of Jack Kerouac's (here known by the name of his fictional alter-ego Jack Duluoz) three sojourns to the cabin in Big Sur, owned by poet Lawrence Ferlinghetti.\",\n      \"rank\": 119,\n      \"running_time_secs\": 6000,\n      \"actors\": [\"Stana Katic\", \"Radha Mitchell\", \"Kate Bosworth\"]\n    }\n  },\n  {\n    \"year\": 1985,\n    \"title\": \"The Breakfast Club\",\n    \"info\": {\n      \"directors\": [\"John Hughes\"],\n      \"release_date\": \"1985-02-07T00:00:00Z\",\n      \"rating\": 7.9,\n      \"genres\": [\"Comedy\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMzYyNTQ1Nzk2M15BMl5BanBnXkFtZTcwODk0NTQyMQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Five high school students, all different stereotypes, meet in detention, where they pour their hearts out to each other, and discover how they have a lot more in common than they thought.\",\n      \"rank\": 120,\n      \"running_time_secs\": 5820,\n      \"actors\": [\"Emilio Estevez\", \"Judd Nelson\", \"Molly Ringwald\"]\n    }\n  },\n  {\n    \"year\": 2010,\n    \"title\": \"Inception\",\n    \"info\": {\n      \"directors\": [\"Christopher Nolan\"],\n      \"release_date\": \"2010-07-08T00:00:00Z\",\n      \"rating\": 8.8,\n      \"genres\": [\"Action\", \"Adventure\", \"Mystery\", \"Sci-Fi\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjAxMzY3NjcxNF5BMl5BanBnXkFtZTcwNTI5OTM0Mw@@._V1_SX400_.jpg\",\n      \"plot\": \"A skilled extractor is offered a chance to regain his old life as payment for a task considered to be impossible.\",\n      \"rank\": 121,\n      \"running_time_secs\": 8880,\n      \"actors\": [\"Leonardo DiCaprio\", \"Joseph Gordon-Levitt\", \"Ellen Page\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"Hitchcock\",\n    \"info\": {\n      \"directors\": [\"Sacha Gervasi\"],\n      \"release_date\": \"2012-11-01T00:00:00Z\",\n      \"rating\": 6.9,\n      \"genres\": [\"Biography\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BODAwNDI5NjIwN15BMl5BanBnXkFtZTcwNjc4ODc2OA@@._V1_SX400_.jpg\",\n      \"plot\": \"A love story between influential filmmaker Alfred Hitchcock and wife Alma Reville during the filming of [link=tt0054215] in 1959.\",\n      \"rank\": 122,\n      \"running_time_secs\": 5880,\n      \"actors\": [\"Anthony Hopkins\", \"Helen Mirren\", \"Scarlett Johansson\"]\n    }\n  },\n  {\n    \"year\": 2014,\n    \"title\": \"The Expendables 3\",\n    \"info\": {\n      \"directors\": [\"Patrick Hughes\"],\n      \"release_date\": \"2014-08-13T00:00:00Z\",\n      \"genres\": [\"Action\", \"Adventure\", \"Thriller\"],\n      \"plot\": \"The third installment of the action-adventure franchise that follows the exploits of Barney Ross, Lee Christmas, and their associates.\",\n      \"rank\": 123,\n      \"actors\": [\"Jason Statham\", \"Sylvester Stallone\", \"Arnold Schwarzenegger\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Wolverine\",\n    \"info\": {\n      \"directors\": [\"James Mangold\"],\n      \"release_date\": \"2013-07-16T00:00:00Z\",\n      \"rating\": 7.1,\n      \"genres\": [\"Action\", \"Adventure\", \"Fantasy\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BNzg1MDQxMTQ2OF5BMl5BanBnXkFtZTcwMTk3MjAzOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"When Wolverine is summoned to Japan by an old acquaintance, he is embroiled in a conflict that forces him to confront his own demons.\",\n      \"rank\": 124,\n      \"running_time_secs\": 7560,\n      \"actors\": [\"Hugh Jackman\", \"Will Yun Lee\", \"Tao Okamoto\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Purge\",\n    \"info\": {\n      \"directors\": [\"James DeMonaco\"],\n      \"release_date\": \"2013-05-02T00:00:00Z\",\n      \"rating\": 5.5,\n      \"genres\": [\"Horror\", \"Sci-Fi\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTU0OTE1Nzk2NF5BMl5BanBnXkFtZTcwMjE5NDY0OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A family is held hostage for harboring the target of a murderous syndicate during the Purge, a 12-hour period in which any and all crime is legalized.\",\n      \"rank\": 125,\n      \"running_time_secs\": 5100,\n      \"actors\": [\"Ethan Hawke\", \"Lena Headey\", \"Max Burkholder\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Safe Haven\",\n    \"info\": {\n      \"directors\": [\"Lasse Hallstrom\"],\n      \"release_date\": \"2013-02-13T00:00:00Z\",\n      \"rating\": 6.4,\n      \"genres\": [\"Drama\", \"Mystery\", \"Romance\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTg4MzcxODA3OV5BMl5BanBnXkFtZTcwMTYzNDkwOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A young woman with a mysterious past lands in Southport, North Carolina where her bond with a widower forces her to confront the dark secret that haunts her.\",\n      \"rank\": 126,\n      \"running_time_secs\": 6900,\n      \"actors\": [\"Julianne Hough\", \"Josh Duhamel\", \"Cobie Smulders\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"The Perks of Being a Wallflower\",\n    \"info\": {\n      \"directors\": [\"Stephen Chbosky\"],\n      \"release_date\": \"2012-09-08T00:00:00Z\",\n      \"rating\": 8,\n      \"genres\": [\"Drama\", \"Romance\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMzIxOTQyODU1OV5BMl5BanBnXkFtZTcwMDQ4Mjg4Nw@@._V1_SX400_.jpg\",\n      \"plot\": \"An introvert freshman is taken under the wings of two seniors who welcome him to the real world.\",\n      \"rank\": 127,\n      \"running_time_secs\": 6120,\n      \"actors\": [\"Logan Lerman\", \"Emma Watson\", \"Ezra Miller\"]\n    }\n  },\n  {\n    \"year\": 2009,\n    \"title\": \"Star Trek\",\n    \"info\": {\n      \"directors\": [\"J.J. Abrams\"],\n      \"release_date\": \"2009-04-06T00:00:00Z\",\n      \"rating\": 8,\n      \"genres\": [\"Action\", \"Adventure\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjE5NDQ5OTE4Ml5BMl5BanBnXkFtZTcwOTE3NDIzMw@@._V1_SX400_.jpg\",\n      \"plot\": \"The brash James T. Kirk tries to live up to his father's legacy with Mr. Spock keeping him in check as a vengeful, time-traveling Romulan creates black holes to destroy the Federation one planet at a time.\",\n      \"rank\": 128,\n      \"running_time_secs\": 7620,\n      \"actors\": [\"Chris Pine\", \"Zachary Quinto\", \"Simon Pegg\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"One Direction: This Is Us\",\n    \"info\": {\n      \"directors\": [\"Morgan Spurlock\"],\n      \"release_date\": \"2013-08-20T00:00:00Z\",\n      \"rating\": 3.1,\n      \"genres\": [\"Documentary\", \"Music\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTk5NTIxNzg3Nl5BMl5BanBnXkFtZTcwMzc5MDE0OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A look at Niall, Zayn, Liam, Louis, and Harry's meteoric rise to fame, from their humble hometown beginnings and competing on the X-Factor, to conquering the world and performing at London's famed O2 Arena.\",\n      \"rank\": 129,\n      \"running_time_secs\": 5520,\n      \"actors\": [\"Liam Payne\", \"Harry Styles\", \"Zayn Malik\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"Cloud Atlas\",\n    \"info\": {\n      \"directors\": [\"Tom Tykwer\", \"Andy Wachowski\", \"Lana Wachowski\"],\n      \"release_date\": \"2012-09-08T00:00:00Z\",\n      \"rating\": 7.6,\n      \"genres\": [\"Adventure\", \"Drama\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTczMTgxMjc4NF5BMl5BanBnXkFtZTcwNjM5MTA2OA@@._V1_SX400_.jpg\",\n      \"plot\": \"An exploration of how the actions of individual lives impact one another in the past, present and future, as one soul is shaped from a killer into a hero, and an act of kindness ripples across centuries to inspire a revolution.\",\n      \"rank\": 130,\n      \"running_time_secs\": 10320,\n      \"actors\": [\"Tom Hanks\", \"Halle Berry\", \"Hugh Grant\"]\n    }\n  },\n  {\n    \"year\": 2011,\n    \"title\": \"Harry Potter and the Deathly Hallows: Part 2\",\n    \"info\": {\n      \"directors\": [\"David Yates\"],\n      \"release_date\": \"2011-07-07T00:00:00Z\",\n      \"rating\": 8.1,\n      \"genres\": [\"Adventure\", \"Family\", \"Fantasy\", \"Mystery\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTY2MTk3MDQ1N15BMl5BanBnXkFtZTcwMzI4NzA2NQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Harry, Ron and Hermione search for Voldemort's remaining Horcruxes in their effort to destroy the Dark Lord.\",\n      \"rank\": 131,\n      \"running_time_secs\": 7800,\n      \"actors\": [\"Daniel Radcliffe\", \"Emma Watson\", \"Rupert Grint\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Empire State\",\n    \"info\": {\n      \"directors\": [\"Dito Montiel\"],\n      \"release_date\": \"2013-03-19T00:00:00Z\",\n      \"rating\": 5,\n      \"genres\": [\"Action\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjExOTY4MDEzNF5BMl5BanBnXkFtZTcwNzIyMTY3OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A drama centered on two childhood friends who plan to rob an armored car depository, and the NYPD officer who stands in their way.\",\n      \"rank\": 132,\n      \"running_time_secs\": 5640,\n      \"actors\": [\"Liam Hemsworth\", \"Michael Angarano\", \"Dwayne Johnson\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Frozen Ground\",\n    \"info\": {\n      \"directors\": [\"Scott Walker\"],\n      \"release_date\": \"2013-07-11T00:00:00Z\",\n      \"rating\": 6.2,\n      \"genres\": [\"Biography\", \"Crime\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjA0MjAyMjIxMl5BMl5BanBnXkFtZTcwNTQ1NDc2OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"An Alaska State Trooper partners with a young woman who escaped the clutches of serial killer Robert Hansen to bring the murderer to justice. Based on actual events.\",\n      \"rank\": 133,\n      \"running_time_secs\": 6300,\n      \"actors\": [\"Nicolas Cage\", \"Vanessa Hudgens\", \"John Cusack\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Wolf of Wall Street\",\n    \"info\": {\n      \"directors\": [\"Martin Scorsese\"],\n      \"release_date\": \"2013-11-14T00:00:00Z\",\n      \"genres\": [\"Biography\", \"Crime\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTQ5OTI2MTQ1MV5BMl5BanBnXkFtZTcwMjY0Njk2OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Based on the true story of Jordan Belfort, from his rise to a wealthy stockbroker living the high life to his fall involving crime, corruption and the federal government.\",\n      \"rank\": 134,\n      \"actors\": [\"Leonardo DiCaprio\", \"P.J. Byrne\", \"Jon Favreau\"]\n    }\n  },\n  {\n    \"year\": 2011,\n    \"title\": \"Thor\",\n    \"info\": {\n      \"directors\": [\"Kenneth Branagh\", \"Joss Whedon\"],\n      \"release_date\": \"2011-04-21T00:00:00Z\",\n      \"rating\": 7,\n      \"genres\": [\"Action\", \"Adventure\", \"Fantasy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTYxMjA5NDMzNV5BMl5BanBnXkFtZTcwOTk2Mjk3NA@@._V1_SX400_.jpg\",\n      \"plot\": \"The powerful but arrogant god Thor is cast out of Asgard to live amongst humans in Midgard (Earth), where he soon becomes one of their finest defenders.\",\n      \"rank\": 135,\n      \"running_time_secs\": 6900,\n      \"actors\": [\"Chris Hemsworth\", \"Anthony Hopkins\", \"Natalie Portman\"]\n    }\n  },\n  {\n    \"year\": 2010,\n    \"title\": \"I Spit on Your Grave\",\n    \"info\": {\n      \"directors\": [\"Steven R. Monroe\"],\n      \"release_date\": \"2010-05-01T00:00:00Z\",\n      \"rating\": 6.2,\n      \"genres\": [\"Crime\", \"Horror\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTkxMTE3NzEzMl5BMl5BanBnXkFtZTcwMzc4MTU2Mw@@._V1_SX400_.jpg\",\n      \"plot\": \"A writer who is brutalized during her cabin retreat seeks revenge on her attackers, who left her for dead.\",\n      \"rank\": 136,\n      \"running_time_secs\": 6480,\n      \"actors\": [\"Sarah Butler\", \"Jeff Branson\", \"Andrew Howard\"]\n    }\n  },\n  {\n    \"year\": 2004,\n    \"title\": \"The Notebook\",\n    \"info\": {\n      \"directors\": [\"Nick Cassavetes\"],\n      \"release_date\": \"2004-05-20T00:00:00Z\",\n      \"rating\": 7.9,\n      \"genres\": [\"Drama\", \"Romance\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTk3OTM5Njg5M15BMl5BanBnXkFtZTYwMzA0ODI3._V1_SX400_.jpg\",\n      \"plot\": \"A poor and passionate young man falls in love with a rich young woman and gives her a sense of freedom. They soon are separated by their social differences.\",\n      \"rank\": 137,\n      \"running_time_secs\": 7380,\n      \"actors\": [\"Gena Rowlands\", \"James Garner\", \"Rachel McAdams\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"Looper\",\n    \"info\": {\n      \"directors\": [\"Rian Johnson\"],\n      \"release_date\": \"2012-09-06T00:00:00Z\",\n      \"rating\": 7.5,\n      \"genres\": [\"Action\", \"Crime\", \"Sci-Fi\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTY3NTY0MjEwNV5BMl5BanBnXkFtZTcwNTE3NDA1OA@@._V1_SX400_.jpg\",\n      \"plot\": \"In 2074, when the mob wants to get rid of someone, the target is sent 30 years into the past, where a hired gun awaits. Someone like Joe, who one day learns the mob wants to 'close the loop' by transporting back Joe's future self.\",\n      \"rank\": 139,\n      \"running_time_secs\": 7140,\n      \"actors\": [\"Joseph Gordon-Levitt\", \"Bruce Willis\", \"Emily Blunt\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Spectacular Now\",\n    \"info\": {\n      \"directors\": [\"James Ponsoldt\"],\n      \"release_date\": \"2013-01-18T00:00:00Z\",\n      \"rating\": 7.7,\n      \"genres\": [\"Comedy\", \"Drama\", \"Romance\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjA5MTc0NTkzM15BMl5BanBnXkFtZTcwODEwNjE3OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A hard-partying high school senior's philosophy on life changes when he meets the not-so-typical \\\"nice girl.\\\"\",\n      \"rank\": 140,\n      \"running_time_secs\": 5700,\n      \"actors\": [\"Miles Teller\", \"Shailene Woodley\", \"Kyle Chandler\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Heat\",\n    \"info\": {\n      \"directors\": [\"Paul Feig\"],\n      \"release_date\": \"2013-06-27T00:00:00Z\",\n      \"rating\": 6.9,\n      \"genres\": [\"Action\", \"Comedy\", \"Crime\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BNDEwMTg2OTI5MF5BMl5BanBnXkFtZTcwNjgyNjkzOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"An uptight FBI Special Agent is paired with a foul-mouthed Boston cop to take down a ruthless drug lord.\",\n      \"rank\": 141,\n      \"running_time_secs\": 7020,\n      \"actors\": [\"Sandra Bullock\", \"Michael McDonald\", \"Melissa McCarthy\"]\n    }\n  },\n  {\n    \"year\": 2009,\n    \"title\": \"Inglourious Basterds\",\n    \"info\": {\n      \"directors\": [\"Quentin Tarantino\", \"Eli Roth\"],\n      \"release_date\": \"2009-05-20T00:00:00Z\",\n      \"rating\": 8.3,\n      \"genres\": [\"Adventure\", \"Drama\", \"War\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjIzMDI4MTUzOV5BMl5BanBnXkFtZTcwNDY3NjA3Mg@@._V1_SX400_.jpg\",\n      \"plot\": \"In Nazi-occupied France during World War II, a plan to assassinate Nazi leaders by a group of Jewish U.S. soldiers coincides with a theatre owner's vengeful plans for the same.\",\n      \"rank\": 142,\n      \"running_time_secs\": 9180,\n      \"actors\": [\"Brad Pitt\", \"Diane Kruger\", \"Eli Roth\"]\n    }\n  },\n  {\n    \"year\": 1972,\n    \"title\": \"The Godfather\",\n    \"info\": {\n      \"directors\": [\"Francis Ford Coppola\"],\n      \"release_date\": \"1972-03-15T00:00:00Z\",\n      \"rating\": 9.2,\n      \"genres\": [\"Crime\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjEyMjcyNDI4MF5BMl5BanBnXkFtZTcwMDA5Mzg3OA@@._V1_SX400_.jpg\",\n      \"plot\": \"The aging patriarch of an organized crime dynasty transfers control of his clandestine empire to his reluctant son.\",\n      \"rank\": 143,\n      \"running_time_secs\": 10500,\n      \"actors\": [\"Marlon Brando\", \"Al Pacino\", \"James Caan\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Filth\",\n    \"info\": {\n      \"directors\": [\"Jon S. Baird\"],\n      \"release_date\": \"2013-09-16T00:00:00Z\",\n      \"rating\": 7.2,\n      \"genres\": [\"Comedy\", \"Crime\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BODc3MjY5NTQxNl5BMl5BanBnXkFtZTcwNTQxMzczOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A bipolar, bigoted junkie cop manipulates and hallucinates his way through the festive season in a bid to secure promotion and win back his wife and daughter.\",\n      \"rank\": 144,\n      \"running_time_secs\": 5820,\n      \"actors\": [\"James McAvoy\", \"Imogen Poots\", \"Iain De Caestecker\"]\n    }\n  },\n  {\n    \"year\": 1999,\n    \"title\": \"Fight Club\",\n    \"info\": {\n      \"directors\": [\"David Fincher\"],\n      \"release_date\": \"1999-09-10T00:00:00Z\",\n      \"rating\": 8.8,\n      \"genres\": [\"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjIwNTYzMzE1M15BMl5BanBnXkFtZTcwOTE5Mzg3OA@@._V1_SX400_.jpg\",\n      \"plot\": \"An insomniac office worker looking for a way to change his life crosses paths with a devil-may-care soap maker and they form an underground fight club that evolves into something much, much more...\",\n      \"rank\": 145,\n      \"running_time_secs\": 8340,\n      \"actors\": [\"Brad Pitt\", \"Edward Norton\", \"Helena Bonham Carter\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Escape from Tomorrow\",\n    \"info\": {\n      \"directors\": [\"Randy Moore\"],\n      \"release_date\": \"2013-01-18T00:00:00Z\",\n      \"rating\": 5.9,\n      \"genres\": [\"Drama\", \"Fantasy\", \"Horror\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BNTIxNjcxOTgxM15BMl5BanBnXkFtZTgwMjYzODEzMDE@._V1_SX400_.jpg\",\n      \"plot\": \"In a world of fake castles and anthropomorphic rodents, an epic battle begins when an unemployed father's sanity is challenged by a chance encounter with two underage girls on holiday.\",\n      \"rank\": 146,\n      \"running_time_secs\": 5400,\n      \"actors\": [\"Roy Abramsohn\", \"Elena Schuber\", \"Katelynn Rodriguez\"]\n    }\n  },\n  {\n    \"year\": 1976,\n    \"title\": \"Carrie\",\n    \"info\": {\n      \"directors\": [\"Brian De Palma\"],\n      \"release_date\": \"1976-11-03T00:00:00Z\",\n      \"rating\": 7.4,\n      \"genres\": [\"Horror\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTg1NjEwOTUxN15BMl5BanBnXkFtZTcwOTI0MTU0NA@@._V1_SX400_.jpg\",\n      \"plot\": \"A young, abused and timid 17-year-old girl discovers she has telekinesis, and gets pushed to the limit on the night of her school's prom by a humiliating prank.\",\n      \"rank\": 147,\n      \"running_time_secs\": 5880,\n      \"actors\": [\"Sissy Spacek\", \"Piper Laurie\", \"Amy Irving\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Enough Said\",\n    \"info\": {\n      \"directors\": [\"Nicole Holofcener\"],\n      \"release_date\": \"2013-09-07T00:00:00Z\",\n      \"rating\": 7.5,\n      \"genres\": [\"Comedy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjI2MjIwMDk2Ml5BMl5BanBnXkFtZTcwNTQ1MzQ5OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A divorced woman who decides to pursue the man she's interested in learns he's her new friend's ex-husband.\",\n      \"rank\": 148,\n      \"running_time_secs\": 5580,\n      \"actors\": [\"Julia Louis-Dreyfus\", \"James Gandolfini\", \"Catherine Keener\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"Prometheus\",\n    \"info\": {\n      \"directors\": [\"Ridley Scott\"],\n      \"release_date\": \"2012-05-30T00:00:00Z\",\n      \"rating\": 7.1,\n      \"genres\": [\"Adventure\", \"Mystery\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTY3NzIyNTA2NV5BMl5BanBnXkFtZTcwNzE2NjI4Nw@@._V1_SX400_.jpg\",\n      \"plot\": \"A team of explorers discover a clue to the origins of mankind on Earth, leading them on a journey to the darkest corners of the universe. There, they must fight a terrifying battle to save the future of the human race.\",\n      \"rank\": 149,\n      \"running_time_secs\": 7440,\n      \"actors\": [\"Noomi Rapace\", \"Logan Marshall-Green\", \"Michael Fassbender\"]\n    }\n  },\n  {\n    \"year\": 2006,\n    \"title\": \"The Departed\",\n    \"info\": {\n      \"directors\": [\"Martin Scorsese\"],\n      \"release_date\": \"2006-09-26T00:00:00Z\",\n      \"rating\": 8.5,\n      \"genres\": [\"Crime\", \"Drama\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTI1MTY2OTIxNV5BMl5BanBnXkFtZTYwNjQ4NjY3._V1_SX400_.jpg\",\n      \"plot\": \"An undercover state cop who has infiltrated an Irish gang and a mole in the police force working for the same mob race to track down and identify each other before being exposed to the enemy, after both sides realize their outfit has a rat.\",\n      \"rank\": 150,\n      \"running_time_secs\": 9060,\n      \"actors\": [\"Leonardo DiCaprio\", \"Matt Damon\", \"Jack Nicholson\"]\n    }\n  },\n  {\n    \"year\": 1994,\n    \"title\": \"Dumb & Dumber\",\n    \"info\": {\n      \"directors\": [\"Peter Farrelly\", \"Bobby Farrelly\"],\n      \"release_date\": \"1994-12-06T00:00:00Z\",\n      \"rating\": 7.2,\n      \"genres\": [\"Comedy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTIzNDI5MTc0M15BMl5BanBnXkFtZTYwMjM5NDU5._V1_SX400_.jpg\",\n      \"plot\": \"The cross-country adventures of two good-hearted but incredibly stupid friends.\",\n      \"rank\": 151,\n      \"running_time_secs\": 6420,\n      \"actors\": [\"Jim Carrey\", \"Jeff Daniels\", \"Lauren Holly\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Romeo and Juliet\",\n    \"info\": {\n      \"directors\": [\"Carlo Carlei\"],\n      \"release_date\": \"2013-09-24T00:00:00Z\",\n      \"rating\": 5,\n      \"genres\": [\"Drama\", \"Romance\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTA3MjQwOTg4MTheQTJeQWpwZ15BbWU3MDM3NDE0OTk@._V1_SX400_.jpg\",\n      \"plot\": \"When the star-crossed lovers of two enemy families meet, forbidden love ensues.\",\n      \"rank\": 152,\n      \"running_time_secs\": 7080,\n      \"actors\": [\"Hailee Steinfeld\", \"Douglas Booth\", \"Damian Lewis\"]\n    }\n  },\n  {\n    \"year\": 2009,\n    \"title\": \"Cloudy with a Chance of Meatballs\",\n    \"info\": {\n      \"directors\": [\"Phil Lord\", \"Chris Miller\"],\n      \"release_date\": \"2009-09-16T00:00:00Z\",\n      \"rating\": 7,\n      \"genres\": [\"Animation\", \"Comedy\", \"Family\", \"Fantasy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTg0MjAwNDI5MV5BMl5BanBnXkFtZTcwODkyMzg2Mg@@._V1_SX400_.jpg\",\n      \"plot\": \"The most delicious event since macaroni met cheese. Inspired by the beloved children's book, the film focuses on a town where food falls from the sky like rain.\",\n      \"rank\": 153,\n      \"running_time_secs\": 5400,\n      \"actors\": [\"Anna Faris\", \"Bill Hader\", \"Bruce Campbell\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"CBGB\",\n    \"info\": {\n      \"directors\": [\"Randall Miller\"],\n      \"release_date\": \"2013-09-05T00:00:00Z\",\n      \"rating\": 6.3,\n      \"genres\": [\"Drama\", \"History\", \"Music\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTg1NDcxODY0OV5BMl5BanBnXkFtZTgwOTgwMzQxMDE@._V1_SX400_.jpg\",\n      \"plot\": \"A look at the New York City punk-rock scene and the venerable nightclub, CBGB.\",\n      \"rank\": 154,\n      \"actors\": [\"Malin Akerman\", \"Stana Katic\", \"Johnny Galecki\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Counselor\",\n    \"info\": {\n      \"directors\": [\"Ridley Scott\"],\n      \"release_date\": \"2013-10-25T00:00:00Z\",\n      \"genres\": [\"Crime\", \"Drama\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTc3ODk0MTY0N15BMl5BanBnXkFtZTgwOTU2MTEzMDE@._V1_SX400_.jpg\",\n      \"plot\": \"A lawyer finds himself in over his head when he gets involved in drug trafficking.\",\n      \"rank\": 155,\n      \"running_time_secs\": 6660,\n      \"actors\": [\"Brad Pitt\", \"Goran Visnjic\", \"Michael Fassbender\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Kill Your Darlings\",\n    \"info\": {\n      \"directors\": [\"John Krokidas\"],\n      \"release_date\": \"2013-01-18T00:00:00Z\",\n      \"rating\": 7.1,\n      \"genres\": [\"Biography\", \"Drama\", \"Romance\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjA4MzAxMTE1N15BMl5BanBnXkFtZTgwMDY2OTIxMDE@._V1_SX400_.jpg\",\n      \"plot\": \"A murder in 1944 draws together the great poets of the beat generation: Allen Ginsberg, Jack Kerouac and William Burroughs.\",\n      \"rank\": 156,\n      \"running_time_secs\": 6240,\n      \"actors\": [\"Michael C. Hall\", \"Elizabeth Olsen\", \"Daniel Radcliffe\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Only God Forgives\",\n    \"info\": {\n      \"directors\": [\"Nicolas Winding Refn\"],\n      \"release_date\": \"2013-05-22T00:00:00Z\",\n      \"rating\": 6,\n      \"genres\": [\"Crime\", \"Drama\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMzE5NzcxMTk5NF5BMl5BanBnXkFtZTcwNjE2MDg2OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Julian, a drug-smuggler thriving in Bangkok's criminal underworld, sees his life get even more complicated when his mother compels him to find and kill whoever is responsible for his brother's recent death.\",\n      \"rank\": 157,\n      \"running_time_secs\": 5400,\n      \"actors\": [\"Ryan Gosling\", \"Kristin Scott Thomas\", \"Vithaya Pansringarm\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Evil Dead\",\n    \"info\": {\n      \"directors\": [\"Fede Alvarez\"],\n      \"release_date\": \"2013-03-08T00:00:00Z\",\n      \"rating\": 6.5,\n      \"genres\": [\"Horror\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BNTQ3OTkwNTgyN15BMl5BanBnXkFtZTcwNTAzOTAzOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Five friends head to a remote cabin, where the discovery of a Book of the Dead leads them to unwittingly summon up demons living in the nearby woods. The evil presence possesses them until only one is left to fight for survival.\",\n      \"rank\": 158,\n      \"running_time_secs\": 5460,\n      \"actors\": [\"Jane Levy\", \"Shiloh Fernandez\", \"Jessica Lucas\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"Stuck in Love\",\n    \"info\": {\n      \"directors\": [\"Josh Boone\"],\n      \"release_date\": \"2012-09-09T00:00:00Z\",\n      \"rating\": 7,\n      \"genres\": [\"Comedy\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTU1NzI5MDU3OV5BMl5BanBnXkFtZTcwNTE0NDMzOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"An acclaimed writer, his ex-wife, and their teenaged children come to terms with the complexities of love in all its forms over the course of one tumultuous year.\",\n      \"rank\": 159,\n      \"running_time_secs\": 5820,\n      \"actors\": [\"Lily Collins\", \"Logan Lerman\", \"Kristen Bell\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Bad Grandpa\",\n    \"info\": {\n      \"directors\": [\"Jeff Tremaine\"],\n      \"release_date\": \"2013-10-23T00:00:00Z\",\n      \"genres\": [\"Comedy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTg4NjIwMTI5OV5BMl5BanBnXkFtZTgwNjU1MTMyMDE@._V1_SX400_.jpg\",\n      \"plot\": \"86-year-old Irving Zisman is on a journey across America with the most unlikely companion: his 8 year-old grandson, Billy.\",\n      \"rank\": 160,\n      \"actors\": [\"Johnny Knoxville\", \"Jackson Nicoll\", \"Spike Jonze\"]\n    }\n  },\n  {\n    \"year\": 2011,\n    \"title\": \"You're Next\",\n    \"info\": {\n      \"directors\": [\"Adam Wingard\"],\n      \"release_date\": \"2011-09-10T00:00:00Z\",\n      \"rating\": 6.9,\n      \"genres\": [\"Comedy\", \"Horror\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTQwODAxMTE1NF5BMl5BanBnXkFtZTcwNTQ0MjY3OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"When the Davison family comes under attack during their wedding anniversary getaway, the gang of mysterious killers soon learns that one of victims harbors a secret talent for fighting back.\",\n      \"rank\": 161,\n      \"running_time_secs\": 5640,\n      \"actors\": [\"Sharni Vinson\", \"Joe Swanberg\", \"AJ Bowen\"]\n    }\n  },\n  {\n    \"year\": 2011,\n    \"title\": \"Crazy, Stupid, Love.\",\n    \"info\": {\n      \"directors\": [\"Glenn Ficarra\", \"John Requa\"],\n      \"release_date\": \"2011-07-28T00:00:00Z\",\n      \"rating\": 7.4,\n      \"genres\": [\"Comedy\", \"Drama\", \"Romance\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTg2MjkwMTM0NF5BMl5BanBnXkFtZTcwMzc4NDg2NQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A middle-aged husband's life changes dramatically when his wife asks him for a divorce. He seeks to rediscover his manhood with the help of a newfound friend, Jacob, learning to pick up girls at bars.\",\n      \"rank\": 163,\n      \"running_time_secs\": 7080,\n      \"actors\": [\"Steve Carell\", \"Ryan Gosling\", \"Julianne Moore\"]\n    }\n  },\n  {\n    \"year\": 2006,\n    \"title\": \"300\",\n    \"info\": {\n      \"directors\": [\"Zack Snyder\"],\n      \"release_date\": \"2006-12-09T00:00:00Z\",\n      \"rating\": 7.7,\n      \"genres\": [\"Action\", \"Fantasy\", \"History\", \"War\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjAzNTkzNjcxNl5BMl5BanBnXkFtZTYwNDA4NjE3._V1_SX400_.jpg\",\n      \"plot\": \"King Leonidas and a force of 300 men fight the Persians at Thermopylae in 480 B.C.\",\n      \"rank\": 164,\n      \"running_time_secs\": 7020,\n      \"actors\": [\"Gerard Butler\", \"Lena Headey\", \"David Wenham\"]\n    }\n  },\n  {\n    \"year\": 2011,\n    \"title\": \"Conan the Barbarian\",\n    \"info\": {\n      \"directors\": [\"Marcus Nispel\"],\n      \"release_date\": \"2011-08-11T00:00:00Z\",\n      \"rating\": 5.1,\n      \"genres\": [\"Action\", \"Adventure\", \"Fantasy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTQ1NDUyODk5NF5BMl5BanBnXkFtZTcwODk0MjIwNg@@._V1_SX400_.jpg\",\n      \"plot\": \"An vengeful barbarian warrior sets off to get his revenge on the evil warlord who attacked his village and murdered his father when he was a boy.\",\n      \"rank\": 165,\n      \"running_time_secs\": 6780,\n      \"actors\": [\"Jason Momoa\", \"Ron Perlman\", \"Rose McGowan\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Scenic Route\",\n    \"info\": {\n      \"directors\": [\"Kevin Goetz\", \"Michael Goetz\"],\n      \"release_date\": \"2013-03-09T00:00:00Z\",\n      \"rating\": 6.3,\n      \"genres\": [\"Drama\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjAyNjIyOTU0M15BMl5BanBnXkFtZTcwNTUwOTI2OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Tensions rise between lifelong friends Mitchell and Carter after their truck breaks down on an isolated desert road as they start to attack each other's life decisions with unwavering brutality.\",\n      \"rank\": 166,\n      \"actors\": [\"Josh Duhamel\", \"Dan Fogler\", \"Miracle Laurie\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"Zero Dark Thirty\",\n    \"info\": {\n      \"directors\": [\"Kathryn Bigelow\"],\n      \"release_date\": \"2012-12-19T00:00:00Z\",\n      \"rating\": 7.4,\n      \"genres\": [\"Drama\", \"History\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTQ4OTUyNzcwN15BMl5BanBnXkFtZTcwMTQ1NDE3OA@@._V1_SX400_.jpg\",\n      \"plot\": \"A chronicle of the decade-long hunt for al-Qaeda terrorist leader [link=nm1136915] after the September 2001 attacks, and his death at the hands of the Navy S.E.A.L. Team 6 in May 2011.\",\n      \"rank\": 167,\n      \"running_time_secs\": 9420,\n      \"actors\": [\"Jessica Chastain\", \"Joel Edgerton\", \"Chris Pratt\"]\n    }\n  },\n  {\n    \"year\": 2011,\n    \"title\": \"The Awakening\",\n    \"info\": {\n      \"directors\": [\"Nick Murphy\"],\n      \"release_date\": \"2011-09-16T00:00:00Z\",\n      \"rating\": 6.4,\n      \"genres\": [\"Horror\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMzk0ODc1NDMxOV5BMl5BanBnXkFtZTcwNTAzMzgwOA@@._V1_SX400_.jpg\",\n      \"plot\": \"In 1921, England is overwhelmed by the loss and grief of World War I. Hoax exposer Florence Cathcart visits a boarding school to explain sightings of a child ghost. Everything she believes unravels as the 'missing' begin to show themselves.\",\n      \"rank\": 169,\n      \"running_time_secs\": 6420,\n      \"actors\": [\"Rebecca Hall\", \"Dominic West\", \"Imelda Staunton\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"The Twilight Saga: Breaking Dawn - Part 2\",\n    \"info\": {\n      \"directors\": [\"Bill Condon\"],\n      \"release_date\": \"2012-11-14T00:00:00Z\",\n      \"rating\": 5.5,\n      \"genres\": [\"Adventure\", \"Drama\", \"Fantasy\", \"Romance\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTcyMzUyMzY1OF5BMl5BanBnXkFtZTcwNDQ4ODk1OA@@._V1_SX400_.jpg\",\n      \"plot\": \"After the birth of Renesmee, the Cullens gather other vampire clans in order to protect the child from a false allegation that puts the family in front of the Volturi.\",\n      \"rank\": 170,\n      \"running_time_secs\": 6900,\n      \"actors\": [\"Kristen Stewart\", \"Robert Pattinson\", \"Taylor Lautner\"]\n    }\n  },\n  {\n    \"year\": 2008,\n    \"title\": \"Iron Man\",\n    \"info\": {\n      \"directors\": [\"Jon Favreau\"],\n      \"release_date\": \"2008-04-14T00:00:00Z\",\n      \"rating\": 7.9,\n      \"genres\": [\"Action\", \"Adventure\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTczNTI2ODUwOF5BMl5BanBnXkFtZTcwMTU0NTIzMw@@._V1_SX400_.jpg\",\n      \"plot\": \"When wealthy industrialist Tony Stark is forced to build an armored suit after a life-threatening incident, he ultimately decides to use its technology to fight against evil.\",\n      \"rank\": 171,\n      \"running_time_secs\": 7560,\n      \"actors\": [\"Robert Downey Jr.\", \"Gwyneth Paltrow\", \"Terrence Howard\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Oz the Great and Powerful\",\n    \"info\": {\n      \"directors\": [\"Sam Raimi\"],\n      \"release_date\": \"2013-02-14T00:00:00Z\",\n      \"rating\": 6.5,\n      \"genres\": [\"Adventure\", \"Family\", \"Fantasy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjMyMzQ1ODM1MF5BMl5BanBnXkFtZTcwMjE2MTQxOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A small-time magician is swept away to an enchanted land and is forced into a power struggle between three witches.\",\n      \"rank\": 172,\n      \"running_time_secs\": 7800,\n      \"actors\": [\"James Franco\", \"Michelle Williams\", \"Rachel Weisz\"]\n    }\n  },\n  {\n    \"year\": 2010,\n    \"title\": \"Despicable Me\",\n    \"info\": {\n      \"directors\": [\"Pierre Coffin\", \"Chris Renaud\"],\n      \"release_date\": \"2010-06-20T00:00:00Z\",\n      \"rating\": 7.6,\n      \"genres\": [\"Animation\", \"Comedy\", \"Crime\", \"Family\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTY3NjY0MTQ0Nl5BMl5BanBnXkFtZTcwMzQ2MTc0Mw@@._V1_SX400_.jpg\",\n      \"plot\": \"When a criminal mastermind uses a trio of orphan girls as pawns for a grand scheme, he finds their love is profoundly changing him for the better.\",\n      \"rank\": 173,\n      \"running_time_secs\": 5700,\n      \"actors\": [\"Steve Carell\", \"Jason Segel\", \"Russell Brand\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Movie 43\",\n    \"info\": {\n      \"directors\": [\"Elizabeth Banks\", \"Steven Brill\", \"Steve Carr\"],\n      \"release_date\": \"2013-01-01T00:00:00Z\",\n      \"rating\": 4.4,\n      \"genres\": [\"Comedy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTg4NzQ3NDM1Nl5BMl5BanBnXkFtZTcwNjEzMjM3OA@@._V1_SX400_.jpg\",\n      \"plot\": \"A series of interconnected short films follows a washed-up producer as he pitches insane story lines featuring some of the biggest stars in Hollywood.\",\n      \"rank\": 174,\n      \"running_time_secs\": 5640,\n      \"actors\": [\"Emma Stone\", \"Stephen Merchant\", \"Richard Gere\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Warm Bodies\",\n    \"info\": {\n      \"directors\": [\"Jonathan Levine\"],\n      \"release_date\": \"2013-01-16T00:00:00Z\",\n      \"rating\": 6.9,\n      \"genres\": [\"Comedy\", \"Horror\", \"Romance\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTQ4MjY2MjMzOV5BMl5BanBnXkFtZTcwMDUxNzIwOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"After a highly unusual zombie saves a still-living girl from an attack, the two form a relationship that sets in motion events that might transform the entire lifeless world.\",\n      \"rank\": 175,\n      \"running_time_secs\": 5880,\n      \"actors\": [\"Nicholas Hoult\", \"Teresa Palmer\", \"John Malkovich\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"Flight\",\n    \"info\": {\n      \"directors\": [\"Robert Zemeckis\"],\n      \"release_date\": \"2012-10-14T00:00:00Z\",\n      \"rating\": 7.3,\n      \"genres\": [\"Drama\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTUxMjI1OTMxNl5BMl5BanBnXkFtZTcwNjc3NTY1OA@@._V1_SX400_.jpg\",\n      \"plot\": \"An airline pilot saves almost all his passengers on his malfunctioning airliner which eventually crashed, but an investigation into the accident reveals something troubling.\",\n      \"rank\": 176,\n      \"running_time_secs\": 8280,\n      \"actors\": [\"Denzel Washington\", \"Nadine Velazquez\", \"Don Cheadle\"]\n    }\n  },\n  {\n    \"year\": 2014,\n    \"title\": \"I, Frankenstein\",\n    \"info\": {\n      \"directors\": [\"Stuart Beattie\"],\n      \"release_date\": \"2014-01-22T00:00:00Z\",\n      \"genres\": [\"Action\", \"Fantasy\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTQzNDA3MjQwMl5BMl5BanBnXkFtZTcwNTgyNTc4OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Frankenstein's creature finds himself caught in an all-out, centuries old war between two immortal clans.\",\n      \"rank\": 177,\n      \"actors\": [\"Aaron Eckhart\", \"Bill Nighy\", \"Miranda Otto\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"G.I. Joe: Retaliation\",\n    \"info\": {\n      \"directors\": [\"Jon M. Chu\"],\n      \"release_date\": \"2013-03-11T00:00:00Z\",\n      \"rating\": 5.8,\n      \"genres\": [\"Action\", \"Adventure\", \"Sci-Fi\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BNzk5ODM0OTQ0N15BMl5BanBnXkFtZTcwODg2ODE4OA@@._V1_SX400_.jpg\",\n      \"plot\": \"The G.I. Joes are not only fighting their mortal enemy Cobra; they are forced to contend with threats from within the government that jeopardize their very existence.\",\n      \"rank\": 178,\n      \"running_time_secs\": 6600,\n      \"actors\": [\"Dwayne Johnson\", \"Channing Tatum\", \"Adrianne Palicki\"]\n    }\n  },\n  {\n    \"year\": 2014,\n    \"title\": \"300: Rise of an Empire\",\n    \"info\": {\n      \"directors\": [\"Noam Murro\"],\n      \"release_date\": \"2014-03-05T00:00:00Z\",\n      \"genres\": [\"Action\", \"Drama\", \"War\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTEwNTU2MjAwMDdeQTJeQWpwZ15BbWU3MDk2Njc2Njk@._V1_SX400_.jpg\",\n      \"plot\": \"The Greek general Themistocles battles an invading army of Persians under the mortal-turned-god, Xerxes.\",\n      \"rank\": 179,\n      \"actors\": [\"Sullivan Stapleton\", \"Rodrigo Santoro\", \"Eva Green\"]\n    }\n  },\n  {\n    \"year\": 2001,\n    \"title\": \"The Lord of the Rings: The Fellowship of the Ring\",\n    \"info\": {\n      \"directors\": [\"Peter Jackson\"],\n      \"release_date\": \"2001-12-10T00:00:00Z\",\n      \"rating\": 8.8,\n      \"genres\": [\"Action\", \"Adventure\", \"Fantasy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BNTEyMjAwMDU1OV5BMl5BanBnXkFtZTcwNDQyNTkxMw@@._V1_SX400_.jpg\",\n      \"plot\": \"A meek hobbit of The Shire and eight companions set out on a journey to Mount Doom to destroy the One Ring and the dark lord Sauron.\",\n      \"rank\": 180,\n      \"running_time_secs\": 10680,\n      \"actors\": [\"Elijah Wood\", \"Ian McKellen\", \"Orlando Bloom\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Red 2\",\n    \"info\": {\n      \"directors\": [\"Dean Parisot\"],\n      \"release_date\": \"2013-07-18T00:00:00Z\",\n      \"rating\": 7,\n      \"genres\": [\"Action\", \"Comedy\", \"Crime\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjI2ODQ4ODY3Nl5BMl5BanBnXkFtZTcwNTc2NzE1OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Retired C.I.A. agent Frank Moses reunites his unlikely team of elite operatives for a global quest to track down a missing portable nuclear device.\",\n      \"rank\": 181,\n      \"running_time_secs\": 6960,\n      \"actors\": [\"Bruce Willis\", \"Helen Mirren\", \"John Malkovich\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Anchorman 2: The Legend Continues\",\n    \"info\": {\n      \"directors\": [\"Adam McKay\"],\n      \"release_date\": \"2013-12-19T00:00:00Z\",\n      \"genres\": [\"Comedy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTM5NTY0NTUzOV5BMl5BanBnXkFtZTcwMDY2MzA3OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"With the 70s behind him, San Diego's top rated newsman, Ron Burgundy, returns to take New York's first 24-hour news channel by storm.\",\n      \"rank\": 182,\n      \"actors\": [\"Will Ferrell\", \"Christina Applegate\", \"Paul Rudd\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"Dredd\",\n    \"info\": {\n      \"directors\": [\"Pete Travis\"],\n      \"release_date\": \"2012-07-11T00:00:00Z\",\n      \"rating\": 7,\n      \"genres\": [\"Action\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BODkyNDQzMzUzOF5BMl5BanBnXkFtZTcwODYyMDEyOA@@._V1_SX400_.jpg\",\n      \"plot\": \"In a violent, futuristic city where the police have the authority to act as judge, jury and executioner, a cop teams with a trainee to take down a gang that deals the reality-altering drug, SLO-MO.\",\n      \"rank\": 183,\n      \"running_time_secs\": 5700,\n      \"actors\": [\"Karl Urban\", \"Olivia Thirlby\", \"Lena Headey\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Smurfs 2\",\n    \"info\": {\n      \"directors\": [\"Raja Gosnell\"],\n      \"release_date\": \"2013-07-28T00:00:00Z\",\n      \"rating\": 4.9,\n      \"genres\": [\"Animation\", \"Comedy\", \"Family\", \"Fantasy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTkyNDUxODg3MV5BMl5BanBnXkFtZTcwNjE5OTY2OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"The Smurfs team up with their human friends to rescue Smurfette, who has been kidnapped by Gargamel since she knows a secret spell that can turn the evil sorcerer's newest creation - creatures called the Naughties - into real Smurfs.\",\n      \"rank\": 184,\n      \"running_time_secs\": 6300,\n      \"actors\": [\"Neil Patrick Harris\", \"Jayma Mays\", \"Katy Perry\"]\n    }\n  },\n  {\n    \"year\": 2001,\n    \"title\": \"Harry Potter and the Sorcerer's Stone\",\n    \"info\": {\n      \"directors\": [\"Chris Columbus\"],\n      \"release_date\": \"2001-11-04T00:00:00Z\",\n      \"rating\": 7.3,\n      \"genres\": [\"Adventure\", \"Family\", \"Fantasy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTYwNTM5NDkzNV5BMl5BanBnXkFtZTYwODQ4MzY5._V1_SX400_.jpg\",\n      \"plot\": \"Rescued from the outrageous neglect of his aunt and uncle, a young boy with a great destiny proves his worth while attending Hogwarts School of Witchcraft and Wizardry.\",\n      \"rank\": 185,\n      \"running_time_secs\": 9120,\n      \"actors\": [\"Daniel Radcliffe\", \"Rupert Grint\", \"Richard Harris\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"21 Jump Street\",\n    \"info\": {\n      \"directors\": [\"Phil Lord\", \"Chris Miller\"],\n      \"release_date\": \"2012-03-12T00:00:00Z\",\n      \"rating\": 7.1,\n      \"genres\": [\"Action\", \"Comedy\", \"Crime\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTc3NzQ3OTg3NF5BMl5BanBnXkFtZTcwMjk5OTcxNw@@._V1_SX400_.jpg\",\n      \"plot\": \"A pair of underachieving cops are sent back to a local high school to blend in and bring down a synthetic drug ring.\",\n      \"rank\": 186,\n      \"running_time_secs\": 6540,\n      \"actors\": [\"Jonah Hill\", \"Channing Tatum\", \"Ice Cube\"]\n    }\n  },\n  {\n    \"year\": 1980,\n    \"title\": \"The Shining\",\n    \"info\": {\n      \"directors\": [\"Stanley Kubrick\"],\n      \"release_date\": \"1980-05-23T00:00:00Z\",\n      \"rating\": 8.5,\n      \"genres\": [\"Horror\", \"Mystery\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BODMxMjE3NTA4Ml5BMl5BanBnXkFtZTgwNDc0NTIxMDE@._V1_SX400_.jpg\",\n      \"plot\": \"A family heads to an isolated hotel for the winter where an evil and spiritual presence influences the father into violence, while his psychic son sees horrific forebodings from the past and of the future.\",\n      \"rank\": 187,\n      \"running_time_secs\": 8760,\n      \"actors\": [\"Jack Nicholson\", \"Shelley Duvall\", \"Danny Lloyd\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"The Cabin in the Woods\",\n    \"info\": {\n      \"directors\": [\"Drew Goddard\"],\n      \"release_date\": \"2012-03-09T00:00:00Z\",\n      \"rating\": 7.1,\n      \"genres\": [\"Horror\", \"Mystery\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BNTUxNzYyMjg2N15BMl5BanBnXkFtZTcwMTExNzExNw@@._V1_SX400_.jpg\",\n      \"plot\": \"Five friends go for a break at a remote cabin in the woods, where they get more than they bargained for. Together, they must discover the truth behind the cabin in the woods.\",\n      \"rank\": 188,\n      \"running_time_secs\": 5700,\n      \"actors\": [\"Kristen Connolly\", \"Chris Hemsworth\", \"Anna Hutchison\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Turbo\",\n    \"info\": {\n      \"directors\": [\"David Soren\"],\n      \"release_date\": \"2013-07-17T00:00:00Z\",\n      \"rating\": 6.3,\n      \"genres\": [\"Animation\", \"Adventure\", \"Comedy\", \"Family\", \"Sport\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTA4NTgwMjM5MzheQTJeQWpwZ15BbWU3MDg2ODA1ODk@._V1_SX400_.jpg\",\n      \"plot\": \"A freak accident might just help an everyday garden snail achieve his biggest dream: winning the Indy 500.\",\n      \"rank\": 189,\n      \"running_time_secs\": 5760,\n      \"actors\": [\"Ryan Reynolds\", \"Paul Giamatti\", \"Maya Rudolph\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Lone Ranger\",\n    \"info\": {\n      \"directors\": [\"Gore Verbinski\"],\n      \"release_date\": \"2013-06-22T00:00:00Z\",\n      \"rating\": 6.6,\n      \"genres\": [\"Action\", \"Adventure\", \"Western\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjI3Mjk5MTUxOV5BMl5BanBnXkFtZTcwNTMyNzY3OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Native American warrior Tonto recounts the untold tales that transformed John Reid, a man of the law, into a legend of justice.\",\n      \"rank\": 190,\n      \"running_time_secs\": 8940,\n      \"actors\": [\"Johnny Depp\", \"Armie Hammer\", \"William Fichtner\"]\n    }\n  },\n  {\n    \"year\": 2011,\n    \"title\": \"Moneyball\",\n    \"info\": {\n      \"directors\": [\"Bennett Miller\"],\n      \"release_date\": \"2011-09-09T00:00:00Z\",\n      \"rating\": 7.6,\n      \"genres\": [\"Biography\", \"Drama\", \"Sport\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjAxOTU3Mzc1M15BMl5BanBnXkFtZTcwMzk1ODUzNg@@._V1_SX400_.jpg\",\n      \"plot\": \"Oakland A's general manager Billy Beane's successful attempt to assemble a baseball team on a lean budget by employing computer-generated analysis to acquire new players.\",\n      \"rank\": 193,\n      \"running_time_secs\": 7980,\n      \"actors\": [\"Brad Pitt\", \"Robin Wright\", \"Jonah Hill\"]\n    }\n  },\n  {\n    \"year\": 2001,\n    \"title\": \"Donnie Darko\",\n    \"info\": {\n      \"directors\": [\"Richard Kelly\"],\n      \"release_date\": \"2001-01-19T00:00:00Z\",\n      \"rating\": 8.1,\n      \"genres\": [\"Drama\", \"Mystery\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTczMzE4Nzk3N15BMl5BanBnXkFtZTcwNDg5Mjc4NA@@._V1_SX400_.jpg\",\n      \"plot\": \"A troubled teenager is plagued by visions of a large bunny rabbit that manipulates him to commit a series of crimes, after narrowly escaping a bizarre accident.\",\n      \"rank\": 194,\n      \"running_time_secs\": 6780,\n      \"actors\": [\"Jake Gyllenhaal\", \"Jena Malone\", \"Mary McDonnell\"]\n    }\n  },\n  {\n    \"year\": 2011,\n    \"title\": \"Drive\",\n    \"info\": {\n      \"directors\": [\"Nicolas Winding Refn\"],\n      \"release_date\": \"2011-05-20T00:00:00Z\",\n      \"rating\": 7.9,\n      \"genres\": [\"Crime\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BOTM1ODQ0Nzc4NF5BMl5BanBnXkFtZTcwMTM0MjQyNg@@._V1_SX400_.jpg\",\n      \"plot\": \"A mysterious Hollywood stuntman, mechanic and getaway driver lands himself in trouble when he helps out his neighbor.\",\n      \"rank\": 195,\n      \"running_time_secs\": 6000,\n      \"actors\": [\"Ryan Gosling\", \"Carey Mulligan\", \"Bryan Cranston\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Internship\",\n    \"info\": {\n      \"directors\": [\"Shawn Levy\"],\n      \"release_date\": \"2013-06-05T00:00:00Z\",\n      \"rating\": 6.3,\n      \"genres\": [\"Comedy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjM1MzczMDgwOV5BMl5BanBnXkFtZTcwMDM4NjM2OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Two salesmen whose careers have been torpedoed by the digital age find their way into a coveted internship at Google, where they must compete with a group of young, tech-savvy geniuses for a shot at employment.\",\n      \"rank\": 196,\n      \"running_time_secs\": 7140,\n      \"actors\": [\"Vince Vaughn\", \"Owen Wilson\", \"Rose Byrne\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"Skyfall\",\n    \"info\": {\n      \"directors\": [\"Sam Mendes\"],\n      \"release_date\": \"2012-10-23T00:00:00Z\",\n      \"rating\": 7.8,\n      \"genres\": [\"Action\", \"Adventure\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjM1MzMzOTA3MV5BMl5BanBnXkFtZTcwOTE3NzA1OA@@._V1_SX400_.jpg\",\n      \"plot\": \"Bond's loyalty to M is tested when her past comes back to haunt her. Whilst MI6 comes under attack, 007 must track down and destroy the threat, no matter how personal the cost.\",\n      \"rank\": 197,\n      \"running_time_secs\": 8580,\n      \"actors\": [\"Daniel Craig\", \"Javier Bardem\", \"Naomie Harris\"]\n    }\n  },\n  {\n    \"year\": 2004,\n    \"title\": \"Mean Girls\",\n    \"info\": {\n      \"directors\": [\"Mark Waters\"],\n      \"release_date\": \"2004-04-19T00:00:00Z\",\n      \"rating\": 6.8,\n      \"genres\": [\"Comedy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjE1MDQ4MjI1OV5BMl5BanBnXkFtZTcwNzcwODAzMw@@._V1_SX400_.jpg\",\n      \"plot\": \"Cady Heron is a hit with The Plastics, the A-list girl clique at her new school, until she makes the mistake of falling for Aaron Samuels, the ex-boyfriend of alpha Plastic Regina George.\",\n      \"rank\": 198,\n      \"running_time_secs\": 5820,\n      \"actors\": [\"Lindsay Lohan\", \"Jonathan Bennett\", \"Rachel McAdams\"]\n    }\n  },\n  {\n    \"year\": 2006,\n    \"title\": \"The Prestige\",\n    \"info\": {\n      \"directors\": [\"Christopher Nolan\"],\n      \"release_date\": \"2006-10-17T00:00:00Z\",\n      \"rating\": 8.4,\n      \"genres\": [\"Drama\", \"Mystery\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjA4NDI0MTIxNF5BMl5BanBnXkFtZTYwNTM0MzY2._V1_SX400_.jpg\",\n      \"plot\": \"The rivalry between two magicians becomes more exacerbated by their attempt to perform the ultimate illusion.\",\n      \"rank\": 199,\n      \"running_time_secs\": 7800,\n      \"actors\": [\"Christian Bale\", \"Hugh Jackman\", \"Scarlett Johansson\"]\n    }\n  },\n  {\n    \"year\": 2011,\n    \"title\": \"Intouchables\",\n    \"info\": {\n      \"directors\": [\"Olivier Nakache\", \"Eric Toledano\"],\n      \"release_date\": \"2011-09-23T00:00:00Z\",\n      \"rating\": 8.5,\n      \"genres\": [\"Biography\", \"Comedy\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTYxNDA3MDQwNl5BMl5BanBnXkFtZTcwNTU4Mzc1Nw@@._V1_SX400_.jpg\",\n      \"plot\": \"After he becomes a quadriplegic from a paragliding accident, an aristocrat hires a young man from the projects to be his caretaker.\",\n      \"rank\": 200,\n      \"running_time_secs\": 6720,\n      \"actors\": [\"Francois Cluzet\", \"Omar Sy\", \"Anne Le Ny\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Nebraska\",\n    \"info\": {\n      \"directors\": [\"Alexander Payne\"],\n      \"release_date\": \"2013-05-23T00:00:00Z\",\n      \"rating\": 7.5,\n      \"genres\": [\"Adventure\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTU2Mjk2NDkyMl5BMl5BanBnXkFtZTgwNTk0NzcyMDE@._V1_SX400_.jpg\",\n      \"plot\": \"An aging, booze-addled father makes the trip from Montana to Nebraska with his estranged son in order to claim a million dollar Mega Sweepstakes Marketing prize.\",\n      \"rank\": 201,\n      \"running_time_secs\": 6900,\n      \"actors\": [\"Bruce Dern\", \"Will Forte\", \"June Squibb\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Zero Charisma\",\n    \"info\": {\n      \"directors\": [\"Katie Graham\", \"Andrew Matthews\"],\n      \"release_date\": \"2013-04-25T00:00:00Z\",\n      \"rating\": 6.2,\n      \"genres\": [\"Comedy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTQ3MDU4MTI3NV5BMl5BanBnXkFtZTgwMzg5NDYyMDE@._V1_SX400_.jpg\",\n      \"plot\": \"An overgrown nerd who serves as Grand Master of a fantasy board game finds his role as leader of the misfits put into jeopardy when a new initiate enters the group.\",\n      \"rank\": 202,\n      \"running_time_secs\": 5160,\n      \"actors\": [\"Sam Eidson\", \"Anne Gee Byrd\", \"Brock England\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"American Hustle\",\n    \"info\": {\n      \"directors\": [\"David O. Russell\"],\n      \"release_date\": \"2013-12-13T00:00:00Z\",\n      \"genres\": [\"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjkyNDY3Mzg2Ml5BMl5BanBnXkFtZTgwMzU0OTYzMDE@._V1_SX400_.jpg\",\n      \"plot\": \"The story of a con artist and his partner in crime, who were forced to work with a federal agent to turn the tables on other cons, mobsters, and politicians - namely, the volatile mayor of impoverished Camden, New Jersey.\",\n      \"rank\": 203,\n      \"actors\": [\"Christian Bale\", \"Amy Adams\", \"Bradley Cooper\"]\n    }\n  },\n  {\n    \"year\": 1985,\n    \"title\": \"Back to the Future\",\n    \"info\": {\n      \"directors\": [\"Robert Zemeckis\"],\n      \"release_date\": \"1985-07-03T00:00:00Z\",\n      \"rating\": 8.5,\n      \"genres\": [\"Adventure\", \"Comedy\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTk4OTQ1OTMwN15BMl5BanBnXkFtZTcwOTIwMzM3MQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A teenager is accidentally sent 30 years into the past in a time-traveling DeLorean invented by his friend, Dr. Emmett Brown, and must make sure his high-school-age parents unite in order to save his own existence.\",\n      \"rank\": 204,\n      \"running_time_secs\": 6960,\n      \"actors\": [\"Michael J. Fox\", \"Christopher Lloyd\", \"Lea Thompson\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Adore\",\n    \"info\": {\n      \"directors\": [\"Anne Fontaine\"],\n      \"release_date\": \"2013-01-18T00:00:00Z\",\n      \"rating\": 6.1,\n      \"genres\": [\"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjg5ODY2MzcwMF5BMl5BanBnXkFtZTcwODEwNjQ3OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A pair of childhood friends and neighbors fall for each other's sons.\",\n      \"rank\": 205,\n      \"running_time_secs\": 6000,\n      \"actors\": [\"Naomi Watts\", \"Robin Wright\", \"Xavier Samuel\"]\n    }\n  },\n  {\n    \"year\": 2000,\n    \"title\": \"Requiem for a Dream\",\n    \"info\": {\n      \"directors\": [\"Darren Aronofsky\"],\n      \"release_date\": \"2000-05-14T00:00:00Z\",\n      \"rating\": 8.4,\n      \"genres\": [\"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMzM2OTYwMTY4Nl5BMl5BanBnXkFtZTcwMjU1Njg3OA@@._V1_SX400_.jpg\",\n      \"plot\": \"The drug-induced utopias of four Coney Island individuals are shattered when their addictions become stronger.\",\n      \"rank\": 206,\n      \"running_time_secs\": 6120,\n      \"actors\": [\"Ellen Burstyn\", \"Jared Leto\", \"Jennifer Connelly\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Monsters University\",\n    \"info\": {\n      \"directors\": [\"Dan Scanlon\"],\n      \"release_date\": \"2013-06-08T00:00:00Z\",\n      \"rating\": 7.6,\n      \"genres\": [\"Animation\", \"Adventure\", \"Comedy\", \"Family\", \"Fantasy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTUyODgwMDU3M15BMl5BanBnXkFtZTcwOTM4MjcxOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A look at the relationship between Mike and Sulley during their days at Monsters University -- when they weren't necessarily the best of friends.\",\n      \"rank\": 207,\n      \"running_time_secs\": 6240,\n      \"actors\": [\"Billy Crystal\", \"John Goodman\", \"Steve Buscemi\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Parkland\",\n    \"info\": {\n      \"directors\": [\"Peter Landesman\"],\n      \"release_date\": \"2013-09-01T00:00:00Z\",\n      \"rating\": 5.6,\n      \"genres\": [\"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjE2NjkwNDE2MF5BMl5BanBnXkFtZTgwNDY5ODIxMDE@._V1_SX400_.jpg\",\n      \"plot\": \"A recounting of the chaotic events that occurred at Dallas' Parkland Hospital on the day U.S. President John F. Kennedy was assassinated.\",\n      \"rank\": 208,\n      \"running_time_secs\": 5580,\n      \"actors\": [\"Zac Efron\", \"Tom Welling\", \"Billy Bob Thornton\"]\n    }\n  },\n  {\n    \"year\": 2010,\n    \"title\": \"She's Out of My League\",\n    \"info\": {\n      \"directors\": [\"Jim Field Smith\"],\n      \"release_date\": \"2010-03-11T00:00:00Z\",\n      \"rating\": 6.4,\n      \"genres\": [\"Comedy\", \"Romance\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTkwMTY5ODA1MF5BMl5BanBnXkFtZTcwODYyNzAxMw@@._V1_SX400_.jpg\",\n      \"plot\": \"An average Joe meets the perfect woman, but his lack of confidence and the influence of his friends and family begin to pick away at the relationship.\",\n      \"rank\": 209,\n      \"running_time_secs\": 6240,\n      \"actors\": [\"Jay Baruchel\", \"Alice Eve\", \"T.J. Miller\"]\n    }\n  },\n  {\n    \"year\": 1999,\n    \"title\": \"American Beauty\",\n    \"info\": {\n      \"directors\": [\"Sam Mendes\"],\n      \"release_date\": \"1999-09-08T00:00:00Z\",\n      \"rating\": 8.5,\n      \"genres\": [\"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BOTU1MzExMDg3N15BMl5BanBnXkFtZTcwODExNDg3OA@@._V1_SX400_.jpg\",\n      \"plot\": \"Lester Burnham, a depressed suburban father in a mid-life crisis, decides to turn his hectic life around after developing an infatuation for his daughter's attractive friend.\",\n      \"rank\": 210,\n      \"running_time_secs\": 7320,\n      \"actors\": [\"Kevin Spacey\", \"Annette Bening\", \"Thora Birch\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Homefront\",\n    \"info\": {\n      \"directors\": [\"Gary Fleder\"],\n      \"release_date\": \"2013-11-27T00:00:00Z\",\n      \"genres\": [\"Action\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTUwOTAzNzAwMl5BMl5BanBnXkFtZTgwOTc1NDIyMDE@._V1_SX400_.jpg\",\n      \"plot\": \"A former DEA agent moves his family to a quiet town, where he soon tangles with a local meth druglord.\",\n      \"rank\": 211,\n      \"actors\": [\"James Franco\", \"Jason Statham\", \"Rachelle Lefevre\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"Magic Mike\",\n    \"info\": {\n      \"directors\": [\"Steven Soderbergh\"],\n      \"release_date\": \"2012-06-24T00:00:00Z\",\n      \"rating\": 6.1,\n      \"genres\": [\"Comedy\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTQzMDMzOTA5M15BMl5BanBnXkFtZTcwMjc4MTg4Nw@@._V1_SX400_.jpg\",\n      \"plot\": \"A male stripper teaches a younger performer how to party, pick up women, and make easy money.\",\n      \"rank\": 212,\n      \"running_time_secs\": 6600,\n      \"actors\": [\"Channing Tatum\", \"Alex Pettyfer\", \"Olivia Munn\"]\n    }\n  },\n  {\n    \"year\": 2009,\n    \"title\": \"The Hangover\",\n    \"info\": {\n      \"directors\": [\"Todd Phillips\"],\n      \"release_date\": \"2009-05-30T00:00:00Z\",\n      \"rating\": 7.8,\n      \"genres\": [\"Comedy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTU1MDA1MTYwMF5BMl5BanBnXkFtZTcwMDcxMzA1Mg@@._V1_SX400_.jpg\",\n      \"plot\": \"Three buddies wake up from a bachelor party in Las Vegas, with no memory of the previous night and the bachelor missing. They make their way around the city in order to find their friend before his wedding.\",\n      \"rank\": 213,\n      \"running_time_secs\": 6000,\n      \"actors\": [\"Zach Galifianakis\", \"Bradley Cooper\", \"Justin Bartha\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"Lawless\",\n    \"info\": {\n      \"directors\": [\"John Hillcoat\"],\n      \"release_date\": \"2012-05-19T00:00:00Z\",\n      \"rating\": 7.2,\n      \"genres\": [\"Crime\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjAxNjUyNjUwN15BMl5BanBnXkFtZTcwMDgwOTIyOA@@._V1_SX400_.jpg\",\n      \"plot\": \"Set in Depression-era Franklin County, Virginia, a bootlegging gang is threatened by a new deputy and other authorities who want a cut of their profits.\",\n      \"rank\": 214,\n      \"running_time_secs\": 6960,\n      \"actors\": [\"Tom Hardy\", \"Shia LaBeouf\", \"Guy Pearce\"]\n    }\n  },\n  {\n    \"year\": 2014,\n    \"title\": \"Teenage Mutant Ninja Turtles\",\n    \"info\": {\n      \"directors\": [\"Jonathan Liebesman\"],\n      \"release_date\": \"2014-05-15T00:00:00Z\",\n      \"genres\": [\"Action\", \"Adventure\", \"Comedy\", \"Fantasy\", \"Sci-Fi\"],\n      \"plot\": \"Aliens invade Earth and inadvertently spawn a quartet of mutated reptilian warriors, the Ninja Turtles, who rise up against them to defend the world.\",\n      \"rank\": 215,\n      \"actors\": [\"Megan Fox\", \"Will Arnett\", \"William Fichtner\"]\n    }\n  },\n  {\n    \"year\": 2011,\n    \"title\": \"Pirates of the Caribbean: On Stranger Tides\",\n    \"info\": {\n      \"directors\": [\"Rob Marshall\"],\n      \"release_date\": \"2011-05-07T00:00:00Z\",\n      \"rating\": 6.6,\n      \"genres\": [\"Action\", \"Adventure\", \"Fantasy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjE5MjkwODI3Nl5BMl5BanBnXkFtZTcwNjcwMDk4NA@@._V1_SX400_.jpg\",\n      \"plot\": \"Jack Sparrow and Barbossa embark on a quest to find the elusive fountain of youth, only to discover that Blackbeard and his daughter are after it too.\",\n      \"rank\": 216,\n      \"running_time_secs\": 8220,\n      \"actors\": [\"Johnny Depp\", \"Penelope Cruz\", \"Ian McShane\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Trance\",\n    \"info\": {\n      \"directors\": [\"Danny Boyle\"],\n      \"release_date\": \"2013-03-27T00:00:00Z\",\n      \"rating\": 6.9,\n      \"genres\": [\"Crime\", \"Drama\", \"Mystery\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjMzNjU1MTg5NF5BMl5BanBnXkFtZTcwMTExMTcwOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"An art auctioneer who has become mixed up with a group of criminals partners with a hypnotherapist in order to recover a lost painting.\",\n      \"rank\": 217,\n      \"running_time_secs\": 6060,\n      \"actors\": [\"James McAvoy\", \"Rosario Dawson\", \"Vincent Cassel\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"One Chance\",\n    \"info\": {\n      \"directors\": [\"David Frankel\"],\n      \"release_date\": \"2013-09-09T00:00:00Z\",\n      \"rating\": 5.2,\n      \"genres\": [\"Biography\", \"Comedy\", \"Music\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTU4NzkxMzY2Nl5BMl5BanBnXkFtZTgwMjM5NDYxMDE@._V1_SX400_.jpg\",\n      \"plot\": \"The true story of Paul Potts, a shy, bullied shop assistant by day and an amateur opera singer by night who became a phenomenon after being chosen for -- and ultimately winning -- \\\"Britain's Got Talent\\\".\",\n      \"rank\": 218,\n      \"running_time_secs\": 6180,\n      \"actors\": [\"James Corden\", \"Colm Meaney\", \"Mackenzie Crook\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Colony\",\n    \"info\": {\n      \"directors\": [\"Jeff Renfroe\"],\n      \"release_date\": \"2013-04-26T00:00:00Z\",\n      \"rating\": 5.2,\n      \"genres\": [\"Action\", \"Sci-Fi\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BNzAzNzEzNDA4OF5BMl5BanBnXkFtZTcwOTUwODA3OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Forced underground by the next ice age, a struggling outpost of survivors must fight to preserve humanity against a threat even more savage than nature.\",\n      \"rank\": 219,\n      \"running_time_secs\": 5700,\n      \"actors\": [\"Kevin Zegers\", \"Laurence Fishburne\", \"Bill Paxton\"]\n    }\n  },\n  {\n    \"year\": 2003,\n    \"title\": \"Love Actually\",\n    \"info\": {\n      \"directors\": [\"Richard Curtis\"],\n      \"release_date\": \"2003-09-07T00:00:00Z\",\n      \"rating\": 7.7,\n      \"genres\": [\"Comedy\", \"Drama\", \"Romance\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTY4NjQ5NDc0Nl5BMl5BanBnXkFtZTYwNjk5NDM3._V1_SX400_.jpg\",\n      \"plot\": \"Follows the lives of eight very different couples in dealing with their love lives in various loosely and interrelated tales all set during a frantic month before Christmas in London, England.\",\n      \"rank\": 220,\n      \"running_time_secs\": 8100,\n      \"actors\": [\"Hugh Grant\", \"Martine McCutcheon\", \"Liam Neeson\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"Ted\",\n    \"info\": {\n      \"directors\": [\"Seth MacFarlane\"],\n      \"release_date\": \"2012-06-29T00:00:00Z\",\n      \"rating\": 7.1,\n      \"genres\": [\"Comedy\", \"Fantasy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTQ1OTU0ODcxMV5BMl5BanBnXkFtZTcwOTMxNTUwOA@@._V1_SX400_.jpg\",\n      \"plot\": \"As the result of a childhood wish, John Bennett's teddy bear, Ted, came to life and has been by John's side ever since - a friendship that's tested when Lori, John's girlfriend of four years, wants more from their relationship.\",\n      \"rank\": 221,\n      \"running_time_secs\": 6360,\n      \"actors\": [\"Mark Wahlberg\", \"Mila Kunis\", \"Seth MacFarlane\"]\n    }\n  },\n  {\n    \"year\": 2014,\n    \"title\": \"Maleficent\",\n    \"info\": {\n      \"directors\": [\"Robert Stromberg\"],\n      \"release_date\": \"2014-05-30T00:00:00Z\",\n      \"genres\": [\n        \"Action\",\n        \"Adventure\",\n        \"Drama\",\n        \"Family\",\n        \"Fantasy\",\n        \"Mystery\",\n        \"Romance\",\n        \"Thriller\"\n      ],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTk1OTk1MDMxNV5BMl5BanBnXkFtZTgwODMwMzQwMDE@._V1_SX400_.jpg\",\n      \"plot\": \"The \\\"Sleeping Beauty\\\" tale is told from the perspective of the villainous Maleficent and looks at the events that hardened her heart and drove her to curse young Princess Aurora.\",\n      \"rank\": 222,\n      \"actors\": [\"Angelina Jolie\", \"Elle Fanning\", \"Sharlto Copley\"]\n    }\n  },\n  {\n    \"year\": 2008,\n    \"title\": \"Twilight\",\n    \"info\": {\n      \"directors\": [\"Catherine Hardwicke\"],\n      \"release_date\": \"2008-11-17T00:00:00Z\",\n      \"rating\": 5.2,\n      \"genres\": [\"Drama\", \"Fantasy\", \"Romance\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTQ2NzUxMTAxN15BMl5BanBnXkFtZTcwMzEyMTIwMg@@._V1_SX400_.jpg\",\n      \"plot\": \"A teenage girl risks everything when she falls in love with a vampire.\",\n      \"rank\": 223,\n      \"running_time_secs\": 7320,\n      \"actors\": [\"Kristen Stewart\", \"Robert Pattinson\", \"Billy Burke\"]\n    }\n  },\n  {\n    \"year\": 2014,\n    \"title\": \"The Giver\",\n    \"info\": {\n      \"release_date\": \"2014-08-15T00:00:00Z\",\n      \"genres\": [\"Drama\", \"Fantasy\", \"Sci-Fi\"],\n      \"plot\": \"In a seemingly perfect community, without war, pain, suffering, differences or choice, a young boy is chosen to learn from an elderly man about the true pain and pleasure of the \\\"real\\\" world.\",\n      \"rank\": 224,\n      \"actors\": [\"Alexander Skarsgard\", \"Taylor Swift\", \"Meryl Streep\"]\n    }\n  },\n  {\n    \"year\": 2014,\n    \"title\": \"Edge of Tomorrow\",\n    \"info\": {\n      \"directors\": [\"Doug Liman\"],\n      \"release_date\": \"2014-05-28T00:00:00Z\",\n      \"genres\": [\"Action\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTgzMDQ0ODgwN15BMl5BanBnXkFtZTcwMzI4NTc4OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A soldier fighting in a war with aliens finds himself caught in a time loop of his last day in the battle, though he becomes better skilled along the way.\",\n      \"rank\": 225,\n      \"actors\": [\"Tom Cruise\", \"Emily Blunt\", \"Bill Paxton\"]\n    }\n  },\n  {\n    \"year\": 1977,\n    \"title\": \"Star Wars\",\n    \"info\": {\n      \"directors\": [\"George Lucas\"],\n      \"release_date\": \"1977-05-25T00:00:00Z\",\n      \"rating\": 8.7,\n      \"genres\": [\"Action\", \"Adventure\", \"Fantasy\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTU4NTczODkwM15BMl5BanBnXkFtZTcwMzEyMTIyMw@@._V1_SX400_.jpg\",\n      \"plot\": \"Luke Skywalker joins forces with a Jedi Knight, a cocky pilot, a wookiee and two droids to save the universe from the Empire's world-destroying battle-station, while also attempting to rescue Princess Leia from the evil Darth Vader.\",\n      \"rank\": 226,\n      \"running_time_secs\": 7260,\n      \"actors\": [\"Mark Hamill\", \"Harrison Ford\", \"Carrie Fisher\"]\n    }\n  },\n  {\n    \"year\": 2011,\n    \"title\": \"In Time\",\n    \"info\": {\n      \"directors\": [\"Andrew Niccol\"],\n      \"release_date\": \"2011-10-26T00:00:00Z\",\n      \"rating\": 6.6,\n      \"genres\": [\"Action\", \"Sci-Fi\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjA3NzI1ODc1MV5BMl5BanBnXkFtZTcwMzI5NjQwNg@@._V1_SX400_.jpg\",\n      \"plot\": \"In a future where people stop aging at 25, but are engineered to live only one more year, having the means to buy your way out of the situation is a shot at immortal youth. Here, Will Salas finds himself accused of murder and on the run with a hostage - a connection that becomes an important part of the way against the system.\",\n      \"rank\": 227,\n      \"running_time_secs\": 6540,\n      \"actors\": [\"Justin Timberlake\", \"Amanda Seyfried\", \"Cillian Murphy\"]\n    }\n  },\n  {\n    \"year\": 2005,\n    \"title\": \"Batman Begins\",\n    \"info\": {\n      \"directors\": [\"Christopher Nolan\"],\n      \"release_date\": \"2005-06-10T00:00:00Z\",\n      \"rating\": 8.3,\n      \"genres\": [\"Action\", \"Adventure\", \"Crime\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BNTM3OTc0MzM2OV5BMl5BanBnXkFtZTYwNzUwMTI3._V1_SX400_.jpg\",\n      \"plot\": \"After training with his mentor, Batman begins his war on crime to free the crime-ridden Gotham City from corruption that the Scarecrow and the League of Shadows have cast upon it.\",\n      \"rank\": 228,\n      \"running_time_secs\": 8400,\n      \"actors\": [\"Christian Bale\", \"Michael Caine\", \"Ken Watanabe\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"42\",\n    \"info\": {\n      \"directors\": [\"Brian Helgeland\"],\n      \"release_date\": \"2013-04-12T00:00:00Z\",\n      \"rating\": 7.5,\n      \"genres\": [\"Biography\", \"Drama\", \"Sport\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTQwMDU4MDI3MV5BMl5BanBnXkFtZTcwMjU1NDgyOQ@@._V1_SX400_.jpg\",\n      \"plot\": \"The life story of Jackie Robinson and his history-making signing with the Brooklyn Dodgers under the guidance of team executive Branch Rickey.\",\n      \"rank\": 229,\n      \"running_time_secs\": 7680,\n      \"actors\": [\"Chadwick Boseman\", \"T.R. Knight\", \"Harrison Ford\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Host\",\n    \"info\": {\n      \"directors\": [\"Andrew Niccol\"],\n      \"release_date\": \"2013-03-22T00:00:00Z\",\n      \"rating\": 5.7,\n      \"genres\": [\"Adventure\", \"Romance\", \"Sci-Fi\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjMwNDg1MTAzNV5BMl5BanBnXkFtZTcwNTk5ODI3OA@@._V1_SX400_.jpg\",\n      \"plot\": \"When an unseen enemy threatens mankind by taking over their bodies and erasing their memories, Melanie will risk everything to protect the people she cares most about, proving that love can conquer all in a dangerous new world.\",\n      \"rank\": 230,\n      \"running_time_secs\": 7500,\n      \"actors\": [\"Saoirse Ronan\", \"Max Irons\", \"Jake Abel\"]\n    }\n  },\n  {\n    \"year\": 2014,\n    \"title\": \"Neighbors\",\n    \"info\": {\n      \"directors\": [\"Nicholas Stoller\"],\n      \"release_date\": \"2014-05-08T00:00:00Z\",\n      \"genres\": [\"Comedy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTkxMzE2MzgxMV5BMl5BanBnXkFtZTgwMjUwOTYxMDE@._V1_SX400_.jpg\",\n      \"plot\": \"A couple with a newborn baby face unexpected difficulties after they are forced to live next to a fraternity house.\",\n      \"rank\": 231,\n      \"actors\": [\"Seth Rogen\", \"Rose Byrne\", \"Zac Efron\"]\n    }\n  },\n  {\n    \"year\": 2007,\n    \"title\": \"Into the Wild\",\n    \"info\": {\n      \"directors\": [\"Sean Penn\"],\n      \"release_date\": \"2007-09-01T00:00:00Z\",\n      \"rating\": 8.1,\n      \"genres\": [\"Adventure\", \"Biography\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTAwNDEyODU1MjheQTJeQWpwZ15BbWU2MDc3NDQwNw@@._V1_SX400_.jpg\",\n      \"plot\": \"After graduating from Emory University, top student and athlete Christopher McCandless abandons his possessions, gives his entire $24,000 savings account to charity and hitchhikes to Alaska to live in the wilderness. Along the way, Christopher encounters a series of characters that shape his life.\",\n      \"rank\": 232,\n      \"running_time_secs\": 8880,\n      \"actors\": [\"Emile Hirsch\", \"Vince Vaughn\", \"Catherine Keener\"]\n    }\n  },\n  {\n    \"year\": 2000,\n    \"title\": \"Pitch Black\",\n    \"info\": {\n      \"directors\": [\"David Twohy\"],\n      \"release_date\": \"2000-02-18T00:00:00Z\",\n      \"rating\": 7,\n      \"genres\": [\"Action\", \"Sci-Fi\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjE4MDY1NzM4OF5BMl5BanBnXkFtZTcwNDU1NDUyMQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A prisoner transport ship and its crew are marooned on a planet full of bloodthirsty creatures that only come out to feast at night. But then, they learn that a month-long eclipse is about to occur.\",\n      \"rank\": 233,\n      \"running_time_secs\": 6540,\n      \"actors\": [\"Radha Mitchell\", \"Cole Hauser\", \"Vin Diesel\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Hansel & Gretel: Witch Hunters\",\n    \"info\": {\n      \"directors\": [\"Tommy Wirkola\"],\n      \"release_date\": \"2013-01-17T00:00:00Z\",\n      \"rating\": 6.1,\n      \"genres\": [\"Action\", \"Fantasy\", \"Horror\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjA4MDQwODg2NV5BMl5BanBnXkFtZTcwNTc5ODc2OA@@._V1_SX400_.jpg\",\n      \"plot\": \"Hansel & Gretel are bounty hunters who track and kill witches all over the world. As the fabled Blood Moon approaches, the siblings encounter a new form of evil that might hold a secret to their past.\",\n      \"rank\": 234,\n      \"running_time_secs\": 5280,\n      \"actors\": [\"Jeremy Renner\", \"Gemma Arterton\", \"Peter Stormare\"]\n    }\n  },\n  {\n    \"year\": 2012,\n    \"title\": \"The Amazing Spider-Man\",\n    \"info\": {\n      \"directors\": [\"Marc Webb\"],\n      \"release_date\": \"2012-06-13T00:00:00Z\",\n      \"rating\": 7.1,\n      \"genres\": [\"Action\", \"Adventure\", \"Fantasy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjMyOTM4MDMxNV5BMl5BanBnXkFtZTcwNjIyNzExOA@@._V1_SX400_.jpg\",\n      \"plot\": \"Peter Parker finds a clue that might help him understand why his parents disappeared when he was young. His path puts him on a collision course with Dr. Curt Connors, his father's former partner.\",\n      \"rank\": 235,\n      \"running_time_secs\": 8160,\n      \"actors\": [\"Andrew Garfield\", \"Emma Stone\", \"Rhys Ifans\"]\n    }\n  },\n  {\n    \"year\": 2005,\n    \"title\": \"Sin City\",\n    \"info\": {\n      \"directors\": [\"Frank Miller\", \"Robert Rodriguez\", \"Quentin Tarantino\"],\n      \"release_date\": \"2005-03-28T00:00:00Z\",\n      \"rating\": 8.2,\n      \"genres\": [\"Crime\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTI2NjUyMDUyMV5BMl5BanBnXkFtZTcwMzU0OTkyMQ@@._V1_SX400_.jpg\",\n      \"plot\": \"A film that explores the dark and miserable town, Basin City, and tells the story of three different people, all caught up in violent corruption.\",\n      \"rank\": 236,\n      \"running_time_secs\": 7440,\n      \"actors\": [\"Mickey Rourke\", \"Clive Owen\", \"Bruce Willis\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"The Way Way Back\",\n    \"info\": {\n      \"directors\": [\"Nat Faxon\", \"Jim Rash\"],\n      \"release_date\": \"2013-01-21T00:00:00Z\",\n      \"rating\": 7.8,\n      \"genres\": [\"Comedy\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BNTU5ODk5NDg0Nl5BMl5BanBnXkFtZTcwNzQwMjI1OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Shy 14-year-old Duncan goes on summer vacation with his mother, her overbearing boyfriend, and her boyfriend's daughter. Having a rough time fitting in, Duncan finds an unexpected friend in Owen, manager of the Water Wizz water park.\",\n      \"rank\": 237,\n      \"running_time_secs\": 6180,\n      \"actors\": [\"Steve Carell\", \"Toni Collette\", \"Allison Janney\"]\n    }\n  },\n  {\n    \"year\": 1991,\n    \"title\": \"The Silence of the Lambs\",\n    \"info\": {\n      \"directors\": [\"Jonathan Demme\"],\n      \"release_date\": \"1991-01-30T00:00:00Z\",\n      \"rating\": 8.7,\n      \"genres\": [\"Crime\", \"Drama\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTQ2NzkzMDI4OF5BMl5BanBnXkFtZTcwMDA0NzE1NA@@._V1_SX400_.jpg\",\n      \"plot\": \"A young F.B.I. cadet must confide in an incarcerated and manipulative killer to receive his help on catching another serial killer who skins his victims.\",\n      \"rank\": 238,\n      \"running_time_secs\": 7080,\n      \"actors\": [\"Jodie Foster\", \"Anthony Hopkins\", \"Lawrence A. Bonney\"]\n    }\n  },\n  {\n    \"year\": 2003,\n    \"title\": \"Pirates of the Caribbean: The Curse of the Black Pearl\",\n    \"info\": {\n      \"directors\": [\"Gore Verbinski\"],\n      \"release_date\": \"2003-06-28T00:00:00Z\",\n      \"rating\": 8,\n      \"genres\": [\"Action\", \"Adventure\", \"Fantasy\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjAyNDM4MTc2N15BMl5BanBnXkFtZTYwNDk0Mjc3._V1_SX400_.jpg\",\n      \"plot\": \"Blacksmith Will Turner teams up with eccentric pirate \\\"Captain\\\" Jack Sparrow to save his love, the governor's daughter, from Jack's former pirate allies, who are now undead.\",\n      \"rank\": 239,\n      \"running_time_secs\": 8580,\n      \"actors\": [\"Johnny Depp\", \"Geoffrey Rush\", \"Orlando Bloom\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Generation Iron\",\n    \"info\": {\n      \"directors\": [\"Vlad Yudin\"],\n      \"release_date\": \"2013-09-20T00:00:00Z\",\n      \"rating\": 6.7,\n      \"genres\": [\"Documentary\", \"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTY3NDcxNjIzMF5BMl5BanBnXkFtZTgwMzM1NDAxMDE@._V1_SX400_.jpg\",\n      \"plot\": \"A documentary that follows top bodybuilders as they train to compete in the Mr. Olympia competition.\",\n      \"rank\": 240,\n      \"running_time_secs\": 6360,\n      \"actors\": [\"Arnold Schwarzenegger\", \"Mickey Rourke\", \"Michael Jai White\"]\n    }\n  },\n  {\n    \"year\": 2011,\n    \"title\": \"The Help\",\n    \"info\": {\n      \"directors\": [\"Tate Taylor\"],\n      \"release_date\": \"2011-08-09T00:00:00Z\",\n      \"rating\": 8,\n      \"genres\": [\"Drama\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTM5OTMyMjIxOV5BMl5BanBnXkFtZTcwNzU4MjIwNQ@@._V1_SX400_.jpg\",\n      \"plot\": \"An aspiring author during the civil rights movement of the 1960s decides to write a book detailing the African-American maids' point of view on the white families for which they work, and the hardships they go through on a daily basis.\",\n      \"rank\": 241,\n      \"running_time_secs\": 8760,\n      \"actors\": [\"Emma Stone\", \"Viola Davis\", \"Octavia Spencer\"]\n    }\n  },\n  {\n    \"year\": 1993,\n    \"title\": \"Schindler's List\",\n    \"info\": {\n      \"directors\": [\"Steven Spielberg\"],\n      \"release_date\": \"1993-11-30T00:00:00Z\",\n      \"rating\": 8.9,\n      \"genres\": [\"Biography\", \"Drama\", \"History\", \"War\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMzMwMTM4MDU2N15BMl5BanBnXkFtZTgwMzQ0MjMxMDE@._V1_SX400_.jpg\",\n      \"plot\": \"In Poland during World War II, Oskar Schindler gradually becomes concerned for his Jewish workforce after witnessing their persecution by the Nazis.\",\n      \"rank\": 242,\n      \"running_time_secs\": 11700,\n      \"actors\": [\"Liam Neeson\", \"Ralph Fiennes\", \"Ben Kingsley\"]\n    }\n  },\n  {\n    \"year\": 2011,\n    \"title\": \"No Strings Attached\",\n    \"info\": {\n      \"directors\": [\"Ivan Reitman\"],\n      \"release_date\": \"2011-01-11T00:00:00Z\",\n      \"rating\": 6.1,\n      \"genres\": [\"Comedy\", \"Romance\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMTg2MDQ1NTEzNl5BMl5BanBnXkFtZTcwOTgxNTMyNA@@._V1_SX400_.jpg\",\n      \"plot\": \"A guy and girl try to keep their relationship strictly physical, but it's not long before they learn that they want something more.\",\n      \"rank\": 243,\n      \"running_time_secs\": 6480,\n      \"actors\": [\"Natalie Portman\", \"Ashton Kutcher\", \"Kevin Kline\"]\n    }\n  },\n  {\n    \"year\": 2014,\n    \"title\": \"The Maze Runner\",\n    \"info\": {\n      \"directors\": [\"Wes Ball\"],\n      \"release_date\": \"2014-02-12T00:00:00Z\",\n      \"genres\": [\"Mystery\", \"Sci-Fi\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BOTg4ODI2MTc5N15BMl5BanBnXkFtZTcwNzU2NzA4OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Set in a post-apocalyptic world, young Thomas is deposited in a community of boys after his memory is erased, soon learning they're all trapped in a maze that will require him to join forces with fellow \\\"runners\\\" for a shot at escape.\",\n      \"rank\": 244,\n      \"actors\": [\"Will Poulter\", \"Dylan O'Brien\", \"Thomas Brodie-Sangster\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Stoker\",\n    \"info\": {\n      \"directors\": [\"Chan-wook Park\"],\n      \"release_date\": \"2013-01-20T00:00:00Z\",\n      \"rating\": 6.9,\n      \"genres\": [\"Drama\", \"Mystery\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjI3MTM5ODI5MV5BMl5BanBnXkFtZTcwMjE1Mzc4OA@@._V1_SX400_.jpg\",\n      \"plot\": \"After India's father dies, her Uncle Charlie, who she never knew existed, comes to live with her and her unstable mother. She comes to suspect this mysterious, charming man has ulterior motives and becomes increasingly infatuated with him.\",\n      \"rank\": 245,\n      \"running_time_secs\": 5940,\n      \"actors\": [\"Mia Wasikowska\", \"Nicole Kidman\", \"Matthew Goode\"]\n    }\n  },\n  {\n    \"year\": 2013,\n    \"title\": \"Lone Survivor\",\n    \"info\": {\n      \"directors\": [\"Peter Berg\"],\n      \"release_date\": \"2013-12-27T00:00:00Z\",\n      \"genres\": [\"Action\", \"Drama\", \"Thriller\", \"War\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjA0NTgwOTk5Ml5BMl5BanBnXkFtZTcwMjE3NDc5OQ@@._V1_SX400_.jpg\",\n      \"plot\": \"Based on the failed June 28, 2005 mission \\\"Operation Red Wings\\\". Four members of SEAL Team 10 were tasked with the mission to capture or kill notorious Taliban leader Ahmad Shahd. Marcus Luttrell was the only member of his team to survive.\",\n      \"rank\": 246,\n      \"actors\": [\"Mark Wahlberg\", \"Ben Foster\", \"Eric Bana\"]\n    }\n  },\n  {\n    \"year\": 1990,\n    \"title\": \"Goodfellas\",\n    \"info\": {\n      \"directors\": [\"Martin Scorsese\"],\n      \"release_date\": \"1990-09-12T00:00:00Z\",\n      \"rating\": 8.8,\n      \"genres\": [\"Biography\", \"Crime\", \"Drama\", \"Thriller\"],\n      \"image_url\": \"http://ia.media-imdb.com/images/M/MV5BMjU3MTQ4OTA0MV5BMl5BanBnXkFtZTYwNjAyMDg4._V1_SX400_.jpg\",\n      \"plot\": \"Henry Hill and his friends work their way up through the mob hierarchy.\",\n      \"rank\": 248,\n      \"running_time_secs\": 8760,\n      \"actors\": [\"Robert De Niro\", \"Ray Liotta\", \"Joe Pesci\"]\n    }\n  }\n]\n"
  },
  {
    "path": "examples/react/react-native/src/hooks/useAppState.ts",
    "content": "import { useEffect } from 'react'\nimport { AppState } from 'react-native'\nimport type { AppStateStatus } from 'react-native'\n\nexport function useAppState(onChange: (status: AppStateStatus) => void) {\n  useEffect(() => {\n    const subscription = AppState.addEventListener('change', onChange)\n    return () => {\n      subscription.remove()\n    }\n  }, [onChange])\n}\n"
  },
  {
    "path": "examples/react/react-native/src/hooks/useOnlineManager.ts",
    "content": "import * as React from 'react'\nimport NetInfo from '@react-native-community/netinfo'\nimport { onlineManager } from '@tanstack/react-query'\nimport { Platform } from 'react-native'\n\nexport function useOnlineManager() {\n  React.useEffect(() => {\n    // React Query already supports on reconnect auto refetch in web browser\n    if (Platform.OS !== 'web') {\n      return NetInfo.addEventListener((state) => {\n        onlineManager.setOnline(\n          state.isConnected != null &&\n            state.isConnected &&\n            Boolean(state.isInternetReachable),\n        )\n      })\n    }\n  }, [])\n}\n"
  },
  {
    "path": "examples/react/react-native/src/hooks/useRefreshByUser.ts",
    "content": "import * as React from 'react'\n\nexport function useRefreshByUser(refetch: () => Promise<unknown>) {\n  const [isRefetchingByUser, setIsRefetchingByUser] = React.useState(false)\n\n  async function refetchByUser() {\n    setIsRefetchingByUser(true)\n\n    try {\n      await refetch()\n    } finally {\n      setIsRefetchingByUser(false)\n    }\n  }\n\n  return {\n    isRefetchingByUser,\n    refetchByUser,\n  }\n}\n"
  },
  {
    "path": "examples/react/react-native/src/hooks/useRefreshOnFocus.ts",
    "content": "import * as React from 'react'\nimport { useFocusEffect } from '@react-navigation/native'\n\nexport function useRefreshOnFocus(refetch: () => void) {\n  const enabledRef = React.useRef(false)\n\n  useFocusEffect(\n    React.useCallback(() => {\n      if (enabledRef.current) {\n        refetch()\n      } else {\n        enabledRef.current = true\n      }\n    }, [refetch]),\n  )\n}\n"
  },
  {
    "path": "examples/react/react-native/src/lib/api.ts",
    "content": "import movies from '../data/movies.json'\n\nexport type Movie = {\n  title: string\n  year: number\n}\n\nexport type MovieDetails = Movie & {\n  info: {\n    plot: string\n    actors: string[]\n  }\n}\n\nfunction delay(t: number) {\n  return new Promise(function (resolve) {\n    setTimeout(resolve, t)\n  })\n}\n\nexport async function fetchMovies(): Promise<Movie[]> {\n  console.log('fetchMovies')\n\n  await delay(200 + Math.floor(Math.random() * 2000))\n\n  return Promise.resolve(\n    movies\n      .slice(0, 100)\n      .map((movie) => ({ title: movie.title, year: movie.year })),\n  )\n}\n\nexport async function fetchMovie(title: string): Promise<MovieDetails> {\n  console.log('fetchMovie', title)\n\n  await delay(200 + Math.floor(Math.random() * 2000))\n\n  const result = movies.filter((item) => item.title === title)\n\n  if (result.length === 0) {\n    throw new Error('Movie not found')\n  }\n  return Promise.resolve(result[0] as MovieDetails)\n}\n"
  },
  {
    "path": "examples/react/react-native/src/navigation/MoviesStack.tsx",
    "content": "import * as React from 'react'\nimport { createStackNavigator } from '@react-navigation/stack'\n\nimport { MoviesListScreen } from '../screens/MoviesListScreen'\nimport { MovieDetailsScreen } from '../screens/MovieDetailsScreen'\nimport type { MoviesStackNavigator } from './types'\n\nconst Stack = createStackNavigator<MoviesStackNavigator>()\n\nexport function MoviesStack() {\n  return (\n    <Stack.Navigator initialRouteName=\"MoviesList\">\n      <Stack.Screen\n        name=\"MoviesList\"\n        component={MoviesListScreen}\n        options={{\n          headerTitle: 'Movies',\n        }}\n      />\n      <Stack.Screen\n        name=\"MovieDetails\"\n        component={MovieDetailsScreen}\n        options={{\n          headerTitle: 'Movie details',\n        }}\n      />\n    </Stack.Navigator>\n  )\n}\n"
  },
  {
    "path": "examples/react/react-native/src/navigation/types.ts",
    "content": "import type { Movie } from '../lib/api'\n\nexport type MoviesStackNavigator = {\n  MoviesList: undefined\n  MovieDetails: { movie: Movie }\n}\n"
  },
  {
    "path": "examples/react/react-native/src/screens/MovieDetailsScreen.tsx",
    "content": "import * as React from 'react'\nimport { RefreshControl, ScrollView, StyleSheet, View } from 'react-native'\nimport { Paragraph, Title } from 'react-native-paper'\nimport { useQuery } from '@tanstack/react-query'\nimport { LoadingIndicator } from '../components/LoadingIndicator'\nimport { ErrorMessage } from '../components/ErrorMessage'\nimport { useRefreshByUser } from '../hooks/useRefreshByUser'\nimport { fetchMovie } from '../lib/api'\nimport type { MovieDetails } from '../lib/api'\nimport type { MoviesStackNavigator } from '../navigation/types'\nimport type { StackNavigationProp } from '@react-navigation/stack'\nimport type { RouteProp } from '@react-navigation/native'\n\ntype MoviesDetailsScreenNavigationProp = StackNavigationProp<\n  MoviesStackNavigator,\n  'MovieDetails'\n>\n\ntype Props = {\n  navigation: MoviesDetailsScreenNavigationProp\n  route: RouteProp<MoviesStackNavigator, 'MovieDetails'>\n}\n\nexport function MovieDetailsScreen({ route }: Props) {\n  const { isPending, error, data, refetch } = useQuery<MovieDetails, Error>({\n    queryKey: ['movie', route.params.movie.title],\n    queryFn: () => fetchMovie(route.params.movie.title),\n    initialData: route.params.movie as MovieDetails,\n  })\n\n  const { isRefetchingByUser, refetchByUser } = useRefreshByUser(refetch)\n\n  if (isPending) return <LoadingIndicator />\n  if (error) return <ErrorMessage message={error.message}></ErrorMessage>\n  if (!data) return null\n\n  return (\n    <ScrollView\n      refreshControl={\n        <RefreshControl\n          refreshing={isRefetchingByUser}\n          onRefresh={refetchByUser}\n        />\n      }\n    >\n      <View style={styles.titleRow}>\n        <Title>\n          {data.title} ({data.year})\n        </Title>\n      </View>\n      {data.info ? (\n        <>\n          <View style={styles.infoRow}>\n            <Paragraph>{data.info.plot}</Paragraph>\n          </View>\n          <View style={styles.actorsRow}>\n            <Paragraph>\n              {data.info.actors.slice(0, -1).join(', ') +\n                ' or ' +\n                data.info.actors.slice(-1)}\n            </Paragraph>\n          </View>\n        </>\n      ) : (\n        <LoadingIndicator />\n      )}\n    </ScrollView>\n  )\n}\n\nconst styles = StyleSheet.create({\n  titleRow: {\n    flexDirection: 'row',\n    margin: 20,\n  },\n  infoRow: {\n    flexDirection: 'row',\n    margin: 20,\n  },\n  actorsRow: {\n    flexDirection: 'column',\n    margin: 20,\n    marginTop: 10,\n  },\n})\n"
  },
  {
    "path": "examples/react/react-native/src/screens/MoviesListScreen.tsx",
    "content": "import * as React from 'react'\nimport { FlatList, RefreshControl } from 'react-native'\nimport { useQuery } from '@tanstack/react-query'\nimport { LoadingIndicator } from '../components/LoadingIndicator'\nimport { ErrorMessage } from '../components/ErrorMessage'\nimport { Divider } from '../components/Divider'\nimport { ListItem } from '../components/ListItem'\nimport { useRefreshByUser } from '../hooks/useRefreshByUser'\nimport { useRefreshOnFocus } from '../hooks/useRefreshOnFocus'\nimport { fetchMovies } from '../lib/api'\nimport type { Movie, MovieDetails } from '../lib/api'\nimport type { MoviesStackNavigator } from '../navigation/types'\nimport type { StackNavigationProp } from '@react-navigation/stack'\n\ntype MoviesListScreenNavigationProp = StackNavigationProp<\n  MoviesStackNavigator,\n  'MoviesList'\n>\n\ntype Props = {\n  navigation: MoviesListScreenNavigationProp\n}\n\nexport function MoviesListScreen({ navigation }: Props) {\n  const { isPending, error, data, refetch } = useQuery<Movie[], Error>({\n    queryKey: ['movies'],\n    queryFn: fetchMovies,\n  })\n  const { isRefetchingByUser, refetchByUser } = useRefreshByUser(refetch)\n  useRefreshOnFocus(refetch)\n\n  const onListItemPress = React.useCallback(\n    (movie: MovieDetails) => {\n      navigation.navigate('MovieDetails', {\n        movie,\n      })\n    },\n    [navigation],\n  )\n\n  const renderItem = React.useCallback(\n    ({ item }: { item: MovieDetails }) => {\n      return <ListItem item={item} onPress={onListItemPress} />\n    },\n    [onListItemPress],\n  )\n\n  if (isPending) return <LoadingIndicator />\n\n  if (error) return <ErrorMessage message={error.message}></ErrorMessage>\n  return (\n    <FlatList\n      data={data}\n      renderItem={renderItem}\n      keyExtractor={(item) => item.title}\n      ItemSeparatorComponent={() => <Divider />}\n      refreshControl={\n        <RefreshControl\n          refreshing={isRefetchingByUser}\n          onRefresh={refetchByUser}\n        />\n      }\n    ></FlatList>\n  )\n}\n"
  },
  {
    "path": "examples/react/react-native/tsconfig.json",
    "content": "{\n  \"extends\": \"expo/tsconfig.base\",\n  \"compilerOptions\": {\n    \"strict\": true\n  }\n}\n"
  },
  {
    "path": "examples/react/react-router/.eslintrc",
    "content": "{\n  \"extends\": [\"plugin:react/jsx-runtime\", \"plugin:react-hooks/recommended\"]\n}\n"
  },
  {
    "path": "examples/react/react-router/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\npnpm-lock.yaml\nyarn.lock\npackage-lock.json\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "examples/react/react-router/README.md",
    "content": "# React Router Example\n\nTo run this example:\n\n- `npm install`\n- `npm run dev`\n"
  },
  {
    "path": "examples/react/react-router/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/emblem-light.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <meta name=\"theme-color\" content=\"#000000\" />\n\n    <title>TanStack Query React Router Example App</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/index.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/react/react-router/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-react-router\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"localforage\": \"^1.10.0\",\n    \"match-sorter\": \"^6.3.4\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\",\n    \"react-router\": \"^6.25.1\",\n    \"react-router-dom\": \"^6.25.1\",\n    \"rooks\": \"^8.0.0\",\n    \"sort-by\": \"^1.2.0\"\n  },\n  \"devDependencies\": {\n    \"@types/react\": \"^18.2.79\",\n    \"@types/react-dom\": \"^18.2.25\",\n    \"@types/sort-by\": \"^1.2.3\",\n    \"@vitejs/plugin-react\": \"^4.3.4\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "examples/react/react-router/src/contacts.ts",
    "content": "import localforage from 'localforage'\nimport { matchSorter } from 'match-sorter'\nimport sortBy from 'sort-by'\n\nconst initialData = [\n  {\n    avatar: 'https://avatars.githubusercontent.com/u/5580297?v=4',\n    createdAt: 1660978713047,\n    favorite: false,\n    first: 'Tanner',\n    id: 'usupkc1',\n    last: 'Linsley',\n    notes: 'Created React Query',\n    twitter: '@tannerlinsley',\n  },\n  {\n    avatar: 'https://avatars.githubusercontent.com/u/1021430',\n    createdAt: 1660979124264,\n    favorite: false,\n    first: 'Dominik',\n    id: 'kvvztl7',\n    last: 'D',\n    notes: 'Maintains React Query',\n    twitter: '@tkdodo',\n  },\n]\n\nexport type Contact = (typeof initialData)[number]\n\nconst seed = async () => {\n  const contacts = await localforage.getItem<Contact[]>('contacts')\n  if (!contacts) {\n    set(initialData)\n  }\n}\n\nseed()\n\nexport async function getContacts(query?: string) {\n  await fakeNetwork()\n  let contacts = await localforage.getItem<Contact[]>('contacts')\n  if (!contacts) contacts = []\n  if (query) {\n    contacts = matchSorter(contacts, query, { keys: ['first', 'last'] })\n  }\n  return contacts.sort(sortBy('last', 'createdAt'))\n}\n\nexport async function createContact(\n  data: Pick<Contact, 'first' | 'last' | 'twitter' | 'avatar' | 'notes'>,\n) {\n  await fakeNetwork()\n  let id = Math.random().toString(36).substring(2, 9)\n  let contact = { ...data, id, createdAt: Date.now(), favorite: false }\n  let contacts = await getContacts()\n  contacts.unshift(contact)\n  await set(contacts)\n  return contact\n}\n\nexport async function getContact(id: string) {\n  await fakeNetwork()\n  let contacts = await localforage.getItem<Contact[]>('contacts')\n  if (!contacts) return null\n  let contact = contacts.find((contact) => contact.id === id)\n  return contact ?? null\n}\n\nexport async function updateContact(id: string, updates: Partial<Contact>) {\n  await fakeNetwork()\n  let contacts = await localforage.getItem<Contact[]>('contacts')\n  if (!contacts) return false\n  let contact = contacts.find((contact) => contact.id === id)\n  if (!contact) throw new Error(`No contact found for ${id}`)\n  Object.assign(contact, updates)\n  await set(contacts)\n  return contact\n}\n\nexport async function deleteContact(id: string) {\n  let contacts = await localforage.getItem<Contact[]>('contacts')\n  if (!contacts) return false\n  let index = contacts.findIndex((contact) => contact.id === id)\n  if (index > -1) {\n    contacts.splice(index, 1)\n    await set(contacts)\n    return true\n  }\n  return false\n}\n\nfunction set(contacts: Contact[]) {\n  return localforage.setItem('contacts', contacts)\n}\n\nasync function fakeNetwork() {\n  return new Promise((res) => {\n    setTimeout(res, Math.random() * 800)\n  })\n}\n"
  },
  {
    "path": "examples/react/react-router/src/error-page.tsx",
    "content": "import { useRouteError, isRouteErrorResponse } from 'react-router-dom'\n\nexport default function ErrorPage() {\n  const error = useRouteError()\n  console.error(error)\n\n  let errorMessage = ''\n  if (isRouteErrorResponse(error)) {\n    errorMessage = error.statusText\n  } else if (error instanceof Error) {\n    errorMessage = error.message\n  }\n\n  return (\n    <div id=\"error-page\">\n      <h1>Oops!</h1>\n      <p>Sorry, an unexpected error has occurred.</p>\n      <p>\n        <i>{errorMessage}</i>\n      </p>\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/react/react-router/src/index.css",
    "content": "html {\n  box-sizing: border-box;\n}\n*,\n*:before,\n*:after {\n  box-sizing: inherit;\n}\n\nbody {\n  font-family:\n    -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu',\n    'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\ncode {\n  font-family:\n    source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;\n}\n\nhtml,\nbody {\n  height: 100%;\n  margin: 0;\n  line-height: 1.5;\n  color: #121212;\n}\n\nform textarea,\nform input,\nform button,\na.button {\n  font-size: 1rem;\n  font-family: inherit;\n  border: none;\n  border-radius: 8px;\n  padding: 0.5rem 0.75rem;\n  box-shadow:\n    0 0px 1px hsla(0, 0%, 0%, 0.2),\n    0 1px 2px hsla(0, 0%, 0%, 0.2);\n  background-color: white;\n  line-height: 1.5;\n  margin: 0;\n}\n\nform button,\na.button {\n  color: #3992ff;\n  font-weight: 500;\n  text-decoration: none;\n  cursor: pointer;\n}\n\nform textarea:hover,\nform input:hover,\nform button:hover,\na.button:hover {\n  box-shadow:\n    0 0px 1px hsla(0, 0%, 0%, 0.6),\n    0 1px 2px hsla(0, 0%, 0%, 0.2);\n}\n\nform button:active,\na.button:active {\n  box-shadow: 0 0px 1px hsla(0, 0%, 0%, 0.4);\n  transform: translateY(1px);\n}\n\n#contact h1 {\n  display: flex;\n  align-items: flex-start;\n  gap: 1rem;\n}\n#contact h1 form {\n  display: flex;\n  align-items: center;\n  margin-top: 0.25rem;\n}\n#contact h1 form button {\n  box-shadow: none;\n  font-size: 1.5rem;\n  font-weight: 400;\n  padding: 0;\n}\n#contact h1 form button[value='true'] {\n  color: #a4a4a4;\n}\n#contact h1 form button[value='true']:hover,\n#contact h1 form button[value='false'] {\n  color: #eeb004;\n}\n\nform[action$='destroy'] button {\n  color: #f44250;\n}\n\n.sr-only {\n  position: absolute;\n  width: 1px;\n  height: 1px;\n  padding: 0;\n  margin: -1px;\n  overflow: hidden;\n  clip: rect(0, 0, 0, 0);\n  white-space: nowrap;\n  border-width: 0;\n}\n\n#root {\n  display: flex;\n  height: 100%;\n  width: 100%;\n}\n\n#sidebar {\n  width: 22rem;\n  background-color: #f7f7f7;\n  border-right: solid 1px #e3e3e3;\n  display: flex;\n  flex-direction: column;\n}\n\n#sidebar > * {\n  padding-left: 2rem;\n  padding-right: 2rem;\n}\n\n#sidebar h1 {\n  font-size: 1rem;\n  font-weight: 500;\n  display: flex;\n  align-items: center;\n  margin: 0;\n  padding: 1rem 2rem;\n  border-top: 1px solid #e3e3e3;\n  order: 1;\n  line-height: 1;\n}\n\n#sidebar h1::before {\n  content: url(\"data:image/svg+xml,%3Csvg width='25' height='18' viewBox='0 0 25 18' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M19.4127 6.4904C18.6984 6.26581 18.3295 6.34153 17.5802 6.25965C16.4219 6.13331 15.9604 5.68062 15.7646 4.51554C15.6551 3.86516 15.7844 2.9129 15.5048 2.32334C14.9699 1.19921 13.7183 0.695046 12.461 0.982805C11.3994 1.22611 10.516 2.28708 10.4671 3.37612C10.4112 4.61957 11.1197 5.68054 12.3363 6.04667C12.9143 6.22097 13.5284 6.3087 14.132 6.35315C15.2391 6.43386 15.3241 7.04923 15.6236 7.55574C15.8124 7.87508 15.9954 8.18975 15.9954 9.14193C15.9954 10.0941 15.8112 10.4088 15.6236 10.7281C15.3241 11.2334 14.9547 11.5645 13.8477 11.6464C13.244 11.6908 12.6288 11.7786 12.0519 11.9528C10.8353 12.3201 10.1268 13.3799 10.1828 14.6234C10.2317 15.7124 11.115 16.7734 12.1766 17.0167C13.434 17.3056 14.6855 16.8003 15.2204 15.6762C15.5013 15.0866 15.6551 14.4187 15.7646 13.7683C15.9616 12.6032 16.423 12.1505 17.5802 12.0242C18.3295 11.9423 19.1049 12.0242 19.8071 11.6253C20.5491 11.0832 21.212 10.2696 21.212 9.14192C21.212 8.01428 20.4976 6.83197 19.4127 6.4904Z' fill='%23F44250'/%3E%3Cpath d='M7.59953 11.7459C6.12615 11.7459 4.92432 10.5547 4.92432 9.09441C4.92432 7.63407 6.12615 6.44287 7.59953 6.44287C9.0729 6.44287 10.2747 7.63407 10.2747 9.09441C10.2747 10.5536 9.07172 11.7459 7.59953 11.7459Z' fill='black'/%3E%3Cpath d='M2.64217 17.0965C1.18419 17.093 -0.0034949 15.8971 7.72743e-06 14.4356C0.00352588 12.9765 1.1994 11.7888 2.66089 11.7935C4.12004 11.797 5.30772 12.9929 5.30306 14.4544C5.29953 15.9123 4.10366 17.1 2.64217 17.0965Z' fill='black'/%3E%3Cpath d='M22.3677 17.0965C20.9051 17.1046 19.7046 15.9217 19.6963 14.4649C19.6882 13.0023 20.8712 11.8017 22.3279 11.7935C23.7906 11.7854 24.9911 12.9683 24.9993 14.4251C25.0075 15.8866 23.8245 17.0883 22.3677 17.0965Z' fill='black'/%3E%3C/svg%3E%0A\");\n  margin-right: 0.5rem;\n  position: relative;\n  top: 1px;\n}\n\n#sidebar > div {\n  display: flex;\n  align-items: center;\n  gap: 0.5rem;\n  padding-top: 1rem;\n  padding-bottom: 1rem;\n  border-bottom: 1px solid #e3e3e3;\n}\n\n#sidebar > div form {\n  position: relative;\n}\n\n#sidebar > div form input[type='search'] {\n  width: 100%;\n  padding-left: 2rem;\n  background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' class='h-6 w-6' fill='none' viewBox='0 0 24 24' stroke='%23999' stroke-width='2'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z' /%3E%3C/svg%3E\");\n  background-repeat: no-repeat;\n  background-position: 0.625rem 0.75rem;\n  background-size: 1rem;\n  position: relative;\n}\n\n#sidebar > div form input[type='search'].loading {\n  background-image: none;\n}\n\n#search-spinner {\n  width: 1rem;\n  height: 1rem;\n  background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24'%3E%3Cpath stroke='%23000' strokeLinecap='round' strokeLinejoin='round' strokeWidth='2' d='M20 4v5h-.582m0 0a8.001 8.001 0 00-15.356 2m15.356-2H15M4 20v-5h.581m0 0a8.003 8.003 0 0015.357-2M4.581 15H9' /%3E%3C/svg%3E\");\n  animation: spin 1s infinite linear;\n  position: absolute;\n  left: 0.625rem;\n  top: 0.75rem;\n}\n\n@keyframes spin {\n  from {\n    transform: rotate(0deg);\n  }\n  to {\n    transform: rotate(360deg);\n  }\n}\n\n#sidebar nav {\n  flex: 1;\n  overflow: auto;\n  padding-top: 1rem;\n}\n\n#sidebar nav a span {\n  float: right;\n  color: #eeb004;\n}\n#sidebar nav a.active span {\n  color: inherit;\n}\n\ni {\n  color: #818181;\n}\n#sidebar nav .active i {\n  color: inherit;\n}\n\n#sidebar ul {\n  padding: 0;\n  margin: 0;\n  list-style: none;\n}\n\n#sidebar li {\n  margin: 0.25rem 0;\n}\n\n#sidebar nav a {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  overflow: hidden;\n\n  white-space: pre;\n  padding: 0.5rem;\n  border-radius: 8px;\n  color: inherit;\n  text-decoration: none;\n  gap: 1rem;\n}\n\n#sidebar nav a:hover {\n  background: #e3e3e3;\n}\n\n#sidebar nav a.active {\n  background: hsl(224, 98%, 58%);\n  color: white;\n}\n\n#sidebar nav a.pending {\n  color: hsl(224, 98%, 58%);\n}\n\n#detail {\n  flex: 1;\n  padding: 2rem 4rem;\n  width: 100%;\n}\n\n#detail.loading {\n  opacity: 0.25;\n  transition: opacity 200ms;\n  transition-delay: 200ms;\n}\n\n#contact {\n  max-width: 40rem;\n  display: flex;\n}\n\n#contact h1 {\n  font-size: 2rem;\n  font-weight: 700;\n  margin: 0;\n  line-height: 1.2;\n}\n\n#contact h1 + p {\n  margin: 0;\n}\n\n#contact h1 + p + p {\n  white-space: break-spaces;\n}\n\n#contact h1:focus {\n  outline: none;\n  color: hsl(224, 98%, 58%);\n}\n\n#contact a[href*='twitter'] {\n  display: flex;\n  font-size: 1.5rem;\n  color: #3992ff;\n  text-decoration: none;\n}\n#contact a[href*='twitter']:hover {\n  text-decoration: underline;\n}\n\n#contact img {\n  width: 12rem;\n  height: 12rem;\n  background: #c8c8c8;\n  margin-right: 2rem;\n  border-radius: 1.5rem;\n  object-fit: cover;\n}\n\n#contact h1 ~ div {\n  display: flex;\n  gap: 0.5rem;\n  margin: 1rem 0;\n}\n\n#contact-form {\n  display: flex;\n  max-width: 40rem;\n  flex-direction: column;\n  gap: 1rem;\n}\n#contact-form > p:first-child {\n  margin: 0;\n  padding: 0;\n}\n#contact-form > p:first-child > :nth-child(2) {\n  margin-right: 1rem;\n}\n#contact-form > p:first-child,\n#contact-form label {\n  display: flex;\n}\n#contact-form p:first-child span,\n#contact-form label span {\n  width: 8rem;\n}\n#contact-form p:first-child input,\n#contact-form label input,\n#contact-form label textarea {\n  flex-grow: 2;\n}\n\n#contact-form-avatar {\n  margin-right: 2rem;\n}\n\n#contact-form-avatar img {\n  width: 12rem;\n  height: 12rem;\n  background: hsla(0, 0%, 0%, 0.2);\n  border-radius: 1rem;\n}\n\n#contact-form-avatar input {\n  box-sizing: border-box;\n  width: 100%;\n}\n\n#contact-form p:last-child {\n  display: flex;\n  gap: 0.5rem;\n  margin: 0 0 0 8rem;\n}\n\n#contact-form p:last-child button[type='button'] {\n  color: inherit;\n}\n\n#zero-state {\n  margin: 2rem auto;\n  text-align: center;\n  color: #818181;\n}\n\n#zero-state a {\n  color: inherit;\n}\n\n#zero-state a:hover {\n  color: #121212;\n}\n\n#zero-state:before {\n  display: block;\n  margin-bottom: 0.5rem;\n  content: url(\"data:image/svg+xml,%3Csvg width='50' height='33' viewBox='0 0 50 33' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M38.8262 11.1744C37.3975 10.7252 36.6597 10.8766 35.1611 10.7128C32.8444 10.4602 31.9215 9.55475 31.5299 7.22456C31.3108 5.92377 31.5695 4.01923 31.0102 2.8401C29.9404 0.591789 27.4373 -0.416556 24.9225 0.158973C22.7992 0.645599 21.0326 2.76757 20.9347 4.94569C20.8228 7.43263 22.2399 9.5546 24.6731 10.2869C25.8291 10.6355 27.0574 10.8109 28.2646 10.8998C30.4788 11.0613 30.6489 12.292 31.2479 13.3051C31.6255 13.9438 31.9914 14.5731 31.9914 16.4775C31.9914 18.3819 31.6231 19.0112 31.2479 19.6499C30.6489 20.6606 29.9101 21.3227 27.696 21.4865C26.4887 21.5754 25.2581 21.7508 24.1044 22.0994C21.6712 22.834 20.2542 24.9537 20.366 27.4406C20.4639 29.6187 22.2306 31.7407 24.3538 32.2273C26.8686 32.8052 29.3717 31.7945 30.4415 29.5462C31.0032 28.3671 31.3108 27.0312 31.5299 25.7304C31.9238 23.4002 32.8467 22.4948 35.1611 22.2421C36.6597 22.0784 38.2107 22.2421 39.615 21.4443C41.099 20.36 42.4248 18.7328 42.4248 16.4775C42.4248 14.2222 40.9961 11.8575 38.8262 11.1744Z' fill='%23E3E3E3'/%3E%3Cpath d='M15.1991 21.6854C12.2523 21.6854 9.84863 19.303 9.84863 16.3823C9.84863 13.4615 12.2523 11.0791 15.1991 11.0791C18.1459 11.0791 20.5497 13.4615 20.5497 16.3823C20.5497 19.3006 18.1436 21.6854 15.1991 21.6854Z' fill='%23E3E3E3'/%3E%3Cpath d='M5.28442 32.3871C2.36841 32.38 -0.00698992 29.9882 1.54551e-05 27.0652C0.00705187 24.1469 2.39884 21.7715 5.32187 21.7808C8.24022 21.7878 10.6156 24.1796 10.6063 27.1027C10.5992 30.0187 8.20746 32.3941 5.28442 32.3871Z' fill='%23E3E3E3'/%3E%3Cpath d='M44.736 32.387C41.8107 32.4033 39.4096 30.0373 39.3932 27.1237C39.3769 24.1984 41.7428 21.7973 44.6564 21.7808C47.5817 21.7645 49.9828 24.1305 49.9993 27.0441C50.0156 29.9671 47.6496 32.3705 44.736 32.387Z' fill='%23E3E3E3'/%3E%3C/svg%3E%0A\");\n}\n\n#error-page {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  width: 100%;\n}\n"
  },
  {
    "path": "examples/react/react-router/src/index.tsx",
    "content": "import * as React from 'react'\nimport * as ReactDOM from 'react-dom/client'\nimport { createBrowserRouter, RouterProvider } from 'react-router-dom'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\n\nimport './index.css'\n\nimport ErrorPage from './error-page'\nimport Root, { loader as rootLoader } from './routes/root'\nimport Contact, {\n  loader as contactLoader,\n  action as contactAction,\n} from './routes/contact'\nimport EditContact, { action as editAction } from './routes/edit'\nimport { action as destroyAction } from './routes/destroy'\nimport Index from './routes/index'\nimport NewContact, { action as newAction } from './routes/new'\n\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      staleTime: 1000 * 10,\n    },\n  },\n})\n\nconst router = createBrowserRouter([\n  {\n    path: '/',\n    element: <Root />,\n    errorElement: <ErrorPage />,\n    loader: rootLoader(queryClient),\n    children: [\n      {\n        index: true,\n        element: <Index />,\n      },\n      {\n        path: 'contacts/new',\n        element: <NewContact />,\n        action: newAction(queryClient),\n        errorElement: <ErrorPage />,\n      },\n      {\n        path: 'contacts/:contactId',\n        element: <Contact />,\n        loader: contactLoader(queryClient),\n        action: contactAction(queryClient),\n        errorElement: <ErrorPage />,\n      },\n      {\n        path: 'contacts/:contactId/edit',\n        element: <EditContact />,\n        loader: contactLoader(queryClient),\n        action: editAction(queryClient),\n        errorElement: <ErrorPage />,\n      },\n      {\n        path: 'contacts/:contactId/destroy',\n        element: <EditContact />,\n        action: destroyAction(queryClient),\n        errorElement: <ErrorPage />,\n      },\n    ],\n  },\n])\n\nconst rootElement = document.getElementById('root')\nReactDOM.createRoot(rootElement!).render(\n  <React.StrictMode>\n    <QueryClientProvider client={queryClient}>\n      <RouterProvider router={router} />\n      <ReactQueryDevtools buttonPosition=\"bottom-right\" />\n    </QueryClientProvider>\n  </React.StrictMode>,\n)\n"
  },
  {
    "path": "examples/react/react-router/src/routes/contact.tsx",
    "content": "import { Form, Link, useFetcher, useLoaderData } from 'react-router-dom'\nimport { queryOptions, useSuspenseQuery } from '@tanstack/react-query'\nimport { getContact, updateContact } from '../contacts'\nimport type { ActionFunctionArgs, LoaderFunctionArgs } from 'react-router-dom'\nimport type { Contact } from '../contacts'\nimport type { QueryClient } from '@tanstack/react-query'\n\nexport const contactDetailQuery = (id: string) =>\n  queryOptions({\n    queryKey: ['contacts', 'detail', id],\n    queryFn: async () => {\n      const contact = await getContact(id)\n      if (!contact) {\n        throw new Response('', {\n          status: 404,\n          statusText: 'Not Found',\n        })\n      }\n      return contact\n    },\n  })\n\nexport const loader =\n  (queryClient: QueryClient) =>\n  async ({ params }: LoaderFunctionArgs) => {\n    if (!params.contactId) {\n      throw new Error('No contact ID provided')\n    }\n    await queryClient.ensureQueryData(contactDetailQuery(params.contactId))\n    return { contactId: params.contactId }\n  }\n\nexport const action =\n  (queryClient: QueryClient) =>\n  async ({ request, params }: ActionFunctionArgs) => {\n    const formData = await request.formData()\n    if (!params.contactId) {\n      throw new Error('No contact ID provided')\n    }\n    await updateContact(params.contactId, {\n      favorite: formData.get('favorite') === 'true',\n    })\n    await queryClient.invalidateQueries({ queryKey: ['contacts'] })\n    return null\n  }\n\nexport default function Contact() {\n  const { contactId } = useLoaderData() as Awaited<\n    ReturnType<ReturnType<typeof loader>>\n  >\n  const { data: contact } = useSuspenseQuery(contactDetailQuery(contactId))\n\n  return (\n    <div id=\"contact\">\n      <div>\n        <img key={contact.avatar} src={contact.avatar || undefined} />\n      </div>\n\n      <div>\n        <h1>\n          {contact.first || contact.last ? (\n            <>\n              {contact.first} {contact.last}\n            </>\n          ) : (\n            <i>No Name</i>\n          )}{' '}\n          <Favorite contact={contact} />\n        </h1>\n\n        {contact.twitter && (\n          <p>\n            <a target=\"_blank\" href={`https://twitter.com/${contact.twitter}`}>\n              {contact.twitter}\n            </a>\n          </p>\n        )}\n\n        {contact.notes && <p>{contact.notes}</p>}\n\n        <div>\n          <Link to=\"edit\" className=\"button\">\n            Edit\n          </Link>\n          <Form\n            method=\"post\"\n            action=\"destroy\"\n            onSubmit={(event) => {\n              if (!confirm('Please confirm you want to delete this record.')) {\n                event.preventDefault()\n              }\n            }}\n          >\n            <button type=\"submit\">Delete</button>\n          </Form>\n        </div>\n      </div>\n    </div>\n  )\n}\n\nfunction Favorite({ contact }: { contact: Contact }) {\n  const fetcher = useFetcher({ key: `contact:${contact.id}` })\n  let favorite = contact.favorite\n  if (fetcher.formData) {\n    favorite = fetcher.formData.get('favorite') === 'true'\n  }\n\n  return (\n    <fetcher.Form method=\"post\">\n      <button\n        name=\"favorite\"\n        value={favorite ? 'false' : 'true'}\n        title={favorite ? 'Remove from favorites' : 'Add to favorites'}\n      >\n        {favorite ? '★' : '☆'}\n      </button>\n    </fetcher.Form>\n  )\n}\n"
  },
  {
    "path": "examples/react/react-router/src/routes/destroy.tsx",
    "content": "import { ActionFunctionArgs, redirect } from 'react-router-dom'\nimport { deleteContact } from '../contacts'\nimport { QueryClient } from '@tanstack/react-query'\n\nexport const action =\n  (queryClient: QueryClient) =>\n  async ({ params }: ActionFunctionArgs) => {\n    if (!params.contactId) {\n      throw new Error('No contact ID provided')\n    }\n    await deleteContact(params.contactId)\n    queryClient.invalidateQueries({ queryKey: ['contacts'] })\n    return redirect('/')\n  }\n"
  },
  {
    "path": "examples/react/react-router/src/routes/edit.tsx",
    "content": "import {\n  Form,\n  useLoaderData,\n  redirect,\n  useNavigate,\n  ActionFunctionArgs,\n} from 'react-router-dom'\n\nimport { Contact, updateContact } from '../contacts'\nimport { QueryClient, useSuspenseQuery } from '@tanstack/react-query'\nimport { contactDetailQuery, loader } from './contact'\n\nexport const action =\n  (queryClient: QueryClient) =>\n  async ({ request, params }: ActionFunctionArgs) => {\n    const formData = await request.formData()\n    const updates = Object.fromEntries(formData)\n    if (!params.contactId) {\n      throw new Error('No contact ID provided')\n    }\n    await updateContact(params.contactId, updates)\n    queryClient.invalidateQueries({ queryKey: ['contacts'] })\n    return redirect(`/contacts/${params.contactId}`)\n  }\n\nexport default function Edit() {\n  const { contactId } = useLoaderData() as Awaited<\n    ReturnType<ReturnType<typeof loader>>\n  >\n  const { data: contact } = useSuspenseQuery(contactDetailQuery(contactId))\n\n  return <ContactForm contact={contact} />\n}\n\nexport function ContactForm({ contact }: { contact?: Contact }) {\n  const navigate = useNavigate()\n\n  return (\n    <Form method=\"post\" id=\"contact-form\">\n      <p>\n        <span>Name</span>\n        <input\n          placeholder=\"First\"\n          aria-label=\"First name\"\n          type=\"text\"\n          name=\"first\"\n          defaultValue={contact?.first}\n        />\n        <input\n          placeholder=\"Last\"\n          aria-label=\"Last name\"\n          type=\"text\"\n          name=\"last\"\n          defaultValue={contact?.last}\n        />\n      </p>\n      <label>\n        <span>Twitter</span>\n        <input\n          type=\"text\"\n          name=\"twitter\"\n          placeholder=\"@jack\"\n          defaultValue={contact?.twitter}\n        />\n      </label>\n      <label>\n        <span>Avatar URL</span>\n        <input\n          placeholder=\"https://example.com/avatar.jpg\"\n          type=\"text\"\n          name=\"avatar\"\n          defaultValue={contact?.avatar}\n        />\n      </label>\n      <label>\n        <span>Notes</span>\n        <textarea name=\"notes\" defaultValue={contact?.notes} rows={6} />\n      </label>\n      <p>\n        <button type=\"submit\">Save</button>\n        <button\n          type=\"button\"\n          onClick={() => {\n            navigate(-1)\n          }}\n        >\n          Cancel\n        </button>\n      </p>\n    </Form>\n  )\n}\n"
  },
  {
    "path": "examples/react/react-router/src/routes/index.tsx",
    "content": "export default function Index() {\n  return (\n    <p id=\"zero-state\">\n      This is a demo for integrating React Router with React Query.\n      <br />\n      Check out{' '}\n      <a href=\"https://reactrouter.com/\">\n        the docs at reactrouter.com\n      </a> and{' '}\n      <a href=\"https://tanstack.com/query/v5/docs/\">the docs at tanstack.com</a>\n      .\n    </p>\n  )\n}\n"
  },
  {
    "path": "examples/react/react-router/src/routes/new.tsx",
    "content": "import { redirect, ActionFunctionArgs } from 'react-router-dom'\n\nimport { createContact } from '../contacts'\nimport { QueryClient } from '@tanstack/react-query'\nimport { ContactForm } from './edit'\n\nexport const action =\n  (queryClient: QueryClient) =>\n  async ({ request }: ActionFunctionArgs) => {\n    const formData = await request.formData()\n    const data = Object.fromEntries(formData)\n    const contact = await createContact(data as any)\n    queryClient.invalidateQueries({ queryKey: ['contacts', 'list'] })\n    return redirect(`/contacts/${contact.id}`)\n  }\n\nexport default function New() {\n  return <ContactForm />\n}\n"
  },
  {
    "path": "examples/react/react-router/src/routes/root.tsx",
    "content": "import {\n  Link,\n  NavLink,\n  Outlet,\n  useLoaderData,\n  useNavigation,\n  useSubmit,\n} from 'react-router-dom'\nimport { useDebounce } from 'rooks'\nimport {\n  queryOptions,\n  useIsFetching,\n  useSuspenseQuery,\n} from '@tanstack/react-query'\nimport { getContacts } from '../contacts'\nimport type { QueryClient } from '@tanstack/react-query'\nimport type { LoaderFunctionArgs } from 'react-router-dom'\n\nconst contactListQuery = (q?: string) =>\n  queryOptions({\n    queryKey: ['contacts', 'list', q ?? 'all'],\n    queryFn: () => getContacts(q),\n  })\n\nexport const loader =\n  (queryClient: QueryClient) =>\n  async ({ request }: LoaderFunctionArgs) => {\n    const url = new URL(request.url)\n    const q = url.searchParams.get('q') ?? ''\n    await queryClient.ensureQueryData(contactListQuery(q))\n    return { q }\n  }\n\nexport default function Root() {\n  const { q } = useLoaderData() as Awaited<\n    ReturnType<ReturnType<typeof loader>>\n  >\n  const { data: contacts } = useSuspenseQuery(contactListQuery(q))\n  const searching = useIsFetching({ queryKey: ['contacts', 'list'] }) > 0\n  const navigation = useNavigation()\n  const submit = useSubmit()\n\n  const debouncedSubmit = useDebounce(submit, 500)\n\n  return (\n    <>\n      <div id=\"sidebar\">\n        <h1>React Router Contacts</h1>\n        <div>\n          <form id=\"search-form\" role=\"search\">\n            <input\n              id=\"q\"\n              aria-label=\"Search contacts\"\n              placeholder=\"Search\"\n              type=\"search\"\n              name=\"q\"\n              key={q}\n              autoFocus\n              defaultValue={q}\n              className={searching ? 'loading' : ''}\n              onChange={(event) => {\n                debouncedSubmit(event.currentTarget.form)\n              }}\n            />\n            <div id=\"search-spinner\" aria-hidden hidden={!searching} />\n            <div className=\"sr-only\" aria-live=\"polite\"></div>\n          </form>\n          <Link to=\"contacts/new\" className=\"button\">\n            New\n          </Link>\n        </div>\n        <nav>\n          {contacts.length ? (\n            <ul>\n              {contacts.map((contact) => (\n                <li key={contact.id}>\n                  <NavLink\n                    to={`contacts/${contact.id}`}\n                    className={({ isActive, isPending }) =>\n                      isActive ? 'active' : isPending ? 'pending' : ''\n                    }\n                  >\n                    {contact.first || contact.last ? (\n                      <>\n                        {contact.first} {contact.last}\n                      </>\n                    ) : (\n                      <i>No Name</i>\n                    )}{' '}\n                    {contact.favorite && <span>★</span>}\n                  </NavLink>\n                </li>\n              ))}\n            </ul>\n          ) : (\n            <p>\n              <i>No contacts</i>\n            </p>\n          )}\n        </nav>\n      </div>\n      <div\n        id=\"detail\"\n        className={navigation.state === 'loading' ? 'loading' : ''}\n      >\n        <Outlet />\n      </div>\n    </>\n  )\n}\n"
  },
  {
    "path": "examples/react/react-router/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "examples/react/rick-morty/.eslintrc",
    "content": "{\n  \"extends\": [\"plugin:react/jsx-runtime\", \"plugin:react-hooks/recommended\"]\n}\n"
  },
  {
    "path": "examples/react/rick-morty/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\npnpm-lock.yaml\nyarn.lock\npackage-lock.json\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "examples/react/rick-morty/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `npm install`\n- `npm run dev`\n"
  },
  {
    "path": "examples/react/rick-morty/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"shortcut icon\" type=\"image/svg+xml\" href=\"/emblem-light.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <meta name=\"theme-color\" content=\"#000000\" />\n\n    <title>TanStack Query React Rick And Morty Example</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/index.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/react/rick-morty/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-react-rick-morty\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\",\n    \"react-router\": \"^6.25.1\",\n    \"react-router-dom\": \"^6.25.1\"\n  },\n  \"devDependencies\": {\n    \"@tailwindcss/vite\": \"^4.1.13\",\n    \"@vitejs/plugin-react\": \"^4.3.4\",\n    \"tailwindcss\": \"^4.1.13\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "examples/react/rick-morty/src/App.tsx",
    "content": "import { BrowserRouter as Router } from 'react-router-dom'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\nimport Layout from './Layout'\n\nimport './styles.css'\n\nconst queryClient = new QueryClient()\n\nexport default function App() {\n  return (\n    <QueryClientProvider client={queryClient}>\n      <Router>\n        <Layout />\n        <ReactQueryDevtools initialIsOpen />\n      </Router>\n    </QueryClientProvider>\n  )\n}\n"
  },
  {
    "path": "examples/react/rick-morty/src/Character.tsx",
    "content": "import { useParams, Link as RouterLink } from 'react-router-dom'\nimport { useQuery } from '@tanstack/react-query'\nimport { getCharacter, getEpisode, getLocation } from './api'\n\nfunction Character() {\n  let params = useParams()\n  const characterId = params.characterId!\n\n  const { status, data } = useQuery({\n    queryKey: ['character', characterId],\n    queryFn: () => getCharacter(characterId),\n  })\n\n  if (status === 'pending') return <p>Loading...</p>\n  if (status === 'error') return <p>Error :(</p>\n\n  const locationUrlParts = data.location.url.split('/').filter(Boolean)\n  const locationId = locationUrlParts[locationUrlParts.length - 1]\n\n  return (\n    <div>\n      <h2 className=\"text-4xl\">{data.name}</h2>\n      <p>\n        <strong>Gender</strong>: {data.gender}\n      </p>\n      <p>\n        <strong>Status</strong>: {data.status}\n      </p>\n      <p>\n        <strong>Species</strong>: {data.species}\n      </p>\n      <p>\n        <strong>Origin</strong>: {data.origin.name}\n      </p>\n      <p>\n        <strong>Location</strong>: <Location locationId={locationId} />\n      </p>\n\n      <h4 className=\"text-2xl pt-4\">Episodes</h4>\n      {data.episode.map((episode: any) => {\n        const episodeUrlParts = episode.split('/').filter(Boolean)\n        const episodeId = episodeUrlParts[episodeUrlParts.length - 1]\n        return <Episode episodeId={episodeId} key={`${episodeId}`} />\n      })}\n    </div>\n  )\n}\n\nfunction Episode({ episodeId }: { episodeId: string }) {\n  const { data, status } = useQuery({\n    queryKey: ['episode', episodeId],\n    queryFn: () => getEpisode(episodeId),\n  })\n\n  if (status === 'success') {\n    return (\n      <article key={episodeId}>\n        <RouterLink\n          className=\"text-blue-500 hover:underline\"\n          to={`/episodes/${episodeId}`}\n        >\n          <h6 className=\"text-lg\">\n            {data.episode}. {data.name} - {data.air_date}\n          </h6>\n        </RouterLink>\n      </article>\n    )\n  }\n}\n\nfunction Location({ locationId }: { locationId: string }) {\n  const { data, status } = useQuery({\n    queryKey: ['location', locationId],\n    queryFn: () => getLocation(locationId),\n  })\n\n  if (status === 'pending') return <span>Loading...</span>\n  if (status === 'error') return <span>Error :(</span>\n\n  return (\n    <span>\n      {data.name} - {data.type}\n    </span>\n  )\n}\n\nexport default Character\n"
  },
  {
    "path": "examples/react/rick-morty/src/Characters.tsx",
    "content": "import { Link as RouterLink } from 'react-router-dom'\nimport { useQuery } from '@tanstack/react-query'\nimport { getCharacters } from './api'\n\nexport default function Characters() {\n  const { status, data } = useQuery({\n    queryKey: ['characters'],\n    queryFn: () => getCharacters(),\n  })\n\n  if (status === 'pending') return <p>Loading...</p>\n  if (status === 'error') return <p>Error :(</p>\n\n  return (\n    <div>\n      <h2 className=\"text-4xl\">Characters</h2>\n      {data.results.map((person: any) => {\n        return (\n          <article key={person.id}>\n            <RouterLink\n              className=\"text-blue-500 hover:underline\"\n              to={`/characters/${person.id}`}\n            >\n              <h6 className=\"text-xl\">\n                {person.name} - {person.gender}: {person.species}\n              </h6>\n            </RouterLink>\n          </article>\n        )\n      })}\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/react/rick-morty/src/Episode.tsx",
    "content": "import { useParams, Link as RouterLink } from 'react-router-dom'\nimport { useQuery } from '@tanstack/react-query'\nimport { getCharacter, getEpisode } from './api'\n\nfunction Episode() {\n  let params = useParams()\n  const episodeId = params.episodeId!\n\n  const { data, status } = useQuery({\n    queryKey: ['episode', episodeId],\n    queryFn: () => getEpisode(episodeId),\n  })\n\n  if (status === 'pending') return <p>Loading...</p>\n\n  if (status === 'error') return <p>Error :(</p>\n\n  return (\n    <div>\n      <h2 className=\"text-4xl\">{data.name}</h2>\n      <p>{data.air_date}</p>\n      <br />\n      <h4 className=\"text-2xl\">Characters</h4>\n      {data.characters.map((character: any) => {\n        const characterUrlParts = character.split('/').filter(Boolean)\n        const characterId = characterUrlParts[characterUrlParts.length - 1]\n        return <Character characterId={characterId} key={characterId} />\n      })}\n    </div>\n  )\n}\n\nfunction Character({ characterId }: { characterId: string }) {\n  const { data, status } = useQuery({\n    queryKey: ['character', characterId],\n    queryFn: () => getCharacter(characterId),\n  })\n\n  if (status === 'pending') return <p>Loading...</p>\n  if (status === 'error') return <p>Error :(</p>\n\n  return (\n    <article key={characterId}>\n      <RouterLink\n        className=\"text-blue-500 hover:underline\"\n        to={`/characters/${characterId}`}\n      >\n        <h6 className=\"text-lg\">{data.name}</h6>\n      </RouterLink>\n    </article>\n  )\n}\n\nexport default Episode\n"
  },
  {
    "path": "examples/react/rick-morty/src/Episodes.tsx",
    "content": "import { Link as RouterLink } from 'react-router-dom'\nimport { useQuery } from '@tanstack/react-query'\nimport { getEpisodes } from './api'\n\nexport default function Episodes() {\n  const { data, status } = useQuery({\n    queryKey: ['episodes'],\n    queryFn: () => getEpisodes(),\n  })\n\n  if (status === 'pending') {\n    return <p>Loading...</p>\n  }\n  if (status === 'error') {\n    return <p>Error :(</p>\n  }\n\n  return (\n    <div>\n      <h2 className=\"text-4xl\">Episodes</h2>\n      {data.results.map((episode: any) => (\n        <article key={episode.id}>\n          <RouterLink\n            className=\"text-blue-500 hover:underline\"\n            to={`/episodes/${episode.id}`}\n          >\n            <h6 className=\"text-xl\">\n              {episode.episode} - {episode.name} <em>{episode.airDate}</em>\n            </h6>\n          </RouterLink>\n        </article>\n      ))}\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/react/rick-morty/src/Home.tsx",
    "content": "import { Link as RouterLink } from 'react-router-dom'\n\nexport default function Home() {\n  return (\n    <div>\n      <h2 className=\"text-4xl\">TanStack Query Demo</h2>\n      <p>Using the Rick And Morty API</p>\n      <p>\n        (Built by{' '}\n        <a\n          className=\"text-blue-500 hover:underline\"\n          href=\"https://twitter.com/axelfuh\"\n        >\n          @axelfuh\n        </a>\n        )\n      </p>\n      <h5 className=\"text-2xl pt-4\">Why TanStack Query?</h5>\n      <p>\n        In this demo you will be able to see how TanStack Query is a significant\n        improvement over <strong>redux</strong>, <strong>mobx</strong>, and any\n        other general-purpose state container.\n      </p>\n      <p>\n        No reducers, thunks, or sagas. No ES6 models to maintain in order to tag\n        them as observable.\n      </p>\n      <p>\n        Simply associate a key with your fetch call and let{' '}\n        <strong>TanStack Query</strong> handle the rest.\n      </p>\n      <h5 className=\"text-2xl pt-4\">Ready to get started?</h5>\n      <p>\n        Check out the{' '}\n        <RouterLink className=\"text-blue-500 hover:underline\" to=\"/episodes\">\n          Episodes\n        </RouterLink>{' '}\n        and{' '}\n        <RouterLink className=\"text-blue-500 hover:underline\" to=\"/characters\">\n          Characters\n        </RouterLink>\n        !\n      </p>\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/react/rick-morty/src/Layout.tsx",
    "content": "import { Route, Link as RouterLink, Routes } from 'react-router-dom'\nimport Episodes from './Episodes'\nimport Episode from './Episode'\nimport Characters from './Characters'\nimport Character from './Character'\nimport Home from './Home'\n\nexport default function Layout() {\n  return (\n    <div>\n      <nav className=\"bg-gray-300 w-full flex flex-row gap-6 justify-center items-center h-12\">\n        <RouterLink to=\"/\">\n          <span className=\"uppercase hover:underline\">Home</span>\n        </RouterLink>\n        <RouterLink to=\"/episodes\">\n          <span className=\"uppercase hover:underline\">Episodes</span>\n        </RouterLink>\n        <RouterLink to=\"/characters\">\n          <span className=\"uppercase hover:underline\">Characters</span>\n        </RouterLink>\n      </nav>\n      <div className=\"p-2\">\n        <Routes>\n          <Route exact path=\"/episodes\" element={<Episodes />} />\n          <Route exact path=\"/episodes/:episodeId\" element={<Episode />} />\n          <Route exact path=\"/characters\" element={<Characters />} />\n          <Route\n            exact\n            path=\"/characters/:characterId\"\n            element={<Character />}\n          />\n          <Route path=\"/\" element={<Home />} />\n        </Routes>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/react/rick-morty/src/api.ts",
    "content": "export const getEpisodes = async () => {\n  const res = await fetch('https://rickandmortyapi.com/api/episode/')\n  return await res.json()\n}\n\nexport const getEpisode = async (episodeId: string) => {\n  const res = await fetch(\n    `https://rickandmortyapi.com/api/episode/${episodeId}`,\n  )\n  return await res.json()\n}\n\nexport const getCharacters = async () => {\n  const res = await fetch('https://rickandmortyapi.com/api/character/')\n  return await res.json()\n}\n\nexport const getCharacter = async (characterId: string) => {\n  const res = await fetch(\n    `https://rickandmortyapi.com/api/character/${characterId}`,\n  )\n  return await res.json()\n}\n\nexport const getLocation = async (locationId: string) => {\n  const res = await fetch(\n    `https://rickandmortyapi.com/api/location/${locationId}`,\n  )\n  return await res.json()\n}\n"
  },
  {
    "path": "examples/react/rick-morty/src/index.tsx",
    "content": "import ReactDOM from 'react-dom/client'\nimport App from './App'\n\nconst rootElement = document.getElementById('root')\nif (!rootElement) throw new Error('Missing #root element')\nReactDOM.createRoot(rootElement).render(<App />)\n"
  },
  {
    "path": "examples/react/rick-morty/src/styles.css",
    "content": "@import 'tailwindcss';\n\n@theme {\n  --font-sans:\n    Roboto, BlinkMacSystemFont, -apple-system, Segoe UI, Roboto, Oxygen, Ubuntu,\n    Cantarell, Fira Sans, Droid Sans, Helvetica Neue, Helvetica, Arial,\n    sans-serif;\n  --font-mono:\n    Roboto Mono, BlinkMacSystemFont, -apple-system, Segoe UI, Roboto, Oxygen,\n    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, Helvetica, Arial,\n    sans-serif;\n}\n\n@layer base {\n  body {\n    @apply font-sans;\n  }\n\n  h1,\n  h2,\n  h3,\n  h4,\n  h5,\n  h6 {\n    @apply font-mono;\n  }\n}\n"
  },
  {
    "path": "examples/react/rick-morty/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n    \"allowJs\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src\", \"eslint.config.js\", \"vite.config.ts\"]\n}\n"
  },
  {
    "path": "examples/react/rick-morty/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\nimport tailwindcss from '@tailwindcss/vite'\n\nexport default defineConfig({\n  plugins: [tailwindcss(), react()],\n})\n"
  },
  {
    "path": "examples/react/shadow-dom/.gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "examples/react/shadow-dom/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `pnpm install`\n- `pnpm run dev`\n"
  },
  {
    "path": "examples/react/shadow-dom/eslint.config.js",
    "content": "import { tanstackConfig } from '@tanstack/eslint-config'\nimport pluginQuery from '@tanstack/eslint-plugin-query'\nimport pluginReact from '@eslint-react/eslint-plugin'\n\nexport default [\n  ...tanstackConfig,\n  ...pluginQuery.configs['flat/recommended'],\n  pluginReact.configs.recommended,\n]\n"
  },
  {
    "path": "examples/react/shadow-dom/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/vite.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite + React + TS</title>\n  </head>\n  <body>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/main.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/react/shadow-dom/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-react-shadow-dom\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\"\n  },\n  \"devDependencies\": {\n    \"@types/react\": \"^19.0.1\",\n    \"@types/react-dom\": \"^19.0.2\",\n    \"@vitejs/plugin-react\": \"^4.3.4\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "examples/react/shadow-dom/src/DogList.tsx",
    "content": "import { useQuery } from '@tanstack/react-query'\n\ntype DogsResp = {\n  message: {\n    [dog: string]: Array<string>\n  }\n}\n\nexport const DogList = () => {\n  const { data, status } = useQuery<DogsResp>({\n    queryKey: ['dogs'],\n    queryFn: async () => {\n      const resp = await fetch('https://dog.ceo/api/breeds/list/all')\n      if (resp.ok) {\n        return resp.json()\n      }\n      throw new Error('something went wrong')\n    },\n  })\n\n  if (status === 'pending') return 'Loading...'\n\n  if (status === 'error') return 'Error!'\n\n  const dogs = Object.keys(data.message)\n\n  return (\n    <div>\n      {dogs.map((dog) => (\n        <div key={dog}>{dog}</div>\n      ))}\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/react/shadow-dom/src/index.css",
    "content": ":root {\n  font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;\n  line-height: 1.5;\n  font-weight: 400;\n\n  color-scheme: light dark;\n  color: rgba(255, 255, 255, 0.87);\n  background-color: #242424;\n\n  font-synthesis: none;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\na {\n  font-weight: 500;\n  color: #646cff;\n  text-decoration: inherit;\n}\na:hover {\n  color: #535bf2;\n}\n\nbody {\n  margin: 0;\n  display: flex;\n  place-items: center;\n  min-width: 320px;\n  min-height: 100vh;\n}\n\nh1 {\n  font-size: 3.2em;\n  line-height: 1.1;\n}\n\nbutton {\n  border-radius: 8px;\n  border: 1px solid transparent;\n  padding: 0.6em 1.2em;\n  font-size: 1em;\n  font-weight: 500;\n  font-family: inherit;\n  background-color: #1a1a1a;\n  cursor: pointer;\n  transition: border-color 0.25s;\n}\nbutton:hover {\n  border-color: #646cff;\n}\nbutton:focus,\nbutton:focus-visible {\n  outline: 4px auto -webkit-focus-ring-color;\n}\n\n@media (prefers-color-scheme: light) {\n  :root {\n    color: #213547;\n    background-color: #ffffff;\n  }\n  a:hover {\n    color: #747bff;\n  }\n  button {\n    background-color: #f9f9f9;\n  }\n}\n"
  },
  {
    "path": "examples/react/shadow-dom/src/main.tsx",
    "content": "import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport './index.css'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\nimport { DogList } from './DogList'\n\nconst appRoot = document.getElementById('root')\n\nif (appRoot) {\n  const queryClient = new QueryClient()\n  const shadowRoot = appRoot.attachShadow({ mode: 'open' })\n  const root = ReactDOM.createRoot(shadowRoot)\n\n  root.render(\n    <React.StrictMode>\n      <QueryClientProvider client={queryClient}>\n        <div\n          style={{\n            width: '100vw',\n            padding: '30px',\n          }}\n        >\n          <h2>Dog Breeds</h2>\n          <DogList />\n        </div>\n        <ReactQueryDevtools\n          initialIsOpen={false}\n          buttonPosition=\"bottom-left\"\n          shadowDOMTarget={appRoot.shadowRoot!}\n        />\n      </QueryClientProvider>\n    </React.StrictMode>,\n  )\n}\n"
  },
  {
    "path": "examples/react/shadow-dom/src/vite-env.d.ts",
    "content": "/// <reference types=\"vite/client\" />\n"
  },
  {
    "path": "examples/react/shadow-dom/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src\", \"eslint.config.js\"]\n}\n"
  },
  {
    "path": "examples/react/shadow-dom/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n  plugins: [react()],\n})\n"
  },
  {
    "path": "examples/react/simple/.eslintrc",
    "content": "{\n  \"extends\": [\"plugin:react/jsx-runtime\", \"plugin:react-hooks/recommended\"]\n}\n"
  },
  {
    "path": "examples/react/simple/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\npnpm-lock.yaml\nyarn.lock\npackage-lock.json\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "examples/react/simple/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `npm install`\n- `npm run dev`\n"
  },
  {
    "path": "examples/react/simple/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/emblem-light.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <meta name=\"theme-color\" content=\"#000000\" />\n\n    <title>TanStack Query React Simple Example App</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/index.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/react/simple/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-react-simple\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\"\n  },\n  \"devDependencies\": {\n    \"@vitejs/plugin-react\": \"^4.3.4\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "examples/react/simple/src/index.tsx",
    "content": "import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport {\n  QueryClient,\n  QueryClientProvider,\n  useQuery,\n} from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\n\nconst queryClient = new QueryClient()\n\nexport default function App() {\n  return (\n    <QueryClientProvider client={queryClient}>\n      <ReactQueryDevtools />\n      <Example />\n    </QueryClientProvider>\n  )\n}\n\nfunction Example() {\n  const { isPending, error, data, isFetching } = useQuery({\n    queryKey: ['repoData'],\n    queryFn: async () => {\n      const response = await fetch(\n        'https://api.github.com/repos/TanStack/query',\n      )\n      return await response.json()\n    },\n  })\n\n  if (isPending) return 'Loading...'\n\n  if (error) return 'An error has occurred: ' + error.message\n\n  return (\n    <div>\n      <h1>{data.full_name}</h1>\n      <p>{data.description}</p>\n      <strong>👀 {data.subscribers_count}</strong>{' '}\n      <strong>✨ {data.stargazers_count}</strong>{' '}\n      <strong>🍴 {data.forks_count}</strong>\n      <div>{isFetching ? 'Updating...' : ''}</div>\n    </div>\n  )\n}\n\nconst rootElement = document.getElementById('root')\nif (!rootElement) throw new Error('Missing #root element')\nReactDOM.createRoot(rootElement).render(<App />)\n"
  },
  {
    "path": "examples/react/simple/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src\", \"eslint.config.js\"]\n}\n"
  },
  {
    "path": "examples/react/simple/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\n\nexport default defineConfig({\n  plugins: [react()],\n})\n"
  },
  {
    "path": "examples/react/star-wars/.eslintrc",
    "content": "{\n  \"extends\": [\"plugin:react/jsx-runtime\", \"plugin:react-hooks/recommended\"]\n}\n"
  },
  {
    "path": "examples/react/star-wars/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\npnpm-lock.yaml\nyarn.lock\npackage-lock.json\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "examples/react/star-wars/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `npm install`\n- `npm run dev`\n"
  },
  {
    "path": "examples/react/star-wars/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"shortcut icon\" type=\"image/svg+xml\" href=\"/emblem-light.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <meta name=\"theme-color\" content=\"#000000\" />\n\n    <title>TanStack Query React Star Wars Example</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/index.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/react/star-wars/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-react-star-wars\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\",\n    \"react-router\": \"^6.25.1\",\n    \"react-router-dom\": \"^6.25.1\"\n  },\n  \"devDependencies\": {\n    \"@tailwindcss/vite\": \"^4.1.13\",\n    \"@vitejs/plugin-react\": \"^4.3.4\",\n    \"tailwindcss\": \"^4.1.13\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "examples/react/star-wars/src/App.tsx",
    "content": "import { BrowserRouter as Router } from 'react-router-dom'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\nimport Layout from './Layout'\n\nimport './styles.css'\n\nconst queryClient = new QueryClient()\n\nexport default function App() {\n  return (\n    <QueryClientProvider client={queryClient}>\n      <Router>\n        <Layout />\n        <ReactQueryDevtools initialIsOpen />\n      </Router>\n    </QueryClientProvider>\n  )\n}\n"
  },
  {
    "path": "examples/react/star-wars/src/Character.tsx",
    "content": "import { useParams, Link as RouterLink } from 'react-router-dom'\nimport { useQuery } from '@tanstack/react-query'\nimport { getCharacter, getFilm, getPlanet } from './api'\n\nexport default function Character() {\n  let params = useParams()\n  const characterId = params.characterId!\n\n  const { status, data } = useQuery({\n    queryKey: ['character', characterId],\n    queryFn: () => getCharacter(characterId),\n  })\n\n  if (status === 'pending') return <p>Loading...</p>\n  if (status === 'error') return <p>Error :(</p>\n\n  const homeworldUrlParts = data.homeworld.split('/').filter(Boolean)\n  const homeworldId = homeworldUrlParts[homeworldUrlParts.length - 1]\n\n  return (\n    <div>\n      <h2 className=\"text-4xl\">{data.name}</h2>\n      <p>\n        <strong>Born</strong>: {data.birth_year}\n      </p>\n      <p>\n        <strong>Eyes</strong>: {data.eye_color}\n      </p>\n      <p>\n        <strong>Hair</strong>: {data.hair_color}\n      </p>\n      <p>\n        <strong>Height</strong>: {data.height}\n      </p>\n      <p>\n        <strong>Mass</strong>: {data.mass}\n      </p>\n      <p>\n        <strong>Homeworld</strong>: <Homeworld homeworldId={homeworldId} />\n      </p>\n\n      <h4 className=\"text-2xl pt-4\">Films</h4>\n      {data.films.map((film: any) => {\n        const filmUrlParts = film.split('/').filter(Boolean)\n        const filmId = filmUrlParts[filmUrlParts.length - 1]\n        return <Film filmId={filmId} key={`${filmId}`} />\n      })}\n    </div>\n  )\n}\n\nfunction Film({ filmId }: { filmId: string }) {\n  const { data, status } = useQuery({\n    queryKey: ['film', filmId],\n    queryFn: () => getFilm(filmId),\n  })\n\n  if (status === 'success') {\n    return (\n      <RouterLink\n        className=\"text-blue-500 hover:underline\"\n        to={`/films/${filmId}`}\n      >\n        <h6 className=\"text-lg\">\n          {data.episode_id}. {data.title}\n        </h6>\n      </RouterLink>\n    )\n  }\n}\n\nfunction Homeworld({ homeworldId }: { homeworldId: string }) {\n  const { data, status } = useQuery({\n    queryKey: ['homeworld', homeworldId],\n    queryFn: () => getPlanet(homeworldId),\n  })\n\n  if (status === 'pending') return <span>Loading...</span>\n  if (status === 'error') return <span>Error :(</span>\n\n  return <span>{data.name}</span>\n}\n"
  },
  {
    "path": "examples/react/star-wars/src/Characters.tsx",
    "content": "import { Link as RouterLink } from 'react-router-dom'\nimport { useQuery } from '@tanstack/react-query'\nimport { getCharacters } from './api'\n\nexport default function Characters() {\n  const { status, data } = useQuery({\n    queryKey: ['characters'],\n    queryFn: () => getCharacters(),\n  })\n\n  if (status === 'pending') return <p>Loading...</p>\n  if (status === 'error') return <p>Error :(</p>\n\n  return (\n    <div>\n      <h2 className=\"text-4xl\">Characters</h2>\n      {data.results.map((person: any) => {\n        const personUrlParts = person.url.split('/').filter(Boolean)\n        const personId = personUrlParts[personUrlParts.length - 1]\n        return (\n          <article key={personId}>\n            <RouterLink\n              className=\"text-blue-500 hover:underline\"\n              to={`/characters/${personId}`}\n            >\n              <h6 className=\"text-xl\">{person.name}</h6>\n            </RouterLink>\n          </article>\n        )\n      })}\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/react/star-wars/src/Film.tsx",
    "content": "import { useParams, Link as RouterLink } from 'react-router-dom'\nimport { useQuery } from '@tanstack/react-query'\nimport { getFilm, getCharacter } from './api'\n\nexport default function Film() {\n  let params = useParams()\n  const filmId = params.filmId!\n\n  const { data, status } = useQuery({\n    queryKey: ['film', filmId],\n    queryFn: () => getFilm(filmId),\n  })\n\n  if (status === 'pending') return <p>Loading...</p>\n\n  if (status === 'error') return <p>Error :(</p>\n\n  return (\n    <div>\n      <h2 className=\"text-4xl\">{data.title}</h2>\n      <p>{data.opening_crawl}</p>\n      <br />\n      <h4 className=\"text-2xl\">Characters</h4>\n      {data.characters.map((character: any) => {\n        const characterUrlParts = character.split('/').filter(Boolean)\n        const characterId = characterUrlParts[characterUrlParts.length - 1]\n        return <Character characterId={characterId} key={characterId} />\n      })}\n    </div>\n  )\n}\n\nfunction Character({ characterId }: { characterId: string }) {\n  const { data, status } = useQuery({\n    queryKey: ['character', characterId],\n    queryFn: () => getCharacter(characterId),\n  })\n\n  if (status !== 'success') {\n    return null\n  }\n\n  return (\n    <RouterLink\n      className=\"text-blue-500 hover:underline\"\n      to={`/characters/${characterId}`}\n    >\n      <h6 className=\"text-lg\">{data.name}</h6>\n    </RouterLink>\n  )\n}\n"
  },
  {
    "path": "examples/react/star-wars/src/Films.tsx",
    "content": "import { Link as RouterLink } from 'react-router-dom'\nimport { useQuery } from '@tanstack/react-query'\nimport { getFilms } from './api'\n\nexport default function Films() {\n  const { data, status } = useQuery({\n    queryKey: ['films'],\n    queryFn: () => getFilms(),\n  })\n\n  if (status === 'pending') {\n    return <p>Loading...</p>\n  }\n  if (status === 'error') {\n    return <p>Error :(</p>\n  }\n\n  return (\n    <div>\n      <h2 className=\"text-4xl\">Films</h2>\n      {data.results.map((film: any) => {\n        const filmUrlParts = film.url.split('/').filter(Boolean)\n        const filmId = filmUrlParts[filmUrlParts.length - 1]\n        return (\n          <article key={filmId}>\n            <RouterLink\n              className=\"text-blue-500 hover:underline\"\n              to={`/films/${filmId}`}\n            >\n              <h6 className=\"text-xl\">\n                {film.episode_id}. {film.title}{' '}\n                <em>\n                  ({new Date(Date.parse(film.release_date)).getFullYear()})\n                </em>\n              </h6>\n            </RouterLink>\n          </article>\n        )\n      })}\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/react/star-wars/src/Home.tsx",
    "content": "import { Link as RouterLink } from 'react-router-dom'\n\nexport default function Home() {\n  return (\n    <div>\n      <h2 className=\"text-4xl\">TanStack Query Demo</h2>\n      <p>Using the Star Wars API</p>\n      <p>\n        (Built by{' '}\n        <a\n          className=\"text-blue-500 hover:underline\"\n          href=\"https://twitter.com/Brent_m_Clark\"\n        >\n          @Brent_m_Clark\n        </a>\n        )\n      </p>\n      <h5 className=\"text-2xl pt-4\">Why TanStack Query?</h5>\n      <p>\n        In this demo you will be able to see how TanStack Query is a significant\n        improvement over <strong>redux</strong>, <strong>mobx</strong>, and any\n        other general-purpose state container.\n      </p>\n      <p>\n        No reducers, thunks, or sagas. No ES6 models to maintain in order to tag\n        them as observable.\n      </p>\n      <p>\n        Simply associate a key with your fetch call and let{' '}\n        <strong>TanStack Query</strong> handle the rest.\n      </p>\n      <h5 className=\"text-2xl pt-4\">Ready to get started?</h5>\n      <p>\n        Check out the{' '}\n        <RouterLink className=\"text-blue-500 hover:underline\" to=\"/films\">\n          Films\n        </RouterLink>{' '}\n        and{' '}\n        <RouterLink className=\"text-blue-500 hover:underline\" to=\"/characters\">\n          Characters\n        </RouterLink>\n        !\n      </p>\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/react/star-wars/src/Layout.tsx",
    "content": "import { Route, Link as RouterLink, Routes } from 'react-router-dom'\nimport Films from './Films'\nimport Film from './Film'\nimport Characters from './Characters'\nimport Character from './Character'\nimport Home from './Home'\n\nexport default function Layout() {\n  return (\n    <div>\n      <nav className=\"bg-gray-300 w-full flex flex-row gap-6 justify-center items-center h-12\">\n        <RouterLink to=\"/\">\n          <span className=\"uppercase hover:underline\">Home</span>\n        </RouterLink>\n        <RouterLink to=\"/films\">\n          <span className=\"uppercase hover:underline\">Films</span>\n        </RouterLink>\n        <RouterLink to=\"/characters\">\n          <span className=\"uppercase hover:underline\">Characters</span>\n        </RouterLink>\n      </nav>\n      <div className=\"p-2\">\n        <Routes>\n          <Route exact path=\"/films\" element={<Films />} />\n          <Route exact path=\"/films/:filmId\" element={<Film />} />\n          <Route exact path=\"/characters\" element={<Characters />} />\n          <Route\n            exact\n            path=\"/characters/:characterId\"\n            element={<Character />}\n          />\n          <Route path=\"/\" element={<Home />} />\n        </Routes>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/react/star-wars/src/api.ts",
    "content": "export const getFilms = async () => {\n  const res = await fetch('https://swapi.dev/api/films/')\n  return await res.json()\n}\n\nexport const getFilm = async (filmId: string) => {\n  const res = await fetch(`https://swapi.dev/api/films/${filmId}/`)\n  return await res.json()\n}\n\nexport const getCharacters = async () => {\n  const res = await fetch('https://swapi.dev/api/people/')\n  return await res.json()\n}\n\nexport const getCharacter = async (characterId: string) => {\n  const res = await fetch(`https://swapi.dev/api/people/${characterId}/`)\n  return await res.json()\n}\n\nexport const getPlanet = async (planetId: string) => {\n  const res = await fetch(`https://swapi.dev/api/planets/${planetId}/`)\n  return await res.json()\n}\n"
  },
  {
    "path": "examples/react/star-wars/src/index.tsx",
    "content": "import ReactDOM from 'react-dom/client'\nimport App from './App'\n\nconst rootElement = document.getElementById('root')\nif (!rootElement) throw new Error('Missing #root element')\nReactDOM.createRoot(rootElement).render(<App />)\n"
  },
  {
    "path": "examples/react/star-wars/src/styles.css",
    "content": "@import 'tailwindcss';\n\n@theme {\n  --font-sans:\n    Roboto, BlinkMacSystemFont, -apple-system, Segoe UI, Roboto, Oxygen, Ubuntu,\n    Cantarell, Fira Sans, Droid Sans, Helvetica Neue, Helvetica, Arial,\n    sans-serif;\n  --font-mono:\n    Roboto Mono, BlinkMacSystemFont, -apple-system, Segoe UI, Roboto, Oxygen,\n    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, Helvetica, Arial,\n    sans-serif;\n}\n\n@layer base {\n  body {\n    @apply font-sans;\n  }\n\n  h1,\n  h2,\n  h3,\n  h4,\n  h5,\n  h6 {\n    @apply font-mono;\n  }\n}\n"
  },
  {
    "path": "examples/react/star-wars/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n    \"allowJs\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src\", \"eslint.config.js\", \"vite.config.ts\"]\n}\n"
  },
  {
    "path": "examples/react/star-wars/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\nimport tailwindcss from '@tailwindcss/vite'\n\nexport default defineConfig({\n  plugins: [tailwindcss(), react()],\n})\n"
  },
  {
    "path": "examples/react/suspense/.eslintrc",
    "content": "{\n  \"extends\": [\"plugin:react/jsx-runtime\", \"plugin:react-hooks/recommended\"]\n}\n"
  },
  {
    "path": "examples/react/suspense/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\npnpm-lock.yaml\nyarn.lock\npackage-lock.json\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "examples/react/suspense/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `pnpm install`\n- `pnpm dev`\n"
  },
  {
    "path": "examples/react/suspense/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"shortcut icon\" type=\"image/svg+xml\" href=\"/emblem-light.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <meta name=\"theme-color\" content=\"#000000\" />\n\n    <title>TanStack Query React Suspense Example App</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/index.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/react/suspense/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-react-suspense\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.3\",\n    \"font-awesome\": \"^4.7.0\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\",\n    \"react-error-boundary\": \"^4.1.2\"\n  },\n  \"devDependencies\": {\n    \"@vitejs/plugin-react\": \"^4.3.4\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "examples/react/suspense/src/components/Button.tsx",
    "content": "import React from 'react'\n\nimport Spinner from './Spinner'\n\nexport default function Button({\n  children,\n  onClick,\n}: {\n  children: React.ReactNode\n  onClick: any\n}) {\n  const [isPending, startTransition] = React.useTransition()\n\n  const handleClick = (e: any) => {\n    startTransition(() => {\n      onClick(e)\n    })\n  }\n\n  return (\n    <>\n      <button onClick={handleClick} disabled={isPending}>\n        {children} {isPending ? <Spinner /> : null}\n      </button>\n    </>\n  )\n}\n"
  },
  {
    "path": "examples/react/suspense/src/components/Project.tsx",
    "content": "import React from 'react'\nimport { useSuspenseQuery } from '@tanstack/react-query'\nimport { fetchProject } from '../queries'\nimport Button from './Button'\nimport Spinner from './Spinner'\n\nexport default function Project({\n  activeProject,\n  setActiveProject,\n}: {\n  activeProject: string\n  setActiveProject: React.Dispatch<React.SetStateAction<string | null>>\n}) {\n  const { data, isFetching } = useSuspenseQuery({\n    queryKey: ['project', activeProject],\n    queryFn: () => fetchProject(activeProject),\n  })\n\n  return (\n    <div>\n      <Button onClick={() => setActiveProject(null)}>Back</Button>\n      <h1>\n        {activeProject} {isFetching ? <Spinner /> : null}\n      </h1>\n      <div>\n        <p>forks: {data.forks_count}</p>\n        <p>stars: {data.stargazers_count}</p>\n        <p>watchers: {data.watchers_count}</p>\n      </div>\n      <br />\n      <br />\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/react/suspense/src/components/Projects.tsx",
    "content": "import React from 'react'\nimport { useQueryClient, useSuspenseQuery } from '@tanstack/react-query'\nimport { fetchProject, fetchProjects } from '../queries'\nimport Button from './Button'\nimport Spinner from './Spinner'\n\nexport default function Projects({\n  setActiveProject,\n}: {\n  setActiveProject: React.Dispatch<React.SetStateAction<string | null>>\n}) {\n  const queryClient = useQueryClient()\n  const { data, isFetching } = useSuspenseQuery({\n    queryKey: ['projects'],\n    queryFn: fetchProjects,\n  })\n\n  return (\n    <div>\n      <h1>TanStack Repositories {isFetching ? <Spinner /> : null}</h1>\n      {data.map((project) => (\n        <p key={project.full_name}>\n          <Button\n            onClick={() => {\n              // Prefetch the project query\n              queryClient.prefetchQuery({\n                queryKey: ['project', project.full_name],\n                queryFn: () => fetchProject(project.full_name),\n              })\n              setActiveProject(project.full_name)\n            }}\n          >\n            Load\n          </Button>{' '}\n          {project.name}\n        </p>\n      ))}\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/react/suspense/src/components/Spinner.tsx",
    "content": "import React from 'react'\n\nexport default function Spinner() {\n  return (\n    <span\n      className=\"fa fa-circle-o-notch fa-spin\"\n      style={{\n        marginLeft: 4,\n        fontSize: 'small',\n      }}\n    />\n  )\n}\n"
  },
  {
    "path": "examples/react/suspense/src/index.tsx",
    "content": "import 'font-awesome/css/font-awesome.min.css'\nimport React, { lazy } from 'react'\nimport ReactDOM from 'react-dom/client'\nimport {\n  QueryClient,\n  QueryClientProvider,\n  QueryErrorResetBoundary,\n  useQueryClient,\n} from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\nimport { ErrorBoundary } from 'react-error-boundary'\n\nimport { fetchProjects } from './queries'\n\nimport Button from './components/Button'\n\nconst Projects = lazy(() => import('./components/Projects'))\nconst Project = lazy(() => import('./components/Project'))\n\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      retry: 0,\n    },\n  },\n})\n\nfunction App() {\n  return (\n    <QueryClientProvider client={queryClient}>\n      <Example />\n    </QueryClientProvider>\n  )\n}\n\nfunction Example() {\n  const queryClient = useQueryClient()\n  const [showProjects, setShowProjects] = React.useState(false)\n  const [activeProject, setActiveProject] = React.useState<string | null>(null)\n\n  return (\n    <>\n      <Button\n        onClick={() => {\n          setShowProjects((old) => {\n            if (!old) {\n              queryClient.prefetchQuery({\n                queryKey: ['projects'],\n                queryFn: fetchProjects,\n              })\n            }\n            return !old\n          })\n        }}\n      >\n        {showProjects ? 'Hide Projects' : 'Show Projects'}\n      </Button>\n\n      <hr />\n\n      <QueryErrorResetBoundary>\n        {({ reset }) => (\n          <ErrorBoundary\n            fallbackRender={({ error, resetErrorBoundary }) => (\n              <div>\n                There was an error!{' '}\n                <Button onClick={() => resetErrorBoundary()}>Try again</Button>\n                <pre style={{ whiteSpace: 'normal' }}>{error.message}</pre>\n              </div>\n            )}\n            onReset={reset}\n          >\n            {showProjects ? (\n              <React.Suspense fallback={<h1>Loading projects...</h1>}>\n                {activeProject ? (\n                  <Project\n                    activeProject={activeProject}\n                    setActiveProject={setActiveProject}\n                  />\n                ) : (\n                  <Projects setActiveProject={setActiveProject} />\n                )}\n              </React.Suspense>\n            ) : null}\n          </ErrorBoundary>\n        )}\n      </QueryErrorResetBoundary>\n      <ReactQueryDevtools initialIsOpen />\n    </>\n  )\n}\n\nconst rootElement = document.getElementById('root') as HTMLElement\nReactDOM.createRoot(rootElement).render(<App />)\n"
  },
  {
    "path": "examples/react/suspense/src/queries.ts",
    "content": "export async function fetchProjects(): Promise<\n  Array<{ name: string; full_name: string }>\n> {\n  console.info('Fetching projects')\n\n  const response = await fetch(\n    `https://api.github.com/users/TanStack/repos?sort=updated`,\n  )\n  await new Promise((r) => setTimeout(r, 1000))\n  return await response.json()\n}\n\nexport async function fetchProject(id: string): Promise<{\n  forks_count: number\n  stargazers_count: number\n  watchers_count: number\n}> {\n  console.info('Fetching project:', id)\n\n  const response = await fetch(`https://api.github.com/repos/${id}`)\n  await new Promise((r) => setTimeout(r, 1000))\n  return await response.json()\n}\n"
  },
  {
    "path": "examples/react/suspense/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src\", \"eslint.config.js\"]\n}\n"
  },
  {
    "path": "examples/react/suspense/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\n\nexport default defineConfig({\n  plugins: [react()],\n})\n"
  },
  {
    "path": "examples/solid/astro/.gitignore",
    "content": "# build output\ndist/\n.vercel/\n# generated types\n.astro/\n\n# dependencies\nnode_modules/\n\n# logs\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\n\n\n# environment variables\n.env\n.env.production\n\n# macOS-specific files\n.DS_Store\n\n# jetbrains setting folder\n.idea/\n"
  },
  {
    "path": "examples/solid/astro/README.md",
    "content": "# Astro Starter Kit: Minimal\n\n```sh\nnpm create astro@latest -- --template minimal\n```\n\n[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/minimal)\n[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/minimal)\n[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/minimal/devcontainer.json)\n\n> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun!\n\n## 🚀 Project Structure\n\nInside of your Astro project, you'll see the following folders and files:\n\n```text\n/\n├── public/\n├── src/\n│   └── pages/\n│       └── index.astro\n└── package.json\n```\n\nAstro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.\n\nThere's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.\n\nAny static assets, like images, can be placed in the `public/` directory.\n\n## 🧞 Commands\n\nAll commands are run from the root of the project, from a terminal:\n\n| Command                   | Action                                           |\n| :------------------------ | :----------------------------------------------- |\n| `npm install`             | Installs dependencies                            |\n| `npm run dev`             | Starts local dev server at `localhost:4321`      |\n| `npm run build`           | Build your production site to `./dist/`          |\n| `npm run preview`         | Preview your build locally, before deploying     |\n| `npm run astro ...`       | Run CLI commands like `astro add`, `astro check` |\n| `npm run astro -- --help` | Get help using the Astro CLI                     |\n\n## 👀 Want to learn more?\n\nFeel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).\n"
  },
  {
    "path": "examples/solid/astro/astro.config.mjs",
    "content": "import { defineConfig } from 'astro/config'\nimport solidJs from '@astrojs/solid-js'\nimport tailwind from '@astrojs/tailwind'\nimport node from '@astrojs/node'\n// https://astro.build/config\nexport default defineConfig({\n  output: 'server',\n  integrations: [solidJs(), tailwind()],\n  adapter: node({\n    mode: 'standalone',\n  }),\n})\n"
  },
  {
    "path": "examples/solid/astro/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-solid-astro\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"astro dev\",\n    \"start\": \"astro dev\",\n    \"build\": \"astro check && astro build\",\n    \"preview\": \"astro preview\",\n    \"astro\": \"astro\"\n  },\n  \"dependencies\": {\n    \"@astrojs/check\": \"^0.9.4\",\n    \"@astrojs/node\": \"^9.1.3\",\n    \"@astrojs/solid-js\": \"^5.0.7\",\n    \"@astrojs/tailwind\": \"^6.0.2\",\n    \"@astrojs/vercel\": \"^8.1.3\",\n    \"@tanstack/solid-query\": \"^5.91.3\",\n    \"@tanstack/solid-query-devtools\": \"^5.91.3\",\n    \"astro\": \"^5.5.6\",\n    \"solid-js\": \"^1.9.7\",\n    \"tailwindcss\": \"^3.4.7\",\n    \"typescript\": \"5.8.3\"\n  }\n}\n"
  },
  {
    "path": "examples/solid/astro/src/components/Link.tsx",
    "content": "export const Link = (props: {\n  href: string\n  children: any\n  class?: string\n}) => {\n  // Links doing client-side navigation\n  return (\n    <a\n      href={props.href}\n      onClick={(e) => {\n        e.preventDefault()\n        history.pushState({}, '', props.href)\n        window.dispatchEvent(new PopStateEvent('popstate'))\n      }}\n      class={props.class}\n    >\n      {props.children}\n    </a>\n  )\n}\n"
  },
  {
    "path": "examples/solid/astro/src/components/SolidApp.tsx",
    "content": "import {\n  QueryClient,\n  QueryClientProvider,\n  keepPreviousData,\n  useQuery,\n} from '@tanstack/solid-query'\nimport { SolidQueryDevtools } from '@tanstack/solid-query-devtools'\nimport {\n  For,\n  Show,\n  Suspense,\n  createContext,\n  createSignal,\n  useContext,\n} from 'solid-js'\nimport { isServer } from 'solid-js/web'\nimport { getSearchParams, properCase } from '../utils'\nimport { Link } from './Link'\n\nconst PokemonIdContext = createContext<() => string>()\n\nconst usePokemonID = () => {\n  const id = useContext(PokemonIdContext)\n  if (!id) throw new Error('PokemonIdContext not found')\n  return id\n}\n\nconst MAX_POKEMONS = 100\n\nexport const SolidApp = (props: { pokemon?: string }) => {\n  const client = new QueryClient()\n\n  const search = getSearchParams(props.pokemon || '')\n\n  return (\n    <QueryClientProvider client={client}>\n      <SolidQueryDevtools />\n      <Suspense fallback={'Loading'}>\n        <PokemonIdContext.Provider value={search}>\n          <App />\n        </PokemonIdContext.Provider>\n      </Suspense>\n    </QueryClientProvider>\n  )\n}\n\nconst App = () => {\n  return (\n    <div class=\"flex flex-1 overflow-auto\">\n      <SideNav />\n      <PokemonDetails />\n    </div>\n  )\n}\n\nconst PokemonDetails = () => {\n  const id = usePokemonID()\n  return (\n    <div class=\"flex-1 flex\">\n      <Show when={id()}>\n        <Suspense fallback={'Loading'}>\n          <PokemonDex id={id()} />\n        </Suspense>\n      </Show>\n      <Show when={!id()}>\n        <div class=\"justify-center items-center flex-1 flex text-2xl font-medium text-zinc-700\">\n          <div class=\"\">Select a pokemon to see its stats</div>\n        </div>\n      </Show>\n    </div>\n  )\n}\n\nconst PokemonDex = (props: { id: string }) => {\n  const pokemon = useQuery(() => ({\n    queryKey: ['pokemon', props.id],\n    queryFn: async () => {\n      const res = await fetch(\n        `https://pokeapi.co/api/v2/pokemon/${props.id}`,\n      ).then((res) => res.json())\n      return res\n    },\n    placeholderData: keepPreviousData,\n  }))\n\n  const pokemon_stats = useQuery(() => ({\n    queryKey: ['pokemon', props.id],\n    queryFn: async () => {\n      const res = await fetch(\n        `https://pokeapi.co/api/v2/pokemon/${props.id}`,\n      ).then((res) => res.json())\n\n      return res\n    },\n    select(data) {\n      const nameMap = {\n        hp: 'HP',\n        attack: 'Attack',\n        defense: 'Defense',\n        'special-attack': 'Special Attack',\n        'special-defense': 'Special Defense',\n        speed: 'Speed',\n      }\n      const stats = data.stats.map((stat: any) => ({\n        name: nameMap[stat.stat.name as keyof typeof nameMap],\n        value: stat.base_stat,\n      }))\n      return stats as { name: string; value: number }[]\n    },\n    placeholderData: keepPreviousData,\n    reconcile: 'name',\n  }))\n\n  const is_server_rendered = useQuery(() => ({\n    queryKey: ['is_server_rendered', props.id],\n    queryFn: () => {\n      if (isServer) return true\n      return false\n    },\n    placeholderData: keepPreviousData,\n  }))\n\n  return (\n    <div class=\"flex flex-col flex-1\">\n      <Show when={pokemon.data}>\n        <div class=\"flex justify-center text-3xl font-semibold py-4\">\n          {properCase(pokemon.data.name)}\n        </div>\n        <div class=\"flex justify-center\">\n          <div class=\"h-64 w-64 rounded-lg relative overflow-hidden border\">\n            <img\n              class=\"h-[400%] w-[400%] max-w-[400%] object-contain blur-2xl brightness-125 contrast-150 absolute z-10 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2\"\n              src={`https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/${props.id}.png`}\n              alt={properCase(pokemon.data?.name || '')}\n            />\n            <img\n              class=\"h-full w-full object-contain relative z-20\"\n              src={`https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/${props.id}.png`}\n              alt={properCase(pokemon.data?.name || '')}\n            />\n          </div>\n        </div>\n      </Show>\n\n      <div class=\"flex justify-center py-4\">\n        <div>\n          This query was rendered on the{' '}\n          <Show\n            when={is_server_rendered.data}\n            fallback={\n              <>\n                <b>client</b>. Reload this page to see the page rendered on the\n                server.\n              </>\n            }\n          >\n            <b>server. </b>\n            Click on another pokemon to see queries run and render on the\n            client.\n          </Show>\n        </div>\n      </div>\n\n      <Show when={pokemon_stats.data}>\n        <div class=\"flex justify-center flex-col gap-2\">\n          <For each={pokemon_stats.data}>\n            {(stat) => (\n              <div class=\"flex gap-2 justify-center items-center\">\n                <div class=\"w-36\">{stat.name}</div>\n                <div class=\"w-80 h-8 relative bg-zinc-100 rounded overflow-hidden flex justify-center items-center\">\n                  <div\n                    class=\"absolute z-10 h-full top-0 left-0 bg-lime-300\"\n                    style={{\n                      width: `${(stat.value / 160) * 100}%`,\n                      transition: 'width 0.5s',\n                    }}\n                  ></div>\n                  <div class=\"relative z-20 text-sm mix-blend-darken font-semibold\">\n                    {stat.value}\n                  </div>\n                </div>\n              </div>\n            )}\n          </For>\n        </div>\n      </Show>\n    </div>\n  )\n}\n\nconst SideNav = () => {\n  const id = usePokemonID()\n\n  const pokemonsList = useQuery(() => ({\n    queryKey: ['pokemons'],\n    queryFn: async () => {\n      const res = await fetch(\n        `https://pokeapi.co/api/v2/pokemon?limit=${MAX_POKEMONS}`,\n      ).then((res) => res.json())\n      return res as {\n        results: { name: string; url: string }[]\n      }\n    },\n    select(data) {\n      return data.results.map((p) => {\n        const regex = /\\/pokemon\\/(\\d+)\\/$/\n        const match = p.url.match(regex)\n        const id = match ? match[1] : ''\n        return {\n          name: properCase(p.name),\n          id,\n          avatar: `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/${id}.png`,\n        }\n      })\n    },\n    placeholderData: keepPreviousData,\n    reconcile: 'id',\n  }))\n\n  const activeClass = (pokemonID: string) =>\n    id() === pokemonID ? 'bg-gray-50' : 'hover:bg-gray-50'\n\n  return (\n    <div class=\"w-72 border-r flex flex-col px-2\">\n      <div class=\"pt-3 pb-1 text-sm font-semibold\">Pokemons</div>\n\n      <div class=\"flex-1 overflow-auto flex flex-col gap-1\">\n        <For each={pokemonsList.data}>\n          {(pokemon) => (\n            <Link\n              class={`flex gap-2 items-center border rounded p-1 ${activeClass(\n                pokemon.id,\n              )}`}\n              href={`./?id=${pokemon.id}`}\n            >\n              <span class=\"flex bg-zinc-100 border relative justify-center items-center overflow-hidden rounded-sm w-9 h-9 flex-shrink-0\">\n                <img\n                  class=\"w-7 h-7 relative z-20\"\n                  src={pokemon.avatar}\n                  alt={pokemon.name}\n                />\n              </span>\n              <span>{pokemon.name}</span>\n            </Link>\n          )}\n        </For>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/solid/astro/src/env.d.ts",
    "content": "/// <reference path=\"../.astro/types.d.ts\" />\n/// <reference types=\"astro/client\" />\n"
  },
  {
    "path": "examples/solid/astro/src/layouts/MainLayout.astro",
    "content": "---\nimport { SolidApp } from \"../components/SolidApp\";\nconst { id } = Astro.props;\n\n---\n\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\" />\n\t\t<meta name=\"viewport\" content=\"width=device-width\" />\n\t\t<meta name=\"generator\" content={Astro.generator} />\n\t\t<title>Astro</title>\n\t</head>\n\t<body class=\"text-zinc-900\">\n\t\t<div class=\"flex h-screen flex-col\">\n\t\t\t<nav class=\"flex items-center h-12 border-b px-4 flex-shrink-0\">\n\t\t\t\t<div class=\"font-semibold text-lg\">\n\t\t\t\t\tSolid Query + Astro\n\t\t\t\t</div>\n\t\t\t</nav>\n\t\t\t<SolidApp pokemon={id} client:load />\n\t\t</div>\n\t</body>\n</html>"
  },
  {
    "path": "examples/solid/astro/src/pages/index.astro",
    "content": "---\nimport MainLayout from '../layouts/MainLayout.astro';\n\nconst id = Astro.url.searchParams.get('id') || '';\n---\n\n<MainLayout id={id} />\n"
  },
  {
    "path": "examples/solid/astro/src/utils/index.ts",
    "content": "import { createSignal } from 'solid-js'\n\nexport const getSearchParams = (init: string) => {\n  const [search, setSearch] = createSignal(init)\n  if (typeof window !== 'undefined') {\n    window.addEventListener('popstate', () => {\n      const location = window.location\n      const params = new URLSearchParams(location.search)\n      setSearch(params.get('id') || '')\n    })\n  }\n  return search\n}\n\nexport const properCase = (str: string) =>\n  str.charAt(0).toUpperCase() + str.slice(1)\n"
  },
  {
    "path": "examples/solid/astro/tailwind.config.mjs",
    "content": "/** @type {import('tailwindcss').Config} */\nexport default {\n  content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],\n  theme: {\n    extend: {},\n  },\n  plugins: [],\n}\n"
  },
  {
    "path": "examples/solid/astro/tsconfig.json",
    "content": "{\n  \"extends\": \"astro/tsconfigs/strict\",\n  \"compilerOptions\": {\n    \"jsx\": \"preserve\",\n    \"jsxImportSource\": \"solid-js\"\n  }\n}\n"
  },
  {
    "path": "examples/solid/basic/.eslintrc.cjs",
    "content": "// @ts-check\n\n/** @type {import('eslint').Linter.Config} */\nconst config = {}\n\nmodule.exports = config\n"
  },
  {
    "path": "examples/solid/basic/.gitignore",
    "content": "node_modules\ndist\n.yalc\nyalc.lock"
  },
  {
    "path": "examples/solid/basic/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `npm install`\n- `npm run start`\n"
  },
  {
    "path": "examples/solid/basic/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <meta name=\"theme-color\" content=\"#000000\" />\n    <link rel=\"shortcut icon\" type=\"image/ico\" href=\"/src/assets/favicon.ico\" />\n    <title>Solid App</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n\n    <script src=\"/src/index.tsx\" type=\"module\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/solid/basic/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-solid-basic\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/solid-query\": \"^5.91.3\",\n    \"@tanstack/solid-query-devtools\": \"^5.91.3\",\n    \"solid-js\": \"^1.9.7\"\n  },\n  \"devDependencies\": {\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\",\n    \"vite-plugin-solid\": \"^2.11.6\"\n  }\n}\n"
  },
  {
    "path": "examples/solid/basic/src/index.tsx",
    "content": "/* @refresh reload */\nimport {\n  QueryClient,\n  QueryClientProvider,\n  useQuery,\n} from '@tanstack/solid-query'\nimport { SolidQueryDevtools } from '@tanstack/solid-query-devtools'\nimport { For, Match, Switch, createSignal } from 'solid-js'\nimport { render } from 'solid-js/web'\nimport type { Component, Setter } from 'solid-js'\n\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      gcTime: 1000 * 60 * 60 * 24, // 24 hours\n    },\n  },\n})\n\ntype Post = {\n  id: number\n  title: string\n  body: string\n}\n\nfunction createPosts() {\n  return useQuery(() => ({\n    queryKey: ['posts'],\n    queryFn: async (): Promise<Array<Post>> => {\n      const response = await fetch('https://jsonplaceholder.typicode.com/posts')\n      return await response.json()\n    },\n  }))\n}\n\nfunction Posts(props: { setPostId: Setter<number> }) {\n  const state = createPosts()\n\n  return (\n    <div>\n      <h1>Posts</h1>\n      <div>\n        <Switch>\n          <Match when={state.status === 'pending'}>Loading...</Match>\n          <Match when={state.status === 'error'}>\n            <span>Error: {(state.error as Error).message}</span>\n          </Match>\n          <Match when={state.data !== undefined}>\n            <>\n              <div>\n                <For each={state.data}>\n                  {(post) => (\n                    <p>\n                      <a\n                        onClick={() => props.setPostId(post.id)}\n                        href=\"#\"\n                        style={\n                          // We can access the query data here to show bold links for\n                          // ones that are cached\n                          queryClient.getQueryData(['post', post.id])\n                            ? {\n                                'font-weight': 'bold',\n                                color: 'green',\n                              }\n                            : {}\n                        }\n                      >\n                        {post.title}\n                      </a>\n                    </p>\n                  )}\n                </For>\n              </div>\n              <div>{state.isFetching ? 'Background Updating...' : ' '}</div>\n            </>\n          </Match>\n        </Switch>\n      </div>\n    </div>\n  )\n}\n\nconst getPostById = async (id: number): Promise<Post> => {\n  const response = await fetch(\n    `https://jsonplaceholder.typicode.com/posts/${id}`,\n  )\n  return await response.json()\n}\n\nfunction createPost(postId: number) {\n  return useQuery(() => ({\n    queryKey: ['post', postId],\n    queryFn: () => getPostById(postId),\n    enabled: !!postId,\n  }))\n}\n\nfunction Post(props: { postId: number; setPostId: Setter<number> }) {\n  const state = createPost(props.postId)\n\n  return (\n    <div>\n      <div>\n        <a onClick={() => props.setPostId(-1)} href=\"#\">\n          Back\n        </a>\n      </div>\n      <Switch>\n        <Match when={!props.postId || state.status === 'pending'}>\n          Loading...\n        </Match>\n        <Match when={state.status === 'error'}>\n          <span>Error: {(state.error as Error).message}</span>\n        </Match>\n        <Match when={state.data !== undefined}>\n          <>\n            <h1>{state.data?.title}</h1>\n            <div>\n              <p>{state.data?.body}</p>\n            </div>\n            <div>{state.isFetching ? 'Background Updating...' : ' '}</div>\n          </>\n        </Match>\n      </Switch>\n    </div>\n  )\n}\n\nconst App: Component = () => {\n  const [postId, setPostId] = createSignal(-1)\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      <SolidQueryDevtools />\n      <p>\n        As you visit the posts below, you will notice them in a loading state\n        the first time you load them. However, after you return to this list and\n        click on any posts you have already visited again, you will see them\n        load instantly and background refresh right before your eyes!{' '}\n        <strong>\n          (You may need to throttle your network speed to simulate longer\n          loading sequences)\n        </strong>\n      </p>\n      {postId() > -1 ? (\n        <Post postId={postId()} setPostId={setPostId} />\n      ) : (\n        <Posts setPostId={setPostId} />\n      )}\n    </QueryClientProvider>\n  )\n}\n\nconst root = document.getElementById('root')\nif (!root) throw new Error('Missing #root element')\n\nrender(() => <App />, root)\n"
  },
  {
    "path": "examples/solid/basic/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"module\": \"ESNext\",\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"preserve\",\n    \"jsxImportSource\": \"solid-js\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "examples/solid/basic/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport solid from 'vite-plugin-solid'\n\nexport default defineConfig({\n  plugins: [solid()],\n})\n"
  },
  {
    "path": "examples/solid/basic-graphql-request/.eslintrc.cjs",
    "content": "// @ts-check\n\n/** @type {import('eslint').Linter.Config} */\nconst config = {}\n\nmodule.exports = config\n"
  },
  {
    "path": "examples/solid/basic-graphql-request/.gitignore",
    "content": "node_modules\ndist\n.yalc\nyalc.lock"
  },
  {
    "path": "examples/solid/basic-graphql-request/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `npm install`\n- `npm run start`\n"
  },
  {
    "path": "examples/solid/basic-graphql-request/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <meta name=\"theme-color\" content=\"#000000\" />\n    <link rel=\"shortcut icon\" type=\"image/ico\" href=\"/src/assets/favicon.ico\" />\n    <title>Solid App</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n\n    <script src=\"/src/index.tsx\" type=\"module\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/solid/basic-graphql-request/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-solid-basic-graphql-request\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/solid-query\": \"^5.91.3\",\n    \"@tanstack/solid-query-devtools\": \"^5.91.3\",\n    \"graphql\": \"^16.9.0\",\n    \"graphql-request\": \"^7.1.2\",\n    \"solid-js\": \"^1.9.7\"\n  },\n  \"devDependencies\": {\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\",\n    \"vite-plugin-solid\": \"^2.11.6\"\n  }\n}\n"
  },
  {
    "path": "examples/solid/basic-graphql-request/src/index.tsx",
    "content": "/* @refresh reload */\nimport {\n  QueryClient,\n  QueryClientProvider,\n  useQuery,\n} from '@tanstack/solid-query'\nimport { SolidQueryDevtools } from '@tanstack/solid-query-devtools'\nimport { For, Match, Switch, createSignal } from 'solid-js'\nimport { render } from 'solid-js/web'\nimport { gql, request } from 'graphql-request'\nimport type { Accessor, Setter } from 'solid-js'\n\nconst endpoint = 'https://graphqlzero.almansi.me/api'\n\nconst queryClient = new QueryClient()\n\ntype Post = {\n  id: number\n  title: string\n  body: string\n}\n\nfunction App() {\n  const [postId, setPostId] = createSignal(-1)\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      <SolidQueryDevtools />\n      <p>\n        As you visit the posts below, you will notice them in a loading state\n        the first time you load them. However, after you return to this list and\n        click on any posts you have already visited again, you will see them\n        load instantly and background refresh right before your eyes!{' '}\n        <strong>\n          (You may need to throttle your network speed to simulate longer\n          loading sequences)\n        </strong>\n      </p>\n      {postId() > -1 ? (\n        <Post postId={postId()} setPostId={setPostId} />\n      ) : (\n        <Posts setPostId={setPostId} />\n      )}\n    </QueryClientProvider>\n  )\n}\n\nfunction createPosts() {\n  return useQuery(() => ({\n    queryKey: ['posts'],\n    queryFn: async () => {\n      const {\n        posts: { data },\n      } = await request<{ posts: { data: Array<Post> } }>(\n        endpoint,\n        gql`\n          query {\n            posts {\n              data {\n                id\n                title\n              }\n            }\n          }\n        `,\n      )\n      return data\n    },\n  }))\n}\n\nfunction Posts(props: { setPostId: Setter<number> }) {\n  const state = createPosts()\n\n  return (\n    <div>\n      <h1>Posts</h1>\n      <div>\n        <Switch>\n          <Match when={state.status === 'pending'}>Loading...</Match>\n          <Match when={state.status === 'error'}>\n            <span>Error: {(state.error as Error).message}</span>\n          </Match>\n          <Match when={state.data !== undefined}>\n            <>\n              <div>\n                <For each={state.data}>\n                  {(post: any) => (\n                    <p>\n                      <a\n                        onClick={() => props.setPostId(post.id)}\n                        href=\"#\"\n                        style={\n                          // We can find the existing query data here to show bold links for\n                          // ones that are cached\n                          queryClient.getQueryData(['post', post.id])\n                            ? {\n                                'font-weight': 'bold',\n                                color: 'green',\n                              }\n                            : {}\n                        }\n                      >\n                        {post.title}\n                      </a>\n                    </p>\n                  )}\n                </For>\n              </div>\n              <div>{state.isFetching ? 'Background Updating...' : ' '}</div>\n            </>\n          </Match>\n        </Switch>\n      </div>\n    </div>\n  )\n}\n\nfunction createPost(postId: Accessor<number>) {\n  return useQuery(() => ({\n    queryKey: ['post', postId()],\n    queryFn: async () => {\n      const { post } = await request<{ post: Post }>(\n        endpoint,\n        gql`\n        query {\n          post(id: ${postId()}) {\n            id\n            title\n            body\n          }\n        }\n        `,\n      )\n\n      return post\n    },\n    enabled: !!postId(),\n  }))\n}\n\nfunction Post(props: { postId: number; setPostId: Setter<number> }) {\n  const state = createPost(() => props.postId)\n\n  return (\n    <div>\n      <div>\n        <a onClick={() => props.setPostId(-1)} href=\"#\">\n          Back\n        </a>\n      </div>\n      <Switch>\n        <Match when={!props.postId || state.status === 'pending'}>\n          Loading...\n        </Match>\n        <Match when={state.status === 'error'}>\n          <span>Error: {(state.error as Error).message}</span>\n        </Match>\n        <Match when={state.data !== undefined}>\n          <>\n            <h1>{state.data?.title}</h1>\n            <div>\n              <p>{state.data?.body}</p>\n            </div>\n            <div>{state.isFetching ? 'Background Updating...' : ' '}</div>\n          </>\n        </Match>\n      </Switch>\n    </div>\n  )\n}\n\nconst root = document.getElementById('root')\nif (!root) throw new Error('Missing #root element')\n\nrender(() => <App />, root)\n"
  },
  {
    "path": "examples/solid/basic-graphql-request/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"module\": \"ESNext\",\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"preserve\",\n    \"jsxImportSource\": \"solid-js\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "examples/solid/basic-graphql-request/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport solid from 'vite-plugin-solid'\n\nexport default defineConfig({\n  plugins: [solid()],\n})\n"
  },
  {
    "path": "examples/solid/default-query-function/.eslintrc.cjs",
    "content": "// @ts-check\n\n/** @type {import('eslint').Linter.Config} */\nconst config = {}\n\nmodule.exports = config\n"
  },
  {
    "path": "examples/solid/default-query-function/.gitignore",
    "content": "node_modules\ndist\n.yalc\nyalc.lock"
  },
  {
    "path": "examples/solid/default-query-function/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `npm install`\n- `npm run start`\n"
  },
  {
    "path": "examples/solid/default-query-function/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <meta name=\"theme-color\" content=\"#000000\" />\n    <link rel=\"shortcut icon\" type=\"image/ico\" href=\"/src/assets/favicon.ico\" />\n    <title>Solid App</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n\n    <script src=\"/src/index.tsx\" type=\"module\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/solid/default-query-function/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-solid-default-query-function\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/solid-query\": \"^5.91.3\",\n    \"@tanstack/solid-query-devtools\": \"^5.91.3\",\n    \"solid-js\": \"^1.9.7\"\n  },\n  \"devDependencies\": {\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\",\n    \"vite-plugin-solid\": \"^2.11.6\"\n  }\n}\n"
  },
  {
    "path": "examples/solid/default-query-function/src/index.tsx",
    "content": "/* @refresh reload */\nimport {\n  QueryClient,\n  QueryClientProvider,\n  useQuery,\n} from '@tanstack/solid-query'\nimport { SolidQueryDevtools } from '@tanstack/solid-query-devtools'\nimport { For, Match, Show, Switch, createSignal } from 'solid-js'\nimport { render } from 'solid-js/web'\nimport type { Setter } from 'solid-js'\nimport type { QueryFunction } from '@tanstack/solid-query'\n\n// Define a default query function that will receive the query key\nconst defaultQueryFn: QueryFunction<unknown> = async ({ queryKey }) => {\n  const response = await fetch(\n    `https://jsonplaceholder.typicode.com${queryKey[0]}`,\n    {\n      method: 'GET',\n    },\n  )\n  return response.json()\n}\n\n// provide the default query function to your app via the query client\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      queryFn: defaultQueryFn,\n    },\n  },\n})\n\nfunction App() {\n  const [postId, setPostId] = createSignal(-1)\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      <SolidQueryDevtools />\n      <p>\n        As you visit the posts below, you will notice them in a loading state\n        the first time you load them. However, after you return to this list and\n        click on any posts you have already visited again, you will see them\n        load instantly and background refresh right before your eyes!{' '}\n        <strong>\n          (You may need to throttle your network speed to simulate longer\n          loading sequences)\n        </strong>\n      </p>\n      <Show when={postId() > -1} fallback={<Posts setPostId={setPostId} />}>\n        <Post postId={postId()} setPostId={setPostId} />\n      </Show>\n    </QueryClientProvider>\n  )\n}\n\nfunction Posts(props: { setPostId: Setter<number> }) {\n  // All you have to do now is pass a key!\n  const state = useQuery<any[]>(() => ({ queryKey: ['/posts'] }))\n\n  return (\n    <div>\n      <h1>Posts</h1>\n      <div>\n        <Switch>\n          <Match when={state.status === 'pending'}>Loading...</Match>\n          <Match when={state.status === 'error'}>\n            <span>Error: {(state.error as Error).message}</span>\n          </Match>\n          <Match when={state.data !== undefined}>\n            <>\n              <div>\n                <For each={state.data}>\n                  {(post) => (\n                    <p>\n                      <a\n                        onClick={() => props.setPostId(post.id)}\n                        href=\"#\"\n                        style={\n                          // We can use the queryCache here to show bold links for\n                          // ones that are cached\n                          queryClient.getQueryData(['post', post.id])\n                            ? {\n                                'font-weight': 'bold',\n                                color: 'green',\n                              }\n                            : {}\n                        }\n                      >\n                        {post.title}\n                      </a>\n                    </p>\n                  )}\n                </For>\n              </div>\n              <div>{state.isFetching ? 'Background Updating...' : ' '}</div>\n            </>\n          </Match>\n        </Switch>\n      </div>\n    </div>\n  )\n}\n\nfunction Post(props: { postId: number; setPostId: Setter<number> }) {\n  // You can even leave out the queryFn and just go straight into options\n  const state = useQuery<any>(() => ({\n    queryKey: [`/posts/${props.postId}`],\n    enabled: !!props.postId,\n  }))\n\n  return (\n    <div>\n      <div>\n        <a onClick={() => props.setPostId(-1)} href=\"#\">\n          Back\n        </a>\n      </div>\n      <Switch>\n        <Match when={!props.postId || state.status === 'pending'}>\n          Loading...\n        </Match>\n        <Match when={state.status === 'error'}>\n          <span>Error: {(state.error as Error).message}</span>\n        </Match>\n        <Match when={state.data !== undefined}>\n          <>\n            <h1>{state.data.title}</h1>\n            <div>\n              <p>{state.data.body}</p>\n            </div>\n            <div>{state.isFetching ? 'Background Updating...' : ' '}</div>\n          </>\n        </Match>\n      </Switch>\n    </div>\n  )\n}\n\nconst root = document.getElementById('root')\nif (!root) throw new Error('Missing #root element')\n\nrender(() => <App />, root)\n"
  },
  {
    "path": "examples/solid/default-query-function/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"module\": \"ESNext\",\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"preserve\",\n    \"jsxImportSource\": \"solid-js\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "examples/solid/default-query-function/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport solid from 'vite-plugin-solid'\n\nexport default defineConfig({\n  plugins: [solid()],\n})\n"
  },
  {
    "path": "examples/solid/offline/.eslintrc.cjs",
    "content": "// @ts-check\n\n/** @type {import('eslint').Linter.Config} */\nconst config = {}\n\nmodule.exports = config\n"
  },
  {
    "path": "examples/solid/offline/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `npm install`\n- `npm run start`\n"
  },
  {
    "path": "examples/solid/offline/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <meta name=\"theme-color\" content=\"#000000\" />\n    <link rel=\"shortcut icon\" type=\"image/ico\" href=\"/src/assets/favicon.ico\" />\n    <title>Solid App</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n\n    <script src=\"/src/index.tsx\" type=\"module\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/solid/offline/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-solid-offline\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/query-async-storage-persister\": \"^5.90.27\",\n    \"@tanstack/solid-query\": \"^5.91.3\",\n    \"@tanstack/solid-query-devtools\": \"^5.91.3\",\n    \"@tanstack/solid-query-persist-client\": \"^5.90.28\",\n    \"msw\": \"^2.6.6\",\n    \"solid-js\": \"^1.9.7\"\n  },\n  \"devDependencies\": {\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\",\n    \"vite-plugin-solid\": \"^2.11.6\"\n  },\n  \"msw\": {\n    \"workerDirectory\": [\n      \"public\"\n    ]\n  }\n}\n"
  },
  {
    "path": "examples/solid/offline/src/App.tsx",
    "content": "import { For, Match, Show, Switch, createSignal } from 'solid-js'\nimport { MutationCache, QueryClient, useQuery } from '@tanstack/solid-query'\nimport { SolidQueryDevtools } from '@tanstack/solid-query-devtools'\nimport { PersistQueryClientProvider } from '@tanstack/solid-query-persist-client'\nimport { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister'\n\nimport * as api from './api'\nimport { movieKeys, useMovie } from './movies'\n\nconst persister = createAsyncStoragePersister({\n  storage: window.localStorage,\n})\n\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      gcTime: 1000 * 60 * 60 * 24, // 24 hours\n      staleTime: 2000,\n      retry: 0,\n    },\n  },\n  // configure global cache callbacks to show notifications\n  mutationCache: new MutationCache({\n    onSuccess: (data: any) => {\n      showNotification(data.message, 'success')\n    },\n    onError: (error) => {\n      showNotification(error.message, 'error')\n    },\n  }),\n})\n\n// we need a default mutation function so that paused mutations can resume after a page reload\nqueryClient.setMutationDefaults(movieKeys.all(), {\n  mutationFn: async ({ id, comment }: { id: string; comment: string }) => {\n    // to avoid clashes with our optimistic update when an offline mutation continues\n    await queryClient.cancelQueries({ queryKey: movieKeys.detail(id) })\n    return api.updateMovie(id, comment)\n  },\n})\n\nfunction showNotification(message: string, type: 'success' | 'error') {\n  const el = document.createElement('div')\n  el.style.cssText = `\n    position: fixed; top: 16px; right: 16px; z-index: 9999;\n    padding: 12px 24px; border-radius: 4px; color: white;\n    background: ${type === 'success' ? '#22c55e' : '#ef4444'};\n    animation: fadeIn 0.3s ease-in;\n  `\n  el.textContent = message\n  document.body.appendChild(el)\n  setTimeout(() => el.remove(), 3000)\n}\n\nexport default function App() {\n  return (\n    <PersistQueryClientProvider\n      client={queryClient}\n      persistOptions={{ persister }}\n      onSuccess={() => {\n        // resume mutations after initial restore from localStorage was successful\n        queryClient.resumePausedMutations().then(() => {\n          queryClient.invalidateQueries()\n        })\n      }}\n    >\n      <Movies />\n      <SolidQueryDevtools initialIsOpen />\n    </PersistQueryClientProvider>\n  )\n}\n\nfunction Movies() {\n  const [page, setPage] = createSignal<\n    { type: 'list' } | { type: 'detail'; movieId: string }\n  >({ type: 'list' })\n\n  return (\n    <Switch>\n      <Match when={page().type === 'list'}>\n        <List\n          onSelectMovie={(movieId) => setPage({ type: 'detail', movieId })}\n        />\n      </Match>\n      <Match when={page().type === 'detail'}>\n        <Detail\n          movieId={(page() as { type: 'detail'; movieId: string }).movieId}\n          onBack={() => setPage({ type: 'list' })}\n        />\n      </Match>\n    </Switch>\n  )\n}\n\nfunction List(props: { onSelectMovie: (movieId: string) => void }) {\n  const moviesQuery = useQuery(() => ({\n    queryKey: movieKeys.list(),\n    queryFn: api.fetchMovies,\n  }))\n\n  return (\n    <Switch>\n      <Match when={moviesQuery.isLoading}>Loading...</Match>\n      <Match when={moviesQuery.data}>\n        <div>\n          <h1>Movies</h1>\n          <p>\n            Try to mock offline behavior with the button in the devtools. You\n            can navigate around as long as there is already data in the cache.\n            You'll get a refetch as soon as you go online again.\n          </p>\n          <ul>\n            <For each={moviesQuery.data!.movies}>\n              {(movie) => (\n                <li>\n                  <a\n                    href=\"#\"\n                    onClick={(e) => {\n                      e.preventDefault()\n                      props.onSelectMovie(movie.id)\n                    }}\n                  >\n                    {movie.title}\n                  </a>\n                </li>\n              )}\n            </For>\n          </ul>\n          <div>\n            Updated at: {new Date(moviesQuery.data!.ts).toLocaleTimeString()}\n          </div>\n          <Show when={moviesQuery.isFetching}>\n            <div>fetching...</div>\n          </Show>\n        </div>\n      </Match>\n    </Switch>\n  )\n}\n\nfunction Detail(props: { movieId: string; onBack: () => void }) {\n  const { comment, setComment, updateMovie, movieQuery } = useMovie(\n    props.movieId,\n  )\n\n  function submitForm(event: SubmitEvent) {\n    event.preventDefault()\n\n    updateMovie.mutate({\n      id: props.movieId,\n      comment: comment(),\n    })\n  }\n\n  return (\n    <Switch>\n      <Match when={movieQuery.isLoading}>Loading...</Match>\n      <Match when={movieQuery.data}>\n        <form onSubmit={submitForm}>\n          <a\n            href=\"#\"\n            onClick={(e) => {\n              e.preventDefault()\n              props.onBack()\n            }}\n          >\n            Back\n          </a>\n          <h1>Movie: {movieQuery.data!.movie.title}</h1>\n          <p>\n            Try to mock offline behavior with the button in the devtools, then\n            update the comment. The optimistic update will succeed, but the\n            actual mutation will be paused and resumed once you go online again.\n          </p>\n          <p>\n            You can also reload the page, which will make the persisted mutation\n            resume, as you will be online again when you \"come back\".\n          </p>\n          <p>\n            <label>\n              Comment: <br />\n              <textarea\n                name=\"comment\"\n                value={comment() ?? ''}\n                onInput={(event) => setComment(event.currentTarget.value)}\n              />\n            </label>\n          </p>\n          <button type=\"submit\">Submit</button>\n          <div>\n            Updated at: {new Date(movieQuery.data!.ts).toLocaleTimeString()}\n          </div>\n          <Show when={movieQuery.isFetching}>\n            <div>fetching...</div>\n          </Show>\n          <div>\n            {updateMovie.isPaused\n              ? 'mutation paused - offline'\n              : updateMovie.isPending && 'updating...'}\n          </div>\n        </form>\n      </Match>\n      <Match when={movieQuery.isPaused}>\n        We're offline and have no data to show :(\n      </Match>\n    </Switch>\n  )\n}\n"
  },
  {
    "path": "examples/solid/offline/src/api.ts",
    "content": "import { HttpResponse, delay, http, passthrough } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst movies = [\n  {\n    id: '1',\n    title: 'Guardians of the Galaxy',\n    comment: '',\n  },\n  {\n    id: '2',\n    title: 'Wall-E',\n    comment: '',\n  },\n]\n\nexport const fetchMovie = async (\n  id: string,\n): Promise<{\n  ts: number\n  movie: { comment: string; id: string; title: string }\n}> => {\n  const response = await fetch(`/movies/${id}`)\n  return await response.json()\n}\n\nexport const fetchMovies = async (): Promise<{\n  ts: number\n  movies: typeof movies\n}> => {\n  const response = await fetch('/movies')\n  return await response.json()\n}\n\nexport const updateMovie = async (id: string, comment: string) => {\n  const response = await fetch(`/movies/${id}`, {\n    method: 'POST',\n    body: JSON.stringify({ comment }),\n    headers: { 'Content-Type': 'application/json' },\n  })\n  return await response.json()\n}\n\nexport const worker = setupWorker(\n  http.get('/movies', async () => {\n    await delay(500)\n    return HttpResponse.json({\n      ts: Date.now(),\n      movies: movies.map(({ id, title }) => ({ id, title })),\n    })\n  }),\n\n  http.get('/movies/:id', async ({ params }) => {\n    const { id } = params\n\n    const movie = movies.find((movie) => movie.id === id)\n\n    if (!movie) {\n      return new HttpResponse(`Movie with id ${id} not found`, {\n        status: 404,\n      })\n    }\n\n    await delay(500)\n    return HttpResponse.json({ ts: Date.now(), movie })\n  }),\n\n  http.post('/movies/:id', async ({ request, params }) => {\n    const { id } = params\n    const body = (await request.json()) as { comment: string }\n    const { comment } = body\n\n    movies.forEach((movie) => {\n      if (movie.id === id) {\n        movie.comment = comment.toUpperCase()\n      }\n    })\n\n    await delay(500)\n    return HttpResponse.json({ message: `Successfully updated movie ${id}` })\n  }),\n  http.get('*.js', () => passthrough()),\n  http.get('*.svg', () => passthrough()),\n)\n"
  },
  {
    "path": "examples/solid/offline/src/index.tsx",
    "content": "/* @refresh reload */\nimport { render } from 'solid-js/web'\nimport App from './App'\nimport { worker } from './api'\n\nworker.start()\n\nconst root = document.getElementById('root')\nif (!root) throw new Error('Missing #root element')\n\nrender(\n  () => (\n    <div style={{ padding: '16px' }}>\n      <App />\n    </div>\n  ),\n  root,\n)\n"
  },
  {
    "path": "examples/solid/offline/src/movies.ts",
    "content": "import { createSignal } from 'solid-js'\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/solid-query'\nimport * as api from './api'\n\nexport const movieKeys = {\n  all: () => ['movies'],\n  list: () => [...movieKeys.all(), 'list'],\n  details: () => [...movieKeys.all(), 'detail'],\n  detail: (id: string) => [...movieKeys.details(), id],\n}\n\nexport const useMovie = (movieId: string) => {\n  const queryClient = useQueryClient()\n\n  const movieQuery = useQuery(() => ({\n    queryKey: movieKeys.detail(movieId),\n    queryFn: () => api.fetchMovie(movieId),\n  }))\n\n  const [comment, setComment] = createSignal<string | undefined>()\n\n  const updateMovie = useMutation(() => ({\n    mutationKey: movieKeys.detail(movieId),\n    onMutate: async () => {\n      await queryClient.cancelQueries({ queryKey: movieKeys.detail(movieId) })\n      const previousData = queryClient.getQueryData<\n        Awaited<ReturnType<typeof api.fetchMovie>>\n      >(movieKeys.detail(movieId))\n\n      // remove local state so that server state is taken instead\n      setComment(undefined)\n\n      queryClient.setQueryData(movieKeys.detail(movieId), {\n        ...previousData,\n        movie: {\n          ...previousData?.movie,\n          comment: comment(),\n        },\n      })\n\n      return { previousData }\n    },\n    onError: (_: any, __: any, context: any) => {\n      queryClient.setQueryData(movieKeys.detail(movieId), context.previousData)\n    },\n    onSettled: () => {\n      queryClient.invalidateQueries({ queryKey: movieKeys.detail(movieId) })\n    },\n  }))\n\n  return {\n    comment: () => comment() ?? movieQuery.data?.movie.comment,\n    setComment,\n    updateMovie,\n    movieQuery,\n  }\n}\n"
  },
  {
    "path": "examples/solid/offline/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"module\": \"ESNext\",\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"preserve\",\n    \"jsxImportSource\": \"solid-js\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "examples/solid/offline/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport solid from 'vite-plugin-solid'\n\nexport default defineConfig({\n  plugins: [solid()],\n})\n"
  },
  {
    "path": "examples/solid/simple/.eslintrc.cjs",
    "content": "// @ts-check\n\n/** @type {import('eslint').Linter.Config} */\nconst config = {\n  extends: ['plugin:@tanstack/eslint-plugin-query/recommended'],\n}\n\nmodule.exports = config\n"
  },
  {
    "path": "examples/solid/simple/.gitignore",
    "content": "node_modules\ndist\n.yalc\nyalc.lock"
  },
  {
    "path": "examples/solid/simple/README.md",
    "content": "# Example\n\nTo run this example:\n\n- `npm install`\n- `npm run start`\n"
  },
  {
    "path": "examples/solid/simple/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <meta name=\"theme-color\" content=\"#000000\" />\n    <link rel=\"shortcut icon\" type=\"image/ico\" href=\"/src/assets/favicon.ico\" />\n    <title>Solid App</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n\n    <script src=\"/src/index.tsx\" type=\"module\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/solid/simple/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-solid-simple\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/solid-query\": \"^5.91.3\",\n    \"@tanstack/solid-query-devtools\": \"^5.91.3\",\n    \"solid-js\": \"^1.9.7\"\n  },\n  \"devDependencies\": {\n    \"@tanstack/eslint-plugin-query\": \"^5.91.5\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\",\n    \"vite-plugin-solid\": \"^2.11.6\"\n  }\n}\n"
  },
  {
    "path": "examples/solid/simple/src/index.tsx",
    "content": "/* @refresh reload */\nimport {\n  QueryClient,\n  QueryClientProvider,\n  useQuery,\n} from '@tanstack/solid-query'\nimport { SolidQueryDevtools } from '@tanstack/solid-query-devtools'\nimport { Match, Switch } from 'solid-js'\nimport { render } from 'solid-js/web'\n\nconst queryClient = new QueryClient()\n\nexport default function App() {\n  return (\n    <QueryClientProvider client={queryClient}>\n      <SolidQueryDevtools />\n      <Example />\n    </QueryClientProvider>\n  )\n}\n\nfunction Example() {\n  const state = useQuery(() => ({\n    queryKey: ['repoData'],\n    queryFn: async () => {\n      const response = await fetch(\n        'https://api.github.com/repos/TanStack/query',\n      )\n      return await response.json()\n    },\n  }))\n\n  return (\n    <Switch>\n      <Match when={state.isPending}>Loading...</Match>\n      <Match when={state.error}>\n        {'An error has occurred: ' + (state.error as Error).message}\n      </Match>\n      <Match when={state.data !== undefined}>\n        <div>\n          <h1>{state.data.name}</h1>\n          <p>{state.data.description}</p>\n          <strong>👀 {state.data.subscribers_count}</strong>{' '}\n          <strong>✨ {state.data.stargazers_count}</strong>{' '}\n          <strong>🍴 {state.data.forks_count}</strong>\n          <div>{state.isFetching ? 'Updating...' : ''}</div>\n        </div>\n      </Match>\n    </Switch>\n  )\n}\nconst root = document.getElementById('root')\nif (!root) throw new Error('Missing #root element')\n\nrender(() => <App />, root)\n"
  },
  {
    "path": "examples/solid/simple/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"module\": \"ESNext\",\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"preserve\",\n    \"jsxImportSource\": \"solid-js\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src\", \".eslintrc.cjs\", \"vite.config.ts\"]\n}\n"
  },
  {
    "path": "examples/solid/simple/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport solid from 'vite-plugin-solid'\n\nexport default defineConfig({\n  plugins: [solid()],\n})\n"
  },
  {
    "path": "examples/solid/solid-start-streaming/.gitignore",
    "content": "\ndist\n.solid\n.output\n.vercel\n.netlify\nnetlify\n.vinxi\n\n# Environment\n.env\n.env*.local\n\n# dependencies\n/node_modules\n\n# IDEs and editors\n/.idea\n.project\n.classpath\n*.launch\n.settings/\n\n# Temp\ngitignore\n\n# System Files\n.DS_Store\nThumbs.db\n"
  },
  {
    "path": "examples/solid/solid-start-streaming/README.md",
    "content": "# SolidStart\n\nEverything you need to build a Solid project, powered by [`solid-start`](https://start.solidjs.com);\n\n## Creating a project\n\n```bash\n# create a new project in the current directory\nnpm init solid@latest\n\n# create a new project in my-app\nnpm init solid@latest my-app\n```\n\n## Developing\n\nOnce you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:\n\n```bash\nnpm run dev\n\n# or start the server and open the app in a new browser tab\nnpm run dev -- --open\n```\n\n## Building\n\nSolid apps are built with _presets_, which optimise your project for deployment to different environments.\n\nBy default, `npm run build` will generate a Node app that you can run with `npm start`. To use a different preset, add it to the `devDependencies` in `package.json` and specify in your `app.config.js`.\n\n## This project was created with the [Solid CLI](https://solid-cli.netlify.app)\n"
  },
  {
    "path": "examples/solid/solid-start-streaming/app.config.ts",
    "content": "import { defineConfig } from '@solidjs/start/config'\n\nexport default defineConfig({})\n"
  },
  {
    "path": "examples/solid/solid-start-streaming/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-solid-start-streaming\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vinxi dev\",\n    \"build\": \"vinxi build\",\n    \"start\": \"vinxi start\",\n    \"version\": \"vinxi version\"\n  },\n  \"dependencies\": {\n    \"@solidjs/meta\": \"^0.29.4\",\n    \"@solidjs/router\": \"^0.15.3\",\n    \"@solidjs/start\": \"^1.1.3\",\n    \"@tanstack/solid-query\": \"^5.91.3\",\n    \"@tanstack/solid-query-devtools\": \"^5.91.3\",\n    \"solid-js\": \"^1.9.7\",\n    \"vinxi\": \"^0.5.3\"\n  },\n  \"engines\": {\n    \"node\": \">=18\"\n  }\n}\n"
  },
  {
    "path": "examples/solid/solid-start-streaming/src/app.css",
    "content": "body {\n  font-family:\n    Gordita, Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue',\n    sans-serif;\n  line-height: 1.5;\n}\n\na {\n  margin-right: 1rem;\n}\n\nmain {\n  text-align: center;\n  padding: 1em;\n  margin: 0 auto;\n}\n\nh1 {\n  color: #335d92;\n  text-transform: uppercase;\n  font-size: 2.5rem;\n  font-weight: 100;\n  line-height: 1.1;\n  margin: 2.5rem auto 0 auto;\n  max-width: 14rem;\n}\n\np {\n  max-width: 14rem;\n  margin: 1rem auto;\n  line-height: 1.35;\n}\n\n@media (min-width: 480px) {\n  h1 {\n    max-width: none;\n  }\n\n  p {\n    max-width: none;\n  }\n}\n\n.loader {\n  color: #888;\n  margin-top: 1rem;\n}\n\n.error {\n  color: red;\n  margin-top: 1rem;\n}\n\n.description {\n  max-width: 60rem;\n  margin: 3rem auto;\n}\n\n.description p {\n  line-height: 1.5;\n}\n\n.description *:not(:first-child) {\n  margin-top: 1rem;\n}\n\n.description_img {\n  max-width: 100%;\n  border-radius: 4px;\n}\n\n.example {\n  border: 1px solid #ddd;\n  padding: 1rem;\n  max-width: 50rem;\n  text-align: left;\n  margin: 1rem auto;\n}\n\n.example__header {\n  display: flex;\n}\n\n.example__title {\n  font-size: 1rem;\n  font-weight: bold;\n  flex-grow: 1;\n}\n\n.example--table {\n  padding: 0.5rem;\n}\n\n.example--table th,\n.example--table td {\n  padding: 4px 12px;\n  white-space: nowrap;\n}\n"
  },
  {
    "path": "examples/solid/solid-start-streaming/src/app.tsx",
    "content": "// @refresh reload\nimport { MetaProvider, Title } from '@solidjs/meta'\nimport { A, Router } from '@solidjs/router'\nimport { FileRoutes } from '@solidjs/start/router'\nimport { Suspense } from 'solid-js'\nimport { SolidQueryDevtools } from '@tanstack/solid-query-devtools'\nimport { QueryClient, QueryClientProvider } from '@tanstack/solid-query'\nimport './app.css'\n\nexport default function App() {\n  const queryClient = new QueryClient({\n    defaultOptions: {\n      queries: {\n        retry: false,\n        staleTime: 5000,\n      },\n    },\n  })\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      <SolidQueryDevtools />\n      <Router\n        root={(props) => (\n          <MetaProvider>\n            <Title>SolidStart - Basic</Title>\n            <a href=\"/\">Home</a>\n            <a href=\"/streamed\">Streamed</a>\n            <a href=\"/deferred\">Deferred</a>\n            <a href=\"/mixed\">Mixed</a>\n            <a href=\"/with-error\">With Error</a>\n            <a href=\"/hydration\">Hydration</a>\n            <A preload={true} href=\"/prefetch\">\n              Prefetch\n            </A>\n            <a href=\"/batch-methods\">Batching Methods</a>\n            <Suspense>{props.children}</Suspense>\n          </MetaProvider>\n        )}\n      >\n        <FileRoutes />\n      </Router>\n    </QueryClientProvider>\n  )\n}\n"
  },
  {
    "path": "examples/solid/solid-start-streaming/src/components/example.tsx",
    "content": "import type { ParentComponent } from 'solid-js'\n\nexport interface ExampleProps {\n  title: string\n  deferStream?: boolean\n  sleep?: number\n}\n\nexport const Example: ParentComponent<ExampleProps> = (props) => {\n  return (\n    <div class=\"example\">\n      <div class=\"example__header\">\n        <div class=\"example__title\">{props.title}</div>\n        <div>[deferStream={String(props.deferStream || false)}]</div>\n        <div style={{ 'margin-left': '10px' }}>\n          [simulated sleep: {props.sleep || 0}ms]\n        </div>\n      </div>\n\n      {props.children}\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/solid/solid-start-streaming/src/components/post-viewer.tsx",
    "content": "import { useQuery } from '@tanstack/solid-query'\nimport { resetErrorBoundaries } from 'solid-js'\nimport { createSignal } from 'solid-js'\nimport { For } from 'solid-js'\nimport { Example } from './example'\nimport { QueryBoundary } from './query-boundary'\nimport type { Component } from 'solid-js'\nimport { fetchPost } from '~/utils/api'\n\nexport interface PostViewerProps {\n  deferStream?: boolean\n  sleep?: number\n  simulateError?: boolean\n}\n\nexport const PostViewer: Component<PostViewerProps> = (props) => {\n  const [simulateError, setSimulateError] = createSignal(props.simulateError)\n  const [postId, setPostId] = createSignal(1)\n\n  const query = useQuery(() => ({\n    queryKey: ['posts', postId()],\n    queryFn: () =>\n      fetchPost({\n        postId: postId(),\n        sleep: props.sleep,\n        simulateError:\n          simulateError() || (simulateError() !== false && postId() === 5),\n      }),\n    deferStream: props.deferStream,\n    throwOnError: true,\n  }))\n\n  return (\n    <Example\n      title=\"Post Query\"\n      deferStream={props.deferStream}\n      sleep={props.sleep}\n    >\n      <div style={{ 'margin-top': '20px' }}>\n        <button\n          onClick={() => {\n            setPostId(Math.max(postId() - 1, 1))\n            resetErrorBoundaries()\n          }}\n        >\n          Previous Post\n        </button>\n        <button\n          onClick={() => {\n            setPostId(Math.min(postId() + 1, 100))\n            resetErrorBoundaries()\n          }}\n        >\n          Next Post\n        </button>\n      </div>\n\n      {/* NOTE: without this extra wrapping div, for some reason solid ends up printing two errors... feels like a bug in solid. */}\n      <div>\n        <QueryBoundary\n          query={query}\n          loadingFallback={<div class=\"loader\">loading post...</div>}\n          errorFallback={(err, retry) => (\n            <div>\n              <div class=\"error\">{err.message}</div>\n              <button\n                onClick={() => {\n                  setSimulateError(false)\n                  retry()\n                }}\n              >\n                retry\n              </button>\n            </div>\n          )}\n        >\n          {(posts) => (\n            <For each={posts}>\n              {(post) => (\n                <div style={{ 'margin-top': '20px' }}>\n                  <b>\n                    [post {postId()}] {post.title}\n                  </b>\n                  <p>{post.body}</p>\n                </div>\n              )}\n            </For>\n          )}\n        </QueryBoundary>\n      </div>\n    </Example>\n  )\n}\n"
  },
  {
    "path": "examples/solid/solid-start-streaming/src/components/query-boundary.tsx",
    "content": "import { ErrorBoundary, Match, Suspense, Switch, children } from 'solid-js'\nimport type { UseQueryResult } from '@tanstack/solid-query'\nimport type { JSX } from 'solid-js'\n\nexport interface QueryBoundaryProps<T = unknown> {\n  query: UseQueryResult<T, Error>\n\n  /**\n   * Triggered when the data is initially loading.\n   */\n  loadingFallback?: JSX.Element\n\n  /**\n   * Triggered when fetching is complete, but the returned data was falsey.\n   */\n  notFoundFallback?: JSX.Element\n\n  /**\n   * Triggered when the query results in an error.\n   */\n  errorFallback?: (err: Error, retry: () => void) => JSX.Element\n\n  /**\n   * Triggered when fetching is complete, and the returned data is not falsey.\n   */\n  children: (data: Exclude<T, null | false | undefined>) => JSX.Element\n}\n\n/**\n * Convenience wrapper that handles suspense and errors for queries. Makes the results of query.data available to\n * children (as a render prop) in a type-safe way.\n */\nexport function QueryBoundary<T>(props: QueryBoundaryProps<T>) {\n  return (\n    <Suspense fallback={props.loadingFallback}>\n      <ErrorBoundary\n        fallback={(err: Error, reset) =>\n          props.errorFallback ? (\n            props.errorFallback(err, async () => {\n              await props.query.refetch()\n              reset()\n            })\n          ) : (\n            <div>\n              <div class=\"error\">{err.message}</div>\n              <button\n                onClick={async () => {\n                  await props.query.refetch()\n                  reset()\n                }}\n              >\n                retry\n              </button>\n            </div>\n          )\n        }\n      >\n        <Switch>\n          {/* <Match when={props.query.isError}>\n            {props.errorFallback ? (\n              props.errorFallback\n            ) : (\n              <div>\n                <div class=\"error\">{props.query.error?.message}</div>\n                <button\n                  onClick={() => {\n                    props.query.refetch();\n                  }}\n                >\n                  retry\n                </button>\n              </div>\n            )}\n          </Match> */}\n\n          <Match when={!props.query.isFetching && !props.query.data}>\n            {props.notFoundFallback ? (\n              props.notFoundFallback\n            ) : (\n              <div>not found</div>\n            )}\n          </Match>\n\n          <Match when={props.query.data}>\n            {props.children(\n              props.query.data as Exclude<T, null | false | undefined>,\n            )}\n          </Match>\n        </Switch>\n      </ErrorBoundary>\n    </Suspense>\n  )\n}\n"
  },
  {
    "path": "examples/solid/solid-start-streaming/src/components/user-info.tsx",
    "content": "import { useQuery } from '@tanstack/solid-query'\nimport { createSignal } from 'solid-js'\nimport { Example } from './example'\nimport { QueryBoundary } from './query-boundary'\nimport type { Component } from 'solid-js'\nimport { fetchUser } from '~/utils/api'\n\nexport interface UserInfoProps {\n  deferStream?: boolean\n  sleep?: number\n  simulateError?: boolean\n  staleTime?: number\n  gcTime?: number\n}\n\nexport const userInfoQueryOpts = (props?: UserInfoProps) => ({\n  queryKey: ['user'],\n  queryFn: () => fetchUser(props),\n  deferStream: props?.deferStream,\n  staleTime: props?.staleTime,\n  gcTime: props?.gcTime,\n  throwOnError: true,\n})\n\nexport const UserInfo: Component<UserInfoProps> = (props) => {\n  const [simulateError, setSimulateError] = createSignal(props.simulateError)\n\n  const query = useQuery(() =>\n    userInfoQueryOpts({ ...props, simulateError: simulateError() }),\n  )\n\n  return (\n    <Example\n      title=\"User Query\"\n      deferStream={props.deferStream}\n      sleep={props.sleep}\n    >\n      <QueryBoundary\n        query={query}\n        loadingFallback={<div class=\"loader\">loading user...</div>}\n        errorFallback={(err, retry) => (\n          <div>\n            <div class=\"error\">{err.message}</div>\n            <button\n              onClick={() => {\n                setSimulateError(false)\n                retry()\n              }}\n            >\n              retry\n            </button>\n          </div>\n        )}\n      >\n        {(user) => (\n          <>\n            <div>id: {user.id}</div>\n            <div>name: {user.name}</div>\n            <div>queryTime: {user.queryTime}</div>\n            <button\n              onClick={() => {\n                query.refetch()\n              }}\n            >\n              refetch\n            </button>\n          </>\n        )}\n      </QueryBoundary>\n    </Example>\n  )\n}\n"
  },
  {
    "path": "examples/solid/solid-start-streaming/src/entry-client.tsx",
    "content": "// @refresh reload\nimport { mount, StartClient } from '@solidjs/start/client'\n\nconst app = document.getElementById('app')\nif (!app) throw new Error('Missing #app element')\n\nmount(() => <StartClient />, app)\n"
  },
  {
    "path": "examples/solid/solid-start-streaming/src/entry-server.tsx",
    "content": "// @refresh reload\nimport { createHandler, StartServer } from '@solidjs/start/server'\n\nexport default createHandler(() => (\n  <StartServer\n    document={({ assets, children, scripts }) => (\n      <html lang=\"en\">\n        <head>\n          <meta charset=\"utf-8\" />\n          <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n          <link rel=\"icon\" href=\"/favicon.ico\" />\n          {assets}\n        </head>\n        <body>\n          <div id=\"app\">{children}</div>\n          {scripts}\n        </body>\n      </html>\n    )}\n  />\n))\n"
  },
  {
    "path": "examples/solid/solid-start-streaming/src/global.d.ts",
    "content": "/// <reference types=\"@solidjs/start/env\" />\n"
  },
  {
    "path": "examples/solid/solid-start-streaming/src/routes/[...404].tsx",
    "content": "import { Title } from '@solidjs/meta'\nimport { HttpStatusCode } from '@solidjs/start'\n\nexport default function NotFound() {\n  return (\n    <main>\n      <Title>Not Found</Title>\n      <HttpStatusCode code={404} />\n      <h1>Page Not Found</h1>\n      <p>\n        Visit{' '}\n        <a href=\"https://start.solidjs.com\" target=\"_blank\">\n          start.solidjs.com\n        </a>{' '}\n        to learn how to build SolidStart apps.\n      </p>\n    </main>\n  )\n}\n"
  },
  {
    "path": "examples/solid/solid-start-streaming/src/routes/batch-methods.tsx",
    "content": "import { notifyManager, useQuery } from '@tanstack/solid-query'\nimport { createSignal } from 'solid-js'\nimport { QueryBoundary } from '~/components/query-boundary'\n\nfunction sleep(milliseconds: number) {\n  return new Promise((res) => setTimeout(res, milliseconds))\n}\n\nfunction spin(milliseconds: number) {\n  const start = performance.now()\n  while (performance.now() - start <= milliseconds) {\n    // do nothing\n  }\n}\n\nasync function sayHello(name: string) {\n  console.info('[api] sayHello.start')\n\n  await sleep(500)\n\n  // make the layout shift more obvious, it doesn't always happen\n  console.time('[api] sayHello.spin')\n  spin(20)\n  console.timeEnd('[api] sayHello.spin')\n\n  console.info('[api] sayHello.end')\n  return `Hello ${name}`\n}\n\nexport default function BatchMethods() {\n  const [count, setCount] = createSignal(0)\n\n  const hello = useQuery(() => ({\n    queryKey: ['hello', count()] as const,\n    queryFn: ({ queryKey: [_, count] }) => sayHello(`solid ${count}`),\n  }))\n\n  return (\n    <div>\n      <select\n        value=\"timer\"\n        ref={(el) => (el.value = 'timer')} // browser caches form input\n        onInput={(e) => {\n          const type = e.currentTarget.value\n          if (type === 'raf') notifyManager.setScheduler(requestAnimationFrame)\n          if (type === 'tick') notifyManager.setScheduler(queueMicrotask)\n          if (type === 'timer')\n            notifyManager.setScheduler((cb) => setTimeout(cb, 0))\n        }}\n      >\n        <option value=\"raf\">requestAnimationFrame</option>\n        <option value=\"timer\">setTimeout</option>\n        <option value=\"tick\">queueMicrotick</option>\n      </select>\n      <button class=\"increment\" onClick={() => setCount((x) => x + 1)}>\n        Clicks: {count()}\n      </button>\n      <p>\n        <QueryBoundary loadingFallback={'Loading...'} query={hello}>\n          {(data) => <div style={{ 'background-color': 'aqua' }}>{data}</div>}\n        </QueryBoundary>\n      </p>\n      <div style={{ 'background-color': 'red' }}>\n        Something below to demonstrate layout shift\n      </div>\n      <p>\n        Due to the way solidjs handles updates, sometimes the updating of a\n        query results in DOM modifications triggering a rerender twice. This is\n        perceived as a glitch in the layout of the webpage that usually lasts\n        for one frame. By using another batching strategy in the browser,\n        instead of the default setTimeout one, we can mitigate this issue. Try\n        out requestAnimationFrame or queueMicrotick.\n      </p>\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/solid/solid-start-streaming/src/routes/deferred.tsx",
    "content": "import { Title } from '@solidjs/meta'\nimport { PostViewer } from '~/components/post-viewer'\nimport { UserInfo } from '~/components/user-info'\n\nexport default function Deferred() {\n  return (\n    <main>\n      <Title>Solid Query - Deferred</Title>\n\n      <h1>Solid Query - Deferred Example</h1>\n\n      <div class=\"description\">\n        <p>\n          Both queries are configured with deferStream=true, so the server will\n          not start streaming HTML to the client until the queries have\n          resolved. In this case we are not really taking advantage of streaming\n          - this mimics traditional renderAsync + Suspense behavior. Note how\n          the green bar in the devtools is much larger now - the client does not\n          start receiving any information until 2+ seconds (both queries\n          resolve).\n        </p>\n\n        <p>\n          Clients with javascript disabled will see the resolved state for both\n          queries. (try turning off javascript and reloading this page)\n        </p>\n\n        <img\n          class=\"description_img\"\n          src=\"/imgs/deferred.png\"\n          alt=\"devtools deferred requests\"\n        />\n      </div>\n\n      <UserInfo sleep={2000} deferStream />\n\n      <PostViewer sleep={2000} deferStream />\n    </main>\n  )\n}\n"
  },
  {
    "path": "examples/solid/solid-start-streaming/src/routes/hydration.tsx",
    "content": "import { useQuery } from '@tanstack/solid-query'\nimport { Suspense, createSignal } from 'solid-js'\nimport { NoHydration } from 'solid-js/web'\nimport { Title } from '@solidjs/meta'\nimport type { UseQueryResult } from '@tanstack/solid-query'\nimport { fetchUser } from '~/utils/api'\n\nexport default function Hydration() {\n  const query = useQuery(() => ({\n    queryKey: ['user'],\n    queryFn: () => fetchUser({ sleep: 500 }),\n    deferStream: true,\n  }))\n\n  const [initialQueryState] = createSignal(JSON.parse(JSON.stringify(query)))\n\n  return (\n    <main>\n      <Title>Solid Query - Hydration</Title>\n\n      <h1>Solid Query - Hydration Example</h1>\n\n      <div class=\"description\">\n        <p>\n          Lists the query state as seen on the server, initial render on the\n          client (right after hydration), and current client value. Ideally, if\n          SSR is setup correctly, these values are exactly the same in all three\n          contexts.\n        </p>\n      </div>\n\n      <button onClick={() => query.refetch()}>Refetch</button>\n\n      <table class=\"example example--table\">\n        <thead>\n          <tr>\n            <th>Context</th>\n            <th>data.name</th>\n            <th>isFetching</th>\n            <th>isFetched</th>\n            <th>isPending</th>\n            <th>isRefetching</th>\n            <th>isLoading</th>\n            <th>isStale</th>\n            <th>isSuccess</th>\n            <th>isError</th>\n            <th>error</th>\n            <th>fetchStatus</th>\n            <th>dataUpdatedAt</th>\n          </tr>\n        </thead>\n\n        <tbody>\n          <Suspense>\n            <NoHydration>\n              <QueryStateRow context=\"server\" query={query} />\n            </NoHydration>\n\n            <QueryStateRow\n              context=\"client (initial render)\"\n              query={initialQueryState()!}\n            />\n\n            <QueryStateRow context=\"client\" query={query} />\n          </Suspense>\n        </tbody>\n      </table>\n    </main>\n  )\n}\n\ntype QueryState = UseQueryResult<\n  {\n    id: string\n    name: string\n    queryTime: number\n  },\n  Error\n>\n\nconst QueryStateRow = (props: { context: string; query: QueryState }) => {\n  return (\n    <tr>\n      <td>{props.context}</td>\n      <td>{props.query.data?.name}</td>\n      <td>{String(props.query.isFetching)}</td>\n      <td>{String(props.query.isFetched)}</td>\n      <td>{String(props.query.isPending)}</td>\n      <td>{String(props.query.isRefetching)}</td>\n      <td>{String(props.query.isLoading)}</td>\n      <td>{String(props.query.isStale)}</td>\n      <td>{String(props.query.isSuccess)}</td>\n      <td>{String(props.query.isError)}</td>\n      <td>{String(props.query.error)}</td>\n      <td>{String(props.query.fetchStatus)}</td>\n      <td>{String(props.query.dataUpdatedAt)}</td>\n    </tr>\n  )\n}\n"
  },
  {
    "path": "examples/solid/solid-start-streaming/src/routes/index.tsx",
    "content": "import { Title } from '@solidjs/meta'\n\nexport default function Home() {\n  return (\n    <main>\n      <Title>Solid Query v5</Title>\n\n      <h1>Solid Query v5</h1>\n\n      <p>\n        This demo demonstrates how Solid Query can be used in SSR, with\n        streaming support. Use the links in the top left to navigate between the\n        various examples.\n      </p>\n    </main>\n  )\n}\n"
  },
  {
    "path": "examples/solid/solid-start-streaming/src/routes/mixed.tsx",
    "content": "import { Title } from '@solidjs/meta'\nimport { PostViewer } from '~/components/post-viewer'\nimport { UserInfo } from '~/components/user-info'\n\nexport default function Mixed() {\n  return (\n    <main>\n      <Title>Solid Query - Mixed</Title>\n\n      <h1>Solid Query - Mixed Example</h1>\n\n      <div class=\"description\">\n        <p>\n          You may want to require that key queries resolve before the initial\n          HTML is streamed to the client, while allowing the rest of your\n          queries to stream to the client as they resolve. A common use case for\n          this is to populate SEO meta tags and/or social graph information for\n          unfurl scenarios such as sharing the page as a link in Slack.\n        </p>\n\n        <p>\n          In this example, the quick (100ms) user query has deferStream set to\n          true, while the more expensive post query (1000ms) is streamed to the\n          client when ready. Clients with javascript disabled will see the\n          resolved state for the user query, and the loading state for the post\n          query. (try turning off javascript and reloading this page)\n        </p>\n      </div>\n\n      <UserInfo deferStream sleep={100} />\n\n      <PostViewer sleep={1000} />\n    </main>\n  )\n}\n"
  },
  {
    "path": "examples/solid/solid-start-streaming/src/routes/prefetch.tsx",
    "content": "import { useQueryClient } from '@tanstack/solid-query'\nimport { isServer } from 'solid-js/web'\nimport { Title } from '@solidjs/meta'\nimport { UserInfo, userInfoQueryOpts } from '~/components/user-info'\n\nexport const route = {\n  load: () => {\n    const queryClient = useQueryClient()\n    // Prefetching the user info and caching it for 15 seconds.\n    queryClient.prefetchQuery(userInfoQueryOpts({ sleep: 500, gcTime: 15000 }))\n  },\n}\n\nexport default function Prefetch() {\n  return (\n    <main>\n      <Title>Solid Query - Prefetch</Title>\n\n      <h1>Solid Query - Prefetch Example</h1>\n\n      <div class=\"description\">\n        <p>\n          SolidStart now supports link prefetching. This means that when a user\n          hovers over a link, the browser can prefetch the data for that page\n          before the user even clicks on the link. This can make navigating\n          around your app feel much faster.\n        </p>\n        <p>\n          To see this in action, go to the home page and reload the page. Then\n          hover over the \"Prefetch\" link in the navigation. You should see the\n          user data prefetch in the background and in the devtools. When you\n          click on the link, the page should load instantly.\n        </p>\n      </div>\n\n      <UserInfo sleep={500} />\n    </main>\n  )\n}\n"
  },
  {
    "path": "examples/solid/solid-start-streaming/src/routes/streamed.tsx",
    "content": "import { Title } from '@solidjs/meta'\nimport { PostViewer } from '~/components/post-viewer'\nimport { UserInfo } from '~/components/user-info'\n\nexport default function Streamed() {\n  return (\n    <main>\n      <Title>Solid Query - Streamed</Title>\n\n      <h1>Solid Query - Streamed Example</h1>\n\n      <div class=\"description\">\n        <p>\n          HTML is streamed from the server ASAP, reducing key metrics such as\n          TTFB and TTI. Suspended queries are streamed to the client when they\n          resolve on the server. This is represented in your devtools by the\n          green and blue chunks of the waterfall.\n        </p>\n\n        <p>\n          Clients with javascript disabled will see the loading state for both\n          queries. (try turning off javascript and reloading this page)\n        </p>\n\n        <img\n          class=\"description_img\"\n          src=\"/imgs/streaming.png\"\n          alt=\"devtools streaming request\"\n        />\n      </div>\n\n      <UserInfo sleep={2500} />\n\n      <PostViewer sleep={300} />\n    </main>\n  )\n}\n"
  },
  {
    "path": "examples/solid/solid-start-streaming/src/routes/with-error.tsx",
    "content": "import { Title } from '@solidjs/meta'\nimport { PostViewer } from '~/components/post-viewer'\nimport { UserInfo } from '~/components/user-info'\n\nexport default function Streamed() {\n  return (\n    <main>\n      <Title>Solid Query - Errors</Title>\n\n      <h1>Solid Query - Errors</h1>\n\n      <div class=\"description\">\n        <p>\n          For more control over error handling, try leveraging the `Switch`\n          component and watching the reactive `query.isError` property. See\n          `compoennts/query-boundary.tsx` for one possible approach.\n        </p>\n      </div>\n\n      <UserInfo sleep={10} deferStream simulateError />\n\n      <PostViewer sleep={3000} deferStream simulateError />\n    </main>\n  )\n}\n"
  },
  {
    "path": "examples/solid/solid-start-streaming/src/utils/api.ts",
    "content": "interface PostData {\n  userId: number\n  id: number\n  title: string\n  body: string\n}\n\nconst doSleep = (ms: number) => new Promise((r) => setTimeout(r, ms))\n\nexport const fetchPost = async ({\n  postId,\n  simulateError,\n  sleep,\n}: {\n  postId: number\n  simulateError?: boolean\n  sleep?: number\n}) => {\n  console.info('[api] fetchPost.start', { postId, sleep, simulateError })\n\n  let response\n  if (!simulateError) {\n    response = await fetch(\n      `https://jsonplaceholder.typicode.com/posts/${postId}`,\n    ).then((res) => res.json())\n  }\n\n  // simulate extra latency to make things like streaming behavior more clear\n  if (sleep) {\n    await doSleep(sleep)\n  }\n\n  console.info('[api] fetchPost.done', { postId, sleep, simulateError })\n\n  if (simulateError) {\n    throw new Error('API request to get post was not OK')\n  }\n\n  return [response] as PostData[]\n}\n\nexport const fetchUser = async ({\n  sleep,\n  simulateError,\n}: { sleep?: number; simulateError?: boolean } = {}) => {\n  console.info('[api] fetchUser.start', { sleep, simulateError })\n\n  if (sleep) {\n    await doSleep(sleep)\n  }\n\n  console.info('[api] fetchUser.done', { sleep, simulateError })\n\n  if (simulateError) {\n    throw new Error('API request to get user was not OK')\n  }\n\n  return {\n    id: 'abc',\n    name: `john doe`,\n    queryTime: Date.now(),\n  }\n}\n"
  },
  {
    "path": "examples/solid/solid-start-streaming/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ESNext\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"allowSyntheticDefaultImports\": true,\n    \"esModuleInterop\": true,\n    \"jsx\": \"preserve\",\n    \"jsxImportSource\": \"solid-js\",\n    \"allowJs\": true,\n    \"strict\": true,\n    \"noEmit\": true,\n    \"types\": [\"vinxi/client\", \"vite/client\"],\n    \"isolatedModules\": true,\n    \"paths\": {\n      \"~/*\": [\"./src/*\"]\n    }\n  }\n}\n"
  },
  {
    "path": "examples/svelte/auto-refetching/.gitignore",
    "content": ".DS_Store\nnode_modules\n/build\n/.svelte-kit\n/package\n.env\n.env.*\n!.env.example\n!lib/\n"
  },
  {
    "path": "examples/svelte/auto-refetching/README.md",
    "content": "# create-svelte\n\nEverything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte).\n\n## Creating a project\n\nIf you're seeing this, you've probably already done this step. Congrats!\n\n```bash\n# create a new project in the current directory\nnpm create svelte@latest\n\n# create a new project in my-app\nnpm create svelte@latest my-app\n```\n\n## Developing\n\nOnce you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn` or `bun install`), start a development server:\n\n```bash\nnpm run dev\n\n# or start the server and open the app in a new browser tab\nnpm run dev -- --open\n```\n\n## Building\n\nTo create a production version of your app:\n\n```bash\nnpm run build\n```\n\nYou can preview the production build with `npm run preview`.\n\n> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.\n"
  },
  {
    "path": "examples/svelte/auto-refetching/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-svelte-auto-refetching\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite dev\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/svelte-query\": \"^6.1.3\",\n    \"@tanstack/svelte-query-devtools\": \"^6.0.4\"\n  },\n  \"devDependencies\": {\n    \"@sveltejs/adapter-auto\": \"^6.1.0\",\n    \"@sveltejs/kit\": \"^2.42.2\",\n    \"@sveltejs/vite-plugin-svelte\": \"^5.1.1\",\n    \"svelte\": \"^5.39.3\",\n    \"svelte-check\": \"^4.3.1\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "examples/svelte/auto-refetching/src/app.css",
    "content": ":root {\n  font-family: Inter, Avenir, Helvetica, Arial, sans-serif;\n  font-size: 16px;\n  line-height: 24px;\n  font-weight: 400;\n\n  color-scheme: light dark;\n  color: rgba(255, 255, 255, 0.87);\n  background-color: #242424;\n\n  font-synthesis: none;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-text-size-adjust: 100%;\n}\n\na {\n  font-weight: 500;\n  color: #646cff;\n  text-decoration: inherit;\n}\na:hover {\n  color: #535bf2;\n}\n\nbody {\n  margin: 0;\n  display: flex;\n  place-items: center;\n  min-width: 320px;\n  min-height: 100vh;\n}\n\nh1 {\n  font-size: 3.2em;\n  line-height: 1.1;\n}\n\n.card {\n  padding: 2em;\n}\n\nmain {\n  max-width: 1280px;\n  margin: 0 auto;\n  padding: 2rem;\n  text-align: center;\n}\n\nbutton {\n  border-radius: 8px;\n  border: 1px solid transparent;\n  padding: 0.6em 1.2em;\n  font-size: 1em;\n  font-weight: 500;\n  font-family: inherit;\n  background-color: #1a1a1a;\n  cursor: pointer;\n  transition: border-color 0.25s;\n}\nbutton:hover {\n  border-color: #646cff;\n}\nbutton:focus,\nbutton:focus-visible {\n  outline: 4px auto -webkit-focus-ring-color;\n}\n\n@media (prefers-color-scheme: light) {\n  :root {\n    color: #213547;\n    background-color: #ffffff;\n  }\n  a:hover {\n    color: #747bff;\n  }\n  button {\n    background-color: #f9f9f9;\n  }\n}\n"
  },
  {
    "path": "examples/svelte/auto-refetching/src/app.d.ts",
    "content": "// See https://kit.svelte.dev/docs/types#app\n// for information about these interfaces\ndeclare global {\n  namespace App {\n    // interface Error {}\n    // interface Locals {}\n    // interface PageData {}\n    // interface Platform {}\n  }\n}\n\nexport {}\n"
  },
  {
    "path": "examples/svelte/auto-refetching/src/app.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"icon\" href=\"%sveltekit.assets%/favicon.png\" />\n    <meta name=\"viewport\" content=\"width=device-width\" />\n    %sveltekit.head%\n  </head>\n  <body data-sveltekit-preload-data=\"hover\">\n    <div style=\"display: contents\">%sveltekit.body%</div>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/svelte/auto-refetching/src/routes/+layout.svelte",
    "content": "<script lang=\"ts\">\n  import '../app.css'\n  import { browser } from '$app/environment'\n  import { QueryClientProvider, QueryClient } from '@tanstack/svelte-query'\n  import { SvelteQueryDevtools } from '@tanstack/svelte-query-devtools'\n\n  const { children } = $props()\n\n  const queryClient = new QueryClient({\n    defaultOptions: {\n      queries: {\n        enabled: browser,\n      },\n    },\n  })\n</script>\n\n<QueryClientProvider client={queryClient}>\n  <main>\n    {@render children()}\n  </main>\n  <SvelteQueryDevtools />\n</QueryClientProvider>\n"
  },
  {
    "path": "examples/svelte/auto-refetching/src/routes/+page.svelte",
    "content": "<script lang=\"ts\">\n  import {\n    useQueryClient,\n    createQuery,\n    createMutation,\n  } from '@tanstack/svelte-query'\n\n  let intervalMs = $state(1000)\n  let value = $state<string>('')\n\n  const client = useQueryClient()\n\n  const endpoint = '/api/data'\n\n  const todos = createQuery<{ items: string[] }>(() => ({\n    queryKey: ['refetch'],\n    queryFn: async () => await fetch(endpoint).then((r) => r.json()),\n    // Refetch the data every second\n    refetchInterval: intervalMs,\n  }))\n\n  const addMutation = createMutation(() => ({\n    mutationFn: (value: string) =>\n      fetch(`${endpoint}?add=${encodeURIComponent(value)}`).then((r) =>\n        r.json(),\n      ),\n    onSuccess: () => client.invalidateQueries({ queryKey: ['refetch'] }),\n  }))\n\n  const clearMutation = createMutation(() => ({\n    mutationFn: () => fetch(`${endpoint}?clear=1`).then((r) => r.json()),\n    onSuccess: () => client.invalidateQueries({ queryKey: ['refetch'] }),\n  }))\n</script>\n\n<h1>Auto Refetch with stale-time set to {intervalMs}ms</h1>\n\n<p>\n  This example is best experienced on your own machine, where you can open\n  multiple tabs to the same localhost server and see your changes propagate\n  between the two.\n</p>\n\n<label>\n  Query Interval speed (ms):{' '}\n  <div class=\"flex\">\n    <input bind:value={intervalMs} type=\"number\" step=\"100\" />{' '}\n\n    <span\n      style=\"display:inline-block; \n          margin-left:.5rem;\n          width:.75rem;\n          height:.75rem; \n          background: {todos.isFetching ? 'green' : 'transparent'};\n          transition: {!todos.isFetching ? 'all .3s ease' : 'none'};\n          border-radius: 100%;\n          transform: scale(1.5)\"\n    ></span>\n  </div>\n</label>\n<h2>Todo List</h2>\n<form\n  onsubmit={(e) => {\n    e.preventDefault()\n    e.stopPropagation()\n    addMutation.mutate(value, {\n      onSuccess: () => (value = ''),\n    })\n  }}\n>\n  <input placeholder=\"enter something\" bind:value />\n</form>\n\n{#if todos.isPending}\n  Loading...\n{/if}\n{#if todos.error}\n  An error has occurred:\n  {todos.error.message}\n{/if}\n{#if todos.isSuccess}\n  <ul>\n    {#each todos.data.items as item}\n      <li>{item}</li>\n    {/each}\n  </ul>\n  <div>\n    <button onclick={() => clearMutation.mutate(undefined)}> Clear All </button>\n  </div>\n{/if}\n\n<pre\n  class={['updating-text', todos.isFetching && 'on']}\n  style=\"font-weight:700\">Background Updating...</pre>\n\n<style>\n  li {\n    text-align: left;\n  }\n\n  .updating-text {\n    color: transparent;\n    transition: all 0.3s ease;\n  }\n  .updating-text.on {\n    color: green;\n    transition: none;\n  }\n</style>\n"
  },
  {
    "path": "examples/svelte/auto-refetching/src/routes/api/data/+server.ts",
    "content": "import { json } from '@sveltejs/kit'\nimport type { RequestHandler } from '@sveltejs/kit'\n\nconst list = { items: ['Item 1', 'Item 2', 'Item 3'] }\n\n/** @type {import('./$types').RequestHandler} */\nexport const GET: RequestHandler = async ({ url }) => {\n  const add = url.searchParams.get('add')\n  const clear = url.searchParams.get('clear')\n\n  if (add) {\n    if (!list.items.includes(add)) {\n      list.items.push(add)\n    }\n  } else if (clear) {\n    list.items = []\n  }\n  await new Promise((r) => setTimeout(r, 200))\n  return json(list, { status: 200 })\n}\n"
  },
  {
    "path": "examples/svelte/auto-refetching/svelte.config.js",
    "content": "import adapter from '@sveltejs/adapter-auto'\nimport { vitePreprocess } from '@sveltejs/vite-plugin-svelte'\n\n/** @type {import('@sveltejs/kit').Config} */\nconst config = {\n  preprocess: vitePreprocess(),\n  kit: {\n    adapter: adapter(),\n  },\n  compilerOptions: {\n    runes: true,\n  },\n}\n\nexport default config\n"
  },
  {
    "path": "examples/svelte/auto-refetching/tsconfig.json",
    "content": "{\n  \"extends\": \"./.svelte-kit/tsconfig.json\",\n  \"compilerOptions\": {\n    \"allowJs\": true,\n    \"checkJs\": true,\n    \"esModuleInterop\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"resolveJsonModule\": true,\n    \"skipLibCheck\": true,\n    \"sourceMap\": true,\n    \"strict\": true\n  }\n  // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias\n  //\n  // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes\n  // from the referenced tsconfig.json - TypeScript does not merge them in\n}\n"
  },
  {
    "path": "examples/svelte/auto-refetching/vite.config.ts",
    "content": "import { sveltekit } from '@sveltejs/kit/vite'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  plugins: [sveltekit()],\n})\n"
  },
  {
    "path": "examples/svelte/basic/.gitignore",
    "content": ".DS_Store\nnode_modules\n/build\n/.svelte-kit\n/package\n.env\n.env.*\n!.env.example\n!lib/\n"
  },
  {
    "path": "examples/svelte/basic/README.md",
    "content": "# create-svelte\n\nEverything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte).\n\n## Creating a project\n\nIf you're seeing this, you've probably already done this step. Congrats!\n\n```bash\n# create a new project in the current directory\nnpm create svelte@latest\n\n# create a new project in my-app\nnpm create svelte@latest my-app\n```\n\n## Developing\n\nOnce you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn` or `bun install`), start a development server:\n\n```bash\nnpm run dev\n\n# or start the server and open the app in a new browser tab\nnpm run dev -- --open\n```\n\n## Building\n\nTo create a production version of your app:\n\n```bash\nnpm run build\n```\n\nYou can preview the production build with `npm run preview`.\n\n> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.\n"
  },
  {
    "path": "examples/svelte/basic/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-svelte-basic\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite dev\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/query-async-storage-persister\": \"^5.90.27\",\n    \"@tanstack/svelte-query\": \"^6.1.3\",\n    \"@tanstack/svelte-query-devtools\": \"^6.0.4\",\n    \"@tanstack/svelte-query-persist-client\": \"^6.0.25\"\n  },\n  \"devDependencies\": {\n    \"@sveltejs/adapter-auto\": \"^6.1.0\",\n    \"@sveltejs/kit\": \"^2.42.2\",\n    \"@sveltejs/vite-plugin-svelte\": \"^5.1.1\",\n    \"svelte\": \"^5.39.3\",\n    \"svelte-check\": \"^4.3.1\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "examples/svelte/basic/src/app.css",
    "content": ":root {\n  font-family: Inter, Avenir, Helvetica, Arial, sans-serif;\n  font-size: 16px;\n  line-height: 24px;\n  font-weight: 400;\n\n  color-scheme: light dark;\n  color: rgba(255, 255, 255, 0.87);\n  background-color: #242424;\n\n  font-synthesis: none;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-text-size-adjust: 100%;\n}\n\na {\n  font-weight: 500;\n  color: #646cff;\n  text-decoration: inherit;\n}\na:hover {\n  color: #535bf2;\n}\n\nbody {\n  margin: 0;\n  display: flex;\n  place-items: center;\n  min-width: 320px;\n  min-height: 100vh;\n}\n\nh1 {\n  font-size: 3.2em;\n  line-height: 1.1;\n}\n\n.card {\n  padding: 2em;\n}\n\nmain {\n  max-width: 1280px;\n  margin: 0 auto;\n  padding: 2rem;\n  text-align: center;\n}\n\n.button {\n  border-radius: 8px;\n  border: 1px solid transparent;\n  padding: 0.6em 1.2em;\n  font-size: 1em;\n  font-weight: 500;\n  font-family: inherit;\n  background-color: #1a1a1a;\n  cursor: pointer;\n  transition: border-color 0.25s;\n}\n.button:hover {\n  border-color: #646cff;\n}\n.button:focus,\n.button:focus-visible {\n  outline: 4px auto -webkit-focus-ring-color;\n}\n\n@media (prefers-color-scheme: light) {\n  :root {\n    color: #213547;\n    background-color: #ffffff;\n  }\n  a:hover {\n    color: #747bff;\n  }\n  .button {\n    background-color: #f9f9f9;\n  }\n}\n"
  },
  {
    "path": "examples/svelte/basic/src/app.d.ts",
    "content": "// See https://kit.svelte.dev/docs/types#app\n// for information about these interfaces\ndeclare global {\n  namespace App {\n    // interface Error {}\n    // interface Locals {}\n    // interface PageData {}\n    // interface Platform {}\n  }\n}\n\nexport {}\n"
  },
  {
    "path": "examples/svelte/basic/src/app.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"icon\" href=\"%sveltekit.assets%/favicon.png\" />\n    <meta name=\"viewport\" content=\"width=device-width\" />\n    %sveltekit.head%\n  </head>\n  <body data-sveltekit-preload-data=\"hover\">\n    <div style=\"display: contents\">%sveltekit.body%</div>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/svelte/basic/src/lib/Post.svelte",
    "content": "<script lang=\"ts\">\n  import { createQuery } from '@tanstack/svelte-query'\n  import { getPostById } from './data'\n  import type { Post } from './types'\n\n  const { postId }: { postId: number } = $props()\n\n  const post = createQuery<Post>(() => ({\n    queryKey: ['post', postId],\n    queryFn: () => getPostById(postId),\n  }))\n</script>\n\n<div>\n  <div>\n    <a class=\"button\" href=\"/\"> Back </a>\n  </div>\n  {#if !postId || post.isPending}\n    <span>Loading...</span>\n  {/if}\n  {#if post.error}\n    <span>Error: {post.error.message}</span>\n  {/if}\n  {#if post.isSuccess}\n    <h1>{post.data.title}</h1>\n    <div>\n      <p>{post.data.body}</p>\n    </div>\n    <div>{post.isFetching ? 'Background Updating...' : ' '}</div>\n  {/if}\n</div>\n"
  },
  {
    "path": "examples/svelte/basic/src/lib/Posts.svelte",
    "content": "<script lang=\"ts\">\n  import { useQueryClient, createQuery } from '@tanstack/svelte-query'\n  import { getPosts } from './data'\n\n  const client = useQueryClient()\n\n  let limit = 10\n\n  const posts = createQuery<\n    { id: number; title: string; body: string }[],\n    Error\n  >(() => ({\n    queryKey: ['posts', limit],\n    queryFn: () => getPosts(limit),\n  }))\n</script>\n\n<div>\n  <div>\n    {#if posts.status === 'pending'}\n      <span>Loading...</span>\n    {:else if posts.status === 'error'}\n      <span>Error: {posts.error.message}</span>\n    {:else}\n      <ul>\n        {#each posts.data as post}\n          <article>\n            <a\n              href={`/${post.id}`}\n              style={// We can use the queryCache here to show bold links for\n              // ones that are cached\n              client.getQueryData(['post', post.id])\n                ? 'font-weight: bold; color: indianred'\n                : 'cursor: pointer'}\n            >\n              {post.title}\n            </a>\n          </article>\n        {/each}\n      </ul>\n      <pre\n        class={['updating-text', posts.isFetching && 'on']}\n        style=\"font-weight:700\">Background Updating...</pre>\n    {/if}\n  </div>\n</div>\n\n<style>\n  article {\n    text-align: left;\n  }\n  a {\n    display: block;\n    font-size: 1.5rem;\n    margin-bottom: 1rem;\n  }\n\n  .updating-text {\n    color: transparent;\n    transition: all 0.3s ease;\n  }\n  .updating-text.on {\n    color: green;\n    transition: none;\n  }\n</style>\n"
  },
  {
    "path": "examples/svelte/basic/src/lib/data.ts",
    "content": "import type { Post } from './types'\n\nexport const getPosts = async (limit: number) => {\n  const response = await fetch('https://jsonplaceholder.typicode.com/posts')\n  const data = (await response.json()) as Array<Post>\n  return data.filter((x) => x.id <= limit)\n}\n\nexport const getPostById = async (id: number): Promise<Post> => {\n  const response = await fetch(\n    `https://jsonplaceholder.typicode.com/posts/${id}`,\n  )\n  const data = (await response.json()) as Post\n  return data\n}\n"
  },
  {
    "path": "examples/svelte/basic/src/lib/types.ts",
    "content": "export type Post = {\n  id: number\n  title: string\n  body: string\n}\n"
  },
  {
    "path": "examples/svelte/basic/src/routes/+layout.svelte",
    "content": "<script lang=\"ts\">\n  import '../app.css'\n  import { browser } from '$app/environment'\n  import { QueryClient } from '@tanstack/svelte-query'\n  import { SvelteQueryDevtools } from '@tanstack/svelte-query-devtools'\n  import { PersistQueryClientProvider } from '@tanstack/svelte-query-persist-client'\n  import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister'\n\n  const { children } = $props()\n\n  const queryClient = new QueryClient({\n    defaultOptions: {\n      queries: {\n        enabled: browser,\n      },\n    },\n  })\n\n  const persister = createAsyncStoragePersister({\n    storage: browser ? window.localStorage : null,\n  })\n</script>\n\n<PersistQueryClientProvider client={queryClient} persistOptions={{ persister }}>\n  <main>\n    {@render children()}\n  </main>\n  <SvelteQueryDevtools />\n</PersistQueryClientProvider>\n"
  },
  {
    "path": "examples/svelte/basic/src/routes/+page.svelte",
    "content": "<script lang=\"ts\">\n  import Posts from '$lib/Posts.svelte'\n</script>\n\n<h1>Basic Query</h1>\n<Posts />\n"
  },
  {
    "path": "examples/svelte/basic/src/routes/[postId]/+page.svelte",
    "content": "<script lang=\"ts\">\n  import Post from '$lib/Post.svelte'\n\n  const { data } = $props()\n</script>\n\n<Post postId={data.postId} />\n"
  },
  {
    "path": "examples/svelte/basic/src/routes/[postId]/+page.ts",
    "content": "import type { PageLoad } from './$types'\n\nexport const load: PageLoad = async ({ params }) => {\n  const postId = parseInt(params.postId)\n  return { postId }\n}\n"
  },
  {
    "path": "examples/svelte/basic/svelte.config.js",
    "content": "import adapter from '@sveltejs/adapter-auto'\nimport { vitePreprocess } from '@sveltejs/vite-plugin-svelte'\n\n/** @type {import('@sveltejs/kit').Config} */\nconst config = {\n  preprocess: vitePreprocess(),\n  kit: {\n    adapter: adapter(),\n  },\n  compilerOptions: {\n    runes: true,\n  },\n}\n\nexport default config\n"
  },
  {
    "path": "examples/svelte/basic/tsconfig.json",
    "content": "{\n  \"extends\": \"./.svelte-kit/tsconfig.json\",\n  \"compilerOptions\": {\n    \"allowJs\": true,\n    \"checkJs\": true,\n    \"esModuleInterop\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"resolveJsonModule\": true,\n    \"skipLibCheck\": true,\n    \"sourceMap\": true,\n    \"strict\": true\n  }\n  // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias\n  //\n  // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes\n  // from the referenced tsconfig.json - TypeScript does not merge them in\n}\n"
  },
  {
    "path": "examples/svelte/basic/vite.config.ts",
    "content": "import { sveltekit } from '@sveltejs/kit/vite'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  plugins: [sveltekit()],\n})\n"
  },
  {
    "path": "examples/svelte/load-more-infinite-scroll/.gitignore",
    "content": ".DS_Store\nnode_modules\n/build\n/.svelte-kit\n/package\n.env\n.env.*\n!.env.example\nvite.config.js.timestamp-*\nvite.config.ts.timestamp-*\n"
  },
  {
    "path": "examples/svelte/load-more-infinite-scroll/README.md",
    "content": "# create-svelte\n\nEverything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte).\n\n## Creating a project\n\nIf you're seeing this, you've probably already done this step. Congrats!\n\n```bash\n# create a new project in the current directory\nnpm create svelte@latest\n\n# create a new project in my-app\nnpm create svelte@latest my-app\n```\n\n## Developing\n\nOnce you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn` or `bun install`), start a development server:\n\n```bash\nnpm run dev\n\n# or start the server and open the app in a new browser tab\nnpm run dev -- --open\n```\n\n## Building\n\nTo create a production version of your app:\n\n```bash\nnpm run build\n```\n\nYou can preview the production build with `npm run preview`.\n\n> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.\n"
  },
  {
    "path": "examples/svelte/load-more-infinite-scroll/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-svelte-load-more-infinite-scroll\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite dev\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/svelte-query\": \"^6.1.3\",\n    \"@tanstack/svelte-query-devtools\": \"^6.0.4\"\n  },\n  \"devDependencies\": {\n    \"@sveltejs/adapter-auto\": \"^6.1.0\",\n    \"@sveltejs/kit\": \"^2.42.2\",\n    \"@sveltejs/vite-plugin-svelte\": \"^5.1.1\",\n    \"svelte\": \"^5.39.3\",\n    \"svelte-check\": \"^4.3.1\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "examples/svelte/load-more-infinite-scroll/src/app.css",
    "content": ":root {\n  font-family: Inter, Avenir, Helvetica, Arial, sans-serif;\n  font-size: 16px;\n  line-height: 24px;\n  font-weight: 400;\n\n  color-scheme: light dark;\n  color: rgba(255, 255, 255, 0.87);\n  background-color: #242424;\n\n  font-synthesis: none;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-text-size-adjust: 100%;\n}\n\na {\n  font-weight: 500;\n  color: #646cff;\n  text-decoration: inherit;\n}\na:hover {\n  color: #535bf2;\n}\n\nbody {\n  margin: 0;\n  display: flex;\n  place-items: center;\n  min-width: 320px;\n  min-height: 100vh;\n}\n\nh1 {\n  font-size: 3.2em;\n  line-height: 1.1;\n}\n\n.card {\n  padding: 2em;\n}\n\nmain {\n  max-width: 1280px;\n  margin: 0 auto;\n  padding: 2rem;\n  text-align: center;\n}\n\n.button {\n  border-radius: 8px;\n  border: 1px solid transparent;\n  padding: 0.6em 1.2em;\n  font-size: 1em;\n  font-weight: 500;\n  font-family: inherit;\n  background-color: #1a1a1a;\n  cursor: pointer;\n  transition: border-color 0.25s;\n}\n.button:hover {\n  border-color: #646cff;\n}\n.button:focus,\n.button:focus-visible {\n  outline: 4px auto -webkit-focus-ring-color;\n}\n\n@media (prefers-color-scheme: light) {\n  :root {\n    color: #213547;\n    background-color: #ffffff;\n  }\n  a:hover {\n    color: #747bff;\n  }\n  .button {\n    background-color: #f9f9f9;\n  }\n}\n"
  },
  {
    "path": "examples/svelte/load-more-infinite-scroll/src/app.d.ts",
    "content": "// See https://kit.svelte.dev/docs/types#app\n// for information about these interfaces\ndeclare global {\n  namespace App {\n    // interface Error {}\n    // interface Locals {}\n    // interface PageData {}\n    // interface Platform {}\n  }\n}\n\nexport {}\n"
  },
  {
    "path": "examples/svelte/load-more-infinite-scroll/src/app.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"icon\" href=\"%sveltekit.assets%/favicon.png\" />\n    <meta name=\"viewport\" content=\"width=device-width\" />\n    %sveltekit.head%\n  </head>\n  <body data-sveltekit-preload-data=\"hover\">\n    <div style=\"display: contents\">%sveltekit.body%</div>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/svelte/load-more-infinite-scroll/src/lib/LoadMore.svelte",
    "content": "<script lang=\"ts\">\n  import { createInfiniteQuery } from '@tanstack/svelte-query'\n\n  const endPoint = 'https://swapi.dev/api'\n\n  const fetchPlanets = async ({ pageParam = 1 }) =>\n    await fetch(`${endPoint}/planets/?page=${pageParam}`).then((r) => r.json())\n\n  const query = createInfiniteQuery(() => ({\n    queryKey: ['planets'],\n    queryFn: ({ pageParam }) => fetchPlanets({ pageParam }),\n    initialPageParam: 1,\n    getNextPageParam: (lastPage) => {\n      if (lastPage.next) {\n        const nextUrl = new URLSearchParams(new URL(lastPage.next).search)\n        const nextCursor = nextUrl.get('page')\n        if (nextCursor) {\n          return +nextCursor\n        }\n      }\n      return undefined\n    },\n  }))\n</script>\n\n{#if query.isPending}\n  Loading...\n{/if}\n{#if query.error}\n  <span>Error: {query.error.message}</span>\n{/if}\n{#if query.isSuccess}\n  <div>\n    {#each query.data.pages as { results }}\n      {#each results as planet}\n        <div class=\"card\">\n          <div class=\"card-body\">\n            <h2 class=\"card-title\">Planet Name: {planet.name}</h2>\n            <p>Population: {planet.population}</p>\n          </div>\n        </div>\n      {/each}\n    {/each}\n  </div>\n  <div>\n    <button\n      onclick={() => query.fetchNextPage()}\n      disabled={!query.hasNextPage || query.isFetchingNextPage}\n    >\n      {#if query.isFetching}\n        Loading more...\n      {:else if query.hasNextPage}\n        Load More\n      {:else}Nothing more to load{/if}\n    </button>\n  </div>\n{/if}\n\n<style>\n  .card {\n    background-color: #111;\n    margin-bottom: 1rem;\n    color: rgba(255, 255, 255, 0.87);\n  }\n</style>\n"
  },
  {
    "path": "examples/svelte/load-more-infinite-scroll/src/routes/+layout.svelte",
    "content": "<script lang=\"ts\">\n  import '../app.css'\n  import { browser } from '$app/environment'\n  import { QueryClientProvider, QueryClient } from '@tanstack/svelte-query'\n  import { SvelteQueryDevtools } from '@tanstack/svelte-query-devtools'\n\n  const { children } = $props()\n\n  const queryClient = new QueryClient({\n    defaultOptions: {\n      queries: {\n        enabled: browser,\n      },\n    },\n  })\n</script>\n\n<QueryClientProvider client={queryClient}>\n  <main>\n    {@render children()}\n  </main>\n  <SvelteQueryDevtools />\n</QueryClientProvider>\n"
  },
  {
    "path": "examples/svelte/load-more-infinite-scroll/src/routes/+page.svelte",
    "content": "<script lang=\"ts\">\n  import LoadMore from '../lib/LoadMore.svelte'\n</script>\n\n<h1>Infinite Load More</h1>\n<LoadMore />\n"
  },
  {
    "path": "examples/svelte/load-more-infinite-scroll/svelte.config.js",
    "content": "import adapter from '@sveltejs/adapter-auto'\nimport { vitePreprocess } from '@sveltejs/vite-plugin-svelte'\n\n/** @type {import('@sveltejs/kit').Config} */\nconst config = {\n  preprocess: vitePreprocess(),\n  kit: {\n    adapter: adapter(),\n  },\n  compilerOptions: {\n    runes: true,\n  },\n}\n\nexport default config\n"
  },
  {
    "path": "examples/svelte/load-more-infinite-scroll/tsconfig.json",
    "content": "{\n  \"extends\": \"./.svelte-kit/tsconfig.json\",\n  \"compilerOptions\": {\n    \"allowJs\": true,\n    \"checkJs\": true,\n    \"esModuleInterop\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"resolveJsonModule\": true,\n    \"skipLibCheck\": true,\n    \"sourceMap\": true,\n    \"strict\": true\n  }\n  // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias\n  //\n  // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes\n  // from the referenced tsconfig.json - TypeScript does not merge them in\n}\n"
  },
  {
    "path": "examples/svelte/load-more-infinite-scroll/vite.config.ts",
    "content": "import { sveltekit } from '@sveltejs/kit/vite'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  plugins: [sveltekit()],\n})\n"
  },
  {
    "path": "examples/svelte/optimistic-updates/.gitignore",
    "content": ".DS_Store\nnode_modules\n/build\n/.svelte-kit\n/package\n.env\n.env.*\n!.env.example\n!lib/\n"
  },
  {
    "path": "examples/svelte/optimistic-updates/README.md",
    "content": "# create-svelte\n\nEverything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte).\n\n## Creating a project\n\nIf you're seeing this, you've probably already done this step. Congrats!\n\n```bash\n# create a new project in the current directory\nnpm create svelte@latest\n\n# create a new project in my-app\nnpm create svelte@latest my-app\n```\n\n## Developing\n\nOnce you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn` or `bun install`), start a development server:\n\n```bash\nnpm run dev\n\n# or start the server and open the app in a new browser tab\nnpm run dev -- --open\n```\n\n## Building\n\nTo create a production version of your app:\n\n```bash\nnpm run build\n```\n\nYou can preview the production build with `npm run preview`.\n\n> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.\n"
  },
  {
    "path": "examples/svelte/optimistic-updates/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-svelte-optimistic-updates\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite dev\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/svelte-query\": \"^6.1.3\",\n    \"@tanstack/svelte-query-devtools\": \"^6.0.4\"\n  },\n  \"devDependencies\": {\n    \"@sveltejs/adapter-auto\": \"^6.1.0\",\n    \"@sveltejs/kit\": \"^2.42.2\",\n    \"@sveltejs/vite-plugin-svelte\": \"^5.1.1\",\n    \"svelte\": \"^5.39.3\",\n    \"svelte-check\": \"^4.3.1\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "examples/svelte/optimistic-updates/src/app.css",
    "content": ":root {\n  font-family: Inter, Avenir, Helvetica, Arial, sans-serif;\n  font-size: 16px;\n  line-height: 24px;\n  font-weight: 400;\n\n  color-scheme: light dark;\n  color: rgba(255, 255, 255, 0.87);\n  background-color: #242424;\n\n  font-synthesis: none;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-text-size-adjust: 100%;\n}\n\na {\n  font-weight: 500;\n  color: #646cff;\n  text-decoration: inherit;\n}\na:hover {\n  color: #535bf2;\n}\n\nbody {\n  margin: 0;\n  display: flex;\n  place-items: center;\n  min-width: 320px;\n  min-height: 100vh;\n}\n\nh1 {\n  font-size: 3.2em;\n  line-height: 1.1;\n}\n\n.card {\n  padding: 2em;\n}\n\nmain {\n  max-width: 1280px;\n  margin: 0 auto;\n  padding: 2rem;\n  text-align: center;\n}\n\nbutton {\n  border-radius: 8px;\n  border: 1px solid transparent;\n  padding: 0.6em 1.2em;\n  font-size: 1em;\n  font-weight: 500;\n  font-family: inherit;\n  background-color: #1a1a1a;\n  cursor: pointer;\n  transition: border-color 0.25s;\n}\nbutton:hover {\n  border-color: #646cff;\n}\nbutton:focus,\nbutton:focus-visible {\n  outline: 4px auto -webkit-focus-ring-color;\n}\n\n@media (prefers-color-scheme: light) {\n  :root {\n    color: #213547;\n    background-color: #ffffff;\n  }\n  a:hover {\n    color: #747bff;\n  }\n  button {\n    background-color: #f9f9f9;\n  }\n}\n"
  },
  {
    "path": "examples/svelte/optimistic-updates/src/app.d.ts",
    "content": "// See https://kit.svelte.dev/docs/types#app\n// for information about these interfaces\ndeclare global {\n  namespace App {\n    // interface Error {}\n    // interface Locals {}\n    // interface PageData {}\n    // interface Platform {}\n  }\n}\n\nexport {}\n"
  },
  {
    "path": "examples/svelte/optimistic-updates/src/app.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"icon\" href=\"%sveltekit.assets%/favicon.png\" />\n    <meta name=\"viewport\" content=\"width=device-width\" />\n    %sveltekit.head%\n  </head>\n  <body data-sveltekit-preload-data=\"hover\">\n    <div style=\"display: contents\">%sveltekit.body%</div>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/svelte/optimistic-updates/src/routes/+layout.svelte",
    "content": "<script lang=\"ts\">\n  import '../app.css'\n  import { browser } from '$app/environment'\n  import { QueryClientProvider, QueryClient } from '@tanstack/svelte-query'\n  import { SvelteQueryDevtools } from '@tanstack/svelte-query-devtools'\n\n  const { children } = $props()\n\n  const queryClient = new QueryClient({\n    defaultOptions: {\n      queries: {\n        enabled: browser,\n      },\n    },\n  })\n</script>\n\n<QueryClientProvider client={queryClient}>\n  <main>\n    {@render children()}\n  </main>\n  <SvelteQueryDevtools />\n</QueryClientProvider>\n"
  },
  {
    "path": "examples/svelte/optimistic-updates/src/routes/+page.svelte",
    "content": "<script lang=\"ts\">\n  import '../app.css'\n  import {\n    useQueryClient,\n    createQuery,\n    createMutation,\n  } from '@tanstack/svelte-query'\n\n  type Todo = {\n    id: string\n    text: string\n  }\n\n  type Todos = {\n    items: readonly Todo[]\n    ts: number\n  }\n\n  let text = $state<string>('')\n\n  const client = useQueryClient()\n\n  const endpoint = '/api/data'\n\n  const fetchTodos = async (): Promise<Todos> =>\n    await fetch(endpoint).then((r) => r.json())\n\n  const createTodo = async (text: string): Promise<Todo> =>\n    await fetch(endpoint, {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n      },\n      body: JSON.stringify({\n        text,\n      }),\n    }).then((res) => res.json())\n\n  const todos = createQuery<Todos>(() => ({\n    queryKey: ['optimistic'],\n    queryFn: fetchTodos,\n  }))\n\n  const addTodoMutation = createMutation(() => ({\n    mutationFn: createTodo,\n    onMutate: async (newTodo: string) => {\n      text = ''\n      // Cancel any outgoing refetches (so they don't overwrite our optimistic update)\n      await client.cancelQueries({ queryKey: ['optimistic'] })\n\n      // Snapshot the previous value\n      const previousTodos = client.getQueryData<Todos>(['optimistic'])\n\n      // Optimistically update to the new value\n      if (previousTodos) {\n        client.setQueryData<Todos>(['optimistic'], {\n          ...previousTodos,\n          items: [\n            ...previousTodos.items,\n            { id: Math.random().toString(), text: newTodo },\n          ],\n        })\n      }\n\n      return { previousTodos }\n    },\n    // If the mutation fails, use the context returned from onMutate to roll back\n    onError: (err: any, variables: any, context: any) => {\n      if (context?.previousTodos) {\n        client.setQueryData<Todos>(['optimistic'], context.previousTodos)\n      }\n    },\n    // Always refetch after error or success:\n    onSettled: () => {\n      client.invalidateQueries({ queryKey: ['optimistic'] })\n    },\n  }))\n</script>\n\n<h1>Optimistic Updates</h1>\n<p>\n  In this example, new items can be created using a mutation. The new item will\n  be optimistically added to the list in hopes that the server accepts the item.\n  If it does, the list is refetched with the true items from the list. Every now\n  and then, the mutation may fail though. When that happens, the previous list\n  of items is restored and the list is again refetched from the server.\n</p>\n\n<form\n  onsubmit={(e) => {\n    e.preventDefault()\n    e.stopPropagation()\n    addTodoMutation.mutate(text)\n  }}\n>\n  <div>\n    <input type=\"text\" bind:value={text} />\n    <button disabled={addTodoMutation.isPending}>Create</button>\n  </div>\n</form>\n\n{#if todos.isPending}\n  Loading...\n{/if}\n{#if todos.error}\n  An error has occurred:\n  {todos.error.message}\n{/if}\n{#if todos.isSuccess}\n  <div class=\"mb-4\">\n    Updated At: {new Date(todos.data.ts).toLocaleTimeString()}\n  </div>\n  <ul>\n    {#each todos.data.items as todo}\n      <li>{todo.text}</li>\n    {/each}\n  </ul>\n{/if}\n{#if todos.isFetching}\n  <div style=\"color:darkgreen; font-weight:700\">\n    'Background Updating...' : ' '\n  </div>\n{/if}\n\n<style>\n  li {\n    text-align: left;\n  }\n</style>\n"
  },
  {
    "path": "examples/svelte/optimistic-updates/src/routes/api/data/+server.ts",
    "content": "import { json } from '@sveltejs/kit'\nimport type { RequestHandler } from '@sveltejs/kit'\n\ntype Todo = {\n  id: string\n  text: string\n}\n\nconst items: Array<Todo> = []\n\n/** @type {import('./$types').RequestHandler} */\nexport const GET: RequestHandler = async (req) => {\n  await new Promise((r) => setTimeout(r, 1000))\n  return json({ ts: Date.now(), items }, { status: 200 })\n}\n\n/** @type {import('./$types').RequestHandler} */\nexport const POST: RequestHandler = async ({ request }) => {\n  const { text } = await request.json()\n\n  if (Math.random() > 0.7) {\n    return json({ message: 'Could not add item!' }, { status: 500 })\n  }\n\n  const newTodo = {\n    id: Math.random().toString(),\n    text: text.toUpperCase() as string,\n  }\n  items.push(newTodo)\n  return json(newTodo, { status: 200 })\n}\n"
  },
  {
    "path": "examples/svelte/optimistic-updates/svelte.config.js",
    "content": "import adapter from '@sveltejs/adapter-auto'\nimport { vitePreprocess } from '@sveltejs/vite-plugin-svelte'\n\n/** @type {import('@sveltejs/kit').Config} */\nconst config = {\n  preprocess: vitePreprocess(),\n  kit: {\n    adapter: adapter(),\n  },\n  compilerOptions: {\n    runes: true,\n  },\n}\n\nexport default config\n"
  },
  {
    "path": "examples/svelte/optimistic-updates/tsconfig.json",
    "content": "{\n  \"extends\": \"./.svelte-kit/tsconfig.json\",\n  \"compilerOptions\": {\n    \"allowJs\": true,\n    \"checkJs\": true,\n    \"esModuleInterop\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"resolveJsonModule\": true,\n    \"skipLibCheck\": true,\n    \"sourceMap\": true,\n    \"strict\": true\n  }\n  // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias\n  //\n  // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes\n  // from the referenced tsconfig.json - TypeScript does not merge them in\n}\n"
  },
  {
    "path": "examples/svelte/optimistic-updates/vite.config.ts",
    "content": "import { sveltekit } from '@sveltejs/kit/vite'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  plugins: [sveltekit()],\n})\n"
  },
  {
    "path": "examples/svelte/playground/.gitignore",
    "content": ".DS_Store\nnode_modules\n/build\n/.svelte-kit\n/package\n.env\n.env.*\n!.env.example\n!lib/\n"
  },
  {
    "path": "examples/svelte/playground/README.md",
    "content": "# Example\n\nThis example is a rewrite of the React Query playground example.\n\nTo run this example:\n\n- `npm install`\n- `npm run dev`\n"
  },
  {
    "path": "examples/svelte/playground/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-svelte-playground\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite dev\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/svelte-query\": \"^6.1.3\",\n    \"@tanstack/svelte-query-devtools\": \"^6.0.4\"\n  },\n  \"devDependencies\": {\n    \"@sveltejs/adapter-auto\": \"^6.1.0\",\n    \"@sveltejs/kit\": \"^2.42.2\",\n    \"@sveltejs/vite-plugin-svelte\": \"^5.1.1\",\n    \"svelte\": \"^5.39.3\",\n    \"svelte-check\": \"^4.3.1\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "examples/svelte/playground/src/app.css",
    "content": "body {\n  margin: 0;\n  padding: 1rem;\n  font-family:\n    -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu',\n    'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  color: white;\n  background: #0b1521;\n}\n"
  },
  {
    "path": "examples/svelte/playground/src/app.d.ts",
    "content": "// See https://kit.svelte.dev/docs/types#app\n// for information about these interfaces\ndeclare global {\n  namespace App {\n    // interface Error {}\n    // interface Locals {}\n    // interface PageData {}\n    // interface Platform {}\n  }\n}\n\nexport {}\n"
  },
  {
    "path": "examples/svelte/playground/src/app.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"icon\" href=\"%sveltekit.assets%/favicon.png\" />\n    <meta name=\"viewport\" content=\"width=device-width\" />\n    %sveltekit.head%\n  </head>\n  <body data-sveltekit-preload-data=\"hover\">\n    <div style=\"display: contents\">%sveltekit.body%</div>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/svelte/playground/src/lib/stores.svelte.ts",
    "content": "export function ref<T>(initial: T) {\n  let value = $state(initial)\n\n  return {\n    get value() {\n      return value\n    },\n    set value(newValue) {\n      value = newValue\n    },\n  }\n}\n\nexport const staleTime = ref(1000)\nexport const gcTime = ref(3000)\nexport const errorRate = ref(0.05)\nexport const queryTimeMin = ref(1000)\nexport const queryTimeMax = ref(2000)\n\nexport const editingIndex = ref<number | null>(null)\nexport const views = ref(['', 'fruit', 'grape'])\n\nlet initialId = 0\nconst initialList = [\n  'apple',\n  'banana',\n  'pineapple',\n  'grapefruit',\n  'dragonfruit',\n  'grapes',\n].map((d) => ({ id: initialId++, name: d, notes: 'These are some notes' }))\n\nexport const list = ref(initialList)\nexport const id = ref(initialId)\n\nexport type Todos = typeof initialList\nexport type Todo = Todos[0]\n"
  },
  {
    "path": "examples/svelte/playground/src/routes/+layout.svelte",
    "content": "<script lang=\"ts\">\n  import '../app.css'\n  import { browser } from '$app/environment'\n  import { QueryClientProvider, QueryClient } from '@tanstack/svelte-query'\n  import { SvelteQueryDevtools } from '@tanstack/svelte-query-devtools'\n\n  const { children } = $props()\n\n  const queryClient = new QueryClient({\n    defaultOptions: {\n      queries: {\n        enabled: browser,\n      },\n    },\n  })\n</script>\n\n<svelte:head>\n  <title>Svelte Query Playground Example</title>\n</svelte:head>\n\n<QueryClientProvider client={queryClient}>\n  <div id=\"app\">\n    {@render children()}\n  </div>\n  <SvelteQueryDevtools />\n</QueryClientProvider>\n"
  },
  {
    "path": "examples/svelte/playground/src/routes/+page.svelte",
    "content": "<script lang=\"ts\">\n  import { useQueryClient } from '@tanstack/svelte-query'\n  import {\n    staleTime,\n    gcTime,\n    errorRate,\n    queryTimeMin,\n    queryTimeMax,\n  } from '../lib/stores.svelte'\n  import App from './App.svelte'\n\n  const queryClient = useQueryClient()\n\n  queryClient.setDefaultOptions({\n    queries: {\n      staleTime: staleTime.value,\n      gcTime: gcTime.value,\n    },\n  })\n</script>\n\n<p>\n  The \"staleTime\" and \"gcTime\" durations have been altered in this example to\n  show how query stale-ness and query caching work on a granular level\n</p>\n<div>\n  Stale Time:{' '}\n  <input\n    type=\"number\"\n    min=\"0\"\n    step=\"1000\"\n    bind:value={staleTime.value}\n    style=\"width: 100px\"\n  />\n</div>\n<div>\n  GcTime:{' '}\n  <input\n    type=\"number\"\n    min=\"0\"\n    step=\"1000\"\n    bind:value={gcTime.value}\n    style=\"width: 100px\"\n  />\n</div>\n<br />\n<div>\n  Error Rate:{' '}\n  <input\n    type=\"number\"\n    min=\"0\"\n    max=\"1\"\n    step=\".05\"\n    bind:value={errorRate.value}\n    style=\"width: 100px\"\n  />\n</div>\n<div>\n  Fetch Time Min:{' '}\n  <input\n    type=\"number\"\n    min=\"1\"\n    step=\"500\"\n    bind:value={queryTimeMin.value}\n    style=\"width: 100px\"\n  />{' '}\n</div>\n<div>\n  Fetch Time Max:{' '}\n  <input\n    type=\"number\"\n    min=\"1\"\n    step=\"500\"\n    bind:value={queryTimeMax.value}\n    style=\"width: 100px\"\n  />\n</div>\n\n<br />\n<App />\n<br />\n"
  },
  {
    "path": "examples/svelte/playground/src/routes/AddTodo.svelte",
    "content": "<script lang=\"ts\">\n  import { createMutation, useQueryClient } from '@tanstack/svelte-query'\n  import {\n    errorRate,\n    queryTimeMin,\n    queryTimeMax,\n    list,\n    id,\n  } from '$lib/stores.svelte'\n  import type { Todo } from '$lib/stores.svelte'\n\n  const queryClient = useQueryClient()\n\n  let name = $state('')\n\n  const postTodo = async ({ name, notes }: Omit<Todo, 'id'>) => {\n    return new Promise((resolve, reject) => {\n      setTimeout(\n        () => {\n          if (Math.random() < errorRate.value) {\n            return reject(\n              new Error(\n                JSON.stringify(\n                  { postTodo: { name: $state.snapshot(name), notes } },\n                  null,\n                  2,\n                ),\n              ),\n            )\n          }\n          const todo = { name, notes, id: id.value }\n          id.value = id.value + 1\n          list.value.push(todo)\n          resolve(todo)\n        },\n        queryTimeMin.value +\n          Math.random() * (queryTimeMax.value - queryTimeMin.value),\n      )\n    })\n  }\n\n  const addMutation = createMutation(() => ({\n    mutationFn: postTodo,\n    onSuccess: () => {\n      queryClient.invalidateQueries({ queryKey: ['todos'] })\n    },\n  }))\n</script>\n\n<div>\n  <input bind:value={name} disabled={addMutation.status === 'pending'} />\n\n  <button\n    onclick={() => addMutation.mutate({ name, notes: name })}\n    disabled={addMutation.status === 'pending' || !name}\n  >\n    Add Todo\n  </button>\n\n  <div>\n    {addMutation.status === 'pending'\n      ? 'Saving...'\n      : addMutation.status === 'error'\n        ? addMutation.error.message\n        : 'Saved!'}\n  </div>\n</div>\n"
  },
  {
    "path": "examples/svelte/playground/src/routes/App.svelte",
    "content": "<script lang=\"ts\">\n  import { useQueryClient } from '@tanstack/svelte-query'\n  import TodosList from './TodosList.svelte'\n  import EditTodo from './EditTodo.svelte'\n  import AddTodo from './AddTodo.svelte'\n  import { views, editingIndex } from '../lib/stores.svelte'\n\n  const queryClient = useQueryClient()\n</script>\n\n<div>\n  <div>\n    <button onclick={() => queryClient.invalidateQueries()}>\n      Force Refetch All\n    </button>\n  </div>\n  <br />\n  <hr />\n\n  {#each views.value as view}\n    <div>\n      <TodosList initialFilter={view} />\n      <br />\n    </div>\n  {/each}\n\n  <button\n    onclick={() => {\n      views.value.push('')\n    }}\n  >\n    Add Filter List\n  </button>\n  <hr />\n\n  {#if editingIndex.value !== null}\n    <EditTodo />\n    <hr />\n  {/if}\n\n  <AddTodo />\n</div>\n"
  },
  {
    "path": "examples/svelte/playground/src/routes/EditTodo.svelte",
    "content": "<script lang=\"ts\">\n  import {\n    useQueryClient,\n    createQuery,\n    createMutation,\n  } from '@tanstack/svelte-query'\n  import {\n    errorRate,\n    queryTimeMin,\n    queryTimeMax,\n    list,\n    editingIndex,\n  } from '$lib/stores.svelte'\n  import type { Todo } from '$lib/stores.svelte'\n\n  const queryClient = useQueryClient()\n\n  const fetchTodoById = async ({ id }: { id: number }): Promise<Todo> => {\n    return new Promise((resolve, reject) => {\n      setTimeout(\n        () => {\n          if (Math.random() < errorRate.value) {\n            return reject(\n              new Error(JSON.stringify({ fetchTodoById: { id } }, null, 2)),\n            )\n          }\n          const todo = $state.snapshot(list.value.find((d) => d.id === id))\n          if (!todo) {\n            return reject(\n              new Error(JSON.stringify({ fetchTodoById: { id } }, null, 2)),\n            )\n          }\n          resolve(todo)\n        },\n        queryTimeMin.value +\n          Math.random() * (queryTimeMax.value - queryTimeMin.value),\n      )\n    })\n  }\n\n  function patchTodo(todo?: Todo): Promise<Todo> {\n    console.info('patchTodo', todo)\n    return new Promise((resolve, reject) => {\n      setTimeout(\n        () => {\n          if (Math.random() < errorRate.value) {\n            return reject(\n              new Error(JSON.stringify({ patchTodo: todo }, null, 2)),\n            )\n          }\n          if (!todo) {\n            return reject(\n              new Error(JSON.stringify({ patchTodo: todo }, null, 2)),\n            )\n          }\n          list.value = list.value.map((d) => {\n            if (d.id === todo.id) {\n              return $state.snapshot(todo)\n            }\n            return d\n          })\n          resolve(todo)\n        },\n        queryTimeMin.value +\n          Math.random() * (queryTimeMax.value - queryTimeMin.value),\n      )\n    })\n  }\n\n  const query = createQuery(() => ({\n    queryKey: ['todo', { id: editingIndex.value }],\n    queryFn: () => fetchTodoById({ id: editingIndex.value || 0 }),\n    enabled: editingIndex.value !== null,\n  }))\n\n  const saveMutation = createMutation(() => ({\n    mutationFn: patchTodo,\n    onSuccess: (data) => {\n      // Update `todos` and the individual todo queries when this mutation succeeds\n      queryClient.invalidateQueries({ queryKey: ['todos'] })\n      queryClient.setQueryData(['todo', { id: editingIndex }], data)\n    },\n  }))\n\n  const todo = $derived(query.data)\n\n  const onSave = () => {\n    saveMutation.mutate(todo)\n  }\n\n  const disableEditSave = $derived(\n    query.status === 'pending' || saveMutation.status === 'pending',\n  )\n</script>\n\n<div>\n  <div>\n    {#if query.data}\n      <button onclick={() => (editingIndex.value = null)}>Back</button> Editing\n      Todo \"{query.data.name}\" (#{editingIndex.value})\n    {/if}\n  </div>\n  {#if query.status === 'pending'}\n    <span>Loading... (Attempt: {query.failureCount + 1})</span>\n  {:else if query.error}\n    <span>\n      Error! <button onclick={() => query.refetch()}>Retry</button>\n    </span>\n  {:else if todo}\n    <label>\n      Name:{' '}\n      <input bind:value={todo.name} disabled={disableEditSave} />\n    </label>\n    <label>\n      Notes:{' '}\n      <input bind:value={todo.notes} disabled={disableEditSave} />\n    </label>\n    <div>\n      <button onclick={onSave} disabled={disableEditSave}> Save </button>\n    </div>\n    <div>\n      {saveMutation.status === 'pending'\n        ? 'Saving...'\n        : saveMutation.status === 'error'\n          ? saveMutation.error.message\n          : 'Saved!'}\n    </div>\n    <div>\n      {#if query.isFetching}\n        <span>\n          Background Refreshing... (Attempt: {query.failureCount + 1})\n        </span>\n      {:else}\n        <span>&nbsp;</span>\n      {/if}\n    </div>\n  {/if}\n</div>\n"
  },
  {
    "path": "examples/svelte/playground/src/routes/TodosList.svelte",
    "content": "<script lang=\"ts\">\n  import { createQuery } from '@tanstack/svelte-query'\n  import {\n    errorRate,\n    queryTimeMin,\n    queryTimeMax,\n    list,\n    editingIndex,\n  } from '$lib/stores.svelte'\n  import type { Todos } from '$lib/stores.svelte'\n\n  let { initialFilter }: { initialFilter: string } = $props()\n\n  let filter = $state(initialFilter)\n\n  const fetchTodos = async ({ filter }: { filter: string }): Promise<Todos> => {\n    return new Promise((resolve, reject) => {\n      setTimeout(\n        () => {\n          if (Math.random() < errorRate.value) {\n            return reject(\n              new Error(JSON.stringify({ fetchTodos: { filter } }, null, 2)),\n            )\n          }\n          resolve(list.value.filter((d) => d.name.includes(filter)))\n        },\n        queryTimeMin.value +\n          Math.random() * (queryTimeMax.value - queryTimeMin.value),\n      )\n    })\n  }\n\n  const query = createQuery(() => ({\n    queryKey: ['todos', { filter: filter }],\n    queryFn: () => fetchTodos({ filter: filter }),\n  }))\n</script>\n\n<div>\n  <label>\n    Filter:{' '}\n    <input bind:value={filter} />\n  </label>\n</div>\n\n{#if query.status === 'pending'}\n  <span>Loading... (Attempt: {query.failureCount + 1})</span>\n{:else if query.status === 'error'}\n  <span>\n    Error: {query.error.message}\n    <br />\n    <button onclick={() => query.refetch()}>Retry</button>\n  </span>\n{:else}\n  <ul>\n    {#if query.data}\n      {#each query.data as todo}\n        <li>\n          {todo.name}{' '}\n          <button onclick={() => (editingIndex.value = todo.id)}> Edit </button>\n        </li>\n      {/each}\n    {/if}\n  </ul>\n  <div>\n    {#if query.isFetching}\n      <span>\n        Background Refreshing... (Attempt: {query.failureCount + 1})\n      </span>\n    {:else}\n      <span>&nbsp;</span>\n    {/if}\n  </div>\n{/if}\n"
  },
  {
    "path": "examples/svelte/playground/svelte.config.js",
    "content": "import adapter from '@sveltejs/adapter-auto'\nimport { vitePreprocess } from '@sveltejs/vite-plugin-svelte'\n\n/** @type {import('@sveltejs/kit').Config} */\nconst config = {\n  preprocess: vitePreprocess(),\n  kit: {\n    adapter: adapter(),\n  },\n  compilerOptions: {\n    runes: true,\n  },\n}\n\nexport default config\n"
  },
  {
    "path": "examples/svelte/playground/tsconfig.json",
    "content": "{\n  \"extends\": \"./.svelte-kit/tsconfig.json\",\n  \"compilerOptions\": {\n    \"allowJs\": true,\n    \"checkJs\": true,\n    \"esModuleInterop\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"resolveJsonModule\": true,\n    \"skipLibCheck\": true,\n    \"sourceMap\": true,\n    \"strict\": true\n  }\n}\n"
  },
  {
    "path": "examples/svelte/playground/vite.config.ts",
    "content": "import { sveltekit } from '@sveltejs/kit/vite'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  plugins: [sveltekit()],\n})\n"
  },
  {
    "path": "examples/svelte/simple/.gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n!lib/\n\n# Editor directories and files\n.vscode\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "examples/svelte/simple/README.md",
    "content": "# Svelte + TS + Vite\n\nThis template should help get you started developing with Svelte and TypeScript in Vite.\n\n## Recommended IDE Setup\n\n[VS Code](https://code.visualstudio.com/) + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode).\n\n## Need an official Svelte framework?\n\nCheck out [SvelteKit](https://github.com/sveltejs/kit#readme), which is also powered by Vite. Deploy anywhere with its serverless-first approach and adapt to various platforms, with out of the box support for TypeScript, SCSS, and Less, and easily-added support for mdsvex, GraphQL, PostCSS, Tailwind CSS, and more.\n\n## Technical considerations\n\n**Why use this over SvelteKit?**\n\n- It brings its own routing solution which might not be preferable for some users.\n- It is first and foremost a framework that just happens to use Vite under the hood, not a Vite app.\n  `vite dev` and `vite build` wouldn't work in a SvelteKit environment, for example.\n\nThis template contains as little as possible to get started with Vite + TypeScript + Svelte, while taking into account the developer experience with regards to HMR and intellisense. It demonstrates capabilities on par with the other `create-vite` templates and is a good starting point for beginners dipping their toes into a Vite + Svelte project.\n\nShould you later need the extended capabilities and extensibility provided by SvelteKit, the template has been structured similarly to SvelteKit so that it is easy to migrate.\n\n**Why `global.d.ts` instead of `compilerOptions.types` inside `jsconfig.json` or `tsconfig.json`?**\n\nSetting `compilerOptions.types` shuts out all other types not explicitly listed in the configuration. Using triple-slash references keeps the default TypeScript setting of accepting type information from the entire workspace, while also adding `svelte` and `vite/client` type information.\n\n**Why include `.vscode/extensions.json`?**\n\nOther templates indirectly recommend extensions via the README, but this file allows VS Code to prompt the user to install the recommended extension upon opening the project.\n\n**Why enable `allowJs` in the TS template?**\n\nWhile `allowJs: false` would indeed prevent the use of `.js` files in the project, it does not prevent the use of JavaScript syntax in `.svelte` files. In addition, it would force `checkJs: false`, bringing the worst of both worlds: not being able to guarantee the entire codebase is TypeScript, and also having worse typechecking for the existing JavaScript. In addition, there are valid use cases in which a mixed codebase may be relevant.\n\n**Why is HMR not preserving my local component state?**\n\nHMR state preservation comes with a number of gotchas! It has been disabled by default in both `svelte-hmr` and `@sveltejs/vite-plugin-svelte` due to its often surprising behavior. You can read the details [here](https://github.com/rixo/svelte-hmr#svelte-hmr).\n\nIf you have state that's important to retain within a component, consider creating an external store which would not be replaced by HMR.\n\n```ts\n// store.ts\n// An extremely simple external store\nimport { writable } from 'svelte/store'\nexport default writable(0)\n```\n"
  },
  {
    "path": "examples/svelte/simple/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width\" />\n    <title>Vite + Svelte + TS</title>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/src/main.ts\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/svelte/simple/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-svelte-simple\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/svelte-query\": \"^6.1.3\",\n    \"@tanstack/svelte-query-devtools\": \"^6.0.4\"\n  },\n  \"devDependencies\": {\n    \"@sveltejs/vite-plugin-svelte\": \"^5.1.1\",\n    \"@tsconfig/svelte\": \"^5.0.4\",\n    \"svelte\": \"^5.39.3\",\n    \"svelte-check\": \"^4.3.1\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "examples/svelte/simple/src/App.svelte",
    "content": "<script lang=\"ts\">\n  import { QueryClientProvider, QueryClient } from '@tanstack/svelte-query'\n  import { SvelteQueryDevtools } from '@tanstack/svelte-query-devtools'\n  import Simple from './lib/Simple.svelte'\n\n  const queryClient = new QueryClient()\n</script>\n\n<QueryClientProvider client={queryClient}>\n  <main>\n    <Simple />\n  </main>\n  <SvelteQueryDevtools />\n</QueryClientProvider>\n"
  },
  {
    "path": "examples/svelte/simple/src/app.css",
    "content": ":root {\n  font-family: Inter, Avenir, Helvetica, Arial, sans-serif;\n  font-size: 16px;\n  line-height: 24px;\n  font-weight: 400;\n\n  color-scheme: light dark;\n  color: rgba(255, 255, 255, 0.87);\n  background-color: #242424;\n\n  font-synthesis: none;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-text-size-adjust: 100%;\n}\n\na {\n  font-weight: 500;\n  color: #646cff;\n  text-decoration: inherit;\n}\na:hover {\n  color: #535bf2;\n}\n\nbody {\n  margin: 0;\n  display: flex;\n  place-items: center;\n  min-width: 320px;\n  min-height: 100vh;\n}\n\nh1 {\n  font-size: 3.2em;\n  line-height: 1.1;\n}\n\n.card {\n  padding: 2em;\n}\n\n#app {\n  max-width: 1280px;\n  margin: 0 auto;\n  padding: 2rem;\n  text-align: center;\n}\n\nbutton {\n  border-radius: 8px;\n  border: 1px solid transparent;\n  padding: 0.6em 1.2em;\n  font-size: 1em;\n  font-weight: 500;\n  font-family: inherit;\n  background-color: #1a1a1a;\n  cursor: pointer;\n  transition: border-color 0.25s;\n}\nbutton:hover {\n  border-color: #646cff;\n}\nbutton:focus,\nbutton:focus-visible {\n  outline: 4px auto -webkit-focus-ring-color;\n}\n\n@media (prefers-color-scheme: light) {\n  :root {\n    color: #213547;\n    background-color: #ffffff;\n  }\n  a:hover {\n    color: #747bff;\n  }\n  button {\n    background-color: #f9f9f9;\n  }\n}\n"
  },
  {
    "path": "examples/svelte/simple/src/lib/Simple.svelte",
    "content": "<script lang=\"ts\">\n  import { createQuery } from '@tanstack/svelte-query'\n\n  type Repo = {\n    full_name: string\n    description: string\n    subscribers_count: number\n    stargazers_count: number\n    forks_count: number\n  }\n\n  const query = createQuery<Repo>(() => ({\n    queryKey: ['repoData'],\n    queryFn: async () =>\n      await fetch('https://api.github.com/repos/TanStack/query').then((r) =>\n        r.json(),\n      ),\n  }))\n</script>\n\n<h1>Simple</h1>\n<div class=\"my-4\">\n  <div>\n    {#if query.isPending}\n      Loading...\n    {/if}\n    {#if query.error}\n      An error has occurred:\n      {query.error.message}\n    {/if}\n    {#if query.isSuccess}\n      <div>\n        <h1>{query.data.full_name}</h1>\n        <p>{query.data.description}</p>\n        <strong>👀 {query.data.subscribers_count}</strong>{' '}\n        <strong>✨ {query.data.stargazers_count}</strong>{' '}\n        <strong>🍴 {query.data.forks_count}</strong>\n      </div>\n    {/if}\n  </div>\n</div>\n"
  },
  {
    "path": "examples/svelte/simple/src/main.ts",
    "content": "import { mount } from 'svelte'\nimport './app.css'\nimport App from './App.svelte'\n\nconst target = document.querySelector('#app')\nif (!target) throw new Error('Missing #app element')\n\nconst app = mount(App, { target })\n\nexport default app\n"
  },
  {
    "path": "examples/svelte/simple/src/vite-env.d.ts",
    "content": "/// <reference types=\"svelte\" />\n/// <reference types=\"vite/client\" />\n"
  },
  {
    "path": "examples/svelte/simple/svelte.config.js",
    "content": "import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'\n\nexport default {\n  preprocess: vitePreprocess(),\n  compilerOptions: {\n    runes: true,\n  },\n}\n"
  },
  {
    "path": "examples/svelte/simple/tsconfig.json",
    "content": "{\n  \"extends\": \"@tsconfig/svelte/tsconfig.json\",\n  \"compilerOptions\": {\n    \"target\": \"ESNext\",\n    \"useDefineForClassFields\": true,\n    \"module\": \"ESNext\",\n    \"resolveJsonModule\": true,\n    /**\n     * Typecheck JS in `.svelte` and `.js` files by default.\n     * Disable checkJs if you'd like to use dynamic types in JS.\n     * Note that setting allowJs false does not prevent the use\n     * of JS in `.svelte` files.\n     */\n    \"allowJs\": true,\n    \"checkJs\": true,\n    \"isolatedModules\": true\n  },\n  \"include\": [\n    \"src/**/*.d.ts\",\n    \"src/**/*.ts\",\n    \"src/**/*.js\",\n    \"src/**/*.svelte\",\n    \"vite.config.ts\"\n  ]\n}\n"
  },
  {
    "path": "examples/svelte/simple/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport { svelte } from '@sveltejs/vite-plugin-svelte'\n\nexport default defineConfig({\n  plugins: [svelte()],\n})\n"
  },
  {
    "path": "examples/svelte/ssr/.gitignore",
    "content": ".DS_Store\nnode_modules\n/build\n/.svelte-kit\n/package\n.env\n.env.*\n!.env.example\n!lib/\n"
  },
  {
    "path": "examples/svelte/ssr/README.md",
    "content": "# create-svelte\n\nEverything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte).\n\n## Creating a project\n\nIf you're seeing this, you've probably already done this step. Congrats!\n\n```bash\n# create a new project in the current directory\nnpm create svelte@latest\n\n# create a new project in my-app\nnpm create svelte@latest my-app\n```\n\n## Developing\n\nOnce you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn` or `bun install`), start a development server:\n\n```bash\nnpm run dev\n\n# or start the server and open the app in a new browser tab\nnpm run dev -- --open\n```\n\n## Building\n\nTo create a production version of your app:\n\n```bash\nnpm run build\n```\n\nYou can preview the production build with `npm run preview`.\n\n> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.\n"
  },
  {
    "path": "examples/svelte/ssr/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-svelte-ssr\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite dev\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/svelte-query\": \"^6.1.3\",\n    \"@tanstack/svelte-query-devtools\": \"^6.0.4\"\n  },\n  \"devDependencies\": {\n    \"@sveltejs/adapter-auto\": \"^6.1.0\",\n    \"@sveltejs/kit\": \"^2.42.2\",\n    \"@sveltejs/vite-plugin-svelte\": \"^5.1.1\",\n    \"svelte\": \"^5.39.3\",\n    \"svelte-check\": \"^4.3.1\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "examples/svelte/ssr/src/app.css",
    "content": ":root {\n  font-family: Inter, Avenir, Helvetica, Arial, sans-serif;\n  font-size: 16px;\n  line-height: 24px;\n  font-weight: 400;\n\n  color-scheme: light dark;\n  color: rgba(255, 255, 255, 0.87);\n  background-color: #242424;\n\n  font-synthesis: none;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-text-size-adjust: 100%;\n}\n\na {\n  font-weight: 500;\n  color: #646cff;\n  text-decoration: inherit;\n}\na:hover {\n  color: #535bf2;\n}\n\nbody {\n  margin: 0;\n  display: flex;\n  place-items: center;\n  min-width: 320px;\n  min-height: 100vh;\n}\n\nh1 {\n  font-size: 3.2em;\n  line-height: 1.1;\n}\n\n.card {\n  padding: 2em;\n}\n\nmain {\n  max-width: 1280px;\n  margin: 0 auto;\n  padding: 2rem;\n  text-align: center;\n}\n\n.button {\n  border-radius: 8px;\n  border: 1px solid transparent;\n  padding: 0.6em 1.2em;\n  font-size: 1em;\n  font-weight: 500;\n  font-family: inherit;\n  background-color: #1a1a1a;\n  cursor: pointer;\n  transition: border-color 0.25s;\n}\n.button:hover {\n  border-color: #646cff;\n}\n.button:focus,\n.button:focus-visible {\n  outline: 4px auto -webkit-focus-ring-color;\n}\n\n@media (prefers-color-scheme: light) {\n  :root {\n    color: #213547;\n    background-color: #ffffff;\n  }\n  a:hover {\n    color: #747bff;\n  }\n  .button {\n    background-color: #f9f9f9;\n  }\n}\n"
  },
  {
    "path": "examples/svelte/ssr/src/app.d.ts",
    "content": "// See https://kit.svelte.dev/docs/types#app\n// for information about these interfaces\ndeclare global {\n  namespace App {\n    // interface Error {}\n    // interface Locals {}\n    // interface PageData {}\n    // interface Platform {}\n  }\n}\n\nexport {}\n"
  },
  {
    "path": "examples/svelte/ssr/src/app.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"icon\" href=\"%sveltekit.assets%/favicon.png\" />\n    <meta name=\"viewport\" content=\"width=device-width\" />\n    %sveltekit.head%\n  </head>\n  <body data-sveltekit-preload-data=\"hover\">\n    <div style=\"display: contents\">%sveltekit.body%</div>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/svelte/ssr/src/lib/Post.svelte",
    "content": "<script lang=\"ts\">\n  import { createQuery } from '@tanstack/svelte-query'\n  import { api } from './api'\n  import type { Post } from './types'\n\n  const { postId }: { postId: number } = $props()\n\n  const post = createQuery<Post>(() => ({\n    queryKey: ['post', postId],\n    queryFn: () => api().getPostById(postId),\n  }))\n</script>\n\n<div>\n  <div>\n    <a class=\"button\" href=\"/\"> Back </a>\n  </div>\n  {#if !postId || post.isPending}\n    <span>Loading...</span>\n  {/if}\n  {#if post.error}\n    <span>Error: {post.error.message}</span>\n  {/if}\n  {#if post.isSuccess}\n    <h1>{post.data.title}</h1>\n    <div>\n      <p>{post.data.body}</p>\n    </div>\n    <div>{post.isFetching ? 'Background Updating...' : ' '}</div>\n  {/if}\n</div>\n"
  },
  {
    "path": "examples/svelte/ssr/src/lib/Posts.svelte",
    "content": "<script lang=\"ts\">\n  import { useQueryClient, createQuery } from '@tanstack/svelte-query'\n  import { api } from './api'\n\n  const client = useQueryClient()\n\n  const limit = 10\n\n  const posts = createQuery<\n    { id: number; title: string; body: string }[],\n    Error\n  >(() => ({\n    queryKey: ['posts', limit],\n    queryFn: () => api().getPosts(limit),\n  }))\n</script>\n\n<div>\n  <div>\n    {#if posts.status === 'pending'}\n      <span>Loading...</span>\n    {:else if posts.status === 'error'}\n      <span>Error: {posts.error.message}</span>\n    {:else}\n      <ul>\n        {#each posts.data as post}\n          <article>\n            <a\n              href={`/${post.id}`}\n              style={// We can use the queryCache here to show bold links for\n              // ones that are cached\n              client.getQueryData(['post', post.id])\n                ? 'font-weight: bold; color: indianred'\n                : 'cursor: pointer'}\n            >\n              {post.title}\n            </a>\n          </article>\n        {/each}\n      </ul>\n      <pre\n        class={['updating-text', posts.isFetching && 'on']}\n        style=\"font-weight:700\">Background Updating...</pre>\n    {/if}\n  </div>\n</div>\n\n<style>\n  article {\n    text-align: left;\n  }\n  a {\n    display: block;\n    font-size: 1.5rem;\n    margin-bottom: 1rem;\n  }\n  .updating-text {\n    color: transparent;\n    transition: all 0.3s ease;\n  }\n  .updating-text.on {\n    color: green;\n    transition: none;\n  }\n</style>\n"
  },
  {
    "path": "examples/svelte/ssr/src/lib/api.ts",
    "content": "import type { Post } from './types'\n\nexport const api = (customFetch = fetch) => ({\n  getPosts: async (limit: number) => {\n    const response = await customFetch(\n      'https://jsonplaceholder.typicode.com/posts',\n    )\n    const data = (await response.json()) as Array<Post>\n    return data.filter((x) => x.id <= limit)\n  },\n  getPostById: async (id: number): Promise<Post> => {\n    const response = await customFetch(\n      `https://jsonplaceholder.typicode.com/posts/${id}`,\n    )\n    const data = (await response.json()) as Post\n    return data\n  },\n})\n"
  },
  {
    "path": "examples/svelte/ssr/src/lib/types.ts",
    "content": "export type Post = {\n  id: number\n  title: string\n  body: string\n}\n"
  },
  {
    "path": "examples/svelte/ssr/src/routes/+layout.svelte",
    "content": "<script lang=\"ts\">\n  import '../app.css'\n  import { QueryClientProvider } from '@tanstack/svelte-query'\n  import { SvelteQueryDevtools } from '@tanstack/svelte-query-devtools'\n\n  const { data, children } = $props()\n</script>\n\n<QueryClientProvider client={data.queryClient}>\n  <main>\n    {@render children()}\n  </main>\n  <SvelteQueryDevtools />\n</QueryClientProvider>\n"
  },
  {
    "path": "examples/svelte/ssr/src/routes/+layout.ts",
    "content": "import { QueryClient } from '@tanstack/svelte-query'\nimport type { LayoutLoad } from './$types'\nimport { browser } from '$app/environment'\n\nexport const load: LayoutLoad = () => {\n  const queryClient = new QueryClient({\n    defaultOptions: {\n      queries: {\n        enabled: browser,\n        staleTime: 60 * 1000,\n      },\n    },\n  })\n\n  return { queryClient }\n}\n"
  },
  {
    "path": "examples/svelte/ssr/src/routes/+page.svelte",
    "content": "<script lang=\"ts\">\n  import Posts from '$lib/Posts.svelte'\n</script>\n\n<h1>Basic Query with SSR</h1>\n<Posts />\n"
  },
  {
    "path": "examples/svelte/ssr/src/routes/+page.ts",
    "content": "import type { PageLoad } from './$types'\nimport { api } from '$lib/api'\n\nexport const load: PageLoad = async ({ parent, fetch }) => {\n  const { queryClient } = await parent()\n\n  await queryClient.prefetchQuery({\n    queryKey: ['posts', 10],\n    queryFn: () => api(fetch).getPosts(10),\n  })\n}\n"
  },
  {
    "path": "examples/svelte/ssr/src/routes/[postId]/+page.svelte",
    "content": "<script lang=\"ts\">\n  import Post from '$lib/Post.svelte'\n\n  const { data } = $props()\n</script>\n\n<Post postId={data.postId} />\n"
  },
  {
    "path": "examples/svelte/ssr/src/routes/[postId]/+page.ts",
    "content": "import type { PageLoad } from './$types'\nimport { api } from '$lib/api'\n\nexport const load: PageLoad = async ({ parent, fetch, params }) => {\n  const { queryClient } = await parent()\n\n  const postId = parseInt(params.postId)\n\n  await queryClient.prefetchQuery({\n    queryKey: ['post', postId],\n    queryFn: () => api(fetch).getPostById(postId),\n  })\n\n  return { postId }\n}\n"
  },
  {
    "path": "examples/svelte/ssr/svelte.config.js",
    "content": "import adapter from '@sveltejs/adapter-auto'\nimport { vitePreprocess } from '@sveltejs/vite-plugin-svelte'\n\n/** @type {import('@sveltejs/kit').Config} */\nconst config = {\n  preprocess: vitePreprocess(),\n  kit: {\n    adapter: adapter(),\n  },\n  compilerOptions: {\n    runes: true,\n  },\n}\n\nexport default config\n"
  },
  {
    "path": "examples/svelte/ssr/tsconfig.json",
    "content": "{\n  \"extends\": \"./.svelte-kit/tsconfig.json\",\n  \"compilerOptions\": {\n    \"allowJs\": true,\n    \"checkJs\": true,\n    \"esModuleInterop\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"resolveJsonModule\": true,\n    \"skipLibCheck\": true,\n    \"sourceMap\": true,\n    \"strict\": true\n  }\n  // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias\n  //\n  // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes\n  // from the referenced tsconfig.json - TypeScript does not merge them in\n}\n"
  },
  {
    "path": "examples/svelte/ssr/vite.config.ts",
    "content": "import { sveltekit } from '@sveltejs/kit/vite'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  plugins: [sveltekit()],\n})\n"
  },
  {
    "path": "examples/svelte/star-wars/.gitignore",
    "content": ".DS_Store\nnode_modules\n/build\n/.svelte-kit\n/package\n.env\n.env.*\n!.env.example\n!lib/\n"
  },
  {
    "path": "examples/svelte/star-wars/README.md",
    "content": "# Example\n\nThis example is a rewrite of the React Query star-wars example.\n\nTo run this example:\n\n- `npm install`\n- `npm run dev`\n"
  },
  {
    "path": "examples/svelte/star-wars/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-svelte-star-wars\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite dev\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/svelte-query\": \"^6.1.3\",\n    \"@tanstack/svelte-query-devtools\": \"^6.0.4\"\n  },\n  \"devDependencies\": {\n    \"@sveltejs/adapter-auto\": \"^6.1.0\",\n    \"@sveltejs/kit\": \"^2.42.2\",\n    \"@sveltejs/vite-plugin-svelte\": \"^5.1.1\",\n    \"@tailwindcss/vite\": \"^4.1.13\",\n    \"svelte\": \"^5.39.3\",\n    \"svelte-check\": \"^4.3.1\",\n    \"tailwindcss\": \"^4.1.13\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "examples/svelte/star-wars/src/app.css",
    "content": "@import 'tailwindcss';\n\n@theme {\n  --font-sans:\n    Roboto, BlinkMacSystemFont, -apple-system, Segoe UI, Roboto, Oxygen, Ubuntu,\n    Cantarell, Fira Sans, Droid Sans, Helvetica Neue, Helvetica, Arial,\n    sans-serif;\n  --font-mono:\n    Roboto Mono, BlinkMacSystemFont, -apple-system, Segoe UI, Roboto, Oxygen,\n    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, Helvetica, Arial,\n    sans-serif;\n}\n\n@layer base {\n  body {\n    @apply font-sans;\n  }\n\n  h1,\n  h2,\n  h3,\n  h4,\n  h5,\n  h6 {\n    @apply font-mono;\n  }\n}\n"
  },
  {
    "path": "examples/svelte/star-wars/src/app.d.ts",
    "content": "// See https://kit.svelte.dev/docs/types#app\n// for information about these interfaces\ndeclare global {\n  namespace App {\n    // interface Error {}\n    // interface Locals {}\n    // interface PageData {}\n    // interface Platform {}\n  }\n}\n\nexport {}\n"
  },
  {
    "path": "examples/svelte/star-wars/src/app.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link\n      rel=\"shortcut icon\"\n      type=\"image/svg+xml\"\n      href=\"%sveltekit.assets%/emblem-light.svg\"\n    />\n    <meta name=\"viewport\" content=\"width=device-width\" />\n    %sveltekit.head%\n  </head>\n  <body data-sveltekit-preload-data=\"hover\">\n    <div style=\"display: contents\">%sveltekit.body%</div>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/svelte/star-wars/src/lib/api.ts",
    "content": "export const getFilms = async () => {\n  const res = await fetch('https://swapi.dev/api/films/')\n  return await res.json()\n}\n\nexport const getFilm = async (filmId: string) => {\n  const res = await fetch(`https://swapi.dev/api/films/${filmId}/`)\n  return await res.json()\n}\n\nexport const getCharacters = async () => {\n  const res = await fetch('https://swapi.dev/api/people/')\n  return await res.json()\n}\n\nexport const getCharacter = async (characterId: string) => {\n  const res = await fetch(`https://swapi.dev/api/people/${characterId}/`)\n  return await res.json()\n}\n\nexport const getPlanet = async (planetId: string) => {\n  const res = await fetch(`https://swapi.dev/api/planets/${planetId}/`)\n  return await res.json()\n}\n"
  },
  {
    "path": "examples/svelte/star-wars/src/routes/+layout.svelte",
    "content": "<script lang=\"ts\">\n  import '../app.css'\n  import { browser } from '$app/environment'\n  import { QueryClientProvider, QueryClient } from '@tanstack/svelte-query'\n  import { SvelteQueryDevtools } from '@tanstack/svelte-query-devtools'\n\n  const { children } = $props()\n\n  const queryClient = new QueryClient({\n    defaultOptions: {\n      queries: {\n        enabled: browser,\n      },\n    },\n  })\n</script>\n\n<svelte:head>\n  <title>TanStack Query Svelte Star Wars Example</title>\n</svelte:head>\n\n<QueryClientProvider client={queryClient}>\n  <nav\n    class=\"bg-gray-300 w-full flex flex-row gap-6 justify-center items-center h-12\"\n  >\n    <a class=\"uppercase hover:underline\" href=\"/\">Home</a>\n    <a class=\"uppercase hover:underline\" href=\"/films\">Films</a>\n    <a class=\"uppercase hover:underline\" href=\"/characters\">Characters</a>\n  </nav>\n  <div class=\"p-2\">\n    {@render children()}\n  </div>\n  <SvelteQueryDevtools />\n</QueryClientProvider>\n"
  },
  {
    "path": "examples/svelte/star-wars/src/routes/+page.svelte",
    "content": "<h2 class=\"text-4xl\">TanStack Query Demo</h2>\n<p>Using the Star Wars API</p>\n<p>\n  (Built by <a\n    class=\"text-blue-500 hover:underline\"\n    href=\"https://twitter.com/Brent_m_Clark\">@Brent_m_Clark</a\n  >)\n</p>\n\n<h5 class=\"text-2xl pt-4\">Why TanStack Query?</h5>\n<p>\n  In this demo you will be able to see how TanStack Query is a significant\n  improvement over <strong>redux</strong>, <strong>mobx</strong>, and any other\n  general-purpose state container.\n</p>\n<p>\n  No reducers, thunks, or sagas. No ES6 models to maintain in order to tag them\n  as observable.\n</p>\n<p>\n  Simply associate a key with your fetch call and let{' '}\n  <strong>TanStack Query</strong> handle the rest.\n</p>\n<h5 class=\"text-2xl pt-4\">Ready to get started?</h5>\n<p>\n  Check out the{' '}\n  <a href=\"/films\" class=\"text-blue-500 hover:underline\">Films</a>\n  and\n  <a href=\"/characters\" class=\"text-blue-500 hover:underline\">Characters</a>\n  !\n</p>\n"
  },
  {
    "path": "examples/svelte/star-wars/src/routes/characters/+page.svelte",
    "content": "<script lang=\"ts\">\n  import { createQuery } from '@tanstack/svelte-query'\n  import { getCharacters } from '$lib/api'\n\n  const query = createQuery(() => ({\n    queryKey: ['characters'],\n    queryFn: () => getCharacters(),\n  }))\n</script>\n\n{#if query.status === 'pending'}\n  <p>Loading...</p>\n{/if}\n\n{#if query.status === 'error'}\n  <p>Error :(</p>\n{/if}\n\n{#if query.status === 'success'}\n  <div>\n    <h2 class=\"text-4xl\">Characters</h2>\n    {#each query.data.results as person}\n      {@const personUrlParts = person.url.split('/').filter(Boolean)}\n      {@const personId = personUrlParts[personUrlParts.length - 1]}\n      <article>\n        <a\n          class=\"text-blue-500 hover:underline\"\n          href={`/characters/${personId}`}\n        >\n          <h6 class=\"text-xl\">{person.name}</h6>\n        </a>\n      </article>\n    {/each}\n  </div>\n{/if}\n"
  },
  {
    "path": "examples/svelte/star-wars/src/routes/characters/[characterId]/+page.svelte",
    "content": "<script lang=\"ts\">\n  import { createQuery } from '@tanstack/svelte-query'\n  import Homeworld from './Homeworld.svelte'\n  import Film from './Film.svelte'\n  import { getCharacter } from '$lib/api'\n  import { page } from '$app/state'\n\n  const query = createQuery(() => ({\n    queryKey: ['character', page.params.characterId],\n    queryFn: () => getCharacter(page.params.characterId),\n  }))\n</script>\n\n{#if query.status === 'pending'}\n  <p>Loading...</p>\n{/if}\n\n{#if query.status === 'error'}\n  <p>Error :(</p>\n{/if}\n\n{#if query.status === 'success'}\n  {@const homeworldUrlParts = query.data.homeworld.split('/').filter(Boolean)}\n  {@const homeworldId = homeworldUrlParts[homeworldUrlParts.length - 1]}\n  <h2 class=\"text-4xl\">{query.data.name}</h2>\n\n  <p><strong>Born</strong>: {query.data.birth_year}</p>\n  <p><strong>Eyes</strong>: {query.data.eye_color}</p>\n  <p><strong>Hair</strong>: {query.data.hair_color}</p>\n  <p><strong>Height</strong>: {query.data.height}</p>\n  <p><strong>Mass</strong>: {query.data.mass}</p>\n  <p><strong>Homeworld</strong>: <Homeworld {homeworldId} /></p>\n  <h4 class=\"text-2xl pt-4\">Films</h4>\n  {#each query.data.films as film}\n    {@const filmUrlParts = film.split('/').filter(Boolean)}\n    {@const filmId = filmUrlParts[filmUrlParts.length - 1]}\n    <Film {filmId} />\n  {/each}\n{/if}\n"
  },
  {
    "path": "examples/svelte/star-wars/src/routes/characters/[characterId]/Film.svelte",
    "content": "<script lang=\"ts\">\n  import { getFilm } from '$lib/api'\n  import { createQuery } from '@tanstack/svelte-query'\n\n  let { filmId }: { filmId: string } = $props()\n\n  const query = createQuery(() => ({\n    queryKey: ['film', filmId],\n    queryFn: () => getFilm(filmId),\n  }))\n</script>\n\n{#if query.status === 'success'}\n  <a class=\"text-blue-500 hover:underline\" href={`/films/${filmId}`}>\n    <h6 class=\"text-lg\">{query.data.episode_id}. {query.data.title}</h6>\n  </a>\n{/if}\n"
  },
  {
    "path": "examples/svelte/star-wars/src/routes/characters/[characterId]/Homeworld.svelte",
    "content": "<script lang=\"ts\">\n  import { createQuery } from '@tanstack/svelte-query'\n  import { getPlanet } from '$lib/api'\n\n  let { homeworldId }: { homeworldId: string } = $props()\n\n  const query = createQuery(() => ({\n    queryKey: ['homeworld', homeworldId],\n    queryFn: () => getPlanet(homeworldId),\n  }))\n</script>\n\n{#if query.status === 'pending'}\n  <span>Loading...</span>\n{/if}\n\n{#if query.status === 'error'}\n  <span>Error :(</span>\n{/if}\n\n{#if query.status === 'success'}\n  <span>\n    {query.data.name}\n  </span>\n{/if}\n"
  },
  {
    "path": "examples/svelte/star-wars/src/routes/films/+page.svelte",
    "content": "<script lang=\"ts\">\n  import { getFilms } from '$lib/api'\n  import { createQuery } from '@tanstack/svelte-query'\n\n  const query = createQuery(() => ({\n    queryKey: ['films'],\n    queryFn: () => getFilms(),\n  }))\n</script>\n\n{#if query.status === 'pending'}\n  <p>Loading...</p>\n{/if}\n\n{#if query.status === 'error'}\n  <p>Error :(</p>\n{/if}\n\n{#if query.status === 'success'}\n  <div>\n    <h2 class=\"text-4xl\">Films</h2>\n    {#each query.data.results as film}\n      {@const filmUrlParts = film.url.split('/').filter(Boolean)}\n      {@const filmId = filmUrlParts[filmUrlParts.length - 1]}\n      <article>\n        <a class=\"text-blue-500 hover:underline\" href={`/films/${filmId}`}>\n          <h6 class=\"text-xl\">\n            {film.episode_id}. {film.title}{' '}\n            <em>\n              ({new Date(Date.parse(film.release_date)).getFullYear()})\n            </em>\n          </h6>\n        </a>\n      </article>\n    {/each}\n  </div>\n{/if}\n"
  },
  {
    "path": "examples/svelte/star-wars/src/routes/films/[filmId]/+page.svelte",
    "content": "<script lang=\"ts\">\n  import { createQuery } from '@tanstack/svelte-query'\n  import Character from './Character.svelte'\n  import { getFilm } from '$lib/api'\n  import { page } from '$app/state'\n\n  const query = createQuery(() => ({\n    queryKey: ['film', page.params.filmId],\n    queryFn: () => getFilm(page.params.filmId),\n  }))\n</script>\n\n{#if query.status === 'pending'}\n  <p>Loading...</p>\n{/if}\n\n{#if query.status === 'error'}\n  <p>Error :(</p>\n{/if}\n\n{#if query.status === 'success'}\n  <div>\n    <h2 class=\"text-4xl\">{query.data.title}</h2>\n    <p>{query.data.opening_crawl}</p>\n    <br />\n    <h4 class=\"text-2xl\">Characters</h4>\n    {#each query.data.characters as character}\n      {@const characterUrlParts = character.split('/').filter(Boolean)}\n      {@const characterId = characterUrlParts[characterUrlParts.length - 1]}\n      <Character {characterId} />\n    {/each}\n  </div>\n{/if}\n"
  },
  {
    "path": "examples/svelte/star-wars/src/routes/films/[filmId]/Character.svelte",
    "content": "<script lang=\"ts\">\n  import { getCharacter } from '$lib/api'\n  import { createQuery } from '@tanstack/svelte-query'\n\n  let { characterId }: { characterId: string } = $props()\n\n  const query = createQuery(() => ({\n    queryKey: ['character', characterId],\n    queryFn: () => getCharacter(characterId),\n  }))\n</script>\n\n{#if query.status === 'success'}\n  <article>\n    <a\n      class=\"text-blue-500 hover:underline\"\n      href={`/characters/${characterId}`}\n    >\n      <h6 class=\"text-lg\">{query.data.name}</h6>\n    </a>\n  </article>\n{/if}\n"
  },
  {
    "path": "examples/svelte/star-wars/svelte.config.js",
    "content": "import adapter from '@sveltejs/adapter-auto'\nimport { vitePreprocess } from '@sveltejs/vite-plugin-svelte'\n\n/** @type {import('@sveltejs/kit').Config} */\nconst config = {\n  preprocess: vitePreprocess(),\n  kit: {\n    adapter: adapter(),\n  },\n  compilerOptions: {\n    runes: true,\n  },\n}\n\nexport default config\n"
  },
  {
    "path": "examples/svelte/star-wars/tsconfig.json",
    "content": "{\n  \"extends\": \"./.svelte-kit/tsconfig.json\",\n  \"compilerOptions\": {\n    \"allowJs\": true,\n    \"checkJs\": true,\n    \"esModuleInterop\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"resolveJsonModule\": true,\n    \"skipLibCheck\": true,\n    \"sourceMap\": true,\n    \"strict\": true\n  }\n}\n"
  },
  {
    "path": "examples/svelte/star-wars/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport { sveltekit } from '@sveltejs/kit/vite'\nimport tailwindcss from '@tailwindcss/vite'\n\nexport default defineConfig({\n  plugins: [tailwindcss(), sveltekit()],\n})\n"
  },
  {
    "path": "examples/vue/2.6-basic/.gitignore",
    "content": "node_modules\n.DS_Store\ndist\ndist-ssr\n*.local\n\npackage-lock.json\nyarn.lock\npnpm-lock.yaml\n"
  },
  {
    "path": "examples/vue/2.6-basic/README.md",
    "content": "# 2.6 Basic example\n\nTo run this example:\n\n- `npm install` or `yarn` or `pnpm i` or `bun i`\n- `npm run dev` or `yarn dev` or `pnpm dev` or `bun dev`\n"
  },
  {
    "path": "examples/vue/2.6-basic/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vue Query Example</title>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/src/main.ts\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/vue/2.6-basic/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-vue-2.6-basic\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"postinstall\": \"vue-demi-switch 2\",\n    \"dev\": \"vite\",\n    \"_build\": \"vite build\",\n    \"_preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/vue-query\": \"^5.90.2\",\n    \"@vue/composition-api\": \"1.7.2\",\n    \"vue\": \"2.6.14\",\n    \"vue-template-compiler\": \"2.6.14\"\n  },\n  \"devDependencies\": {\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^4.5.14\",\n    \"vite-plugin-vue2\": \"2.0.3\"\n  }\n}\n"
  },
  {
    "path": "examples/vue/2.6-basic/src/App.vue",
    "content": "<script lang=\"ts\">\nimport { defineComponent, ref } from '@vue/composition-api'\n\nimport Posts from './Posts.vue'\nimport Post from './Post.vue'\n\nexport default defineComponent({\n  name: 'App',\n  components: { Posts, Post },\n  setup() {\n    const visitedPosts = ref(new Set())\n    const isVisited = (id: number) => visitedPosts.value.has(id)\n\n    const postId = ref(-1)\n    const setPostId = (id: number) => {\n      visitedPosts.value.add(id)\n      postId.value = id\n    }\n\n    return {\n      isVisited,\n      postId,\n      setPostId,\n    }\n  },\n})\n</script>\n\n<template>\n  <div>\n    <h1>Vue Query - Basic</h1>\n    <p>\n      As you visit the posts below, you will notice them in a loading state the\n      first time you load them. However, after you return to this list and click\n      on any posts you have already visited again, you will see them load\n      instantly and background refresh right before your eyes!\n      <strong>\n        (You may need to throttle your network speed to simulate longer loading\n        sequences)\n      </strong>\n    </p>\n    <Post v-if=\"postId > -1\" :postId=\"postId\" @setPostId=\"setPostId\" />\n    <Posts v-else :isVisited=\"isVisited\" @setPostId=\"setPostId\" />\n  </div>\n</template>\n"
  },
  {
    "path": "examples/vue/2.6-basic/src/Post.vue",
    "content": "<script lang=\"ts\">\nimport { defineComponent, toRaw } from '@vue/composition-api'\nimport { useQuery } from '@tanstack/vue-query'\n\nimport { Post } from './types'\n\nconst fetcher = async (id: number): Promise<Post> =>\n  await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`).then(\n    (response) => response.json(),\n  )\n\nexport default defineComponent({\n  name: 'PostDetails',\n  props: {\n    postId: {\n      type: Number,\n      required: true,\n    },\n  },\n  emits: ['setPostId'],\n  setup(props) {\n    const { isPending, isError, isFetching, data, error } = useQuery({\n      queryKey: ['post', () => props.postId],\n      queryFn: () => fetcher(props.postId),\n    })\n\n    return { isPending, isError, isFetching, data, error }\n  },\n})\n</script>\n\n<template>\n  <div>\n    <h1>Post {{ postId }}</h1>\n    <a @click=\"$emit('setPostId', -1)\" href=\"#\"> Back </a>\n    <div v-if=\"isPending\" class=\"update\">Loading...</div>\n    <div v-else-if=\"isError\">An error has occurred: {{ error }}</div>\n    <div v-else-if=\"data\">\n      <h1>{{ data.title }}</h1>\n      <div>\n        <p>{{ data.body }}</p>\n      </div>\n      <div v-if=\"isFetching\" class=\"update\">Background Updating...</div>\n    </div>\n  </div>\n</template>\n\n<style scoped>\n.update {\n  font-weight: bold;\n  color: green;\n}\n</style>\n"
  },
  {
    "path": "examples/vue/2.6-basic/src/Posts.vue",
    "content": "<script lang=\"ts\">\nimport { defineComponent } from '@vue/composition-api'\nimport { useQuery } from '@tanstack/vue-query'\n\nimport type { Post } from './types'\n\nconst fetcher = async (): Promise<Post[]> =>\n  await fetch('https://jsonplaceholder.typicode.com/posts').then((response) =>\n    response.json(),\n  )\n\nexport default defineComponent({\n  name: 'PostsList',\n  props: {\n    isVisited: {\n      type: Function,\n      required: true,\n    },\n  },\n  emits: ['setPostId'],\n  setup() {\n    const { isPending, isError, isFetching, data, error, refetch } = useQuery({\n      queryKey: ['posts'],\n      queryFn: fetcher,\n    })\n\n    return { isPending, isError, isFetching, data, error, refetch }\n  },\n})\n</script>\n\n<template>\n  <div>\n    <h1>Posts</h1>\n    <div v-if=\"isPending\">Loading...</div>\n    <div v-else-if=\"isError\">An error has occurred: {{ error }}</div>\n    <div v-else-if=\"data\">\n      <ul>\n        <li v-for=\"item in data\" :key=\"item.id\">\n          <a\n            @click=\"$emit('setPostId', item.id)\"\n            href=\"#\"\n            :class=\"{ visited: isVisited(item.id) }\"\n            >{{ item.title }}</a\n          >\n        </li>\n      </ul>\n    </div>\n  </div>\n</template>\n\n<style scoped>\n.visited {\n  font-weight: bold;\n  color: green;\n}\n</style>\n"
  },
  {
    "path": "examples/vue/2.6-basic/src/main.ts",
    "content": "import Vue from 'vue'\nimport VueCompositionApi, { createApp, h } from '@vue/composition-api'\nimport { VueQueryPlugin } from '@tanstack/vue-query'\n\nimport App from './App.vue'\n\nVue.use(VueCompositionApi)\nVue.use(VueQueryPlugin)\n\ncreateApp({\n  render() {\n    return h(App)\n  },\n}).mount('#app')\n"
  },
  {
    "path": "examples/vue/2.6-basic/src/shims-vue.d.ts",
    "content": "declare module '*.vue' {\n  import Vue from 'vue'\n  export default Vue\n}\n"
  },
  {
    "path": "examples/vue/2.6-basic/src/types.d.ts",
    "content": "export interface Post {\n  userId: number\n  id: number\n  title: string\n  body: string\n}\n"
  },
  {
    "path": "examples/vue/2.6-basic/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ESNext\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"strict\": true,\n    \"jsx\": \"preserve\",\n    \"sourceMap\": true,\n    \"resolveJsonModule\": true,\n    \"esModuleInterop\": true,\n    \"lib\": [\"esnext\", \"dom\"],\n    \"types\": [\"vite/client\"]\n  },\n  \"include\": [\"src/**/*.ts\", \"src/**/*.d.ts\", \"src/**/*.vue\"]\n}\n"
  },
  {
    "path": "examples/vue/2.6-basic/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport { createVuePlugin } from 'vite-plugin-vue2'\n\nexport default defineConfig({\n  plugins: [createVuePlugin()],\n})\n"
  },
  {
    "path": "examples/vue/2.7-basic/.gitignore",
    "content": "node_modules\n.DS_Store\ndist\ndist-ssr\n*.local\n\npackage-lock.json\nyarn.lock\npnpm-lock.yaml\n"
  },
  {
    "path": "examples/vue/2.7-basic/README.md",
    "content": "# 2.7 Basic example\n\nTo run this example:\n\n- `npm install` or `yarn` or `pnpm i`\n- `npm run dev` or `yarn dev` or `pnpm dev`\n"
  },
  {
    "path": "examples/vue/2.7-basic/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vue Query Example</title>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/src/main.ts\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/vue/2.7-basic/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-vue-2.7-basic\",\n  \"private\": true,\n  \"scripts\": {\n    \"postinstall\": \"vue-demi-switch 2.7\",\n    \"dev\": \"vite\",\n    \"_build\": \"vite build\",\n    \"_build:dev\": \"vite build -m development\",\n    \"_serve\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/vue-query\": \"^5.90.2\",\n    \"vue\": \"2.7.16\",\n    \"vue-template-compiler\": \"2.7.16\"\n  },\n  \"devDependencies\": {\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^4.5.14\",\n    \"vite-plugin-vue2\": \"2.0.3\"\n  }\n}\n"
  },
  {
    "path": "examples/vue/2.7-basic/src/App.vue",
    "content": "<script lang=\"ts\">\nimport { defineComponent, ref } from 'vue'\n\nimport Posts from './Posts.vue'\nimport Post from './Post.vue'\n\nexport default defineComponent({\n  name: 'App',\n  components: { Posts, Post },\n  setup() {\n    const visitedPosts = ref(new Set())\n    const isVisited = (id: number) => visitedPosts.value.has(id)\n\n    const postId = ref(-1)\n    const setPostId = (id: number) => {\n      visitedPosts.value.add(id)\n      postId.value = id\n    }\n\n    return {\n      isVisited,\n      postId,\n      setPostId,\n    }\n  },\n})\n</script>\n\n<template>\n  <div>\n    <h1>Vue Query - Basic</h1>\n    <p>\n      As you visit the posts below, you will notice them in a loading state the\n      first time you load them. However, after you return to this list and click\n      on any posts you have already visited again, you will see them load\n      instantly and background refresh right before your eyes!\n      <strong>\n        (You may need to throttle your network speed to simulate longer loading\n        sequences)\n      </strong>\n    </p>\n    <Post v-if=\"postId > -1\" :postId=\"postId\" @setPostId=\"setPostId\" />\n    <Posts v-else :isVisited=\"isVisited\" @setPostId=\"setPostId\" />\n  </div>\n</template>\n"
  },
  {
    "path": "examples/vue/2.7-basic/src/Post.vue",
    "content": "<script lang=\"ts\">\nimport { defineComponent } from 'vue'\nimport { useQuery } from '@tanstack/vue-query'\n\nimport { Post } from './types'\n\nconst fetcher = async (id: number): Promise<Post> =>\n  await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`).then(\n    (response) => response.json(),\n  )\n\nexport default defineComponent({\n  name: 'PostDetails',\n  props: {\n    postId: {\n      type: Number,\n      required: true,\n    },\n  },\n  emits: ['setPostId'],\n  setup(props) {\n    const { isPending, isError, isFetching, data, error } = useQuery({\n      queryKey: ['post', () => props.postId],\n      queryFn: () => fetcher(props.postId),\n    })\n\n    return { isPending, isError, isFetching, data, error }\n  },\n})\n</script>\n\n<template>\n  <div>\n    <h1>Post {{ postId }}</h1>\n    <a @click=\"$emit('setPostId', -1)\" href=\"#\"> Back </a>\n    <div v-if=\"isPending\" class=\"update\">Loading...</div>\n    <div v-else-if=\"isError\">An error has occurred: {{ error }}</div>\n    <div v-else-if=\"data\">\n      <h1>{{ data.title }}</h1>\n      <div>\n        <p>{{ data.body }}</p>\n      </div>\n      <div v-if=\"isFetching\" class=\"update\">Background Updating...</div>\n    </div>\n  </div>\n</template>\n\n<style scoped>\n.update {\n  font-weight: bold;\n  color: green;\n}\n</style>\n"
  },
  {
    "path": "examples/vue/2.7-basic/src/Posts.vue",
    "content": "<script lang=\"ts\">\nimport { defineComponent } from 'vue'\nimport { useQuery } from '@tanstack/vue-query'\n\nimport type { Post } from './types'\n\nconst fetcher = async (): Promise<Post[]> =>\n  await fetch('https://jsonplaceholder.typicode.com/posts').then((response) =>\n    response.json(),\n  )\n\nexport default defineComponent({\n  name: 'PostsList',\n  props: {\n    isVisited: {\n      type: Function,\n      required: true,\n    },\n  },\n  emits: ['setPostId'],\n  setup() {\n    const { isPending, isError, isFetching, data, error, refetch } = useQuery({\n      queryKey: ['posts'],\n      queryFn: fetcher,\n    })\n\n    return { isPending, isError, isFetching, data, error, refetch }\n  },\n})\n</script>\n\n<template>\n  <div>\n    <h1>Posts</h1>\n    <div v-if=\"isPending\">Loading...</div>\n    <div v-else-if=\"isError\">An error has occurred: {{ error }}</div>\n    <div v-else-if=\"data\">\n      <ul>\n        <li v-for=\"item in data\" :key=\"item.id\">\n          <a\n            @click=\"$emit('setPostId', item.id)\"\n            href=\"#\"\n            :class=\"{ visited: isVisited(item.id) }\"\n            >{{ item.title }}</a\n          >\n        </li>\n      </ul>\n    </div>\n  </div>\n</template>\n\n<style scoped>\n.visited {\n  font-weight: bold;\n  color: green;\n}\n</style>\n"
  },
  {
    "path": "examples/vue/2.7-basic/src/main.ts",
    "content": "import Vue, { h } from 'vue'\nimport { VueQueryPlugin } from '@tanstack/vue-query'\n\nimport App from './App.vue'\n\nVue.use(VueQueryPlugin)\n\nvar app = new Vue({\n  el: '#app',\n\n  render: () => {\n    return h(App)\n  },\n})\n"
  },
  {
    "path": "examples/vue/2.7-basic/src/shims-vue.d.ts",
    "content": "declare module '*.vue' {\n  import Vue from 'vue'\n  export default Vue\n}\n"
  },
  {
    "path": "examples/vue/2.7-basic/src/types.d.ts",
    "content": "export interface Post {\n  userId: number\n  id: number\n  title: string\n  body: string\n}\n"
  },
  {
    "path": "examples/vue/2.7-basic/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ESNext\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"strict\": true,\n    \"jsx\": \"preserve\",\n    \"sourceMap\": true,\n    \"resolveJsonModule\": true,\n    \"esModuleInterop\": true,\n    \"lib\": [\"esnext\", \"dom\"],\n    \"types\": [\"vite/client\"]\n  },\n  \"include\": [\"src/*.ts\", \"src/*.d.ts\", \"src/*.vue\"]\n}\n"
  },
  {
    "path": "examples/vue/2.7-basic/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport { createVuePlugin } from 'vite-plugin-vue2'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n  plugins: [createVuePlugin()],\n})\n"
  },
  {
    "path": "examples/vue/basic/.gitignore",
    "content": "node_modules\n.DS_Store\ndist\ndist-ssr\n*.local\n\npackage-lock.json\nyarn.lock\npnpm-lock.yaml\n"
  },
  {
    "path": "examples/vue/basic/README.md",
    "content": "# Basic example\n\nTo run this example:\n\n- `npm install` or `yarn` or `pnpm i` or `bun i`\n- `npm run dev` or `yarn dev` or `pnpm dev` or `bun dev`\n"
  },
  {
    "path": "examples/vue/basic/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vue Query Example</title>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/src/main.ts\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/vue/basic/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-vue-basic\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/vue-query\": \"^5.92.12\",\n    \"@tanstack/vue-query-devtools\": \"^6.1.5\",\n    \"vue\": \"^3.4.27\"\n  },\n  \"devDependencies\": {\n    \"@vitejs/plugin-vue\": \"^5.2.1\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "examples/vue/basic/src/App.vue",
    "content": "<script lang=\"ts\">\nimport { defineComponent, ref } from 'vue'\nimport { VueQueryDevtools } from '@tanstack/vue-query-devtools'\n\nimport Posts from './Posts.vue'\nimport Post from './Post.vue'\n\nexport default defineComponent({\n  name: 'App',\n  components: { Posts, Post, VueQueryDevtools },\n  setup() {\n    const visitedPosts = ref(new Set())\n    const isVisited = (id: number) => visitedPosts.value.has(id)\n\n    const postId = ref(-1)\n    const setPostId = (id: number) => {\n      visitedPosts.value.add(id)\n      postId.value = id\n    }\n\n    return {\n      isVisited,\n      postId,\n      setPostId,\n    }\n  },\n})\n</script>\n\n<template>\n  <h1>Vue Query - Basic</h1>\n  <p>\n    As you visit the posts below, you will notice them in a loading state the\n    first time you load them. However, after you return to this list and click\n    on any posts you have already visited again, you will see them load\n    instantly and background refresh right before your eyes!\n    <strong>\n      (You may need to throttle your network speed to simulate longer loading\n      sequences)\n    </strong>\n  </p>\n  <Post v-if=\"postId > -1\" :postId=\"postId\" @setPostId=\"setPostId\" />\n  <Posts v-else :isVisited=\"isVisited\" @setPostId=\"setPostId\" />\n  <VueQueryDevtools />\n</template>\n"
  },
  {
    "path": "examples/vue/basic/src/Post.vue",
    "content": "<script lang=\"ts\">\nimport { defineComponent } from 'vue'\nimport { useQuery } from '@tanstack/vue-query'\n\nimport { Post } from './types'\n\nconst fetcher = async (id: number): Promise<Post> =>\n  await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`).then(\n    (response) => response.json(),\n  )\n\nexport default defineComponent({\n  name: 'PostDetails',\n  props: {\n    postId: {\n      type: Number,\n      required: true,\n    },\n  },\n  emits: ['setPostId'],\n  setup(props) {\n    const { isPending, isError, isFetching, data, error } = useQuery({\n      queryKey: ['post', () => props.postId],\n      queryFn: () => fetcher(props.postId),\n    })\n\n    return { isPending, isError, isFetching, data, error }\n  },\n})\n</script>\n\n<template>\n  <h1>Post {{ postId }}</h1>\n  <a @click=\"$emit('setPostId', -1)\" href=\"#\"> Back </a>\n  <div v-if=\"isPending\" class=\"update\">Loading...</div>\n  <div v-else-if=\"isError\">An error has occurred: {{ error }}</div>\n  <div v-else-if=\"data\">\n    <h1>{{ data.title }}</h1>\n    <div>\n      <p>{{ data.body }}</p>\n    </div>\n    <div v-if=\"isFetching\" class=\"update\">Background Updating...</div>\n  </div>\n</template>\n\n<style scoped>\n.update {\n  font-weight: bold;\n  color: green;\n}\n</style>\n"
  },
  {
    "path": "examples/vue/basic/src/Posts.vue",
    "content": "<script lang=\"ts\">\nimport { defineComponent } from 'vue'\nimport { useQuery } from '@tanstack/vue-query'\n\nimport type { Post } from './types'\n\nconst fetcher = async (): Promise<Post[]> =>\n  await fetch('https://jsonplaceholder.typicode.com/posts').then((response) =>\n    response.json(),\n  )\n\nexport default defineComponent({\n  name: 'PostsList',\n  props: {\n    isVisited: {\n      type: Function,\n      required: true,\n    },\n  },\n  emits: ['setPostId'],\n  setup() {\n    const { isPending, isError, isFetching, data, error, refetch } = useQuery({\n      queryKey: ['posts'],\n      queryFn: fetcher,\n    })\n\n    return { isPending, isError, isFetching, data, error, refetch }\n  },\n})\n</script>\n\n<template>\n  <h1>Posts</h1>\n  <div v-if=\"isPending\">Loading...</div>\n  <div v-else-if=\"isError\">An error has occurred: {{ error }}</div>\n  <div v-else-if=\"data\">\n    <ul>\n      <li v-for=\"item in data\" :key=\"item.id\">\n        <a\n          @click=\"$emit('setPostId', item.id)\"\n          href=\"#\"\n          :class=\"{ visited: isVisited(item.id) }\"\n          >{{ item.title }}</a\n        >\n      </li>\n    </ul>\n  </div>\n</template>\n\n<style scoped>\n.visited {\n  font-weight: bold;\n  color: green;\n}\n</style>\n"
  },
  {
    "path": "examples/vue/basic/src/main.ts",
    "content": "import { createApp } from 'vue'\nimport { VueQueryPlugin } from '@tanstack/vue-query'\n\nimport App from './App.vue'\n\ncreateApp(App).use(VueQueryPlugin).mount('#app')\n"
  },
  {
    "path": "examples/vue/basic/src/shims-vue.d.ts",
    "content": "declare module '*.vue' {\n  import { DefineComponent } from 'vue'\n  const component: DefineComponent<{}, {}, any>\n  export default component\n}\n"
  },
  {
    "path": "examples/vue/basic/src/types.d.ts",
    "content": "export interface Post {\n  userId: number\n  id: number\n  title: string\n  body: string\n}\n"
  },
  {
    "path": "examples/vue/basic/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"module\": \"ESNext\",\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"preserve\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src/**/*.ts\", \"src/**/*.d.ts\", \"src/**/*.vue\"]\n}\n"
  },
  {
    "path": "examples/vue/basic/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport vue from '@vitejs/plugin-vue'\n\nexport default defineConfig({\n  plugins: [vue()],\n  optimizeDeps: {\n    exclude: ['@tanstack/vue-query', 'vue-demi'],\n  },\n})\n"
  },
  {
    "path": "examples/vue/dependent-queries/.gitignore",
    "content": "node_modules\n.DS_Store\ndist\ndist-ssr\n*.local\npackage-lock.json\n"
  },
  {
    "path": "examples/vue/dependent-queries/README.md",
    "content": "# Dependent queries example\n\nTo run this example:\n\n- `npm install` or `yarn`\n- `npm run dev` or `yarn dev`\n"
  },
  {
    "path": "examples/vue/dependent-queries/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vue Query Example</title>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/src/main.ts\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/vue/dependent-queries/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-vue-dependent-queries\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/vue-query\": \"^5.92.12\",\n    \"vue\": \"^3.4.27\"\n  },\n  \"devDependencies\": {\n    \"@vitejs/plugin-vue\": \"^5.2.1\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "examples/vue/dependent-queries/src/App.vue",
    "content": "<script lang=\"ts\">\nimport { defineComponent, ref } from 'vue'\n\nimport Posts from './Posts.vue'\nimport Post from './Post.vue'\n\nexport default defineComponent({\n  name: 'App',\n  components: { Posts, Post },\n  setup() {\n    const visitedPosts = ref(new Set())\n    const isVisited = (id: number) => visitedPosts.value.has(id)\n\n    const postId = ref(-1)\n    const setPostId = (id: number) => {\n      visitedPosts.value.add(id)\n      postId.value = id\n    }\n\n    return {\n      isVisited,\n      postId,\n      setPostId,\n    }\n  },\n})\n</script>\n\n<template>\n  <h1>Vue Query - Dependent Queries</h1>\n  <p>\n    As you visit the posts below, you will notice them in a loading state the\n    first time you load them. However, after you return to this list and click\n    on any posts you have already visited again, you will see them load\n    instantly and background refresh right before your eyes!\n    <br />\n    You will also notice, that after some time the name of the author gets\n    loaded. This Data is not directly included in the\n    <code>/post/id</code> response but gets fetched when the post gets loaded\n    from its <code>userId</code>.\n    <strong>\n      (You may need to throttle your network speed to simulate longer loading\n      sequences)\n    </strong>\n  </p>\n  <Post v-if=\"postId > -1\" :postId=\"postId\" @setPostId=\"setPostId\" />\n  <Posts v-else :isVisited=\"isVisited\" @setPostId=\"setPostId\" />\n</template>\n"
  },
  {
    "path": "examples/vue/dependent-queries/src/Post.vue",
    "content": "<script lang=\"ts\">\nimport { computed, defineComponent } from 'vue'\nimport { useQuery } from '@tanstack/vue-query'\n\nimport { Author, Post } from './types'\n\nconst fetchPost = async (id: number): Promise<Post> =>\n  await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`).then(\n    (response) => response.json(),\n  )\n\nconst fetchAuthor = async (id: number): Promise<Author> =>\n  await fetch(`https://jsonplaceholder.typicode.com/users/${id}`).then(\n    (response) => response.json(),\n  )\n\nexport default defineComponent({\n  name: 'PostDetails',\n  props: {\n    postId: {\n      type: Number,\n      required: true,\n    },\n  },\n  emits: ['setPostId'],\n  setup(props) {\n    const {\n      isPending,\n      isError,\n      isFetching,\n      data: post,\n      error,\n    } = useQuery({\n      queryKey: ['post', () => props.postId],\n      queryFn: () => fetchPost(props.postId),\n    })\n\n    const authorId = computed(() => post.value?.userId)\n\n    const { data: author } = useQuery({\n      queryKey: ['author', authorId],\n      queryFn: ({ queryKey: [, id] }) => fetchAuthor(id),\n      enabled: computed(() => !!authorId.value),\n    })\n\n    return { isPending, isError, isFetching, post, error, author }\n  },\n})\n</script>\n\n<template>\n  <h1>Post {{ postId }}</h1>\n  <a @click=\"$emit('setPostId', -1)\" href=\"#\"> Back </a>\n  <div v-if=\"isPending\" class=\"update\">Loading...</div>\n  <div v-else-if=\"isError\">An error has occurred: {{ error }}</div>\n  <div v-else-if=\"post\">\n    <h1>\n      {{ post.title }} <span v-if=\"author\">by {{ author.name }}</span>\n    </h1>\n    <div>\n      <p>{{ post.body }}</p>\n    </div>\n    <div v-if=\"isFetching\" class=\"update\">Background Updating...</div>\n  </div>\n</template>\n\n<style scoped>\n.update {\n  font-weight: bold;\n  color: green;\n}\n</style>\n"
  },
  {
    "path": "examples/vue/dependent-queries/src/Posts.vue",
    "content": "<script lang=\"ts\">\nimport { defineComponent } from 'vue'\nimport { useQuery } from '@tanstack/vue-query'\n\nimport { Post } from './types'\n\nconst fetcher = async (): Promise<Post[]> =>\n  await fetch('https://jsonplaceholder.typicode.com/posts').then((response) =>\n    response.json(),\n  )\n\nexport default defineComponent({\n  name: 'PostsList',\n  props: {\n    isVisited: {\n      type: Function,\n      required: true,\n    },\n  },\n  emits: ['setPostId'],\n  setup() {\n    const { isPending, isError, isFetching, data, error, refetch } = useQuery({\n      queryKey: ['posts'],\n      queryFn: fetcher,\n    })\n\n    return { isPending, isError, isFetching, data, error, refetch }\n  },\n})\n</script>\n\n<template>\n  <h1>Posts</h1>\n  <div v-if=\"isPending\">Loading...</div>\n  <div v-else-if=\"isError\">An error has occurred: {{ error }}</div>\n  <div v-else-if=\"data\">\n    <ul>\n      <li v-for=\"item in data\" :key=\"item.id\">\n        <a\n          @click=\"$emit('setPostId', item.id)\"\n          href=\"#\"\n          :class=\"{ visited: isVisited(item.id) }\"\n          >{{ item.title }}</a\n        >\n      </li>\n    </ul>\n  </div>\n</template>\n\n<style scoped>\n.visited {\n  font-weight: bold;\n  color: green;\n}\n</style>\n"
  },
  {
    "path": "examples/vue/dependent-queries/src/main.ts",
    "content": "import { createApp } from 'vue'\nimport { VueQueryPlugin } from '@tanstack/vue-query'\n\nimport App from './App.vue'\n\ncreateApp(App).use(VueQueryPlugin).mount('#app')\n"
  },
  {
    "path": "examples/vue/dependent-queries/src/shims-vue.d.ts",
    "content": "declare module '*.vue' {\n  import { DefineComponent } from 'vue'\n  const component: DefineComponent<{}, {}, any>\n  export default component\n}\n"
  },
  {
    "path": "examples/vue/dependent-queries/src/types.d.ts",
    "content": "export interface Post {\n  userId: number\n  id: number\n  title: string\n  body: string\n}\n\nexport interface Author {\n  id: number\n  name: string\n  username: string\n  email: string\n  address: {\n    street: string\n    suite: string\n    city: string\n    zipcode: string\n    geo: {\n      lat: string\n      lng: string\n    }\n  }\n  phone: string\n  website: string\n  company: {\n    name: string\n    catchPhrase: string\n    bs: string\n  }\n}\n"
  },
  {
    "path": "examples/vue/dependent-queries/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ESNext\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"strict\": true,\n    \"jsx\": \"preserve\",\n    \"sourceMap\": true,\n    \"resolveJsonModule\": true,\n    \"esModuleInterop\": true,\n    \"lib\": [\"esnext\", \"dom\"],\n    \"types\": [\"vite/client\"]\n  },\n  \"include\": [\"src/**/*.ts\", \"src/**/*.d.ts\", \"src/**/*.tsx\", \"src/**/*.vue\"]\n}\n"
  },
  {
    "path": "examples/vue/dependent-queries/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport vue from '@vitejs/plugin-vue'\n\nexport default defineConfig({\n  plugins: [vue()],\n  optimizeDeps: {\n    exclude: ['@tanstack/vue-query', 'vue-demi'],\n  },\n})\n"
  },
  {
    "path": "examples/vue/nuxt3/.gitignore",
    "content": "node_modules\n*.log\n.nuxt\nnuxt.d.ts\n.output\n.env\n\npackage-lock.json\nyarn.lock\npnpm-lock.yaml\n"
  },
  {
    "path": "examples/vue/nuxt3/README.md",
    "content": "# Nuxt 3 Minimal Starter\n\nWe recommend looking at the [documentation](https://nuxt.com/docs/3.x/getting-started/introduction).\n\n## Setup\n\nMake sure to install the dependencies\n\n```bash\npnpm install\n```\n\n## Development\n\nStart the development server on http://localhost:3000\n\n```bash\npnpm dev\n```\n\n## Production\n\nBuild the application for production:\n\n```bash\npnpm build\n```\n\nCheck out the [deployment documentation](https://nuxt.com/docs/3.x/getting-started/deployment).\n"
  },
  {
    "path": "examples/vue/nuxt3/app.vue",
    "content": "<template>\n  <div>{{ data }}</div>\n</template>\n\n<script setup lang=\"ts\">\nimport { useQuery } from '@tanstack/vue-query'\n\nconst fetcher = async () =>\n  await fetch('https://jsonplaceholder.typicode.com/posts').then((response) =>\n    response.json(),\n  )\n\nconst { data, suspense } = useQuery({ queryKey: ['test'], queryFn: fetcher })\n\nawait suspense()\n</script>\n"
  },
  {
    "path": "examples/vue/nuxt3/nuxt.config.ts",
    "content": "import { defineNuxtConfig } from 'nuxt/config'\n\n// https://v3.nuxtjs.org/docs/directory-structure/nuxt.config\nexport default defineNuxtConfig({})\n"
  },
  {
    "path": "examples/vue/nuxt3/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-vue-nuxt3\",\n  \"private\": true,\n  \"scripts\": {\n    \"dev\": \"nuxi dev\",\n    \"_build\": \"nuxi build\",\n    \"_start\": \"node .output/server/index.mjs\"\n  },\n  \"dependencies\": {\n    \"@tanstack/vue-query\": \"^5.90.2\"\n  },\n  \"devDependencies\": {\n    \"nuxt\": \"^3.12.4\"\n  }\n}\n"
  },
  {
    "path": "examples/vue/nuxt3/plugins/vue-query.ts",
    "content": "import type {\n  DehydratedState,\n  VueQueryPluginOptions,\n} from '@tanstack/vue-query'\nimport {\n  VueQueryPlugin,\n  QueryClient,\n  hydrate,\n  dehydrate,\n} from '@tanstack/vue-query'\n// Nuxt 3 app aliases\nimport { defineNuxtPlugin, useState } from '#imports'\n\nexport default defineNuxtPlugin((nuxt) => {\n  const vueQueryState = useState<DehydratedState | null>('vue-query')\n\n  // Modify your Vue Query global settings here\n  const queryClient = new QueryClient({\n    defaultOptions: { queries: { staleTime: 5000 } },\n  })\n  const options: VueQueryPluginOptions = { queryClient }\n\n  nuxt.vueApp.use(VueQueryPlugin, options)\n\n  if (import.meta.server) {\n    nuxt.hooks.hook('app:rendered', () => {\n      vueQueryState.value = dehydrate(queryClient)\n    })\n  }\n\n  if (import.meta.client) {\n    nuxt.hooks.hook('app:created', () => {\n      hydrate(queryClient, vueQueryState.value)\n    })\n  }\n})\n"
  },
  {
    "path": "examples/vue/nuxt3/tsconfig.json",
    "content": "{\n  // https://v3.nuxtjs.org/concepts/typescript\n  \"extends\": \"./.nuxt/tsconfig.json\"\n}\n"
  },
  {
    "path": "examples/vue/persister/.gitignore",
    "content": "node_modules\n.DS_Store\ndist\ndist-ssr\n*.local\npackage-lock.json\n"
  },
  {
    "path": "examples/vue/persister/README.md",
    "content": "# Basic example\n\nTo run this example:\n\n- `npm install` or `yarn`\n- `npm run dev` or `yarn dev`\n"
  },
  {
    "path": "examples/vue/persister/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vue Query Example</title>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/src/main.ts\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/vue/persister/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-vue-persister\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/query-core\": \"^5.91.2\",\n    \"@tanstack/query-persist-client-core\": \"^5.92.4\",\n    \"@tanstack/query-sync-storage-persister\": \"^5.90.27\",\n    \"@tanstack/vue-query\": \"^5.92.12\",\n    \"idb-keyval\": \"^6.2.1\",\n    \"vue\": \"^3.4.27\"\n  },\n  \"devDependencies\": {\n    \"@vitejs/plugin-vue\": \"^5.2.1\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "examples/vue/persister/src/App.vue",
    "content": "<script lang=\"ts\">\nimport { defineComponent, ref } from 'vue'\n\nimport Posts from './Posts.vue'\nimport Post from './Post.vue'\n\nexport default defineComponent({\n  name: 'App',\n  components: { Posts, Post },\n  setup() {\n    const visitedPosts = ref(new Set())\n    const isVisited = (id: number) => visitedPosts.value.has(id)\n\n    const postId = ref(-1)\n    const setPostId = (id: number) => {\n      visitedPosts.value.add(id)\n      postId.value = id\n    }\n\n    return {\n      isVisited,\n      postId,\n      setPostId,\n    }\n  },\n})\n</script>\n\n<template>\n  <h1>Vue Query - Basic</h1>\n  <p>\n    As you visit the posts below, you will notice them in a loading state the\n    first time you load them. However, after you return to this list and click\n    on any posts you have already visited again, you will see them load\n    instantly and background refresh right before your eyes!\n    <strong>\n      (You may need to throttle your network speed to simulate longer loading\n      sequences)\n    </strong>\n  </p>\n  <Post v-if=\"postId > -1\" :postId=\"postId\" @setPostId=\"setPostId\" />\n  <Posts v-else :isVisited=\"isVisited\" @setPostId=\"setPostId\" />\n</template>\n"
  },
  {
    "path": "examples/vue/persister/src/Post.vue",
    "content": "<script lang=\"ts\">\nimport { get, set, del, entries } from 'idb-keyval'\nimport { defineComponent } from 'vue'\nimport { useQuery } from '@tanstack/vue-query'\n\nimport { Post } from './types'\nimport { experimental_createQueryPersister } from '@tanstack/query-persist-client-core'\n\nconst fetcher = async (id: number): Promise<Post> =>\n  await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`).then(\n    (response) => response.json(),\n  )\n\nexport default defineComponent({\n  name: 'PostDetails',\n  props: {\n    postId: {\n      type: Number,\n      required: true,\n    },\n  },\n  emits: ['setPostId'],\n  setup(props) {\n    const { isPending, isError, isFetching, data, error } = useQuery({\n      queryKey: ['post', () => props.postId] as const,\n      queryFn: () => fetcher(props.postId),\n      persister: experimental_createQueryPersister({\n        storage: {\n          getItem: (key: string) => get(key),\n          setItem: (key: string, value: string) => set(key, value),\n          removeItem: (key: string) => del(key),\n          entries: () => entries<string>(),\n        },\n      }).persisterFn,\n    })\n\n    return { isPending, isError, isFetching, data, error }\n  },\n})\n</script>\n\n<template>\n  <h1>Post {{ postId }}</h1>\n  <a @click=\"$emit('setPostId', -1)\" href=\"#\"> Back </a>\n  <div v-if=\"isPending\" class=\"update\">Loading...</div>\n  <div v-else-if=\"isError\">An error has occurred: {{ error }}</div>\n  <div v-else-if=\"data\">\n    <h1>{{ data.title }}</h1>\n    <div>\n      <p>{{ data.body }}</p>\n    </div>\n    <div v-if=\"isFetching\" class=\"update\">Background Updating...</div>\n  </div>\n</template>\n\n<style scoped>\n.update {\n  font-weight: bold;\n  color: green;\n}\n</style>\n"
  },
  {
    "path": "examples/vue/persister/src/Posts.vue",
    "content": "<script lang=\"ts\">\nimport { defineComponent } from 'vue'\nimport { useQuery } from '@tanstack/vue-query'\nimport { experimental_createQueryPersister } from '@tanstack/query-persist-client-core'\n\nimport { Post } from './types'\n\nconst fetcher = async (): Promise<Post[]> =>\n  await fetch('https://jsonplaceholder.typicode.com/posts').then(\n    (response) =>\n      new Promise((resolve) =>\n        setTimeout(() => resolve(response.json()), 1000),\n      ),\n  )\n\nexport default defineComponent({\n  name: 'PostsList',\n  props: {\n    isVisited: {\n      type: Function,\n      required: true,\n    },\n  },\n  emits: ['setPostId'],\n  setup() {\n    const {\n      isPending,\n      isError,\n      isFetching,\n      isRefetching,\n      data,\n      error,\n      refetch,\n    } = useQuery({\n      queryKey: ['posts'] as const,\n      queryFn: () => fetcher(),\n      persister: experimental_createQueryPersister({\n        storage: localStorage,\n      }).persisterFn,\n      staleTime: 5000,\n    })\n\n    return {\n      isPending,\n      isRefetching,\n      isError,\n      isFetching,\n      data,\n      error,\n      refetch,\n    }\n  },\n})\n</script>\n\n<template>\n  <h1>Posts</h1>\n  <div v-if=\"isRefetching\">Refetching...</div>\n  <div v-if=\"isPending\">Loading...</div>\n  <div v-else-if=\"isError\">An error has occurred: {{ error }}</div>\n  <div v-else-if=\"data\">\n    <ul>\n      <li v-for=\"item in data\" :key=\"item.id\">\n        <a\n          @click=\"$emit('setPostId', item.id)\"\n          href=\"#\"\n          :class=\"{ visited: isVisited(item.id) }\"\n          >{{ item.title }}</a\n        >\n      </li>\n    </ul>\n  </div>\n</template>\n\n<style scoped>\n.visited {\n  font-weight: bold;\n  color: green;\n}\n</style>\n"
  },
  {
    "path": "examples/vue/persister/src/main.ts",
    "content": "import { createApp } from 'vue'\nimport { VueQueryPlugin } from '@tanstack/vue-query'\nimport type { VueQueryPluginOptions } from '@tanstack/vue-query'\n\nimport App from './App.vue'\n\nconst vueQueryOptions: VueQueryPluginOptions = {\n  queryClientConfig: {\n    defaultOptions: {\n      queries: {\n        gcTime: 1000 * 60 * 60 * 24,\n        // staleTime: 1000 * 10,\n      },\n    },\n  },\n}\n\ncreateApp(App).use(VueQueryPlugin, vueQueryOptions).mount('#app')\n"
  },
  {
    "path": "examples/vue/persister/src/shims-vue.d.ts",
    "content": "declare module '*.vue' {\n  import { DefineComponent } from 'vue'\n  const component: DefineComponent<{}, {}, any>\n  export default component\n}\n"
  },
  {
    "path": "examples/vue/persister/src/types.d.ts",
    "content": "export interface Post {\n  userId: number\n  id: number\n  title: string\n  body: string\n}\n"
  },
  {
    "path": "examples/vue/persister/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"module\": \"ESNext\",\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"preserve\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src/**/*.ts\", \"src/**/*.d.ts\", \"src/**/*.vue\"]\n}\n"
  },
  {
    "path": "examples/vue/persister/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport vue from '@vitejs/plugin-vue'\n\nexport default defineConfig({\n  plugins: [vue()],\n  optimizeDeps: {\n    exclude: ['@tanstack/vue-query', 'vue-demi'],\n  },\n})\n"
  },
  {
    "path": "examples/vue/simple/.gitignore",
    "content": "node_modules\n.DS_Store\ndist\ndist-ssr\n*.local\n\npackage-lock.json\nyarn.lock\npnpm-lock.yaml\n"
  },
  {
    "path": "examples/vue/simple/README.md",
    "content": "# Basic example\n\nTo run this example:\n\n- `npm install` or `yarn` or `pnpm i` or `bun i`\n- `npm run dev` or `yarn dev` or `pnpm dev` or `bun dev`\n"
  },
  {
    "path": "examples/vue/simple/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>TanStack Query Vue Simple Example App</title>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/src/main.ts\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/vue/simple/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-example-vue-simple\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tanstack/vue-query\": \"^5.92.12\",\n    \"@tanstack/vue-query-devtools\": \"^6.1.5\",\n    \"vue\": \"^3.4.27\"\n  },\n  \"devDependencies\": {\n    \"@vitejs/plugin-vue\": \"^5.2.1\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "examples/vue/simple/src/App.vue",
    "content": "<script lang=\"ts\">\nimport { defineComponent } from 'vue'\nimport { useQuery } from '@tanstack/vue-query'\nimport { VueQueryDevtools } from '@tanstack/vue-query-devtools'\n\nexport default defineComponent({\n  name: 'App',\n  components: { VueQueryDevtools },\n  setup() {\n    const { data, error, isFetching, isPending } = useQuery({\n      queryKey: ['repoData'],\n      async queryFn() {\n        return await fetch('https://api.github.com/repos/Tanstack/query').then(\n          (response) => response.json(),\n        )\n      },\n    })\n\n    return {\n      data,\n      error,\n      isFetching,\n      isPending,\n    }\n  },\n})\n</script>\n\n<template>\n  <template v-if=\"isPending\"> Loading... </template>\n  <template v-else-if=\"error\">\n    'An error has occurred: {{ error.message }}\n  </template>\n  <template v-else>\n    <h1>{{ data.name }}</h1>\n    <p>{{ data.description }}</p>\n    <strong>👀 {{ data.subscribers_count }}</strong>\n    <strong>✨ {{ data.stargazers_count }}</strong>\n    <strong>🍴 {{ data.forks_count }}</strong>\n    <div>{{ isFetching ? 'Updating...' : '' }}</div>\n  </template>\n  <VueQueryDevtools />\n</template>\n"
  },
  {
    "path": "examples/vue/simple/src/main.ts",
    "content": "import { createApp } from 'vue'\nimport { VueQueryPlugin } from '@tanstack/vue-query'\n\nimport App from './App.vue'\n\ncreateApp(App).use(VueQueryPlugin).mount('#app')\n"
  },
  {
    "path": "examples/vue/simple/src/shims-vue.d.ts",
    "content": "declare module '*.vue' {\n  import { DefineComponent } from 'vue'\n  const component: DefineComponent<{}, {}, any>\n  export default component\n}\n"
  },
  {
    "path": "examples/vue/simple/src/types.d.ts",
    "content": "export interface Post {\n  userId: number\n  id: number\n  title: string\n  body: string\n}\n"
  },
  {
    "path": "examples/vue/simple/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ESNext\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"strict\": true,\n    \"jsx\": \"preserve\",\n    \"sourceMap\": true,\n    \"resolveJsonModule\": true,\n    \"esModuleInterop\": true,\n    \"lib\": [\"esnext\", \"dom\"],\n    \"types\": [\"vite/client\"]\n  },\n  \"include\": [\"src/**/*.ts\", \"src/**/*.d.ts\", \"src/**/*.vue\"]\n}\n"
  },
  {
    "path": "examples/vue/simple/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport vue from '@vitejs/plugin-vue'\n\nexport default defineConfig({\n  plugins: [vue()],\n  optimizeDeps: {\n    exclude: ['@tanstack/vue-query', 'vue-demi'],\n  },\n})\n"
  },
  {
    "path": "integrations/angular-cli-20/.gitignore",
    "content": "# See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files.\n\n# Compiled output\n/dist\n/tmp\n/out-tsc\n/bazel-out\n\n# Node\n/node_modules\nnpm-debug.log\nyarn-error.log\n\n# IDEs and editors\n.idea/\n.project\n.classpath\n.c9/\n*.launch\n.settings/\n*.sublime-workspace\n\n# Visual Studio Code\n.vscode/*\n!.vscode/settings.json\n!.vscode/tasks.json\n!.vscode/launch.json\n!.vscode/extensions.json\n.history/*\n\n# Miscellaneous\n/.angular/cache\n.sass-cache/\n/connect.lock\n/coverage\n/libpeerconnection.log\ntestem.log\n/typings\n\n# System files\n.DS_Store\nThumbs.db\n"
  },
  {
    "path": "integrations/angular-cli-20/.vscode/extensions.json",
    "content": "{\n  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846\n  \"recommendations\": [\"angular.ng-template\"]\n}\n"
  },
  {
    "path": "integrations/angular-cli-20/.vscode/launch.json",
    "content": "{\n  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387\n  \"version\": \"0.2.0\",\n  \"configurations\": [\n    {\n      \"name\": \"ng serve\",\n      \"type\": \"chrome\",\n      \"request\": \"launch\",\n      \"preLaunchTask\": \"npm: start\",\n      \"url\": \"http://localhost:4200/\"\n    }\n  ]\n}\n"
  },
  {
    "path": "integrations/angular-cli-20/.vscode/tasks.json",
    "content": "{\n  // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558\n  \"version\": \"2.0.0\",\n  \"tasks\": [\n    {\n      \"type\": \"npm\",\n      \"script\": \"start\",\n      \"isBackground\": true,\n      \"problemMatcher\": {\n        \"owner\": \"typescript\",\n        \"pattern\": \"$tsc\",\n        \"background\": {\n          \"activeOnStart\": true,\n          \"beginsPattern\": {\n            \"regexp\": \"(.*?)\"\n          },\n          \"endsPattern\": {\n            \"regexp\": \"bundle generation complete\"\n          }\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "integrations/angular-cli-20/README.md",
    "content": "# AngularCli20\n\nThis project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 20.0.0-rc.2.\n\n## Development server\n\nTo start a local development server, run:\n\n```bash\nng serve\n```\n\nOnce the server is running, open your browser and navigate to `http://localhost:4200/`. The application will automatically reload whenever you modify any of the source files.\n\n## Code scaffolding\n\nAngular CLI includes powerful code scaffolding tools. To generate a new component, run:\n\n```bash\nng generate component component-name\n```\n\nFor a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:\n\n```bash\nng generate --help\n```\n\n## Building\n\nTo build the project run:\n\n```bash\nng build\n```\n\nThis will compile your project and store the build artifacts in the `dist/` directory. By default, the production build optimizes your application for performance and speed.\n\n## Running unit tests\n\nTo execute unit tests with the [Karma](https://karma-runner.github.io) test runner, use the following command:\n\n```bash\nng test\n```\n\n## Running end-to-end tests\n\nFor end-to-end (e2e) testing, run:\n\n```bash\nng e2e\n```\n\nAngular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.\n\n## Additional Resources\n\nFor more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.\n"
  },
  {
    "path": "integrations/angular-cli-20/angular.json",
    "content": "{\n  \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n  \"version\": 1,\n  \"cli\": {\n    \"packageManager\": \"pnpm\",\n    \"analytics\": false,\n    \"cache\": {\n      \"enabled\": false\n    }\n  },\n  \"newProjectRoot\": \"projects\",\n  \"projects\": {\n    \"angular-cli-20\": {\n      \"projectType\": \"application\",\n      \"schematics\": {\n        \"@schematics/angular:component\": {\n          \"inlineTemplate\": true,\n          \"inlineStyle\": true,\n          \"skipTests\": true\n        },\n        \"@schematics/angular:class\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:directive\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:guard\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:interceptor\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:pipe\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:resolver\": {\n          \"skipTests\": true\n        },\n        \"@schematics/angular:service\": {\n          \"skipTests\": true\n        }\n      },\n      \"root\": \"\",\n      \"sourceRoot\": \"src\",\n      \"prefix\": \"app\",\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular/build:application\",\n          \"options\": {\n            \"browser\": \"src/main.ts\",\n            \"tsConfig\": \"tsconfig.app.json\",\n            \"assets\": [\n              {\n                \"glob\": \"**/*\",\n                \"input\": \"public\"\n              }\n            ],\n            \"styles\": [\"src/styles.css\"]\n          },\n          \"configurations\": {\n            \"production\": {\n              \"budgets\": [\n                {\n                  \"type\": \"initial\",\n                  \"maximumWarning\": \"500kB\",\n                  \"maximumError\": \"1MB\"\n                },\n                {\n                  \"type\": \"anyComponentStyle\",\n                  \"maximumWarning\": \"4kB\",\n                  \"maximumError\": \"8kB\"\n                }\n              ],\n              \"outputHashing\": \"all\"\n            },\n            \"development\": {\n              \"optimization\": false,\n              \"extractLicenses\": false,\n              \"sourceMap\": true\n            }\n          },\n          \"defaultConfiguration\": \"production\"\n        },\n        \"serve\": {\n          \"builder\": \"@angular/build:dev-server\",\n          \"configurations\": {\n            \"production\": {\n              \"buildTarget\": \"angular-cli-20:build:production\"\n            },\n            \"development\": {\n              \"buildTarget\": \"angular-cli-20:build:development\"\n            }\n          },\n          \"defaultConfiguration\": \"development\"\n        },\n        \"extract-i18n\": {\n          \"builder\": \"@angular/build:extract-i18n\"\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "integrations/angular-cli-20/package.json",
    "content": "{\n  \"name\": \"angular-cli-20\",\n  \"private\": true,\n  \"scripts\": {\n    \"ng\": \"ng\",\n    \"start\": \"ng serve\",\n    \"build\": \"ng build\",\n    \"watch\": \"ng build --watch --configuration development\"\n  },\n  \"dependencies\": {\n    \"@angular/common\": \"^20.0.0\",\n    \"@angular/compiler\": \"^20.0.0\",\n    \"@angular/core\": \"^20.0.0\",\n    \"@angular/forms\": \"^20.0.0\",\n    \"@angular/platform-browser\": \"^20.0.0\",\n    \"@angular/router\": \"^20.0.0\",\n    \"@tanstack/angular-query-experimental\": \"^5.90.28\",\n    \"rxjs\": \"~7.8.0\",\n    \"tslib\": \"^2.3.0\",\n    \"zone.js\": \"~0.15.0\"\n  },\n  \"devDependencies\": {\n    \"@angular/build\": \"^20.0.0\",\n    \"@angular/cli\": \"^20.0.0\",\n    \"@angular/compiler-cli\": \"^20.0.0\",\n    \"typescript\": \"~5.8.2\"\n  }\n}\n"
  },
  {
    "path": "integrations/angular-cli-20/src/app/app.config.ts",
    "content": "import {\n  ApplicationConfig,\n  provideBrowserGlobalErrorListeners,\n  provideZonelessChangeDetection,\n} from '@angular/core'\nimport {\n  provideTanStackQuery,\n  QueryClient,\n} from '@tanstack/angular-query-experimental'\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideBrowserGlobalErrorListeners(),\n    provideZonelessChangeDetection(),\n    provideTanStackQuery(new QueryClient()),\n  ],\n}\n"
  },
  {
    "path": "integrations/angular-cli-20/src/app/app.ts",
    "content": "import { Component } from '@angular/core'\nimport { injectQuery } from '@tanstack/angular-query-experimental'\n\n@Component({\n  selector: 'app-root',\n  template: `\n    @if (query.isPending()) {\n      <div>Loading...</div>\n    }\n    @if (query.isError()) {\n      <div>An error has occurred!</div>\n    }\n    @if (query.isSuccess()) {\n      <div>{{ query.data() }}</div>\n    }\n  `,\n})\nexport class App {\n  query = injectQuery(() => ({\n    queryKey: ['test'],\n    queryFn: async () => {\n      await new Promise((r) => setTimeout(r, 1000))\n      return 'Success'\n    },\n  }))\n}\n"
  },
  {
    "path": "integrations/angular-cli-20/src/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>AngularCli20</title>\n    <base href=\"/\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <link rel=\"icon\" type=\"image/x-icon\" href=\"favicon.ico\" />\n  </head>\n  <body>\n    <app-root></app-root>\n  </body>\n</html>\n"
  },
  {
    "path": "integrations/angular-cli-20/src/main.ts",
    "content": "import { bootstrapApplication } from '@angular/platform-browser'\nimport { appConfig } from './app/app.config'\nimport { App } from './app/app'\n\nbootstrapApplication(App, appConfig).catch((err) => console.error(err))\n"
  },
  {
    "path": "integrations/angular-cli-20/src/styles.css",
    "content": "/* You can add global styles to this file, and also import other style files */\n"
  },
  {
    "path": "integrations/angular-cli-20/tsconfig.app.json",
    "content": "/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */\n/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */\n{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./out-tsc/app\",\n    \"types\": []\n  },\n  \"include\": [\"src/**/*.ts\"],\n  \"exclude\": [\"src/**/*.spec.ts\"]\n}\n"
  },
  {
    "path": "integrations/angular-cli-20/tsconfig.json",
    "content": "/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */\n/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */\n{\n  \"compileOnSave\": false,\n  \"compilerOptions\": {\n    \"strict\": true,\n    \"noImplicitOverride\": true,\n    \"noPropertyAccessFromIndexSignature\": true,\n    \"noImplicitReturns\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"skipLibCheck\": true,\n    \"isolatedModules\": true,\n    \"experimentalDecorators\": true,\n    \"importHelpers\": true,\n    \"target\": \"ES2022\",\n    \"module\": \"preserve\"\n  },\n  \"angularCompilerOptions\": {\n    \"enableI18nLegacyMessageIdFormat\": false,\n    \"strictInjectionParameters\": true,\n    \"strictInputAccessModifiers\": true,\n    \"typeCheckHostBindings\": true,\n    \"strictTemplates\": true\n  },\n  \"files\": [],\n  \"references\": [\n    {\n      \"path\": \"./tsconfig.app.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "integrations/react-next-14/.eslintrc.cjs",
    "content": "/** @type {import('eslint').Linter.Config} */\nmodule.exports = {\n  extends: ['plugin:react/jsx-runtime', 'plugin:react-hooks/recommended'],\n  settings: {\n    react: {\n      version: 'detect',\n    },\n  },\n}\n"
  },
  {
    "path": "integrations/react-next-14/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# next.js\n/.next/\n/out/\n\n# production\n/build\n\n# misc\n.DS_Store\n*.pem\n\n# debug\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# local env files\n.env*.local\n\n# vercel\n.vercel\n\n# typescript\n*.tsbuildinfo\n"
  },
  {
    "path": "integrations/react-next-14/README.md",
    "content": "This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).\n\n## Getting Started\n\nFirst, run the development server:\n\n```bash\nnpm run dev\n# or\nyarn dev\n# or\npnpm dev\n```\n\nOpen [http://localhost:3000](http://localhost:3000) with your browser to see the result.\n\nYou can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.\n\nThis project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.\n\n## Learn More\n\nTo learn more about Next.js, take a look at the following resources:\n\n- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.\n- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.\n\nYou can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!\n\n## Deploy on Vercel\n\nThe easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.\n\nCheck out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.\n"
  },
  {
    "path": "integrations/react-next-14/app/client-component.tsx",
    "content": "'use client'\n\nimport React from 'react'\nimport { useQuery } from '@tanstack/react-query'\n\nexport function ClientComponent() {\n  const query = useQuery({\n    queryKey: ['test'],\n    queryFn: async () => {\n      await new Promise((r) => setTimeout(r, 1000))\n      return 'Success'\n    },\n  })\n\n  if (query.isPending) {\n    return <div>Loading...</div>\n  }\n\n  if (query.isError) {\n    return <div>An error has occurred!</div>\n  }\n\n  return <div>{query.data}</div>\n}\n"
  },
  {
    "path": "integrations/react-next-14/app/layout.tsx",
    "content": "import React from 'react'\nimport Providers from './providers'\nimport type { Metadata } from 'next'\n\nexport const metadata: Metadata = {\n  title: 'Create Next App',\n  description: 'Generated by create next app',\n}\n\nexport default function RootLayout({\n  children,\n}: {\n  children: React.ReactNode\n}) {\n  return (\n    <html lang=\"en\">\n      <body>\n        <Providers>{children}</Providers>\n      </body>\n    </html>\n  )\n}\n"
  },
  {
    "path": "integrations/react-next-14/app/page.tsx",
    "content": "import React from 'react'\nimport { queryOptions } from '@tanstack/react-query'\nimport { ClientComponent } from './client-component'\n\nconst options = queryOptions({\n  queryKey: ['foo'],\n})\n\nexport default function Home() {\n  return (\n    <main>\n      <ClientComponent />\n      Key: {JSON.stringify(options.queryKey)}\n    </main>\n  )\n}\n"
  },
  {
    "path": "integrations/react-next-14/app/providers.tsx",
    "content": "'use client'\nimport * as React from 'react'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\n\nexport default function Providers({ children }: { children: React.ReactNode }) {\n  const [queryClient] = React.useState(() => new QueryClient())\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      {children}\n      <ReactQueryDevtools />\n    </QueryClientProvider>\n  )\n}\n"
  },
  {
    "path": "integrations/react-next-14/next.config.js",
    "content": "/** @type {import('next').NextConfig} */\nconst nextConfig = {\n  eslint: {\n    ignoreDuringBuilds: true,\n  },\n  typescript: {\n    ignoreBuildErrors: true,\n  },\n}\n\nmodule.exports = nextConfig\n"
  },
  {
    "path": "integrations/react-next-14/package.json",
    "content": "{\n  \"name\": \"react-next-14\",\n  \"private\": true,\n  \"scripts\": {\n    \"build\": \"next build\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-query\": \"workspace:*\",\n    \"@tanstack/react-query-devtools\": \"workspace:*\",\n    \"next\": \"^14.2.33\",\n    \"react\": \"^18.2.0\",\n    \"react-dom\": \"^18.2.0\"\n  },\n  \"devDependencies\": {\n    \"@types/react\": \"^18.2.79\",\n    \"@types/react-dom\": \"^18.2.25\"\n  }\n}\n"
  },
  {
    "path": "integrations/react-next-14/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES5\",\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"jsx\": \"preserve\",\n    \"incremental\": true,\n    \"plugins\": [\n      {\n        \"name\": \"next\"\n      }\n    ],\n    \"paths\": {\n      \"@/*\": [\"./*\"]\n    }\n  },\n  \"include\": [\n    \"next-env.d.ts\",\n    \"**/*.ts\",\n    \"**/*.tsx\",\n    \".next/types/**/*.ts\",\n    \".eslintrc.cjs\"\n  ],\n  \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "integrations/react-next-15/.eslintrc.cjs",
    "content": "/** @type {import('eslint').Linter.Config} */\nmodule.exports = {\n  extends: ['plugin:react/jsx-runtime', 'plugin:react-hooks/recommended'],\n  settings: {\n    react: {\n      version: 'detect',\n    },\n  },\n}\n"
  },
  {
    "path": "integrations/react-next-15/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# next.js\n/.next/\n/out/\n\n# production\n/build\n\n# misc\n.DS_Store\n*.pem\n\n# debug\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# local env files\n.env*.local\n\n# vercel\n.vercel\n\n# typescript\n*.tsbuildinfo\n"
  },
  {
    "path": "integrations/react-next-15/README.md",
    "content": "This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).\n\n## Getting Started\n\nFirst, run the development server:\n\n```bash\nnpm run dev\n# or\nyarn dev\n# or\npnpm dev\n```\n\nOpen [http://localhost:3000](http://localhost:3000) with your browser to see the result.\n\nYou can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.\n\nThis project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.\n\n## Learn More\n\nTo learn more about Next.js, take a look at the following resources:\n\n- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.\n- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.\n\nYou can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!\n\n## Deploy on Vercel\n\nThe easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.\n\nCheck out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.\n"
  },
  {
    "path": "integrations/react-next-15/app/_action.ts",
    "content": "'use server'\n\nimport { revalidatePath } from 'next/cache'\nimport { countRef } from './make-query-client'\n\nexport async function queryExampleAction() {\n  await Promise.resolve()\n  countRef.current++\n  revalidatePath('/', 'page')\n  return undefined\n}\n"
  },
  {
    "path": "integrations/react-next-15/app/client-component.tsx",
    "content": "'use client'\n\nimport React from 'react'\nimport { useQuery } from '@tanstack/react-query'\nimport { Temporal } from '@js-temporal/polyfill'\n\nexport function ClientComponent() {\n  const query = useQuery({\n    queryKey: ['data'],\n    queryFn: async () => {\n      const { count } = await (\n        await fetch('http://localhost:3000/count')\n      ).json()\n\n      return {\n        text: 'data from client',\n        date: Temporal.PlainDate.from('2023-01-01'),\n        count,\n      }\n    },\n  })\n\n  if (query.isPending) {\n    return <div>Loading...</div>\n  }\n\n  if (query.isError) {\n    return <div>An error has occurred!</div>\n  }\n\n  return (\n    <div>\n      {query.data.text} - {query.data.date.toJSON()} - {query.data.count}\n    </div>\n  )\n}\n"
  },
  {
    "path": "integrations/react-next-15/app/count/route.ts",
    "content": "import { countRef } from '../make-query-client'\n\nexport const GET = () => {\n  return Response.json({ count: countRef.current })\n}\n"
  },
  {
    "path": "integrations/react-next-15/app/layout.tsx",
    "content": "import React from 'react'\nimport Providers from './providers'\nimport type { Metadata } from 'next'\n\nexport const metadata: Metadata = {\n  title: 'Create Next App',\n  description: 'Generated by create next app',\n}\n\nexport default function RootLayout({\n  children,\n}: {\n  children: React.ReactNode\n}) {\n  return (\n    <html lang=\"en\">\n      <body>\n        <Providers>{children}</Providers>\n      </body>\n    </html>\n  )\n}\n"
  },
  {
    "path": "integrations/react-next-15/app/make-query-client.ts",
    "content": "import { Temporal } from '@js-temporal/polyfill'\nimport { QueryClient, defaultShouldDehydrateQuery } from '@tanstack/react-query'\nimport { createTson } from 'tupleson'\nimport type { TsonType } from 'tupleson'\n\nconst plainDate = {\n  deserialize: (v) => Temporal.PlainDate.from(v),\n  key: 'PlainDate',\n  serialize: (v) => v.toJSON(),\n  test: (v) => v instanceof Temporal.PlainDate,\n} satisfies TsonType<Temporal.PlainDate, string>\n\nexport const countRef = {\n  current: 0,\n}\n\nexport const tson = createTson({\n  types: [plainDate],\n})\n\nexport function makeQueryClient() {\n  return new QueryClient({\n    defaultOptions: {\n      hydrate: {\n        /**\n         * Called when the query is rebuilt from a prefetched\n         * promise, before the query data is put into the cache.\n         */\n        deserializeData: (data) => {\n          return tson.deserialize(data)\n        },\n      },\n      queries: {\n        staleTime: 60 * 1000,\n      },\n      dehydrate: {\n        serializeData: (data) => {\n          return tson.serialize(data)\n        },\n        shouldDehydrateQuery: (query) => {\n          return (\n            defaultShouldDehydrateQuery(query) ||\n            query.state.status === 'pending'\n          )\n        },\n        shouldRedactErrors: (error) => {\n          // Next.js automatically redacts errors for us\n          return false\n        },\n      },\n    },\n  })\n}\n"
  },
  {
    "path": "integrations/react-next-15/app/page.tsx",
    "content": "import { headers } from 'next/headers'\nimport React from 'react'\nimport { HydrationBoundary, dehydrate } from '@tanstack/react-query'\nimport { Temporal } from '@js-temporal/polyfill'\nimport { ClientComponent } from './client-component'\nimport { makeQueryClient } from './make-query-client'\nimport { queryExampleAction } from './_action'\n\nexport default function Home() {\n  const queryClient = makeQueryClient()\n\n  queryClient.prefetchQuery({\n    queryKey: ['data'],\n    queryFn: async () => {\n      const { count } = await (\n        await fetch('http://localhost:3000/count', {\n          headers: await headers(),\n        })\n      ).json()\n\n      return {\n        text: 'data from server',\n        date: Temporal.PlainDate.from('2024-01-01'),\n        count,\n      }\n    },\n  })\n\n  const state = dehydrate(queryClient)\n\n  return (\n    <main>\n      <HydrationBoundary state={state}>\n        <ClientComponent />\n      </HydrationBoundary>\n      <form action={queryExampleAction}>\n        <button type=\"submit\">Increment</button>\n      </form>\n    </main>\n  )\n}\n"
  },
  {
    "path": "integrations/react-next-15/app/providers.tsx",
    "content": "// In Next.js, this file would be called: app/providers.tsx\n'use client'\n\n// Since QueryClientProvider relies on useContext under the hood, we have to put 'use client' on top\nimport { QueryClientProvider, isServer } from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\nimport type { QueryClient } from '@tanstack/react-query'\nimport { makeQueryClient } from '@/app/make-query-client'\n\nlet browserQueryClient: QueryClient | undefined = undefined\n\nfunction getQueryClient() {\n  if (isServer) {\n    // Server: always make a new query client\n    return makeQueryClient()\n  } else {\n    // Browser: make a new query client if we don't already have one\n    // This is very important, so we don't re-make a new client if React\n    // suspends during the initial render. This may not be needed if we\n    // have a suspense boundary BELOW the creation of the query client\n    if (!browserQueryClient) browserQueryClient = makeQueryClient()\n    return browserQueryClient\n  }\n}\n\nexport default function Providers({ children }: { children: React.ReactNode }) {\n  // NOTE: Avoid useState when initializing the query client if you don't\n  //       have a suspense boundary between this and the code that may\n  //       suspend because React will throw away the client on the initial\n  //       render if it suspends and there is no boundary\n  const queryClient = getQueryClient()\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      {children}\n      <ReactQueryDevtools />\n    </QueryClientProvider>\n  )\n}\n"
  },
  {
    "path": "integrations/react-next-15/next.config.js",
    "content": "/** @type {import('next').NextConfig} */\nconst nextConfig = {\n  eslint: {\n    ignoreDuringBuilds: true,\n  },\n  typescript: {\n    ignoreBuildErrors: true,\n  },\n}\n\nmodule.exports = nextConfig\n"
  },
  {
    "path": "integrations/react-next-15/package.json",
    "content": "{\n  \"name\": \"react-next-15\",\n  \"private\": true,\n  \"scripts\": {\n    \"dev\": \"next dev\",\n    \"build\": \"next build\"\n  },\n  \"dependencies\": {\n    \"@js-temporal/polyfill\": \"^0.4.4\",\n    \"@tanstack/react-query\": \"workspace:*\",\n    \"@tanstack/react-query-devtools\": \"workspace:*\",\n    \"next\": \"^15.4.8\",\n    \"react\": \"^19.2.1\",\n    \"react-dom\": \"^19.2.1\",\n    \"tupleson\": \"0.23.1\"\n  },\n  \"devDependencies\": {\n    \"@types/react\": \"^19.2.7\",\n    \"@types/react-dom\": \"^19.2.3\"\n  }\n}\n"
  },
  {
    "path": "integrations/react-next-15/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES5\",\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"jsx\": \"preserve\",\n    \"incremental\": true,\n    \"plugins\": [\n      {\n        \"name\": \"next\"\n      }\n    ],\n    \"paths\": {\n      \"@/*\": [\"./*\"]\n    }\n  },\n  \"include\": [\n    \"next-env.d.ts\",\n    \"**/*.ts\",\n    \"**/*.tsx\",\n    \".next/types/**/*.ts\",\n    \".eslintrc.cjs\"\n  ],\n  \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "integrations/react-next-16/.eslintrc.cjs",
    "content": "/** @type {import('eslint').Linter.Config} */\nmodule.exports = {\n  extends: ['plugin:react/jsx-runtime', 'plugin:react-hooks/recommended'],\n  settings: {\n    react: {\n      version: 'detect',\n    },\n  },\n}\n"
  },
  {
    "path": "integrations/react-next-16/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# next.js\n/.next/\n/out/\n\n# production\n/build\n\n# misc\n.DS_Store\n*.pem\n\n# debug\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# local env files\n.env*.local\n\n# vercel\n.vercel\n\n# typescript\n*.tsbuildinfo\n"
  },
  {
    "path": "integrations/react-next-16/README.md",
    "content": "This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).\n\n## Getting Started\n\nFirst, run the development server:\n\n```bash\nnpm run dev\n# or\nyarn dev\n# or\npnpm dev\n```\n\nOpen [http://localhost:3000](http://localhost:3000) with your browser to see the result.\n\nYou can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.\n\nThis project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.\n\n## Learn More\n\nTo learn more about Next.js, take a look at the following resources:\n\n- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.\n- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.\n\nYou can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!\n\n## Deploy on Vercel\n\nThe easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.\n\nCheck out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.\n"
  },
  {
    "path": "integrations/react-next-16/app/_action.ts",
    "content": "'use server'\n\nimport { revalidatePath } from 'next/cache'\nimport { countRef } from './make-query-client'\n\nexport async function queryExampleAction() {\n  await Promise.resolve()\n  countRef.current++\n  revalidatePath('/', 'page')\n  return undefined\n}\n"
  },
  {
    "path": "integrations/react-next-16/app/client-component.tsx",
    "content": "'use client'\n\nimport React from 'react'\nimport { useQuery } from '@tanstack/react-query'\nimport { Temporal } from '@js-temporal/polyfill'\n\nexport function ClientComponent() {\n  const query = useQuery({\n    queryKey: ['data'],\n    queryFn: async () => {\n      const { count } = await (\n        await fetch('http://localhost:3000/count')\n      ).json()\n\n      return {\n        text: 'data from client',\n        date: Temporal.PlainDate.from('2023-01-01'),\n        count,\n      }\n    },\n  })\n\n  if (query.isPending) {\n    return <div>Loading...</div>\n  }\n\n  if (query.isError) {\n    return <div>An error has occurred!</div>\n  }\n\n  return (\n    <div>\n      {query.data.text} - {query.data.date.toJSON()} - {query.data.count}\n    </div>\n  )\n}\n"
  },
  {
    "path": "integrations/react-next-16/app/count/route.ts",
    "content": "import { countRef } from '../make-query-client'\n\nexport const GET = () => {\n  return Response.json({ count: countRef.current })\n}\n"
  },
  {
    "path": "integrations/react-next-16/app/layout.tsx",
    "content": "import React from 'react'\nimport Providers from './providers'\nimport type { Metadata } from 'next'\n\nexport const metadata: Metadata = {\n  title: 'Create Next App',\n  description: 'Generated by create next app',\n}\n\nexport default function RootLayout({\n  children,\n}: {\n  children: React.ReactNode\n}) {\n  return (\n    <html lang=\"en\">\n      <body>\n        <Providers>{children}</Providers>\n      </body>\n    </html>\n  )\n}\n"
  },
  {
    "path": "integrations/react-next-16/app/make-query-client.ts",
    "content": "import { Temporal } from '@js-temporal/polyfill'\nimport { QueryClient, defaultShouldDehydrateQuery } from '@tanstack/react-query'\nimport { createTson } from 'tupleson'\nimport type { TsonType } from 'tupleson'\n\nconst plainDate = {\n  deserialize: (v) => Temporal.PlainDate.from(v),\n  key: 'PlainDate',\n  serialize: (v) => v.toJSON(),\n  test: (v) => v instanceof Temporal.PlainDate,\n} satisfies TsonType<Temporal.PlainDate, string>\n\nexport const countRef = {\n  current: 0,\n}\n\nexport const tson = createTson({\n  types: [plainDate],\n})\n\nexport function makeQueryClient() {\n  return new QueryClient({\n    defaultOptions: {\n      hydrate: {\n        /**\n         * Called when the query is rebuilt from a prefetched\n         * promise, before the query data is put into the cache.\n         */\n        deserializeData: (data) => {\n          return tson.deserialize(data)\n        },\n      },\n      queries: {\n        staleTime: 60 * 1000,\n      },\n      dehydrate: {\n        serializeData: (data) => {\n          return tson.serialize(data)\n        },\n        shouldDehydrateQuery: (query) => {\n          return (\n            defaultShouldDehydrateQuery(query) ||\n            query.state.status === 'pending'\n          )\n        },\n        shouldRedactErrors: (error) => {\n          // Next.js automatically redacts errors for us\n          return false\n        },\n      },\n    },\n  })\n}\n"
  },
  {
    "path": "integrations/react-next-16/app/page.tsx",
    "content": "import { headers } from 'next/headers'\nimport React from 'react'\nimport { HydrationBoundary, dehydrate } from '@tanstack/react-query'\nimport { Temporal } from '@js-temporal/polyfill'\nimport { ClientComponent } from './client-component'\nimport { makeQueryClient } from './make-query-client'\nimport { queryExampleAction } from './_action'\n\nexport default function Home() {\n  const queryClient = makeQueryClient()\n\n  queryClient.prefetchQuery({\n    queryKey: ['data'],\n    queryFn: async () => {\n      const { count } = await (\n        await fetch('http://localhost:3000/count', {\n          headers: await headers(),\n        })\n      ).json()\n\n      return {\n        text: 'data from server',\n        date: Temporal.PlainDate.from('2024-01-01'),\n        count,\n      }\n    },\n  })\n\n  const state = dehydrate(queryClient)\n\n  return (\n    <main>\n      <HydrationBoundary state={state}>\n        <ClientComponent />\n      </HydrationBoundary>\n      <form action={queryExampleAction}>\n        <button type=\"submit\">Increment</button>\n      </form>\n    </main>\n  )\n}\n"
  },
  {
    "path": "integrations/react-next-16/app/providers.tsx",
    "content": "// In Next.js, this file would be called: app/providers.tsx\n'use client'\n\n// Since QueryClientProvider relies on useContext under the hood, we have to put 'use client' on top\nimport { QueryClientProvider, isServer } from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\nimport type { QueryClient } from '@tanstack/react-query'\nimport { makeQueryClient } from '@/app/make-query-client'\n\nlet browserQueryClient: QueryClient | undefined = undefined\n\nfunction getQueryClient() {\n  if (isServer) {\n    // Server: always make a new query client\n    return makeQueryClient()\n  } else {\n    // Browser: make a new query client if we don't already have one\n    // This is very important, so we don't re-make a new client if React\n    // suspends during the initial render. This may not be needed if we\n    // have a suspense boundary BELOW the creation of the query client\n    if (!browserQueryClient) browserQueryClient = makeQueryClient()\n    return browserQueryClient\n  }\n}\n\nexport default function Providers({ children }: { children: React.ReactNode }) {\n  // NOTE: Avoid useState when initializing the query client if you don't\n  //       have a suspense boundary between this and the code that may\n  //       suspend because React will throw away the client on the initial\n  //       render if it suspends and there is no boundary\n  const queryClient = getQueryClient()\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      {children}\n      <ReactQueryDevtools />\n    </QueryClientProvider>\n  )\n}\n"
  },
  {
    "path": "integrations/react-next-16/next.config.js",
    "content": "/** @type {import('next').NextConfig} */\nconst nextConfig = {\n  eslint: {\n    ignoreDuringBuilds: true,\n  },\n  typescript: {\n    ignoreBuildErrors: true,\n  },\n}\n\nmodule.exports = nextConfig\n"
  },
  {
    "path": "integrations/react-next-16/package.json",
    "content": "{\n  \"name\": \"react-next-16\",\n  \"private\": true,\n  \"scripts\": {\n    \"dev\": \"next dev\",\n    \"build\": \"next build\"\n  },\n  \"dependencies\": {\n    \"@js-temporal/polyfill\": \"^0.4.4\",\n    \"@tanstack/react-query\": \"workspace:*\",\n    \"@tanstack/react-query-devtools\": \"workspace:*\",\n    \"next\": \"^16.0.7\",\n    \"react\": \"^19.2.1\",\n    \"react-dom\": \"^19.2.1\",\n    \"tupleson\": \"0.23.1\"\n  },\n  \"devDependencies\": {\n    \"@types/react\": \"^19.2.7\",\n    \"@types/react-dom\": \"^19.2.3\"\n  }\n}\n"
  },
  {
    "path": "integrations/react-next-16/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES5\",\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"jsx\": \"react-jsx\",\n    \"incremental\": true,\n    \"plugins\": [\n      {\n        \"name\": \"next\"\n      }\n    ],\n    \"paths\": {\n      \"@/*\": [\"./*\"]\n    }\n  },\n  \"include\": [\n    \"next-env.d.ts\",\n    \"**/*.ts\",\n    \"**/*.tsx\",\n    \".next/types/**/*.ts\",\n    \".eslintrc.cjs\",\n    \".next/dev/types/**/*.ts\"\n  ],\n  \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "integrations/react-vite/.eslintrc.cjs",
    "content": "/** @type {import('eslint').Linter.Config} */\nmodule.exports = {\n  extends: ['plugin:react/jsx-runtime', 'plugin:react-hooks/recommended'],\n  settings: {\n    react: {\n      version: 'detect',\n    },\n  },\n}\n"
  },
  {
    "path": "integrations/react-vite/.gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "integrations/react-vite/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>Vite + React</title>\n  </head>\n  <body>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/main.jsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "integrations/react-vite/package.json",
    "content": "{\n  \"name\": \"react-vite\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"build\": \"vite build\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-query\": \"workspace:*\",\n    \"@tanstack/react-query-devtools\": \"workspace:*\",\n    \"@vitejs/plugin-react\": \"^4.3.4\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "integrations/react-vite/src/App.jsx",
    "content": "import React from 'react'\nimport { useQuery } from '@tanstack/react-query'\n\nconst App = () => {\n  const query = useQuery({\n    queryKey: ['test'],\n    queryFn: async () => {\n      await new Promise((r) => setTimeout(r, 1000))\n      return 'Success'\n    },\n  })\n\n  if (query.isPending) {\n    return <div>Loading...</div>\n  }\n\n  if (query.isError) {\n    return <div>An error has occurred!</div>\n  }\n\n  return <div>{query.data}</div>\n}\n\nexport default App\n"
  },
  {
    "path": "integrations/react-vite/src/main.jsx",
    "content": "import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\nimport App from './App.jsx'\n\nconst queryClient = new QueryClient()\n\nconst root = ReactDOM.createRoot(document.getElementById('root'))\n\nroot.render(\n  <React.StrictMode>\n    <QueryClientProvider client={queryClient}>\n      <App />\n      <ReactQueryDevtools />\n    </QueryClientProvider>\n  </React.StrictMode>,\n)\n"
  },
  {
    "path": "integrations/react-vite/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"esModuleInterop\": true,\n    \"allowSyntheticDefaultImports\": true,\n    \"strict\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\"\n  },\n  \"include\": [\"src\", \".eslintrc.cjs\"]\n}\n"
  },
  {
    "path": "integrations/react-vite/vite.config.js",
    "content": "import { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\n\nexport default defineConfig({\n  plugins: [react()],\n})\n"
  },
  {
    "path": "integrations/react-webpack-4/package.json",
    "content": "{\n  \"name\": \"react-webpack-4\",\n  \"private\": true,\n  \"scripts\": {\n    \"build\": \"cross-env NODE_OPTIONS=--openssl-legacy-provider webpack --mode production\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-query\": \"workspace:*\",\n    \"@tanstack/react-query-devtools\": \"workspace:*\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.26.0\",\n    \"@babel/preset-env\": \"^7.26.0\",\n    \"@babel/preset-react\": \"^7.25.9\",\n    \"babel-loader\": \"^8.3.0\",\n    \"cross-env\": \"^7.0.3\",\n    \"html-webpack-plugin\": \"^4.5.2\",\n    \"webpack\": \"^4.44.2\",\n    \"webpack-cli\": \"^4.10.0\"\n  }\n}\n"
  },
  {
    "path": "integrations/react-webpack-4/public/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>react-webpack-4</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "integrations/react-webpack-4/src/App.js",
    "content": "import React from 'react'\nimport { useQuery } from '@tanstack/react-query'\n\nconst App = () => {\n  const query = useQuery({\n    queryKey: ['test'],\n    queryFn: async () => {\n      await new Promise((r) => setTimeout(r, 1000))\n      return 'Success'\n    },\n  })\n\n  if (query.isPending) {\n    return <div>Loading...</div>\n  }\n\n  if (query.isError) {\n    return <div>An error has occurred!</div>\n  }\n\n  return <div>{query.data}</div>\n}\n\nexport default App\n"
  },
  {
    "path": "integrations/react-webpack-4/src/index.js",
    "content": "import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\nimport App from './App'\n\nconst queryClient = new QueryClient()\n\nconst root = ReactDOM.createRoot(document.getElementById('root'))\n\nroot.render(\n  <React.StrictMode>\n    <QueryClientProvider client={queryClient}>\n      <App />\n      <ReactQueryDevtools />\n    </QueryClientProvider>\n  </React.StrictMode>,\n)\n"
  },
  {
    "path": "integrations/react-webpack-4/webpack.config.js",
    "content": "const HtmlWebPackPlugin = require('html-webpack-plugin')\n\nconst htmlPlugin = new HtmlWebPackPlugin({\n  template: './public/index.html',\n  filename: './index.html',\n})\n\nmodule.exports = {\n  module: {\n    rules: [\n      {\n        test: /\\.(?:js|mjs|cjs|jsx)$/,\n        exclude: /node_modules/,\n        use: {\n          loader: 'babel-loader',\n          options: {\n            presets: ['@babel/preset-env', '@babel/preset-react'],\n          },\n        },\n      },\n    ],\n  },\n  plugins: [htmlPlugin],\n}\n"
  },
  {
    "path": "integrations/react-webpack-5/package.json",
    "content": "{\n  \"name\": \"react-webpack-5\",\n  \"private\": true,\n  \"scripts\": {\n    \"build\": \"webpack --mode production\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-query\": \"workspace:*\",\n    \"@tanstack/react-query-devtools\": \"workspace:*\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.26.0\",\n    \"@babel/preset-env\": \"^7.26.0\",\n    \"@babel/preset-react\": \"^7.25.9\",\n    \"babel-loader\": \"^9.2.1\",\n    \"html-webpack-plugin\": \"^5.6.3\",\n    \"webpack\": \"^5.96.1\",\n    \"webpack-cli\": \"^5.1.4\"\n  }\n}\n"
  },
  {
    "path": "integrations/react-webpack-5/public/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>react-webpack-5</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "integrations/react-webpack-5/src/App.js",
    "content": "import React from 'react'\nimport { useQuery } from '@tanstack/react-query'\n\nconst App = () => {\n  const query = useQuery({\n    queryKey: ['test'],\n    queryFn: async () => {\n      await new Promise((r) => setTimeout(r, 1000))\n      return 'Success'\n    },\n  })\n\n  if (query.isPending) {\n    return <div>Loading...</div>\n  }\n\n  if (query.isError) {\n    return <div>An error has occurred!</div>\n  }\n\n  return <div>{query.data}</div>\n}\n\nexport default App\n"
  },
  {
    "path": "integrations/react-webpack-5/src/index.js",
    "content": "import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\nimport App from './App'\n\nconst queryClient = new QueryClient()\n\nconst root = ReactDOM.createRoot(document.getElementById('root'))\n\nroot.render(\n  <React.StrictMode>\n    <QueryClientProvider client={queryClient}>\n      <App />\n      <ReactQueryDevtools />\n    </QueryClientProvider>\n  </React.StrictMode>,\n)\n"
  },
  {
    "path": "integrations/react-webpack-5/webpack.config.js",
    "content": "const HtmlWebPackPlugin = require('html-webpack-plugin')\n\nconst htmlPlugin = new HtmlWebPackPlugin({\n  template: './public/index.html',\n  filename: './index.html',\n})\n\nmodule.exports = {\n  module: {\n    rules: [\n      {\n        test: /\\.(?:js|mjs|cjs|jsx)$/,\n        exclude: /node_modules/,\n        use: {\n          loader: 'babel-loader',\n          options: {\n            presets: ['@babel/preset-env', '@babel/preset-react'],\n          },\n        },\n      },\n    ],\n  },\n  plugins: [htmlPlugin],\n}\n"
  },
  {
    "path": "integrations/solid-vite/.gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "integrations/solid-vite/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>Vite + Solid</title>\n  </head>\n  <body>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/index.jsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "integrations/solid-vite/package.json",
    "content": "{\n  \"name\": \"solid-vite\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"build\": \"vite build\"\n  },\n  \"dependencies\": {\n    \"@tanstack/solid-query\": \"workspace:*\",\n    \"@tanstack/solid-query-devtools\": \"workspace:*\",\n    \"solid-js\": \"^1.9.7\",\n    \"vite\": \"^6.4.1\",\n    \"vite-plugin-solid\": \"^2.11.6\"\n  }\n}\n"
  },
  {
    "path": "integrations/solid-vite/src/App.jsx",
    "content": "import { Match, Switch } from 'solid-js'\nimport { useQuery } from '@tanstack/solid-query'\n\nconst App = () => {\n  const query = useQuery(() => ({\n    queryKey: ['test'],\n    queryFn: async () => {\n      await new Promise((r) => setTimeout(r, 1000))\n      return 'Success'\n    },\n  }))\n\n  return (\n    <Switch>\n      <Match when={query.isPending}>Loading...</Match>\n      <Match when={query.isError}>An error has occurred!</Match>\n      <Match when={query.isSuccess}>{query.data}</Match>\n    </Switch>\n  )\n}\n\nexport default App\n"
  },
  {
    "path": "integrations/solid-vite/src/index.jsx",
    "content": "/* @refresh reload */\nimport { render } from 'solid-js/web'\nimport { QueryClient, QueryClientProvider } from '@tanstack/solid-query'\nimport { SolidQueryDevtools } from '@tanstack/solid-query-devtools'\nimport App from './App'\n\nconst queryClient = new QueryClient()\n\nconst root = document.getElementById('root')\n\nrender(\n  () => (\n    <QueryClientProvider client={queryClient}>\n      <SolidQueryDevtools />\n      <App />\n    </QueryClientProvider>\n  ),\n  root,\n)\n"
  },
  {
    "path": "integrations/solid-vite/vite.config.js",
    "content": "import { defineConfig } from 'vite'\nimport solid from 'vite-plugin-solid'\n\nexport default defineConfig({\n  plugins: [solid()],\n})\n"
  },
  {
    "path": "integrations/svelte-vite/.gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "integrations/svelte-vite/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>Vite + Svelte</title>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/src/main.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "integrations/svelte-vite/package.json",
    "content": "{\n  \"name\": \"svelte-vite\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"build\": \"vite build\"\n  },\n  \"devDependencies\": {\n    \"@sveltejs/vite-plugin-svelte\": \"^5.1.1\",\n    \"@tanstack/svelte-query\": \"workspace:*\",\n    \"@tanstack/svelte-query-devtools\": \"workspace:*\",\n    \"svelte\": \"^5.39.3\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "integrations/svelte-vite/src/App.svelte",
    "content": "<script>\n  import { QueryClientProvider, QueryClient } from '@tanstack/svelte-query'\n  import { SvelteQueryDevtools } from '@tanstack/svelte-query-devtools'\n  import Simple from './Simple.svelte'\n\n  const queryClient = new QueryClient()\n</script>\n\n<QueryClientProvider client={queryClient}>\n  <Simple />\n  <SvelteQueryDevtools />\n</QueryClientProvider>\n"
  },
  {
    "path": "integrations/svelte-vite/src/Simple.svelte",
    "content": "<script>\n  import { createQuery } from '@tanstack/svelte-query'\n\n  const query = createQuery({\n    queryKey: ['test'],\n    queryFn: async () => {\n      await new Promise((r) => setTimeout(r, 1000))\n      return 'Success'\n    },\n  })\n</script>\n\n{#if $query.isPending}\n  <div>Loading...</div>\n{:else if $query.error}\n  <div>An error has occurred!</div>\n{:else}\n  <div>{$query.data}</div>\n{/if}\n"
  },
  {
    "path": "integrations/svelte-vite/src/main.js",
    "content": "import App from './App.svelte'\n\nconst app = new App({\n  target: document.getElementById('app'),\n})\n\nexport default app\n"
  },
  {
    "path": "integrations/svelte-vite/src/vite-env.d.ts",
    "content": "/// <reference types=\"svelte\" />\n/// <reference types=\"vite/client\" />\n"
  },
  {
    "path": "integrations/svelte-vite/svelte.config.js",
    "content": "import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'\n\nexport default {\n  preprocess: vitePreprocess(),\n}\n"
  },
  {
    "path": "integrations/svelte-vite/vite.config.js",
    "content": "import { defineConfig } from 'vite'\nimport { svelte } from '@sveltejs/vite-plugin-svelte'\n\nexport default defineConfig({\n  plugins: [svelte()],\n})\n"
  },
  {
    "path": "integrations/vue-vite/.gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "integrations/vue-vite/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>Vite + Vue + TS</title>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/src/main.ts\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "integrations/vue-vite/package.json",
    "content": "{\n  \"name\": \"vue-vite\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"build\": \"vite build\"\n  },\n  \"dependencies\": {\n    \"@tanstack/vue-query\": \"workspace:*\",\n    \"vue\": \"^3.4.27\"\n  },\n  \"devDependencies\": {\n    \"@vitejs/plugin-vue\": \"^5.2.1\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\",\n    \"vue-tsc\": \"^2.2.8\"\n  }\n}\n"
  },
  {
    "path": "integrations/vue-vite/src/App.vue",
    "content": "<script setup lang=\"ts\">\nimport { useQuery } from '@tanstack/vue-query'\n\nconst { isPending, isError, data } = useQuery({\n  queryKey: ['test'],\n  queryFn: async () => {\n    await new Promise((r) => setTimeout(r, 1000))\n    return 'Success'\n  },\n})\n</script>\n\n<template>\n  <div v-if=\"isPending\">Loading...</div>\n  <div v-else-if=\"isError\">An error has occurred!</div>\n  <div v-else-if=\"data\">{{ data }}</div>\n</template>\n"
  },
  {
    "path": "integrations/vue-vite/src/main.ts",
    "content": "import { createApp } from 'vue'\nimport App from './App.vue'\nimport { VueQueryPlugin } from '@tanstack/vue-query'\n\ncreateApp(App).use(VueQueryPlugin).mount('#app')\n"
  },
  {
    "path": "integrations/vue-vite/src/vite-env.d.ts",
    "content": "/// <reference types=\"vite/client\" />\n"
  },
  {
    "path": "integrations/vue-vite/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"module\": \"ESNext\",\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"preserve\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src/**/*.ts\", \"src/**/*.vue\", \"vite.config.ts\"]\n}\n"
  },
  {
    "path": "integrations/vue-vite/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport vue from '@vitejs/plugin-vue'\n\nexport default defineConfig({\n  plugins: [vue()],\n})\n"
  },
  {
    "path": "knip.json",
    "content": "{\n  \"$schema\": \"https://unpkg.com/knip@5/schema.json\",\n  \"ignore\": [\n    \".pnpmfile.cjs\",\n    \"scripts/*.{j,t}s\",\n    \"**/root.*.config.*\",\n    \"**/ts-fixture/file.ts\"\n  ],\n  \"ignoreDependencies\": [\n    \"@types/react\",\n    \"@types/react-dom\",\n    \"react\",\n    \"react-dom\"\n  ],\n  \"ignoreWorkspaces\": [\"examples/**\", \"integrations/**\"],\n  \"workspaces\": {\n    \"packages/angular-query-experimental\": {\n      \"entry\": [\n        \"src/devtools/production/index.ts\",\n        \"src/devtools-panel/production/index.ts\"\n      ]\n    },\n    \"packages/query-codemods\": {\n      \"entry\": [\"src/v4/**/*.cjs\", \"src/v5/**/*.cjs\"],\n      \"ignore\": [\"**/__testfixtures__/**\"]\n    },\n    \"packages/vue-query\": {\n      \"ignore\": [\"**/__mocks__/**\"],\n      \"ignoreDependencies\": [\"vue2\", \"vue2.7\"]\n    }\n  }\n}\n"
  },
  {
    "path": "labeler-config.yml",
    "content": "'package: angular-query-devtools-experimental':\n  - changed-files:\n      - any-glob-to-any-file: 'packages/angular-query-devtools-experimental/**/*'\n'package: angular-query-experimental':\n  - changed-files:\n      - any-glob-to-any-file: 'packages/angular-query-experimental/**/*'\n'package: angular-query-persist-client':\n  - changed-files:\n      - any-glob-to-any-file: 'packages/angular-query-persist-client/**/*'\n'package: eslint-plugin-query':\n  - changed-files:\n      - any-glob-to-any-file: 'packages/eslint-plugin-query/**/*'\n'package: preact-query':\n  - changed-files:\n      - any-glob-to-any-file: 'packages/preact-query/**/*'\n'package: query-async-storage-persister':\n  - changed-files:\n      - any-glob-to-any-file: 'packages/query-async-storage-persister/**/*'\n'package: query-broadcast-client-experimental':\n  - changed-files:\n      - any-glob-to-any-file: 'packages/query-broadcast-client-experimental/**/*'\n'package: query-codemods':\n  - changed-files:\n      - any-glob-to-any-file: 'packages/query-codemods/**/*'\n'package: query-core':\n  - changed-files:\n      - any-glob-to-any-file: 'packages/query-core/**/*'\n'package: query-devtools':\n  - changed-files:\n      - any-glob-to-any-file: 'packages/query-devtools/**/*'\n'package: query-persist-client-core':\n  - changed-files:\n      - any-glob-to-any-file: 'packages/query-persist-client-core/**/*'\n'package: query-sync-storage-persister':\n  - changed-files:\n      - any-glob-to-any-file: 'packages/query-sync-storage-persister/**/*'\n'package: query-test-utils':\n  - changed-files:\n      - any-glob-to-any-file: 'packages/query-test-utils/**/*'\n'package: react-query':\n  - changed-files:\n      - any-glob-to-any-file: 'packages/react-query/**/*'\n'package: react-query-devtools':\n  - changed-files:\n      - any-glob-to-any-file: 'packages/react-query-devtools/**/*'\n'package: react-query-next-experimental':\n  - changed-files:\n      - any-glob-to-any-file: 'packages/react-query-next-experimental/**/*'\n'package: react-query-persist-client':\n  - changed-files:\n      - any-glob-to-any-file: 'packages/react-query-persist-client/**/*'\n'package: solid-query':\n  - changed-files:\n      - any-glob-to-any-file: 'packages/solid-query/**/*'\n'package: solid-query-devtools':\n  - changed-files:\n      - any-glob-to-any-file: 'packages/solid-query-devtools/**/*'\n'package: solid-query-persist-client':\n  - changed-files:\n      - any-glob-to-any-file: 'packages/solid-query-persist-client/**/*'\n'package: svelte-query':\n  - changed-files:\n      - any-glob-to-any-file: 'packages/svelte-query/**/*'\n'package: svelte-query-devtools':\n  - changed-files:\n      - any-glob-to-any-file: 'packages/svelte-query-devtools/**/*'\n'package: svelte-query-persist-client':\n  - changed-files:\n      - any-glob-to-any-file: 'packages/svelte-query-persist-client/**/*'\n'package: vue-query':\n  - changed-files:\n      - any-glob-to-any-file: 'packages/vue-query/**/*'\n'package: vue-query-devtools':\n  - changed-files:\n      - any-glob-to-any-file: 'packages/vue-query-devtools/**/*'\n'documentation':\n  - changed-files:\n      - any-glob-to-any-file: 'docs/**/*'\n"
  },
  {
    "path": "nx.json",
    "content": "{\n  \"$schema\": \"./node_modules/nx/schemas/nx-schema.json\",\n  \"defaultBase\": \"main\",\n  \"nxCloudId\": \"6412c827e6da5d7b4a0b1fe3\",\n  \"useInferencePlugins\": false,\n  \"parallel\": 5,\n  \"namedInputs\": {\n    \"sharedGlobals\": [\n      \"{workspaceRoot}/.nvmrc\",\n      \"{workspaceRoot}/package.json\",\n      \"{workspaceRoot}/scripts/*.js\",\n      \"{workspaceRoot}/tsconfig.json\",\n      \"{workspaceRoot}/eslint.config.js\",\n      \"{workspaceRoot}/pnpm-workspace.yaml\"\n    ],\n    \"default\": [\n      \"sharedGlobals\",\n      \"{projectRoot}/**/*\",\n      \"!{projectRoot}/**/*.md\"\n    ],\n    \"production\": [\n      \"default\",\n      \"!{projectRoot}/tests/**/*\",\n      \"!{projectRoot}/eslint.config.js\"\n    ]\n  },\n  \"targetDefaults\": {\n    \"compile\": {\n      \"cache\": true,\n      \"inputs\": [\"default\", \"^production\"],\n      \"outputs\": [\"{projectRoot}/dist-ts\"]\n    },\n    \"test:docs\": {\n      \"cache\": true,\n      \"inputs\": [\"{workspaceRoot}/docs/**/*\"]\n    },\n    \"test:knip\": {\n      \"cache\": true,\n      \"inputs\": [\"{workspaceRoot}/**/*\"]\n    },\n    \"test:sherif\": {\n      \"cache\": true,\n      \"inputs\": [\"{workspaceRoot}/**/package.json\"]\n    },\n    \"test:size\": {\n      \"cache\": true,\n      \"inputs\": [\n        \"{workspaceRoot}/package.json\",\n        \"{workspaceRoot}/.size-limit.json\"\n      ]\n    },\n    \"test:eslint\": {\n      \"cache\": true,\n      \"dependsOn\": [\"^compile\"],\n      \"inputs\": [\"default\", \"^production\", \"{workspaceRoot}/eslint.config.js\"]\n    },\n    \"test:lib\": {\n      \"cache\": true,\n      \"dependsOn\": [\"^compile\"],\n      \"inputs\": [\"default\", \"^production\"],\n      \"outputs\": [\"{projectRoot}/coverage\"]\n    },\n    \"test:types\": {\n      \"cache\": true,\n      \"inputs\": [\"default\", \"^production\"]\n    },\n    \"build\": {\n      \"cache\": true,\n      \"dependsOn\": [\"^build\"],\n      \"inputs\": [\"production\", \"^production\"],\n      \"outputs\": [\"{projectRoot}/build\", \"{projectRoot}/dist\"]\n    },\n    \"test:build\": {\n      \"cache\": true,\n      \"dependsOn\": [\"build\"],\n      \"inputs\": [\"production\"]\n    }\n  }\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"root\",\n  \"private\": true,\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\"\n  },\n  \"packageManager\": \"pnpm@10.24.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"clean\": \"pnpm --filter \\\"./packages/**\\\" run clean\",\n    \"test\": \"pnpm run test:ci\",\n    \"test:pr\": \"nx affected --targets=test:sherif,test:knip,test:docs,test:eslint,test:lib,test:types,test:build,build\",\n    \"test:ci\": \"nx run-many --targets=test:sherif,test:knip,test:docs,test:eslint,test:lib,test:types,test:build,build\",\n    \"test:eslint\": \"nx affected --target=test:eslint\",\n    \"test:sherif\": \"sherif -i typescript -p \\\"./integrations/*\\\" -p \\\"./examples/*\\\"\",\n    \"test:size\": \"size-limit\",\n    \"test:lib\": \"nx affected --target=test:lib --exclude=examples/**\",\n    \"test:lib:dev\": \"pnpm run test:lib && nx watch --all -- pnpm run test:lib\",\n    \"test:build\": \"nx affected --target=test:build --exclude=examples/**\",\n    \"test:types\": \"nx affected --target=test:types --exclude=examples/**\",\n    \"test:knip\": \"knip\",\n    \"test:docs\": \"node scripts/verify-links.ts\",\n    \"build\": \"nx affected --target=build --exclude=examples/** --exclude=integrations/**\",\n    \"build:all\": \"nx run-many --target=build --exclude=examples/** --exclude=integrations/**\",\n    \"watch\": \"pnpm run build:all && nx watch --all -- pnpm run build:all\",\n    \"dev\": \"pnpm run watch\",\n    \"format\": \"prettier --experimental-cli --ignore-unknown '**/*' --write\",\n    \"generate-docs\": \"node scripts/generate-docs.ts\",\n    \"changeset\": \"changeset\",\n    \"changeset:version\": \"changeset version && pnpm install --no-frozen-lockfile && pnpm format\",\n    \"changeset:publish\": \"changeset publish\"\n  },\n  \"nx\": {\n    \"includedScripts\": [\n      \"test:docs\",\n      \"test:knip\",\n      \"test:sherif\",\n      \"test:size\"\n    ]\n  },\n  \"devDependencies\": {\n    \"@arethetypeswrong/cli\": \"^0.15.3\",\n    \"@changesets/cli\": \"^2.29.8\",\n    \"@cspell/eslint-plugin\": \"^9.2.1\",\n    \"@eslint-react/eslint-plugin\": \"^2.0.1\",\n    \"@size-limit/preset-small-lib\": \"^12.0.0\",\n    \"@svitejs/changesets-changelog-github-compact\": \"^1.2.0\",\n    \"@tanstack/eslint-config\": \"0.3.2\",\n    \"@tanstack/typedoc-config\": \"0.3.1\",\n    \"@tanstack/vite-config\": \"0.4.3\",\n    \"@testing-library/jest-dom\": \"^6.8.0\",\n    \"@types/node\": \"^22.15.3\",\n    \"@types/react\": \"^19.2.7\",\n    \"@types/react-dom\": \"^19.2.3\",\n    \"@vitest/coverage-istanbul\": \"4.0.6\",\n    \"@vitest/eslint-plugin\": \"^1.4.0\",\n    \"esbuild-plugin-file-path-extensions\": \"^2.1.4\",\n    \"eslint\": \"^9.36.0\",\n    \"eslint-plugin-react-hooks\": \"^6.1.1\",\n    \"jsdom\": \"^27.0.0\",\n    \"knip\": \"^5.63.1\",\n    \"markdown-link-extractor\": \"^4.0.2\",\n    \"nx\": \"22.1.3\",\n    \"premove\": \"^4.0.0\",\n    \"prettier\": \"^3.7.4\",\n    \"prettier-plugin-svelte\": \"^3.4.0\",\n    \"publint\": \"^0.3.13\",\n    \"react\": \"^19.2.1\",\n    \"react-dom\": \"^19.2.1\",\n    \"sherif\": \"^1.6.1\",\n    \"size-limit\": \"^12.0.0\",\n    \"tinyglobby\": \"^0.2.15\",\n    \"tsup\": \"^8.4.0\",\n    \"typescript\": \"5.9.3\",\n    \"typescript54\": \"npm:typescript@5.4\",\n    \"typescript55\": \"npm:typescript@5.5\",\n    \"typescript56\": \"npm:typescript@5.6\",\n    \"typescript57\": \"npm:typescript@5.7\",\n    \"typescript58\": \"npm:typescript@5.8\",\n    \"typescript59\": \"npm:typescript@5.9\",\n    \"typescript60\": \"npm:typescript@6.0.1-rc\",\n    \"vite\": \"^6.4.1\",\n    \"vitest\": \"^4.0.18\"\n  },\n  \"pnpm\": {\n    \"overrides\": {\n      \"@types/react\": \"^19.2.7\",\n      \"@types/react-dom\": \"^19.2.3\",\n      \"@types/node\": \"^22.15.3\",\n      \"@typescript-eslint/eslint-plugin\": \"8.56.1\",\n      \"@typescript-eslint/parser\": \"8.56.1\",\n      \"@typescript-eslint/project-service\": \"8.56.1\",\n      \"@typescript-eslint/rule-tester\": \"8.56.1\",\n      \"@typescript-eslint/scope-manager\": \"8.56.1\",\n      \"@typescript-eslint/tsconfig-utils\": \"8.56.1\",\n      \"@typescript-eslint/type-utils\": \"8.56.1\",\n      \"@typescript-eslint/types\": \"8.56.1\",\n      \"@typescript-eslint/typescript-estree\": \"8.56.1\",\n      \"@typescript-eslint/utils\": \"8.56.1\",\n      \"@typescript-eslint/visitor-keys\": \"8.56.1\",\n      \"typescript-eslint\": \"8.56.1\",\n      \"vite\": \"^6.4.1\",\n      \"esbuild\": \"^0.27.2\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/angular-query-experimental/.attw.json",
    "content": "{\n  \"ignoreRules\": [\"cjs-resolves-to-esm\"]\n}\n"
  },
  {
    "path": "packages/angular-query-experimental/CHANGELOG.md",
    "content": "# @tanstack/angular-query-experimental\n\n## 5.90.28\n\n### Patch Changes\n\n- fix(streamedQuery): maintain error state on reset refetch with initialData defined ([#10287](https://github.com/TanStack/query/pull/10287))\n\n- Updated dependencies [[`248975e`](https://github.com/TanStack/query/commit/248975e896f585f6eaa505c796e73fcf7bfd1eec)]:\n  - @tanstack/query-core@5.91.2\n\n## 5.90.27\n\n### Patch Changes\n\n- Updated dependencies [[`a89aab9`](https://github.com/TanStack/query/commit/a89aab975581c25c113a26c8af486b4cafad272a)]:\n  - @tanstack/query-core@5.91.1\n\n## 5.90.26\n\n### Patch Changes\n\n- Updated dependencies [[`6fa901b`](https://github.com/TanStack/query/commit/6fa901b97a22a80d0fca3f6ed86237ff0cbdd13b)]:\n  - @tanstack/query-core@5.91.0\n\n## 5.90.25\n\n## 5.90.24\n\n### Patch Changes\n\n- Updated dependencies [[`e7258c5`](https://github.com/TanStack/query/commit/e7258c5cb30cafa456cdb4e6bc75b43bf619954d)]:\n  - @tanstack/query-core@5.90.20\n\n## 5.90.23\n\n### Patch Changes\n\n- Updated dependencies [[`53fc74e`](https://github.com/TanStack/query/commit/53fc74ebb16730bd3317f039a69c6821386bae93)]:\n  - @tanstack/query-core@5.90.19\n\n## 5.90.22\n\n### Patch Changes\n\n- Updated dependencies [[`dea1614`](https://github.com/TanStack/query/commit/dea1614aaad5c572cf43cea54b64ac09dc4d5b41)]:\n  - @tanstack/query-core@5.90.18\n\n## 5.90.21\n\n### Patch Changes\n\n- Updated dependencies [[`269351b`](https://github.com/TanStack/query/commit/269351b8ce4b4846da3d320ac5b850ee6aada0d6)]:\n  - @tanstack/query-core@5.90.17\n\n## 5.90.20\n\n### Patch Changes\n\n- Updated dependencies [[`7f47906`](https://github.com/TanStack/query/commit/7f47906eaccc3f3aa5ce24b77a83bd7a620a237b)]:\n  - @tanstack/query-core@5.90.16\n\n## 5.90.19\n\n### Patch Changes\n\n- Updated dependencies [[`fccef79`](https://github.com/TanStack/query/commit/fccef797d57d4a9566517bba87c8377f363920f2)]:\n  - @tanstack/query-core@5.90.15\n\n## 5.90.18\n\n### Patch Changes\n\n- Updated dependencies [[`d576092`](https://github.com/TanStack/query/commit/d576092e2ece4ca3936add3eb0da5234c1d82ed4)]:\n  - @tanstack/query-core@5.90.14\n\n## 5.90.17\n\n### Patch Changes\n\n- Updated dependencies [[`4a0a78a`](https://github.com/TanStack/query/commit/4a0a78afbc2432f8cb6828035965853fa98c86a0)]:\n  - @tanstack/query-core@5.90.13\n\n## 5.90.16\n\n### Patch Changes\n\n- Updated dependencies [[`72d8ac5`](https://github.com/TanStack/query/commit/72d8ac5c592004b8f9c3ee086fcb9c3cd615ca05)]:\n  - @tanstack/query-core@5.90.12\n\n## 5.90.15\n\n### Patch Changes\n\n- Updated dependencies [[`c01b150`](https://github.com/TanStack/query/commit/c01b150e3673e11d6533768529a5e6fe3ebee68c)]:\n  - @tanstack/query-core@5.90.11\n\n## 5.90.14\n\n## 5.90.13\n\n## 5.90.12\n\n### Patch Changes\n\n- Updated dependencies [[`8e2e174`](https://github.com/TanStack/query/commit/8e2e174e9fd2e7b94cd232041e49c9d014d74e26), [`eb559a6`](https://github.com/TanStack/query/commit/eb559a66dc0d77dd46435f624fa64fc068bef9ae)]:\n  - @tanstack/query-core@5.90.10\n\n## 5.90.11\n\n### Patch Changes\n\n- Updated dependencies [[`08b211f`](https://github.com/TanStack/query/commit/08b211f8aa475e05d2f13a36517fc556861ef962)]:\n  - @tanstack/query-core@5.90.9\n\n## 5.90.10\n\n### Patch Changes\n\n- Updated dependencies [[`c0ec9fe`](https://github.com/TanStack/query/commit/c0ec9fe0d1426fe3f233adda3ebf23989ffaa110)]:\n  - @tanstack/query-core@5.90.8\n\n## 5.90.9\n\n### Patch Changes\n\n- Updated dependencies [[`b4cd121`](https://github.com/TanStack/query/commit/b4cd121a39d07cefaa3a3411136d342cc54ce8fb)]:\n  - @tanstack/query-core@5.90.7\n\n## 5.90.8\n\n### Patch Changes\n\n- Updated dependencies [[`1638c02`](https://github.com/TanStack/query/commit/1638c028df55648995d04431179904371a189772)]:\n  - @tanstack/query-core@5.90.6\n\n## 5.90.7\n\n### Patch Changes\n\n- Make `injectIsMutating` signal read-only to prevent external modifications to the internal state ([#9801](https://github.com/TanStack/query/pull/9801))\n\n## 5.90.6\n\n### Patch Changes\n\n- Rename `DeveloperToolsFeature` to `DevtoolsFeature` for consistency with internal naming conventions and ecosystem ([#9794](https://github.com/TanStack/query/pull/9794))\n\n## 5.90.5\n\n### Patch Changes\n\n- Updated dependencies [[`e42ddfe`](https://github.com/TanStack/query/commit/e42ddfe919f34f847ca101aeef162c69845f9a1e)]:\n  - @tanstack/query-core@5.90.5\n\n## 5.90.4\n\n### Patch Changes\n\n- Updated dependencies [[`20ef922`](https://github.com/TanStack/query/commit/20ef922a0a7c3aee00150bf69123c338b0922922)]:\n  - @tanstack/query-core@5.90.4\n\n## 5.90.3\n\n### Patch Changes\n\n- Updated dependencies [[`4e1c433`](https://github.com/TanStack/query/commit/4e1c4338a72f7384600bbda99e44bc1891695df4)]:\n  - @tanstack/query-core@5.90.3\n"
  },
  {
    "path": "packages/angular-query-experimental/README.md",
    "content": "![TanStack Query Header](https://github.com/TanStack/query/raw/main/media/repo-header.png)\n\n[![npm version](https://img.shields.io/npm/v/@tanstack/angular-query-experimental)](https://www.npmjs.com/package/@tanstack/angular-query-experimental)\n[![npm license](https://img.shields.io/npm/l/@tanstack/angular-query-experimental)](https://github.com/TanStack/query/blob/main/LICENSE)\n[![bundle size](https://img.shields.io/bundlephobia/minzip/@tanstack/angular-query-experimental)](https://bundlephobia.com/package/@tanstack/angular-query-experimental)\n[![npm](https://img.shields.io/npm/dm/@tanstack/angular-query-experimental)](https://www.npmjs.com/package/@tanstack/angular-query-experimental)\n\n# Angular Query\n\n> IMPORTANT: This library is currently in an experimental stage. This means that breaking changes may happen in minor AND patch releases. Upgrade carefully. If you use this in production while in experimental stage, please lock your version to a patch-level version to avoid unexpected breaking changes.\n\nFunctions for fetching, caching and updating asynchronous data in Angular\n\n# Documentation\n\nVisit https://tanstack.com/query/latest/docs/framework/angular/overview\n\n## Quick Features\n\n- Transport/protocol/backend agnostic data fetching (REST, GraphQL, promises, whatever!)\n- Auto Caching + Refetching (stale-while-revalidate, Window Refocus, Polling/Realtime)\n- Parallel + Dependent Queries\n- Mutations + Reactive Query Refetching\n- Multi-layer Cache + Automatic Garbage Collection\n- Paginated + Cursor-based Queries\n- Load-More + Infinite Scroll Queries w/ Scroll Recovery\n- Request Cancellation\n- Dedicated Devtools\n\n# Quick Start\n\n> The Angular adapter for TanStack Query requires Angular 16 or higher.\n\n1. Install `angular-query`\n\n```bash\n$ npm i @tanstack/angular-query-experimental\n```\n\nor\n\n```bash\n$ pnpm add @tanstack/angular-query-experimental\n```\n\nor\n\n```bash\n$ yarn add @tanstack/angular-query-experimental\n```\n\nor\n\n```bash\n$ bun add @tanstack/angular-query-experimental\n```\n\n2. Initialize **TanStack Query** by adding **provideTanStackQuery** to your application\n\n```ts\nimport { provideTanStackQuery } from '@tanstack/angular-query-experimental'\nimport { QueryClient } from '@tanstack/angular-query-experimental'\n\nbootstrapApplication(AppComponent, {\n  providers: [provideTanStackQuery(new QueryClient())],\n})\n```\n\nor in a NgModule-based app\n\n```ts\nimport { provideHttpClient } from '@angular/common/http'\nimport {\n  provideTanStackQuery,\n  QueryClient,\n} from '@tanstack/angular-query-experimental'\n\n@NgModule({\n  declarations: [AppComponent],\n  imports: [BrowserModule],\n  providers: [provideTanStackQuery(new QueryClient())],\n  bootstrap: [AppComponent],\n})\n```\n\n3. Inject query\n\n```ts\nimport { injectQuery } from '@tanstack/angular-query-experimental'\nimport { Component } from '@angular/core'\n\n@Component({...})\nexport class TodosComponent {\n  info = injectQuery(() => ({ queryKey: ['todos'], queryFn: fetchTodoList }))\n}\n```\n\n4. If you need to update options on your query dynamically, make sure to pass them as signals. The query will refetch automatically if data for an updated query key is stale or not present.\n\n[Open in StackBlitz](https://stackblitz.com/github/TanStack/query/tree/main/examples/angular/router)\n\n```ts\n@Component({})\nexport class PostComponent {\n  #postsService = inject(PostsService)\n  postId = input.required({\n    transform: numberAttribute,\n  })\n\n  postQuery = injectQuery(() => ({\n    queryKey: ['post', this.postId()],\n    queryFn: () => {\n      return lastValueFrom(this.#postsService.postById$(this.postId()))\n    },\n  }))\n}\n\n@Injectable({\n  providedIn: 'root',\n})\nexport class PostsService {\n  #http = inject(HttpClient)\n\n  postById$ = (postId: number) =>\n    this.#http.get<Post>(`https://jsonplaceholder.typicode.com/posts/${postId}`)\n}\n\nexport interface Post {\n  id: number\n  title: string\n  body: string\n}\n```\n\n<!-- -->\n"
  },
  {
    "path": "packages/angular-query-experimental/eslint.config.js",
    "content": "// @ts-check\n\nimport vitest from '@vitest/eslint-plugin'\nimport rootConfig from './root.eslint.config.js'\n\nexport default [\n  ...rootConfig,\n  {\n    plugins: { vitest },\n    rules: {\n      'vitest/expect-expect': [\n        'error',\n        { assertFunctionNames: ['expect', 'expectSignals'] },\n      ],\n    },\n  },\n  {\n    files: ['**/__tests__/**'],\n    rules: {\n      '@typescript-eslint/no-unnecessary-condition': 'off',\n      '@typescript-eslint/require-await': 'off',\n    },\n  },\n]\n"
  },
  {
    "path": "packages/angular-query-experimental/package.json",
    "content": "{\n  \"name\": \"@tanstack/angular-query-experimental\",\n  \"version\": \"5.90.28\",\n  \"description\": \"Signals for managing, caching and syncing asynchronous and remote data in Angular\",\n  \"author\": \"Arnoud de Vries\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/angular-query-experimental\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"keywords\": [\n    \"angular query\",\n    \"angular\",\n    \"cache\",\n    \"performance\",\n    \"reactive\",\n    \"rxjs\",\n    \"signals\",\n    \"state management\",\n    \"state\",\n    \"tanstack\"\n  ],\n  \"scripts\": {\n    \"clean\": \"premove ./dist ./coverage ./dist-ts\",\n    \"compile\": \"tsc --build\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:types\": \"npm-run-all --serial test:types:*\",\n    \"test:types:ts54\": \"node ../../node_modules/typescript54/lib/tsc.js --build\",\n    \"test:types:ts55\": \"node ../../node_modules/typescript55/lib/tsc.js --build\",\n    \"test:types:ts56\": \"node ../../node_modules/typescript56/lib/tsc.js --build\",\n    \"test:types:ts57\": \"node ../../node_modules/typescript57/lib/tsc.js --build\",\n    \"test:types:ts58\": \"node ../../node_modules/typescript58/lib/tsc.js --build\",\n    \"test:types:ts59\": \"node ../../node_modules/typescript59/lib/tsc.js --build\",\n    \"test:types:tscurrent\": \"tsc --build\",\n    \"test:types:ts60\": \"node ../../node_modules/typescript60/lib/tsc.js --build\",\n    \"test:lib\": \"vitest\",\n    \"test:lib:dev\": \"pnpm run test:lib --watch\",\n    \"test:build\": \"pnpm pack && publint ./dist/*.tgz --strict && attw ./dist/*.tgz; premove ./dist/*.tgz\",\n    \"build\": \"vite build\",\n    \"prepack\": \"node scripts/prepack.js\"\n  },\n  \"type\": \"module\",\n  \"types\": \"dist/index.d.ts\",\n  \"module\": \"dist/index.mjs\",\n  \"exports\": {\n    \".\": {\n      \"@tanstack/custom-condition\": \"./src/index.ts\",\n      \"types\": \"./dist/index.d.ts\",\n      \"default\": \"./dist/index.mjs\"\n    },\n    \"./package.json\": \"./package.json\",\n    \"./inject-queries-experimental\": {\n      \"types\": \"./dist/inject-queries-experimental/index.d.ts\",\n      \"default\": \"./dist/inject-queries-experimental/index.mjs\"\n    },\n    \"./devtools\": {\n      \"types\": \"./dist/devtools/index.d.ts\",\n      \"development\": \"./dist/devtools/index.mjs\",\n      \"default\": \"./dist/devtools/stub.mjs\"\n    },\n    \"./devtools/production\": {\n      \"types\": \"./dist/devtools/production/index.d.ts\",\n      \"default\": \"./dist/devtools/index.mjs\"\n    },\n    \"./devtools-panel\": {\n      \"types\": \"./dist/devtools-panel/index.d.ts\",\n      \"development\": \"./dist/devtools-panel/index.mjs\",\n      \"default\": \"./dist/devtools-panel/stub.mjs\"\n    },\n    \"./devtools-panel/production\": {\n      \"types\": \"./dist/devtools-panel/production/index.d.ts\",\n      \"default\": \"./dist/devtools-panel/index.mjs\"\n    }\n  },\n  \"sideEffects\": false,\n  \"files\": [\n    \"**/*.d.ts\",\n    \"**/*.mjs\",\n    \"**/*.mjs.map\"\n  ],\n  \"dependencies\": {\n    \"@tanstack/query-core\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"@angular/common\": \"^20.0.0\",\n    \"@angular/compiler\": \"^20.0.0\",\n    \"@angular/core\": \"^20.0.0\",\n    \"@angular/platform-browser\": \"^20.0.0\",\n    \"@tanstack/query-test-utils\": \"workspace:*\",\n    \"@testing-library/angular\": \"^18.0.0\",\n    \"npm-run-all2\": \"^5.0.0\",\n    \"rxjs\": \"^7.8.2\",\n    \"vite-plugin-dts\": \"4.2.3\",\n    \"vite-plugin-externalize-deps\": \"^0.9.0\",\n    \"vite-tsconfig-paths\": \"^5.1.4\"\n  },\n  \"optionalDependencies\": {\n    \"@tanstack/query-devtools\": \"workspace:*\"\n  },\n  \"peerDependencies\": {\n    \"@angular/common\": \">=16.0.0\",\n    \"@angular/core\": \">=16.0.0\"\n  },\n  \"publishConfig\": {\n    \"directory\": \"dist\",\n    \"linkDirectory\": false\n  }\n}\n"
  },
  {
    "path": "packages/angular-query-experimental/scripts/prepack.js",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\n\n/**\n * Prepack script that prepares the package for publishing by:\n * 1. Creating a modified package.json without dev dependencies, publishConfig and build scripts\n * 2. Updating file paths to remove 'dist/' prefixes (since files will be at root in published package)\n * 3. Writing this modified package.json to the `dist` directory\n * 4. Copying additional files like README.md to the dist directory\n *\n * Type declarations need to be in the package root or corresponding sub-path to support\n * sub-path exports in applications still using `moduleResolution: node`.\n */\n\nconsole.log('Running prepack script')\n\n/**\n * Files to copy to the dist directory\n * @type {string[]}\n */\nconst FILES_TO_COPY = ['README.md']\n\n/**\n * Fields to remove from the package.json copy\n * @type {string[]}\n */\nconst FIELDS_TO_REMOVE = [\n  'devDependencies',\n  'files',\n  'publishConfig',\n  'scripts',\n]\n\n/**\n * Replaces 'dist/' or './dist/' prefix from a file path with './'\n * Only matches at the start of the path to avoid false matches\n * @param {string} filePath - The file path to process\n * @returns {string} The path without dist prefix\n */\nfunction replaceDist(filePath) {\n  // Only match dist/ at the beginning of the path, followed by a filename\n  // This prevents matching strings like \"distributed/file.js\" or \"some/dist/path\"\n  return filePath.replace(/^(?:\\.\\/)?dist\\/(?=.+)/, './')\n}\n\n/**\n * Recursively processes package.json `exports` to remove dist prefixes\n * @param {Record<string, any>} exports - The exports object to process\n * @returns {Record<string, any>} The processed exports object\n */\nfunction processExports(exports) {\n  return Object.fromEntries(\n    Object.entries(exports).map(([key, value]) => [\n      key,\n      typeof value === 'string'\n        ? replaceDist(value)\n        : typeof value === 'object' && value !== null\n          ? processExports(value)\n          : value,\n    ]),\n  )\n}\n\nconsole.log('Copying modified package.json')\n\n/** @type {Record<string, any>} */\nconst packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'))\n\nconst modifiedPackageJson = { ...packageJson }\n\nif (modifiedPackageJson.types) {\n  modifiedPackageJson.types = replaceDist(modifiedPackageJson.types)\n}\n\nif (modifiedPackageJson.module) {\n  modifiedPackageJson.module = replaceDist(modifiedPackageJson.module)\n}\n\nif (modifiedPackageJson.exports) {\n  modifiedPackageJson.exports = processExports(modifiedPackageJson.exports)\n}\n\nfor (const field of FIELDS_TO_REMOVE) {\n  delete modifiedPackageJson[field]\n}\n\nif (!fs.existsSync('dist')) {\n  fs.mkdirSync('dist', { recursive: true })\n}\n\nfs.writeFileSync(\n  path.join('dist', 'package.json'),\n  JSON.stringify(modifiedPackageJson, null, 2),\n)\n\nconsole.log('Copying other files')\nfor (const file of FILES_TO_COPY) {\n  if (fs.existsSync(file)) {\n    fs.copyFileSync(file, path.join('dist', file))\n    console.log(`${file}`)\n  } else {\n    console.log(`${file} not found, skipping`)\n  }\n}\n\nconsole.log('prepack complete')\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/infinite-query-options.test-d.ts",
    "content": "import { assertType, describe, expectTypeOf, it, test } from 'vitest'\nimport { QueryClient, dataTagSymbol } from '@tanstack/query-core'\nimport { infiniteQueryOptions } from '../infinite-query-options'\nimport { injectInfiniteQuery } from '../inject-infinite-query'\nimport { injectQuery } from '../inject-query'\nimport type {\n  DataTag,\n  InfiniteData,\n  InitialDataFunction,\n} from '@tanstack/query-core'\n\ndescribe('infiniteQueryOptions', () => {\n  it('should not allow excess properties', () => {\n    assertType(\n      infiniteQueryOptions({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve('data'),\n        getNextPageParam: () => 1,\n        initialPageParam: 1,\n        // @ts-expect-error this is a good error, because stallTime does not exist!\n        stallTime: 1000,\n      }),\n    )\n  })\n  it('should infer types for callbacks', () => {\n    infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('data'),\n      staleTime: 1000,\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n      select: (data) => {\n        expectTypeOf(data).toEqualTypeOf<InfiniteData<string, number>>()\n      },\n    })\n  })\n  it('should work when passed to useInfiniteQuery', () => {\n    const options = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    const { data } = injectInfiniteQuery(() => options)\n\n    // known issue: type of pageParams is unknown when returned from useInfiniteQuery\n    expectTypeOf(data()).toEqualTypeOf<\n      InfiniteData<string, unknown> | undefined\n    >()\n  })\n\n  it('should work when passed to fetchInfiniteQuery', async () => {\n    const options = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    const data = await new QueryClient().fetchInfiniteQuery(options)\n\n    expectTypeOf(data).toEqualTypeOf<InfiniteData<string, number>>()\n  })\n  it('should tag the queryKey with the result type of the QueryFn', () => {\n    const { queryKey } = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<InfiniteData<string>>()\n  })\n  it('should tag the queryKey even if no promise is returned', () => {\n    const { queryKey } = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => 'string',\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<InfiniteData<string>>()\n  })\n  it('should tag the queryKey with the result type of the QueryFn if select is used', () => {\n    const { queryKey } = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      select: (data) => data.pages,\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<InfiniteData<string>>()\n  })\n  it('should return the proper type when passed to getQueryData', () => {\n    const { queryKey } = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryData(queryKey)\n\n    expectTypeOf(data).toEqualTypeOf<\n      InfiniteData<string, unknown> | undefined\n    >()\n  })\n  it('should properly type when passed to setQueryData', () => {\n    const { queryKey } = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.setQueryData(queryKey, (prev) => {\n      expectTypeOf(prev).toEqualTypeOf<\n        InfiniteData<string, unknown> | undefined\n      >()\n      return prev\n    })\n\n    expectTypeOf(data).toEqualTypeOf<\n      InfiniteData<string, unknown> | undefined\n    >()\n  })\n\n  test('should not be allowed to be passed to non-infinite query functions', () => {\n    const queryClient = new QueryClient()\n    const options = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n    assertType(\n      // @ts-expect-error cannot pass infinite options to non-infinite query functions\n      injectQuery(() => options),\n    )\n    assertType(\n      // @ts-expect-error cannot pass infinite options to non-infinite query functions\n      queryClient.ensureQueryData(options),\n    )\n    assertType(\n      // @ts-expect-error cannot pass infinite options to non-infinite query functions\n      queryClient.fetchQuery(options),\n    )\n    assertType(\n      // @ts-expect-error cannot pass infinite options to non-infinite query functions\n      queryClient.prefetchQuery(options),\n    )\n  })\n\n  test('allow optional initialData function', () => {\n    const initialData: { example: boolean } | undefined = { example: true }\n    const queryOptions = infiniteQueryOptions({\n      queryKey: ['example'],\n      queryFn: () => initialData,\n      initialData: initialData\n        ? () => ({ pages: [initialData], pageParams: [] })\n        : undefined,\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n    expectTypeOf(queryOptions.initialData).toMatchTypeOf<\n      | InitialDataFunction<InfiniteData<{ example: boolean }, number>>\n      | InfiniteData<{ example: boolean }, number>\n      | undefined\n    >()\n  })\n\n  test('allow optional initialData object', () => {\n    const initialData: { example: boolean } | undefined = { example: true }\n    const queryOptions = infiniteQueryOptions({\n      queryKey: ['example'],\n      queryFn: () => initialData,\n      initialData: initialData\n        ? { pages: [initialData], pageParams: [] }\n        : undefined,\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n    expectTypeOf(queryOptions.initialData).toMatchTypeOf<\n      | InitialDataFunction<InfiniteData<{ example: boolean }, number>>\n      | InfiniteData<{ example: boolean }, number>\n      | undefined\n    >()\n  })\n\n  it('should return a custom query key type', () => {\n    type MyQueryKey = [Array<string>, { type: 'foo' }]\n\n    const options = infiniteQueryOptions({\n      queryKey: [['key'], { type: 'foo' }] as MyQueryKey,\n      queryFn: () => Promise.resolve(1),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    expectTypeOf(options.queryKey).toEqualTypeOf<\n      DataTag<MyQueryKey, InfiniteData<number>, Error>\n    >()\n  })\n\n  it('should return a custom query key type with datatag', () => {\n    type MyQueryKey = DataTag<\n      [Array<string>, { type: 'foo' }],\n      number,\n      Error & { myMessage: string }\n    >\n\n    const options = infiniteQueryOptions({\n      queryKey: [['key'], { type: 'foo' }] as MyQueryKey,\n      queryFn: () => Promise.resolve(1),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    expectTypeOf(options.queryKey).toEqualTypeOf<\n      DataTag<MyQueryKey, InfiniteData<number>, Error & { myMessage: string }>\n    >()\n  })\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/infinite-query-options.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\n\nimport { infiniteQueryOptions } from '../infinite-query-options'\nimport type { CreateInfiniteQueryOptions } from '../types'\n\ndescribe('infiniteQueryOptions', () => {\n  it('should return the object received as a parameter without any modification.', () => {\n    const object: CreateInfiniteQueryOptions = {\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n      getNextPageParam: () => null,\n      initialPageParam: null,\n    }\n\n    expect(infiniteQueryOptions(object)).toBe(object)\n  })\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/inject-devtools-panel.test.ts",
    "content": "import {\n  ElementRef,\n  provideZonelessChangeDetection,\n  signal,\n} from '@angular/core'\nimport { TestBed } from '@angular/core/testing'\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { QueryClient } from '@tanstack/query-core'\nimport { provideTanStackQuery } from '../providers'\nimport { injectDevtoolsPanel } from '../devtools-panel'\n\nconst mockDevtoolsPanelInstance = {\n  mount: vi.fn(),\n  unmount: vi.fn(),\n  setClient: vi.fn(),\n  setErrorTypes: vi.fn(),\n  setOnClose: vi.fn(),\n}\n\nconst mocks = vi.hoisted(() => {\n  function MockTanstackQueryDevtoolsPanel() {\n    return mockDevtoolsPanelInstance\n  }\n\n  return {\n    mockTanstackQueryDevtoolsPanel: vi.fn(MockTanstackQueryDevtoolsPanel),\n  }\n})\n\nvi.mock('@tanstack/query-devtools', () => ({\n  TanstackQueryDevtoolsPanel: mocks.mockTanstackQueryDevtoolsPanel,\n}))\n\ndescribe('injectDevtoolsPanel', () => {\n  let queryClient: QueryClient\n  let mockElementRef: ElementRef\n\n  const waitForDevtoolsToBeCreated = async () => {\n    await vi.waitFor(() => {\n      expect(mocks.mockTanstackQueryDevtoolsPanel).toHaveBeenCalledTimes(1)\n    })\n  }\n\n  beforeEach(() => {\n    vi.clearAllMocks()\n    queryClient = new QueryClient()\n    mockElementRef = new ElementRef(document.createElement('div'))\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(queryClient),\n        { provide: ElementRef, useValue: signal(mockElementRef) },\n      ],\n    })\n  })\n\n  afterEach(() => {\n    vi.restoreAllMocks()\n  })\n\n  it('should return a DevtoolsPanelRef', () => {\n    const result = TestBed.runInInjectionContext(() => {\n      return injectDevtoolsPanel(() => ({\n        hostElement: TestBed.inject(ElementRef),\n      }))\n    })\n\n    expect(result).toEqual({\n      destroy: expect.any(Function),\n    })\n  })\n\n  it('should initialize TanstackQueryDevtoolsPanel', async () => {\n    TestBed.runInInjectionContext(() => {\n      injectDevtoolsPanel(() => ({\n        hostElement: TestBed.inject(ElementRef),\n      }))\n    })\n\n    TestBed.tick()\n\n    await waitForDevtoolsToBeCreated()\n\n    expect(mockDevtoolsPanelInstance.mount).toHaveBeenCalledTimes(1)\n  })\n\n  it('should destroy TanstackQueryDevtoolsPanel', async () => {\n    const result = TestBed.runInInjectionContext(() => {\n      return injectDevtoolsPanel(() => ({\n        hostElement: TestBed.inject(ElementRef),\n      }))\n    })\n\n    TestBed.tick()\n\n    await waitForDevtoolsToBeCreated()\n\n    result.destroy()\n\n    expect(mockDevtoolsPanelInstance.unmount).toHaveBeenCalledTimes(1)\n  })\n\n  it('should destroy TanstackQueryDevtoolsPanel when hostElement is removed', async () => {\n    const hostElement = signal<ElementRef>(mockElementRef)\n\n    TestBed.runInInjectionContext(() => {\n      return injectDevtoolsPanel(() => ({\n        hostElement: hostElement(),\n      }))\n    })\n\n    TestBed.tick()\n\n    await waitForDevtoolsToBeCreated()\n\n    expect(mockDevtoolsPanelInstance.unmount).toHaveBeenCalledTimes(0)\n\n    hostElement.set(null as unknown as ElementRef)\n\n    TestBed.tick()\n\n    expect(mockDevtoolsPanelInstance.unmount).toHaveBeenCalledTimes(1)\n  })\n\n  it('should update client', async () => {\n    const client = signal(new QueryClient())\n\n    TestBed.runInInjectionContext(() => {\n      return injectDevtoolsPanel(() => ({\n        hostElement: TestBed.inject(ElementRef),\n        client: client(),\n      }))\n    })\n\n    TestBed.tick()\n\n    await waitForDevtoolsToBeCreated()\n\n    expect(mockDevtoolsPanelInstance.setClient).toHaveBeenCalledTimes(0)\n\n    client.set(new QueryClient())\n\n    TestBed.tick()\n\n    expect(mockDevtoolsPanelInstance.setClient).toHaveBeenCalledTimes(1)\n  })\n\n  it('should update error types', async () => {\n    const errorTypes = signal([])\n\n    TestBed.runInInjectionContext(() => {\n      return injectDevtoolsPanel(() => ({\n        hostElement: TestBed.inject(ElementRef),\n        errorTypes: errorTypes(),\n      }))\n    })\n\n    TestBed.tick()\n\n    await waitForDevtoolsToBeCreated()\n\n    expect(mockDevtoolsPanelInstance.setErrorTypes).toHaveBeenCalledTimes(0)\n\n    errorTypes.set([])\n\n    TestBed.tick()\n\n    expect(mockDevtoolsPanelInstance.setErrorTypes).toHaveBeenCalledTimes(1)\n  })\n\n  it('should update onclose', async () => {\n    const functionA = () => {}\n    const functionB = () => {}\n\n    const onClose = signal(functionA)\n\n    TestBed.runInInjectionContext(() => {\n      return injectDevtoolsPanel(() => ({\n        hostElement: TestBed.inject(ElementRef),\n        onClose: onClose(),\n      }))\n    })\n\n    TestBed.tick()\n\n    await waitForDevtoolsToBeCreated()\n\n    expect(mockDevtoolsPanelInstance.setOnClose).toHaveBeenCalledTimes(0)\n\n    onClose.set(functionB)\n\n    TestBed.tick()\n\n    expect(mockDevtoolsPanelInstance.setOnClose).toHaveBeenCalledTimes(1)\n  })\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/inject-infinite-query.test-d.ts",
    "content": "import { TestBed } from '@angular/core/testing'\nimport { afterEach, beforeEach, describe, expectTypeOf, test, vi } from 'vitest'\nimport { provideZonelessChangeDetection } from '@angular/core'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { QueryClient, injectInfiniteQuery, provideTanStackQuery } from '..'\nimport type { InfiniteData } from '@tanstack/query-core'\n\ndescribe('injectInfiniteQuery', () => {\n  let queryClient: QueryClient\n\n  beforeEach(() => {\n    queryClient = new QueryClient()\n    vi.useFakeTimers()\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(queryClient),\n      ],\n    })\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('should narrow type after isSuccess', () => {\n    const query = TestBed.runInInjectionContext(() => {\n      return injectInfiniteQuery(() => ({\n        queryKey: ['infiniteQuery'],\n        queryFn: ({ pageParam }) =>\n          sleep(0).then(() => 'data on page ' + pageParam),\n        initialPageParam: 0,\n        getNextPageParam: () => 12,\n      }))\n    })\n\n    if (query.isSuccess()) {\n      const data = query.data()\n      expectTypeOf(data).toEqualTypeOf<InfiniteData<string, unknown>>()\n    }\n  })\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/inject-infinite-query.test.ts",
    "content": "import { TestBed } from '@angular/core/testing'\nimport { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { Injector, provideZonelessChangeDetection } from '@angular/core'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { QueryClient, injectInfiniteQuery, provideTanStackQuery } from '..'\nimport { expectSignals } from './test-utils'\n\ndescribe('injectInfiniteQuery', () => {\n  let queryClient: QueryClient\n\n  beforeEach(() => {\n    queryClient = new QueryClient()\n    vi.useFakeTimers()\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(queryClient),\n      ],\n    })\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('should properly execute infinite query', async () => {\n    const query = TestBed.runInInjectionContext(() => {\n      return injectInfiniteQuery(() => ({\n        queryKey: ['infiniteQuery'],\n        queryFn: ({ pageParam }) =>\n          sleep(10).then(() => 'data on page ' + pageParam),\n        initialPageParam: 0,\n        getNextPageParam: () => 12,\n      }))\n    })\n\n    expectSignals(query, {\n      data: undefined,\n      status: 'pending',\n    })\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expectSignals(query, {\n      data: {\n        pageParams: [0],\n        pages: ['data on page 0'],\n      },\n      status: 'success',\n    })\n\n    void query.fetchNextPage()\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expectSignals(query, {\n      data: {\n        pageParams: [0, 12],\n        pages: ['data on page 0', 'data on page 12'],\n      },\n      status: 'success',\n    })\n  })\n\n  describe('injection context', () => {\n    test('throws NG0203 with descriptive error outside injection context', () => {\n      expect(() => {\n        injectInfiniteQuery(() => ({\n          queryKey: ['injectionContextError'],\n          queryFn: ({ pageParam }) =>\n            sleep(0).then(() => 'data on page ' + pageParam),\n          initialPageParam: 0,\n          getNextPageParam: () => 12,\n        }))\n      }).toThrowError(/NG0203(.*?)injectInfiniteQuery/)\n    })\n\n    test('can be used outside injection context when passing an injector', () => {\n      const query = injectInfiniteQuery(\n        () => ({\n          queryKey: ['manualInjector'],\n          queryFn: ({ pageParam }) =>\n            sleep(0).then(() => 'data on page ' + pageParam),\n          initialPageParam: 0,\n          getNextPageParam: () => 12,\n        }),\n        {\n          injector: TestBed.inject(Injector),\n        },\n      )\n\n      expect(query.status()).toBe('pending')\n    })\n  })\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/inject-is-fetching.test.ts",
    "content": "import { TestBed } from '@angular/core/testing'\nimport { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { Injector, provideZonelessChangeDetection } from '@angular/core'\nimport { sleep } from '@tanstack/query-test-utils'\nimport {\n  QueryClient,\n  injectIsFetching,\n  injectQuery,\n  provideTanStackQuery,\n} from '..'\n\ndescribe('injectIsFetching', () => {\n  let queryClient: QueryClient\n\n  beforeEach(() => {\n    vi.useFakeTimers()\n    queryClient = new QueryClient()\n\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(queryClient),\n      ],\n    })\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('Returns number of fetching queries', async () => {\n    const isFetching = TestBed.runInInjectionContext(() => {\n      injectQuery(() => ({\n        queryKey: ['isFetching1'],\n        queryFn: () => sleep(100).then(() => 'Some data'),\n      }))\n      return injectIsFetching()\n    })\n\n    expect(isFetching()).toStrictEqual(0)\n    await vi.advanceTimersByTimeAsync(1)\n    expect(isFetching()).toStrictEqual(1)\n    await vi.advanceTimersByTimeAsync(100)\n    expect(isFetching()).toStrictEqual(0)\n  })\n\n  describe('injection context', () => {\n    test('throws NG0203 with descriptive error outside injection context', () => {\n      expect(() => {\n        injectIsFetching()\n      }).toThrowError(/NG0203(.*?)injectIsFetching/)\n    })\n\n    test('can be used outside injection context when passing an injector', () => {\n      expect(\n        injectIsFetching(undefined, {\n          injector: TestBed.inject(Injector),\n        }),\n      ).not.toThrow()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/inject-is-mutating.test.ts",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { TestBed } from '@angular/core/testing'\nimport { Injector, provideZonelessChangeDetection } from '@angular/core'\nimport { sleep } from '@tanstack/query-test-utils'\nimport {\n  QueryClient,\n  injectIsMutating,\n  injectMutation,\n  provideTanStackQuery,\n} from '..'\n\ndescribe('injectIsMutating', () => {\n  let queryClient: QueryClient\n\n  beforeEach(() => {\n    vi.useFakeTimers()\n    queryClient = new QueryClient()\n\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(queryClient),\n      ],\n    })\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('should properly return isMutating state', async () => {\n    const [mutation, isMutating] = TestBed.runInInjectionContext(() => [\n      injectMutation(() => ({\n        mutationKey: ['isMutating1'],\n        mutationFn: (params: { par1: string }) => sleep(10).then(() => params),\n      })),\n      injectIsMutating(),\n    ])\n\n    expect(isMutating()).toBe(0)\n\n    mutation.mutate({\n      par1: 'par1',\n    })\n\n    expect(isMutating()).toBe(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isMutating()).toBe(1)\n    await vi.advanceTimersByTimeAsync(11)\n    expect(isMutating()).toBe(0)\n  })\n\n  describe('injection context', () => {\n    test('throws NG0203 with descriptive error outside injection context', () => {\n      expect(() => {\n        injectIsMutating()\n      }).toThrowError(/NG0203(.*?)injectIsMutating/)\n    })\n\n    test('can be used outside injection context when passing an injector', () => {\n      expect(\n        injectIsMutating(undefined, {\n          injector: TestBed.inject(Injector),\n        }),\n      ).not.toThrow()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/inject-is-restoring.test.ts",
    "content": "import { TestBed } from '@angular/core/testing'\nimport { describe, expect, test } from 'vitest'\nimport { Injector, provideZonelessChangeDetection, signal } from '@angular/core'\nimport {\n  QueryClient,\n  injectIsRestoring,\n  provideIsRestoring,\n  provideTanStackQuery,\n} from '..'\n\ndescribe('injectIsRestoring', () => {\n  let queryClient: QueryClient\n\n  test('returns false by default when provideIsRestoring is not used', () => {\n    queryClient = new QueryClient()\n\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(queryClient),\n      ],\n    })\n\n    const isRestoring = TestBed.runInInjectionContext(() => {\n      return injectIsRestoring()\n    })\n\n    expect(isRestoring()).toBe(false)\n  })\n\n  test('returns provided signal value when provideIsRestoring is used', () => {\n    queryClient = new QueryClient()\n    const restoringSignal = signal(true)\n\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(queryClient),\n        provideIsRestoring(restoringSignal.asReadonly()),\n      ],\n    })\n\n    const isRestoring = TestBed.runInInjectionContext(() => {\n      return injectIsRestoring()\n    })\n\n    expect(isRestoring()).toBe(true)\n  })\n\n  test('can be used outside injection context when passing an injector', () => {\n    queryClient = new QueryClient()\n\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(queryClient),\n      ],\n    })\n\n    const isRestoring = injectIsRestoring({\n      injector: TestBed.inject(Injector),\n    })\n\n    expect(isRestoring()).toBe(false)\n  })\n\n  test('throws NG0203 with descriptive error outside injection context', () => {\n    expect(() => {\n      injectIsRestoring()\n    }).toThrowError(/NG0203(.*?)injectIsRestoring/)\n  })\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/inject-mutation-state.test-d.ts",
    "content": "import { describe, expectTypeOf, it } from 'vitest'\nimport { injectMutationState } from '..'\nimport type { MutationState, MutationStatus } from '..'\n\ndescribe('injectMutationState', () => {\n  it('should default to QueryState', () => {\n    const result = injectMutationState(() => ({\n      filters: { status: 'pending' },\n    }))\n\n    expectTypeOf(result()).toEqualTypeOf<Array<MutationState>>()\n  })\n\n  it('should infer with select', () => {\n    const result = injectMutationState(() => ({\n      filters: { status: 'pending' },\n      select: (mutation) => mutation.state.status,\n    }))\n\n    expectTypeOf(result()).toEqualTypeOf<Array<MutationStatus>>()\n  })\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/inject-mutation-state.test.ts",
    "content": "import {\n  Component,\n  Injector,\n  input,\n  provideZonelessChangeDetection,\n  signal,\n} from '@angular/core'\nimport { TestBed } from '@angular/core/testing'\nimport { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { By } from '@angular/platform-browser'\nimport { sleep } from '@tanstack/query-test-utils'\nimport {\n  QueryClient,\n  injectMutation,\n  injectMutationState,\n  provideTanStackQuery,\n} from '..'\nimport { setFixtureSignalInputs } from './test-utils'\n\ndescribe('injectMutationState', () => {\n  let queryClient: QueryClient\n\n  beforeEach(() => {\n    queryClient = new QueryClient()\n    vi.useFakeTimers()\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(queryClient),\n      ],\n    })\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  describe('injectMutationState', () => {\n    test('should return variables after calling mutate 1', () => {\n      const mutationKey = ['mutation']\n      const variables = 'foo123'\n\n      const mutation = TestBed.runInInjectionContext(() => {\n        return injectMutation(() => ({\n          mutationKey: mutationKey,\n          mutationFn: (params: string) => sleep(0).then(() => params),\n        }))\n      })\n\n      mutation.mutate(variables)\n\n      const mutationState = TestBed.runInInjectionContext(() => {\n        return injectMutationState(() => ({\n          filters: { mutationKey, status: 'pending' },\n          select: (m) => m.state.variables,\n        }))\n      })\n\n      expect(mutationState()).toEqual([variables])\n    })\n\n    test('reactive options should update injectMutationState', () => {\n      const mutationKey1 = ['mutation1']\n      const mutationKey2 = ['mutation2']\n      const variables1 = 'foo123'\n      const variables2 = 'bar234'\n\n      const [mutation1, mutation2] = TestBed.runInInjectionContext(() => {\n        return [\n          injectMutation(() => ({\n            mutationKey: mutationKey1,\n            mutationFn: (params: string) => sleep(0).then(() => params),\n          })),\n          injectMutation(() => ({\n            mutationKey: mutationKey2,\n            mutationFn: (params: string) => sleep(0).then(() => params),\n          })),\n        ]\n      })\n\n      mutation1.mutate(variables1)\n      mutation2.mutate(variables2)\n\n      const filterKey = signal(mutationKey1)\n\n      const mutationState = TestBed.runInInjectionContext(() => {\n        return injectMutationState(() => ({\n          filters: { mutationKey: filterKey(), status: 'pending' },\n          select: (m) => m.state.variables,\n        }))\n      })\n\n      expect(mutationState()).toEqual([variables1])\n\n      filterKey.set(mutationKey2)\n      expect(mutationState()).toEqual([variables2])\n    })\n\n    test('should return variables after calling mutate 2', () => {\n      queryClient.clear()\n      const mutationKey = ['mutation']\n      const variables = 'bar234'\n\n      const mutation = TestBed.runInInjectionContext(() => {\n        return injectMutation(() => ({\n          mutationKey: mutationKey,\n          mutationFn: (params: string) => sleep(0).then(() => params),\n        }))\n      })\n\n      mutation.mutate(variables)\n\n      const mutationState = TestBed.runInInjectionContext(() => {\n        return injectMutationState()\n      })\n\n      expect(mutationState()[0]?.variables).toEqual(variables)\n    })\n\n    test('should support required signal inputs', async () => {\n      queryClient.clear()\n      const fakeName = 'name1'\n      const mutationKey1 = ['fake', fakeName]\n\n      const mutations = TestBed.runInInjectionContext(() => {\n        return [\n          injectMutation(() => ({\n            mutationKey: mutationKey1,\n            mutationFn: () => sleep(10).then(() => 'myValue'),\n          })),\n          injectMutation(() => ({\n            mutationKey: mutationKey1,\n            mutationFn: () =>\n              sleep(10).then(() => Promise.reject(new Error('myValue2'))),\n          })),\n        ]\n      })\n\n      mutations.forEach((mutation) => mutation.mutate())\n\n      @Component({\n        selector: 'app-fake',\n        template: `\n          @for (mutation of mutationState(); track $index) {\n            <span>{{ mutation.status }}</span>\n          }\n        `,\n      })\n      class FakeComponent {\n        name = input.required<string>()\n\n        mutationState = injectMutationState(() => ({\n          filters: {\n            mutationKey: ['fake', this.name()],\n            exact: true,\n          },\n        }))\n      }\n\n      const fixture = TestBed.createComponent(FakeComponent)\n      const { debugElement } = fixture\n      setFixtureSignalInputs(fixture, { name: fakeName })\n      await vi.advanceTimersByTimeAsync(0)\n\n      let spans = debugElement\n        .queryAll(By.css('span'))\n        .map((span) => span.nativeNode.textContent)\n\n      expect(spans).toEqual(['pending', 'pending'])\n\n      await vi.advanceTimersByTimeAsync(11)\n      fixture.detectChanges()\n\n      spans = debugElement\n        .queryAll(By.css('span'))\n        .map((span) => span.nativeNode.textContent)\n\n      expect(spans).toEqual(['success', 'error'])\n    })\n\n    describe('injection context', () => {\n      test('throws NG0203 with descriptive error outside injection context', () => {\n        expect(() => {\n          injectMutationState()\n        }).toThrowError(/NG0203(.*?)injectMutationState/)\n      })\n\n      test('can be used outside injection context when passing an injector', () => {\n        const injector = TestBed.inject(Injector)\n        expect(\n          injectMutationState(undefined, {\n            injector,\n          }),\n        ).not.toThrow()\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/inject-mutation.test-d.ts",
    "content": "import { describe, expectTypeOf, test } from 'vitest'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { injectMutation } from '..'\nimport type { Signal } from '@angular/core'\n\ndescribe('Discriminated union return type', () => {\n  test('data should be possibly undefined by default', () => {\n    const mutation = injectMutation(() => ({\n      mutationFn: () => sleep(0).then(() => 'string'),\n    }))\n\n    expectTypeOf(mutation.data).toEqualTypeOf<Signal<string | undefined>>()\n  })\n\n  test('data should be defined when mutation is success', () => {\n    const mutation = injectMutation(() => ({\n      mutationFn: () => sleep(0).then(() => 'string'),\n    }))\n\n    if (mutation.isSuccess()) {\n      expectTypeOf(mutation.data).toEqualTypeOf<Signal<string>>()\n    }\n  })\n\n  test('error should be null when mutation is success', () => {\n    const mutation = injectMutation(() => ({\n      mutationFn: () => sleep(0).then(() => 'string'),\n    }))\n\n    if (mutation.isSuccess()) {\n      expectTypeOf(mutation.error).toEqualTypeOf<Signal<null>>()\n    }\n  })\n\n  test('data should be undefined when mutation is pending', () => {\n    const mutation = injectMutation(() => ({\n      mutationFn: () => sleep(0).then(() => 'string'),\n    }))\n\n    if (mutation.isPending()) {\n      expectTypeOf(mutation.data).toEqualTypeOf<Signal<undefined>>()\n    }\n  })\n\n  test('error should be defined when mutation is error', () => {\n    const mutation = injectMutation(() => ({\n      mutationFn: () => sleep(0).then(() => 'string'),\n    }))\n\n    if (mutation.isError()) {\n      expectTypeOf(mutation.error).toEqualTypeOf<Signal<Error>>()\n    }\n  })\n\n  test('should narrow variables', () => {\n    const mutation = injectMutation(() => ({\n      mutationFn: (_variables: string) => sleep(0).then(() => 'string'),\n    }))\n\n    if (mutation.isIdle()) {\n      expectTypeOf(mutation.variables).toEqualTypeOf<Signal<undefined>>()\n    }\n    if (mutation.isPending()) {\n      expectTypeOf(mutation.variables).toEqualTypeOf<Signal<string>>()\n    }\n    if (mutation.isSuccess()) {\n      expectTypeOf(mutation.variables).toEqualTypeOf<Signal<string>>()\n    }\n    expectTypeOf(mutation.variables).toEqualTypeOf<Signal<string | undefined>>()\n  })\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/inject-mutation.test.ts",
    "content": "import {\n  ApplicationRef,\n  Component,\n  Injector,\n  input,\n  provideZonelessChangeDetection,\n  signal,\n} from '@angular/core'\nimport { TestBed } from '@angular/core/testing'\nimport { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { By } from '@angular/platform-browser'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { QueryClient, injectMutation, provideTanStackQuery } from '..'\nimport { expectSignals, setFixtureSignalInputs } from './test-utils'\n\ndescribe('injectMutation', () => {\n  let queryClient: QueryClient\n\n  beforeEach(() => {\n    queryClient = new QueryClient()\n    vi.useFakeTimers()\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(queryClient),\n      ],\n    })\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('should be in idle state initially', () => {\n    const mutation = TestBed.runInInjectionContext(() => {\n      return injectMutation(() => ({\n        mutationFn: (params) => sleep(0).then(() => params),\n      }))\n    })\n\n    expectSignals(mutation, {\n      isIdle: true,\n      isPending: false,\n      isError: false,\n      isSuccess: false,\n    })\n  })\n\n  test('should change state after invoking mutate', async () => {\n    const result = 'Mock data'\n\n    const mutation = TestBed.runInInjectionContext(() => {\n      return injectMutation(() => ({\n        mutationFn: (params: string) => sleep(10).then(() => params),\n      }))\n    })\n\n    TestBed.tick()\n\n    mutation.mutate(result)\n    await vi.advanceTimersByTimeAsync(0)\n\n    expectSignals(mutation, {\n      isIdle: false,\n      isPending: true,\n      isError: false,\n      isSuccess: false,\n      data: undefined,\n      error: null,\n    })\n  })\n\n  test('should return error when request fails', async () => {\n    const mutation = TestBed.runInInjectionContext(() => {\n      return injectMutation(() => ({\n        mutationFn: () =>\n          sleep(10).then(() => Promise.reject(new Error('Some error'))),\n      }))\n    })\n\n    mutation.mutate()\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expectSignals(mutation, {\n      isIdle: false,\n      isPending: false,\n      isError: true,\n      isSuccess: false,\n      data: undefined,\n      error: Error('Some error'),\n    })\n  })\n\n  test('should return data when request succeeds', async () => {\n    const result = 'Mock data'\n    const mutation = TestBed.runInInjectionContext(() => {\n      return injectMutation(() => ({\n        mutationFn: (params: string) => sleep(10).then(() => params),\n      }))\n    })\n\n    mutation.mutate(result)\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expectSignals(mutation, {\n      isIdle: false,\n      isPending: false,\n      isError: false,\n      isSuccess: true,\n      data: result,\n      error: null,\n    })\n  })\n\n  test('reactive options should update mutation', () => {\n    const mutationCache = queryClient.getMutationCache()\n    // Signal will be updated before the mutation is called\n    // this test confirms that the mutation uses the updated value\n    const mutationKey = signal(['1'])\n    const mutation = TestBed.runInInjectionContext(() => {\n      return injectMutation(() => ({\n        mutationKey: mutationKey(),\n        mutationFn: (params: string) => sleep(0).then(() => params),\n      }))\n    })\n\n    mutationKey.set(['2'])\n\n    mutation.mutate('xyz')\n\n    const mutations = mutationCache.find({ mutationKey: ['2'] })\n\n    expect(mutations?.options.mutationKey).toEqual(['2'])\n  })\n\n  test('should reset state after invoking mutation.reset', async () => {\n    const mutation = TestBed.runInInjectionContext(() => {\n      return injectMutation(() => ({\n        mutationFn: () =>\n          sleep(10).then(() => Promise.reject(new Error('Some error'))),\n      }))\n    })\n\n    mutation.mutate()\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(mutation.isError()).toBe(true)\n\n    mutation.reset()\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expectSignals(mutation, {\n      isIdle: true,\n      isPending: false,\n      isError: false,\n      isSuccess: false,\n      data: undefined,\n      error: null,\n    })\n  })\n\n  describe('side effects', () => {\n    beforeEach(() => {\n      vi.clearAllMocks()\n    })\n\n    test('should call onMutate when passed as an option', async () => {\n      const onMutate = vi.fn()\n      const mutation = TestBed.runInInjectionContext(() => {\n        return injectMutation(() => ({\n          mutationFn: (params: string) => sleep(10).then(() => params),\n          onMutate,\n        }))\n      })\n\n      mutation.mutate('')\n\n      await vi.advanceTimersByTimeAsync(0)\n\n      expect(onMutate).toHaveBeenCalledTimes(1)\n    })\n\n    test('should call onError when passed as an option', async () => {\n      const onError = vi.fn()\n      const mutation = TestBed.runInInjectionContext(() => {\n        return injectMutation(() => ({\n          mutationFn: (_params: string) =>\n            sleep(10).then(() => Promise.reject(new Error('Some error'))),\n          onError,\n        }))\n      })\n\n      mutation.mutate('')\n\n      await vi.advanceTimersByTimeAsync(11)\n\n      expect(onError).toHaveBeenCalledTimes(1)\n    })\n\n    test('should call onSuccess when passed as an option', async () => {\n      const onSuccess = vi.fn()\n      const mutation = TestBed.runInInjectionContext(() => {\n        return injectMutation(() => ({\n          mutationFn: (params: string) => sleep(10).then(() => params),\n          onSuccess,\n        }))\n      })\n\n      mutation.mutate('')\n\n      await vi.advanceTimersByTimeAsync(11)\n\n      expect(onSuccess).toHaveBeenCalledTimes(1)\n    })\n\n    test('should call onSettled when passed as an option', async () => {\n      const onSettled = vi.fn()\n      const mutation = TestBed.runInInjectionContext(() => {\n        return injectMutation(() => ({\n          mutationFn: (params: string) => sleep(10).then(() => params),\n          onSettled,\n        }))\n      })\n\n      mutation.mutate('')\n\n      await vi.advanceTimersByTimeAsync(11)\n\n      expect(onSettled).toHaveBeenCalledTimes(1)\n    })\n\n    test('should call onError when passed as an argument of mutate function', async () => {\n      const onError = vi.fn()\n      const mutation = TestBed.runInInjectionContext(() => {\n        return injectMutation(() => ({\n          mutationFn: (_params: string) =>\n            sleep(10).then(() => Promise.reject(new Error('Some error'))),\n        }))\n      })\n\n      mutation.mutate('', { onError })\n\n      await vi.advanceTimersByTimeAsync(11)\n\n      expect(onError).toHaveBeenCalledTimes(1)\n    })\n\n    test('should call onSuccess when passed as an argument of mutate function', async () => {\n      const onSuccess = vi.fn()\n      const mutation = TestBed.runInInjectionContext(() => {\n        return injectMutation(() => ({\n          mutationFn: (params: string) => sleep(10).then(() => params),\n        }))\n      })\n\n      mutation.mutate('', { onSuccess })\n\n      await vi.advanceTimersByTimeAsync(11)\n\n      expect(onSuccess).toHaveBeenCalledTimes(1)\n    })\n\n    test('should call onSettled when passed as an argument of mutate function', async () => {\n      const onSettled = vi.fn()\n      const mutation = TestBed.runInInjectionContext(() => {\n        return injectMutation(() => ({\n          mutationFn: (params: string) => sleep(10).then(() => params),\n        }))\n      })\n\n      mutation.mutate('', { onSettled })\n\n      await vi.advanceTimersByTimeAsync(11)\n\n      expect(onSettled).toHaveBeenCalledTimes(1)\n    })\n\n    test('should fire both onSettled functions', async () => {\n      const onSettled = vi.fn()\n      const onSettledOnFunction = vi.fn()\n      const mutation = TestBed.runInInjectionContext(() => {\n        return injectMutation(() => ({\n          mutationFn: (params: string) => sleep(10).then(() => params),\n          onSettled,\n        }))\n      })\n\n      mutation.mutate('', { onSettled: onSettledOnFunction })\n\n      await vi.advanceTimersByTimeAsync(11)\n\n      expect(onSettled).toHaveBeenCalledTimes(1)\n      expect(onSettledOnFunction).toHaveBeenCalledTimes(1)\n    })\n  })\n\n  test('should support required signal inputs', async () => {\n    const mutationCache = queryClient.getMutationCache()\n\n    @Component({\n      selector: 'app-fake',\n      template: `\n        <button (click)=\"mutate()\"></button>\n        <span>{{ mutation.data() }}</span>\n      `,\n    })\n    class FakeComponent {\n      name = input.required<string>()\n\n      mutation = injectMutation(() => ({\n        mutationKey: ['fake', this.name()],\n        mutationFn: () => sleep(10).then(() => this.name()),\n      }))\n\n      mutate(): void {\n        this.mutation.mutate()\n      }\n    }\n\n    const fixture = TestBed.createComponent(FakeComponent)\n    const { debugElement } = fixture\n    setFixtureSignalInputs(fixture, { name: 'value' })\n\n    const button = debugElement.query(By.css('button'))\n    button.triggerEventHandler('click')\n\n    await vi.advanceTimersByTimeAsync(11)\n    fixture.detectChanges()\n\n    const text = debugElement.query(By.css('span')).nativeElement.textContent\n    expect(text).toEqual('value')\n    const mutation = mutationCache.find({ mutationKey: ['fake', 'value'] })\n    expect(mutation).toBeDefined()\n    expect(mutation!.options.mutationKey).toStrictEqual(['fake', 'value'])\n  })\n\n  test('should update options on required signal input change', async () => {\n    const mutationCache = queryClient.getMutationCache()\n\n    @Component({\n      selector: 'app-fake',\n      template: `\n        <button (click)=\"mutate()\"></button>\n        <span>{{ mutation.data() }}</span>\n      `,\n    })\n    class FakeComponent {\n      name = input.required<string>()\n\n      mutation = injectMutation(() => ({\n        mutationKey: ['fake', this.name()],\n        mutationFn: () => sleep(10).then(() => this.name()),\n      }))\n\n      mutate(): void {\n        this.mutation.mutate()\n      }\n    }\n\n    const fixture = TestBed.createComponent(FakeComponent)\n    const { debugElement } = fixture\n    setFixtureSignalInputs(fixture, { name: 'value' })\n\n    const button = debugElement.query(By.css('button'))\n    const span = debugElement.query(By.css('span'))\n\n    button.triggerEventHandler('click')\n    await vi.advanceTimersByTimeAsync(11)\n    fixture.detectChanges()\n\n    expect(span.nativeElement.textContent).toEqual('value')\n\n    setFixtureSignalInputs(fixture, { name: 'updatedValue' })\n\n    button.triggerEventHandler('click')\n    await vi.advanceTimersByTimeAsync(11)\n    fixture.detectChanges()\n\n    expect(span.nativeElement.textContent).toEqual('updatedValue')\n\n    const mutations = mutationCache.findAll()\n    expect(mutations.length).toBe(2)\n    const [mutation1, mutation2] = mutations\n    expect(mutation1!.options.mutationKey).toEqual(['fake', 'value'])\n    expect(mutation2!.options.mutationKey).toEqual(['fake', 'updatedValue'])\n  })\n\n  describe('throwOnError', () => {\n    test('should evaluate throwOnError when mutation is expected to throw', async () => {\n      const err = new Error('Expected mock error. All is well!')\n      const boundaryFn = vi.fn()\n      const { mutate } = TestBed.runInInjectionContext(() => {\n        return injectMutation(() => ({\n          mutationKey: ['fake'],\n          mutationFn: () => {\n            return Promise.reject(err)\n          },\n          throwOnError: boundaryFn,\n        }))\n      })\n\n      TestBed.tick()\n\n      mutate()\n\n      await vi.advanceTimersByTimeAsync(0)\n\n      expect(boundaryFn).toHaveBeenCalledTimes(1)\n      expect(boundaryFn).toHaveBeenCalledWith(err)\n    })\n\n    test('should throw when throwOnError is true and mutate is used', async () => {\n      const { mutate } = TestBed.runInInjectionContext(() => {\n        return injectMutation(() => ({\n          mutationKey: ['fake'],\n          mutationFn: () => {\n            return Promise.reject(\n              new Error('Expected mock error. All is well!'),\n            )\n          },\n          throwOnError: true,\n        }))\n      })\n\n      TestBed.tick()\n\n      mutate()\n\n      await expect(vi.advanceTimersByTimeAsync(0)).rejects.toThrow(\n        'Expected mock error. All is well!',\n      )\n    })\n  })\n\n  test('should throw when throwOnError is true', async () => {\n    const err = new Error('Expected mock error. All is well!')\n    const { mutateAsync } = TestBed.runInInjectionContext(() => {\n      return injectMutation(() => ({\n        mutationKey: ['fake'],\n        mutationFn: () => {\n          return Promise.reject(err)\n        },\n        throwOnError: true,\n      }))\n    })\n\n    await expect(() => mutateAsync()).rejects.toThrowError(err)\n  })\n\n  test('should throw when throwOnError function returns true', async () => {\n    const err = new Error('Expected mock error. All is well!')\n    const { mutateAsync } = TestBed.runInInjectionContext(() => {\n      return injectMutation(() => ({\n        mutationKey: ['fake'],\n        mutationFn: () => {\n          return Promise.reject(err)\n        },\n        throwOnError: () => true,\n      }))\n    })\n\n    await expect(() => mutateAsync()).rejects.toThrowError(err)\n  })\n\n  describe('injection context', () => {\n    test('throws NG0203 with descriptive error outside injection context', () => {\n      expect(() => {\n        injectMutation(() => ({\n          mutationKey: ['injectionContextError'],\n          mutationFn: () => Promise.resolve(),\n        }))\n      }).toThrowError(/NG0203(.*?)injectMutation/)\n    })\n\n    test('can be used outside injection context when passing an injector', () => {\n      expect(() => {\n        injectMutation(\n          () => ({\n            mutationKey: ['injectionContextError'],\n            mutationFn: () => Promise.resolve(),\n          }),\n          {\n            injector: TestBed.inject(Injector),\n          },\n        )\n      }).not.toThrow()\n    })\n\n    test('should complete mutation before whenStable() resolves', async () => {\n      const app = TestBed.inject(ApplicationRef)\n      let mutationStarted = false\n      let mutationCompleted = false\n\n      const mutation = TestBed.runInInjectionContext(() =>\n        injectMutation(() => ({\n          mutationKey: ['pendingTasksTest'],\n          mutationFn: async (data: string) => {\n            mutationStarted = true\n            await sleep(50)\n            mutationCompleted = true\n            return `processed: ${data}`\n          },\n        })),\n      )\n\n      // Initial state\n      expect(mutation.data()).toBeUndefined()\n      expect(mutationStarted).toBe(false)\n\n      // Start mutation\n      mutation.mutate('test')\n\n      // Wait for mutation to start and Angular to be \"stable\"\n      const stablePromise = app.whenStable()\n      await vi.advanceTimersByTimeAsync(60)\n      await stablePromise\n\n      // After whenStable(), mutation should be complete\n      expect(mutationStarted).toBe(true)\n      expect(mutationCompleted).toBe(true)\n      expect(mutation.isSuccess()).toBe(true)\n      expect(mutation.data()).toBe('processed: test')\n    })\n\n    test('should handle synchronous mutation with retry', async () => {\n      TestBed.resetTestingModule()\n      TestBed.configureTestingModule({\n        providers: [\n          provideZonelessChangeDetection(),\n          provideTanStackQuery(queryClient),\n        ],\n      })\n\n      const app = TestBed.inject(ApplicationRef)\n      let attemptCount = 0\n\n      const mutation = TestBed.runInInjectionContext(() =>\n        injectMutation(() => ({\n          retry: 2,\n          retryDelay: 0, // No delay for synchronous retry\n          mutationFn: async (data: string) => {\n            attemptCount++\n            if (attemptCount <= 2) {\n              throw new Error(`Sync attempt ${attemptCount} failed`)\n            }\n            return `processed: ${data}`\n          },\n        })),\n      )\n\n      // Start mutation\n      mutation.mutate('retry-test')\n\n      // Synchronize pending effects for each retry attempt\n      TestBed.tick()\n      await Promise.resolve()\n      await vi.advanceTimersByTimeAsync(10)\n\n      TestBed.tick()\n      await Promise.resolve()\n      await vi.advanceTimersByTimeAsync(10)\n\n      TestBed.tick()\n\n      const stablePromise = app.whenStable()\n      await Promise.resolve()\n      await vi.advanceTimersByTimeAsync(10)\n      await stablePromise\n\n      expect(mutation.isSuccess()).toBe(true)\n      expect(mutation.data()).toBe('processed: retry-test')\n      expect(attemptCount).toBe(3) // Initial + 2 retries\n    })\n\n    test('should handle multiple synchronous mutations on same key', async () => {\n      TestBed.resetTestingModule()\n      TestBed.configureTestingModule({\n        providers: [\n          provideZonelessChangeDetection(),\n          provideTanStackQuery(queryClient),\n        ],\n      })\n\n      const app = TestBed.inject(ApplicationRef)\n      let callCount = 0\n\n      const mutation1 = TestBed.runInInjectionContext(() =>\n        injectMutation(() => ({\n          mutationKey: ['sync-mutation-key'],\n          mutationFn: async (data: string) => {\n            callCount++\n            return `mutation1: ${data}`\n          },\n        })),\n      )\n\n      const mutation2 = TestBed.runInInjectionContext(() =>\n        injectMutation(() => ({\n          mutationKey: ['sync-mutation-key'],\n          mutationFn: async (data: string) => {\n            callCount++\n            return `mutation2: ${data}`\n          },\n        })),\n      )\n\n      // Start both mutations\n      mutation1.mutate('test1')\n      mutation2.mutate('test2')\n\n      // Synchronize pending effects\n      TestBed.tick()\n\n      const stablePromise = app.whenStable()\n      // Flush microtasks to allow TanStack Query's scheduled notifications to process\n      await Promise.resolve()\n      await vi.advanceTimersByTimeAsync(1)\n      await stablePromise\n\n      expect(mutation1.isSuccess()).toBe(true)\n      expect(mutation1.data()).toBe('mutation1: test1')\n      expect(mutation2.isSuccess()).toBe(true)\n      expect(mutation2.data()).toBe('mutation2: test2')\n      expect(callCount).toBe(2)\n    })\n\n    test('should handle synchronous mutation with optimistic updates', async () => {\n      TestBed.resetTestingModule()\n      TestBed.configureTestingModule({\n        providers: [\n          provideZonelessChangeDetection(),\n          provideTanStackQuery(queryClient),\n        ],\n      })\n\n      const app = TestBed.inject(ApplicationRef)\n      const testQueryKey = ['sync-optimistic']\n      let onMutateCalled = false\n      let onSuccessCalled = false\n\n      // Set initial data\n      queryClient.setQueryData(testQueryKey, 'initial')\n\n      const mutation = TestBed.runInInjectionContext(() =>\n        injectMutation(() => ({\n          mutationFn: async (data: string) => `final: ${data}`, // Synchronous resolution\n          onMutate: async (variables) => {\n            onMutateCalled = true\n            const previousData = queryClient.getQueryData(testQueryKey)\n            queryClient.setQueryData(testQueryKey, `optimistic: ${variables}`)\n            return { previousData }\n          },\n          onSuccess: (data) => {\n            onSuccessCalled = true\n            queryClient.setQueryData(testQueryKey, data)\n          },\n        })),\n      )\n\n      // Start mutation\n      mutation.mutate('test')\n\n      // Synchronize pending effects\n      TestBed.tick()\n\n      const stablePromise = app.whenStable()\n      // Flush microtasks to allow TanStack Query's scheduled notifications to process\n      await Promise.resolve()\n      await vi.advanceTimersByTimeAsync(1)\n      await stablePromise\n\n      expect(onMutateCalled).toBe(true)\n      expect(onSuccessCalled).toBe(true)\n      expect(mutation.isSuccess()).toBe(true)\n      expect(mutation.data()).toBe('final: test')\n      expect(queryClient.getQueryData(testQueryKey)).toBe('final: test')\n    })\n\n    test('should handle synchronous mutation cancellation', async () => {\n      TestBed.resetTestingModule()\n      TestBed.configureTestingModule({\n        providers: [\n          provideZonelessChangeDetection(),\n          provideTanStackQuery(queryClient),\n        ],\n      })\n\n      const app = TestBed.inject(ApplicationRef)\n\n      const mutation = TestBed.runInInjectionContext(() =>\n        injectMutation(() => ({\n          mutationKey: ['cancel-sync'],\n          mutationFn: async (data: string) => `processed: ${data}`, // Synchronous resolution\n        })),\n      )\n\n      // Start mutation\n      mutation.mutate('test')\n\n      // Synchronize pending effects\n      TestBed.tick()\n\n      const stablePromise = app.whenStable()\n      // Flush microtasks to allow TanStack Query's scheduled notifications to process\n      await Promise.resolve()\n      await vi.advanceTimersByTimeAsync(1)\n      await stablePromise\n\n      // Synchronous mutations complete immediately\n      expect(mutation.isSuccess()).toBe(true)\n      expect(mutation.data()).toBe('processed: test')\n    })\n  })\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/inject-queries.test-d.ts",
    "content": "import { describe, expectTypeOf, it } from 'vitest'\nimport { skipToken } from '..'\nimport { injectQueries } from '../inject-queries'\nimport { queryOptions } from '../query-options'\nimport type { CreateQueryOptions, CreateQueryResult, OmitKeyof } from '..'\nimport type { Signal } from '@angular/core'\n\ndescribe('InjectQueries config object overload', () => {\n  it('TData should always be defined when initialData is provided as an object', () => {\n    const query1 = {\n      queryKey: ['key1'],\n      queryFn: () => {\n        return {\n          wow: true,\n        }\n      },\n      initialData: {\n        wow: false,\n      },\n    }\n\n    const query2 = {\n      queryKey: ['key2'],\n      queryFn: () => 'Query Data',\n      initialData: 'initial data',\n    }\n\n    const query3 = {\n      queryKey: ['key2'],\n      queryFn: () => 'Query Data',\n    }\n\n    const queryResults = injectQueries(() => ({\n      queries: [query1, query2, query3],\n    }))\n\n    const query1Data = queryResults()[0].data()\n    const query2Data = queryResults()[1].data()\n    const query3Data = queryResults()[2].data()\n\n    expectTypeOf(query1Data).toEqualTypeOf<{ wow: boolean }>()\n    expectTypeOf(query2Data).toEqualTypeOf<string>()\n    expectTypeOf(query3Data).toEqualTypeOf<string | undefined>()\n  })\n\n  it('TData should be defined when passed through queryOptions', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => {\n        return {\n          wow: true,\n        }\n      },\n      initialData: {\n        wow: true,\n      },\n    })\n    const queryResults = injectQueries(() => ({ queries: [options] }))\n\n    const data = queryResults()[0].data()\n\n    expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n  })\n\n  it('should be possible to define a different TData than TQueryFnData using select with queryOptions spread into injectQuery', () => {\n    const query1 = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(1),\n      select: (data) => data > 1,\n    })\n\n    const query2 = {\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(1),\n      select: (data: number) => data > 1,\n    }\n\n    const queryResults = injectQueries(() => ({ queries: [query1, query2] }))\n    const query1Data = queryResults()[0].data()\n    const query2Data = queryResults()[1].data()\n\n    expectTypeOf(query1Data).toEqualTypeOf<boolean | undefined>()\n    expectTypeOf(query2Data).toEqualTypeOf<boolean | undefined>()\n  })\n\n  it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => {\n    const queryResults = injectQueries(() => ({\n      queries: [\n        {\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n          initialData: () => undefined as { wow: boolean } | undefined,\n        },\n      ],\n    }))\n\n    const data = queryResults()[0].data()\n\n    expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()\n  })\n\n  describe('custom injectable', () => {\n    it('should allow custom hooks using UseQueryOptions', () => {\n      type Data = string\n\n      const injectCustomQueries = (\n        options?: OmitKeyof<CreateQueryOptions<Data>, 'queryKey' | 'queryFn'>,\n      ) => {\n        return injectQueries(() => ({\n          queries: [\n            {\n              ...options,\n              queryKey: ['todos-key'],\n              queryFn: () => Promise.resolve('data'),\n            },\n          ],\n        }))\n      }\n\n      const queryResults = injectCustomQueries()\n      const data = queryResults()[0].data()\n\n      expectTypeOf(data).toEqualTypeOf<Data | undefined>()\n    })\n  })\n\n  it('TData should have correct type when conditional skipToken is passed', () => {\n    const queryResults = injectQueries(() => ({\n      queries: [\n        {\n          queryKey: ['withSkipToken'],\n          queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),\n        },\n      ],\n    }))\n\n    const firstResult = queryResults()[0]\n\n    expectTypeOf(firstResult).toEqualTypeOf<CreateQueryResult<number, Error>>()\n    expectTypeOf(firstResult.data()).toEqualTypeOf<number | undefined>()\n  })\n\n  it('should return correct data for dynamic queries with mixed result types', () => {\n    const Queries1 = {\n      get: () =>\n        queryOptions({\n          queryKey: ['key1'],\n          queryFn: () => Promise.resolve(1),\n        }),\n    }\n    const Queries2 = {\n      get: () =>\n        queryOptions({\n          queryKey: ['key2'],\n          queryFn: () => Promise.resolve(true),\n        }),\n    }\n\n    const queries1List = [1, 2, 3].map(() => ({ ...Queries1.get() }))\n    const result = injectQueries(() => ({\n      queries: [...queries1List, { ...Queries2.get() }],\n    }))\n\n    expectTypeOf(result).branded.toEqualTypeOf<\n      Signal<\n        [\n          ...Array<CreateQueryResult<number, Error>>,\n          CreateQueryResult<boolean, Error>,\n        ]\n      >\n    >()\n  })\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/inject-queries.test.ts",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport {\n  Component,\n  effect,\n  provideZonelessChangeDetection,\n} from '@angular/core'\nimport { TestBed } from '@angular/core/testing'\nimport { render } from '@testing-library/angular'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { QueryClient, provideTanStackQuery } from '..'\nimport { injectQueries } from '../inject-queries'\n\nlet queryClient: QueryClient\n\nbeforeEach(() => {\n  vi.useFakeTimers()\n  queryClient = new QueryClient()\n  TestBed.configureTestingModule({\n    providers: [\n      provideZonelessChangeDetection(),\n      provideTanStackQuery(queryClient),\n    ],\n  })\n})\n\nafterEach(() => {\n  vi.useRealTimers()\n})\n\ndescribe('injectQueries', () => {\n  it('should return the correct states', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const results: Array<Array<Record<string, any>>> = []\n\n    @Component({\n      template: `\n        <div>\n          <div>\n            data1: {{ result()[0].data() ?? 'null' }}, data2:\n            {{ result()[1].data() ?? 'null' }}\n          </div>\n        </div>\n      `,\n    })\n    class Page {\n      result = injectQueries(() => ({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => sleep(10).then(() => 1),\n          },\n          {\n            queryKey: key2,\n            queryFn: () => sleep(100).then(() => 2),\n          },\n        ],\n      }))\n\n      _ = effect(() => {\n        const snapshot = this.result().map((q) => ({ data: q.data() }))\n        results.push(snapshot)\n      })\n    }\n\n    const rendered = await render(Page, {\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(queryClient),\n      ],\n    })\n\n    await vi.advanceTimersByTimeAsync(101)\n    rendered.fixture.detectChanges()\n\n    expect(rendered.getByText('data1: 1, data2: 2')).toBeInTheDocument()\n\n    expect(results.length).toBe(3)\n    expect(results[0]).toMatchObject([{ data: undefined }, { data: undefined }])\n    expect(results[1]).toMatchObject([{ data: 1 }, { data: undefined }])\n    expect(results[2]).toMatchObject([{ data: 1 }, { data: 2 }])\n  })\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/inject-query.test-d.ts",
    "content": "import { describe, expectTypeOf, it, test } from 'vitest'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { injectQuery, queryOptions } from '..'\nimport type { Signal } from '@angular/core'\n\ndescribe('initialData', () => {\n  describe('Config object overload', () => {\n    it('TData should always be defined when initialData is provided as an object', () => {\n      const { data } = injectQuery(() => ({\n        queryKey: ['key'],\n        queryFn: () => ({ wow: true }),\n        initialData: { wow: true },\n      }))\n\n      expectTypeOf(data).toEqualTypeOf<Signal<{ wow: boolean }>>()\n    })\n\n    it('TData should be defined when passed through queryOptions', () => {\n      const options = () =>\n        queryOptions({\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n          initialData: {\n            wow: true,\n          },\n        })\n      const { data } = injectQuery(options)\n\n      expectTypeOf(data).toEqualTypeOf<Signal<{ wow: boolean }>>()\n    })\n\n    it('should be possible to define a different TData than TQueryFnData using select with queryOptions spread into useQuery', () => {\n      const options = queryOptions({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(1),\n      })\n\n      const query = injectQuery(() => ({\n        ...options,\n        select: (data) => data > 1,\n      }))\n\n      expectTypeOf(query.data).toEqualTypeOf<Signal<boolean | undefined>>()\n    })\n\n    it('TData should always be defined when initialData is provided as a function which ALWAYS returns the data', () => {\n      const { data } = injectQuery(() => ({\n        queryKey: ['key'],\n        queryFn: () => {\n          return {\n            wow: true,\n          }\n        },\n        initialData: () => ({\n          wow: true,\n        }),\n      }))\n\n      expectTypeOf(data).toEqualTypeOf<Signal<{ wow: boolean }>>()\n    })\n\n    it('TData should have undefined in the union when initialData is NOT provided', () => {\n      const { data } = injectQuery(() => ({\n        queryKey: ['key'],\n        queryFn: () => {\n          return {\n            wow: true,\n          }\n        },\n      }))\n\n      expectTypeOf(data).toEqualTypeOf<Signal<{ wow: boolean } | undefined>>()\n    })\n\n    it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => {\n      const { data } = injectQuery(() => ({\n        queryKey: ['key'],\n        queryFn: () => {\n          return {\n            wow: true,\n          }\n        },\n        initialData: () => undefined as { wow: boolean } | undefined,\n      }))\n\n      expectTypeOf(data).toEqualTypeOf<Signal<{ wow: boolean } | undefined>>()\n    })\n\n    it('TData should be narrowed after an isSuccess check when initialData is provided as a function which can return undefined', () => {\n      const query = injectQuery(() => ({\n        queryKey: ['key'],\n        queryFn: () => {\n          return {\n            wow: true,\n          }\n        },\n        initialData: () => undefined as { wow: boolean } | undefined,\n      }))\n\n      if (query.isSuccess()) {\n        expectTypeOf(query.data).toEqualTypeOf<Signal<{ wow: boolean }>>()\n      }\n    })\n  })\n\n  describe('structuralSharing', () => {\n    it('should be able to use structuralSharing with unknown types', () => {\n      // https://github.com/TanStack/query/issues/6525#issuecomment-1938411343\n      injectQuery(() => ({\n        queryKey: ['key'],\n        queryFn: () => 5,\n        structuralSharing: (oldData, newData) => {\n          expectTypeOf(oldData).toBeUnknown()\n          expectTypeOf(newData).toBeUnknown()\n          return newData\n        },\n      }))\n    })\n  })\n})\n\ndescribe('Discriminated union return type', () => {\n  test('data should be possibly undefined by default', () => {\n    const query = injectQuery(() => ({\n      queryKey: ['key'],\n      queryFn: () => sleep(0).then(() => 'Some data'),\n    }))\n\n    expectTypeOf(query.data).toEqualTypeOf<Signal<string | undefined>>()\n  })\n\n  test('data should be defined when query is success', () => {\n    const query = injectQuery(() => ({\n      queryKey: ['key'],\n      queryFn: () => sleep(0).then(() => 'Some data'),\n    }))\n\n    if (query.isSuccess()) {\n      expectTypeOf(query.data).toEqualTypeOf<Signal<string>>()\n    }\n  })\n\n  test('error should be null when query is success', () => {\n    const query = injectQuery(() => ({\n      queryKey: ['key'],\n      queryFn: () => sleep(0).then(() => 'Some data'),\n    }))\n\n    if (query.isSuccess()) {\n      expectTypeOf(query.error).toEqualTypeOf<Signal<null>>()\n    }\n  })\n\n  test('data should be undefined when query is pending', () => {\n    const query = injectQuery(() => ({\n      queryKey: ['key'],\n      queryFn: () => sleep(0).then(() => 'Some data'),\n    }))\n\n    if (query.isPending()) {\n      expectTypeOf(query.data).toEqualTypeOf<Signal<undefined>>()\n    }\n  })\n\n  test('error should be defined when query is error', () => {\n    const query = injectQuery(() => ({\n      queryKey: ['key'],\n      queryFn: () => sleep(0).then(() => 'Some data'),\n    }))\n\n    if (query.isError()) {\n      expectTypeOf(query.error).toEqualTypeOf<Signal<Error>>()\n    }\n  })\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/inject-query.test.ts",
    "content": "import {\n  ApplicationRef,\n  Component,\n  Injector,\n  computed,\n  effect,\n  input,\n  provideZonelessChangeDetection,\n  signal,\n} from '@angular/core'\nimport { TestBed } from '@angular/core/testing'\nimport { HttpClient, provideHttpClient } from '@angular/common/http'\nimport {\n  HttpTestingController,\n  provideHttpClientTesting,\n} from '@angular/common/http/testing'\nimport {\n  afterEach,\n  beforeEach,\n  describe,\n  expect,\n  expectTypeOf,\n  test,\n  vi,\n} from 'vitest'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { lastValueFrom } from 'rxjs'\nimport {\n  QueryCache,\n  QueryClient,\n  injectQuery,\n  provideIsRestoring,\n  provideTanStackQuery,\n} from '..'\nimport { setSignalInputs } from './test-utils'\nimport type { CreateQueryOptions, OmitKeyof, QueryFunction } from '..'\n\ndescribe('injectQuery', () => {\n  let queryCache: QueryCache\n  let queryClient: QueryClient\n  beforeEach(() => {\n    vi.useFakeTimers()\n    queryCache = new QueryCache()\n    queryClient = new QueryClient({ queryCache })\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(queryClient),\n      ],\n    })\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('should return the correct types', () => {\n    const key = queryKey()\n    // unspecified query function should default to unknown\n    const noQueryFn = TestBed.runInInjectionContext(() =>\n      injectQuery(() => ({\n        queryKey: key,\n      })),\n    )\n    expectTypeOf(noQueryFn.data()).toEqualTypeOf<unknown>()\n    expectTypeOf(noQueryFn.error()).toEqualTypeOf<Error | null>()\n\n    // it should infer the result type from the query function\n    const fromQueryFn = TestBed.runInInjectionContext(() =>\n      injectQuery(() => ({\n        queryKey: key,\n        queryFn: () => 'test',\n      })),\n    )\n    expectTypeOf(fromQueryFn.data()).toEqualTypeOf<string | undefined>()\n    expectTypeOf(fromQueryFn.error()).toEqualTypeOf<Error | null>()\n\n    // it should be possible to specify the result type\n    const withResult = TestBed.runInInjectionContext(() =>\n      injectQuery<string>(() => ({\n        queryKey: key,\n        queryFn: () => 'test',\n      })),\n    )\n    expectTypeOf(withResult.data()).toEqualTypeOf<string | undefined>()\n    expectTypeOf(withResult.error()).toEqualTypeOf<Error | null>()\n\n    // it should be possible to specify the error type\n    type CustomErrorType = { message: string }\n    const withError = TestBed.runInInjectionContext(() =>\n      injectQuery<string, CustomErrorType>(() => ({\n        queryKey: key,\n        queryFn: () => 'test',\n      })),\n    )\n    expectTypeOf(withError.data()).toEqualTypeOf<string | undefined>()\n    expectTypeOf(withError.error()).toEqualTypeOf<CustomErrorType | null>()\n\n    // it should infer the result type from the configuration\n    const withResultInfer = TestBed.runInInjectionContext(() =>\n      injectQuery(() => ({\n        queryKey: key,\n        queryFn: () => true,\n      })),\n    )\n    expectTypeOf(withResultInfer.data()).toEqualTypeOf<boolean | undefined>()\n    expectTypeOf(withResultInfer.error()).toEqualTypeOf<Error | null>()\n\n    // it should be possible to specify a union type as result type\n    const unionTypeSync = TestBed.runInInjectionContext(() =>\n      injectQuery(() => ({\n        queryKey: key,\n        queryFn: () => (Math.random() > 0.5 ? ('a' as const) : ('b' as const)),\n      })),\n    )\n    expectTypeOf(unionTypeSync.data()).toEqualTypeOf<'a' | 'b' | undefined>()\n    const unionTypeAsync = TestBed.runInInjectionContext(() =>\n      injectQuery<'a' | 'b'>(() => ({\n        queryKey: key,\n        queryFn: () => Promise.resolve(Math.random() > 0.5 ? 'a' : 'b'),\n      })),\n    )\n    expectTypeOf(unionTypeAsync.data()).toEqualTypeOf<'a' | 'b' | undefined>()\n\n    // it should error when the query function result does not match with the specified type\n    TestBed.runInInjectionContext(() =>\n      // @ts-expect-error\n      injectQuery<number>(() => ({ queryKey: key, queryFn: () => 'test' })),\n    )\n\n    // it should infer the result type from a generic query function\n    /**\n     *\n     */\n    function queryFn<T = string>(): Promise<T> {\n      return Promise.resolve({} as T)\n    }\n\n    const fromGenericQueryFn = TestBed.runInInjectionContext(() =>\n      injectQuery(() => ({\n        queryKey: key,\n        queryFn: () => queryFn(),\n      })),\n    )\n    expectTypeOf(fromGenericQueryFn.data()).toEqualTypeOf<string | undefined>()\n    expectTypeOf(fromGenericQueryFn.error()).toEqualTypeOf<Error | null>()\n\n    // todo use query options?\n    const fromGenericOptionsQueryFn = TestBed.runInInjectionContext(() =>\n      injectQuery(() => ({\n        queryKey: key,\n        queryFn: () => queryFn(),\n      })),\n    )\n    expectTypeOf(fromGenericOptionsQueryFn.data()).toEqualTypeOf<\n      string | undefined\n    >()\n    expectTypeOf(\n      fromGenericOptionsQueryFn.error(),\n    ).toEqualTypeOf<Error | null>()\n\n    type MyData = number\n    type MyQueryKey = readonly ['my-data', number]\n\n    const getMyDataArrayKey: QueryFunction<MyData, MyQueryKey> = ({\n      queryKey: [, n],\n    }) => {\n      return n + 42\n    }\n\n    const fromMyDataArrayKeyQueryFn = TestBed.runInInjectionContext(() =>\n      injectQuery(() => ({\n        queryKey: ['my-data', 100] as const,\n        queryFn: getMyDataArrayKey,\n      })),\n    )\n    expectTypeOf(fromMyDataArrayKeyQueryFn.data()).toEqualTypeOf<\n      number | undefined\n    >()\n\n    // it should handle query-functions that return Promise<any>\n    const fromPromiseAnyQueryFn = TestBed.runInInjectionContext(() =>\n      injectQuery(() => ({\n        queryKey: key,\n        queryFn: () => fetch('return Promise<any>').then((resp) => resp.json()),\n      })),\n    )\n    expectTypeOf(fromPromiseAnyQueryFn.data()).toEqualTypeOf<any | undefined>()\n\n    TestBed.runInInjectionContext(() =>\n      effect(() => {\n        expect(fromMyDataArrayKeyQueryFn.data()).toBe(142)\n      }),\n    )\n\n    const getMyDataStringKey: QueryFunction<MyData, ['1']> = (context) => {\n      expectTypeOf(context.queryKey).toEqualTypeOf<['1']>()\n      return Number(context.queryKey[0]) + 42\n    }\n\n    const fromGetMyDataStringKeyQueryFn = TestBed.runInInjectionContext(() =>\n      injectQuery(() => ({\n        queryKey: ['1'] as ['1'],\n        queryFn: getMyDataStringKey,\n      })),\n    )\n    expectTypeOf(fromGetMyDataStringKeyQueryFn.data()).toEqualTypeOf<\n      number | undefined\n    >()\n\n    TestBed.runInInjectionContext(() =>\n      effect(() => {\n        expect(fromGetMyDataStringKeyQueryFn.data()).toBe(43)\n      }),\n    )\n\n    // handles wrapped queries with custom fetcher passed as inline queryFn\n    const createWrappedQuery = <\n      TQueryKey extends [string, Record<string, unknown>?],\n      TQueryFnData,\n      TError,\n      TData = TQueryFnData,\n    >(\n      qk: TQueryKey,\n      fetcher: (\n        obj: TQueryKey[1],\n        token: string,\n        // return type must be wrapped with TQueryFnReturn\n      ) => Promise<TQueryFnData>,\n      options?: OmitKeyof<\n        CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n        'queryKey' | 'queryFn' | 'initialData',\n        'safely'\n      >,\n    ) =>\n      injectQuery(() => ({\n        queryKey: qk,\n        queryFn: () => fetcher(qk[1], 'token'),\n        ...options,\n      }))\n    const fromWrappedQuery = TestBed.runInInjectionContext(() =>\n      createWrappedQuery([''], () => Promise.resolve('1')),\n    )\n    expectTypeOf(fromWrappedQuery.data()).toEqualTypeOf<string | undefined>()\n\n    // handles wrapped queries with custom fetcher passed directly to createQuery\n    const createWrappedFuncStyleQuery = <\n      TQueryKey extends [string, Record<string, unknown>?],\n      TQueryFnData,\n      TError,\n      TData = TQueryFnData,\n    >(\n      qk: TQueryKey,\n      fetcher: () => Promise<TQueryFnData>,\n      options?: OmitKeyof<\n        CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n        'queryKey' | 'queryFn' | 'initialData',\n        'safely'\n      >,\n    ) => injectQuery(() => ({ queryKey: qk, queryFn: fetcher, ...options }))\n    const fromWrappedFuncStyleQuery = TestBed.runInInjectionContext(() =>\n      createWrappedFuncStyleQuery([''], () => Promise.resolve(true)),\n    )\n    expectTypeOf(fromWrappedFuncStyleQuery.data()).toEqualTypeOf<\n      boolean | undefined\n    >()\n  })\n\n  test('should return pending status initially', () => {\n    const query = TestBed.runInInjectionContext(() => {\n      return injectQuery(() => ({\n        queryKey: ['key1'],\n        queryFn: () => sleep(10).then(() => 'Some data'),\n      }))\n    })\n\n    expect(query.status()).toBe('pending')\n    expect(query.isPending()).toBe(true)\n    expect(query.isFetching()).toBe(true)\n    expect(query.isStale()).toBe(true)\n    expect(query.isFetched()).toBe(false)\n  })\n\n  test('should resolve to success and update signal: injectQuery()', async () => {\n    const query = TestBed.runInInjectionContext(() => {\n      return injectQuery(() => ({\n        queryKey: ['key2'],\n        queryFn: () => sleep(10).then(() => 'result2'),\n      }))\n    })\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(query.status()).toBe('success')\n    expect(query.data()).toBe('result2')\n    expect(query.isPending()).toBe(false)\n    expect(query.isFetching()).toBe(false)\n    expect(query.isFetched()).toBe(true)\n    expect(query.isSuccess()).toBe(true)\n  })\n\n  test('should reject and update signal', async () => {\n    const query = TestBed.runInInjectionContext(() => {\n      return injectQuery(() => ({\n        retry: false,\n        queryKey: ['key3'],\n        queryFn: () =>\n          sleep(10).then(() => Promise.reject(new Error('Some error'))),\n      }))\n    })\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(query.status()).toBe('error')\n    expect(query.data()).toBe(undefined)\n    expect(query.error()).toMatchObject({ message: 'Some error' })\n    expect(query.isPending()).toBe(false)\n    expect(query.isFetching()).toBe(false)\n    expect(query.isError()).toBe(true)\n    expect(query.failureCount()).toBe(1)\n    expect(query.failureReason()).toMatchObject({ message: 'Some error' })\n  })\n\n  test('should update query on options contained signal change', async () => {\n    const key = signal(['key6', 'key7'])\n    const spy = vi.fn(() => sleep(10).then(() => 'Some data'))\n\n    const query = TestBed.runInInjectionContext(() => {\n      return injectQuery(() => ({\n        queryKey: key(),\n        queryFn: spy,\n      }))\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(query.status()).toBe('success')\n\n    key.set(['key8'])\n    TestBed.tick()\n\n    expect(spy).toHaveBeenCalledTimes(2)\n    // should call queryFn with context containing the new queryKey\n    expect(spy).toBeCalledWith({\n      client: queryClient,\n      meta: undefined,\n      queryKey: ['key8'],\n      signal: expect.anything(),\n    })\n  })\n\n  test('should only run query once enabled signal is set to true', async () => {\n    const spy = vi.fn(() => sleep(10).then(() => 'Some data'))\n    const enabled = signal(false)\n\n    const query = TestBed.runInInjectionContext(() => {\n      return injectQuery(() => ({\n        queryKey: ['key9'],\n        queryFn: spy,\n        enabled: enabled(),\n      }))\n    })\n\n    expect(spy).not.toHaveBeenCalled()\n    expect(query.status()).toBe('pending')\n\n    enabled.set(true)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(spy).toHaveBeenCalledTimes(1)\n    expect(query.status()).toBe('success')\n  })\n\n  test('should properly execute dependent queries', async () => {\n    const query1 = TestBed.runInInjectionContext(() => {\n      return injectQuery(() => ({\n        queryKey: ['dependent1'],\n        queryFn: () => sleep(10).then(() => 'Some data'),\n      }))\n    })\n\n    const dependentQueryFn = vi\n      .fn()\n      .mockImplementation(() => sleep(1000).then(() => 'Some data'))\n\n    const query2 = TestBed.runInInjectionContext(() => {\n      return injectQuery(\n        computed(() => ({\n          queryKey: ['dependent2'],\n          queryFn: dependentQueryFn,\n          enabled: !!query1.data(),\n        })),\n      )\n    })\n\n    expect(query1.data()).toStrictEqual(undefined)\n    expect(query2.fetchStatus()).toStrictEqual('idle')\n    expect(dependentQueryFn).not.toHaveBeenCalled()\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(query1.data()).toStrictEqual('Some data')\n    expect(query2.fetchStatus()).toStrictEqual('fetching')\n\n    await vi.advanceTimersByTimeAsync(1002)\n\n    expect(query2.fetchStatus()).toStrictEqual('idle')\n    expect(query2.status()).toStrictEqual('success')\n    expect(dependentQueryFn).toHaveBeenCalledTimes(1)\n    expect(dependentQueryFn).toHaveBeenCalledWith(\n      expect.objectContaining({ queryKey: ['dependent2'] }),\n    )\n  })\n\n  test('should use the current value for the queryKey when refetch is called', async () => {\n    const fetchFn = vi.fn(() => sleep(10).then(() => 'Some data'))\n    const keySignal = signal('key11')\n\n    const query = TestBed.runInInjectionContext(() => {\n      return injectQuery(() => ({\n        queryKey: ['key10', keySignal()],\n        queryFn: fetchFn,\n        enabled: false,\n      }))\n    })\n\n    expect(fetchFn).not.toHaveBeenCalled()\n\n    void query.refetch().then(() => {\n      expect(fetchFn).toHaveBeenCalledTimes(1)\n      expect(fetchFn).toHaveBeenCalledWith(\n        expect.objectContaining({\n          queryKey: ['key10', 'key11'],\n        }),\n      )\n    })\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    keySignal.set('key12')\n\n    void query.refetch().then(() => {\n      expect(fetchFn).toHaveBeenCalledTimes(2)\n      expect(fetchFn).toHaveBeenCalledWith(\n        expect.objectContaining({\n          queryKey: ['key10', 'key12'],\n        }),\n      )\n    })\n\n    await vi.advanceTimersByTimeAsync(11)\n  })\n\n  describe('throwOnError', () => {\n    test('should evaluate throwOnError when query is expected to throw', async () => {\n      const boundaryFn = vi.fn()\n      TestBed.runInInjectionContext(() => {\n        return injectQuery(() => ({\n          queryKey: ['key12'],\n          queryFn: () =>\n            sleep(10).then(() => Promise.reject(new Error('Some error'))),\n          retry: false,\n          throwOnError: boundaryFn,\n        }))\n      })\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(boundaryFn).toHaveBeenCalledTimes(1)\n      expect(boundaryFn).toHaveBeenCalledWith(\n        Error('Some error'),\n        expect.objectContaining({\n          state: expect.objectContaining({ status: 'error' }),\n        }),\n      )\n    })\n\n    test('should throw when throwOnError is true', async () => {\n      TestBed.runInInjectionContext(() => {\n        return injectQuery(() => ({\n          queryKey: ['key13'],\n          queryFn: () =>\n            sleep(0).then(() => Promise.reject(new Error('Some error'))),\n          throwOnError: true,\n        }))\n      })\n\n      await expect(vi.runAllTimersAsync()).rejects.toThrow('Some error')\n    })\n\n    test('should throw when throwOnError function returns true', async () => {\n      TestBed.runInInjectionContext(() => {\n        return injectQuery(() => ({\n          queryKey: ['key14'],\n          queryFn: () =>\n            sleep(0).then(() => Promise.reject(new Error('Some error'))),\n          throwOnError: () => true,\n        }))\n      })\n\n      await expect(vi.runAllTimersAsync()).rejects.toThrow('Some error')\n    })\n  })\n\n  test('should set state to error when queryFn returns reject promise', async () => {\n    const query = TestBed.runInInjectionContext(() => {\n      return injectQuery(() => ({\n        retry: false,\n        queryKey: ['key15'],\n        queryFn: () =>\n          sleep(10).then(() => Promise.reject(new Error('Some error'))),\n      }))\n    })\n\n    expect(query.status()).toBe('pending')\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(query.status()).toBe('error')\n  })\n\n  test('should render with required signal inputs', async () => {\n    @Component({\n      selector: 'app-fake',\n      template: `{{ query.data() }}`,\n    })\n    class FakeComponent {\n      name = input.required<string>()\n\n      query = injectQuery(() => ({\n        queryKey: ['fake', this.name()],\n        queryFn: () => this.name(),\n      }))\n    }\n\n    const fixture = TestBed.createComponent(FakeComponent)\n    setSignalInputs(fixture.componentInstance, {\n      name: 'signal-input-required-test',\n    })\n\n    fixture.detectChanges()\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(fixture.componentInstance.query.data()).toEqual(\n      'signal-input-required-test',\n    )\n  })\n\n  describe('isRestoring', () => {\n    test('should not fetch for the duration of the restoring period when isRestoring is true', async () => {\n      const key = queryKey()\n      const queryFn = vi\n        .fn()\n        .mockImplementation(() => sleep(10).then(() => 'data'))\n\n      TestBed.resetTestingModule()\n      TestBed.configureTestingModule({\n        providers: [\n          provideZonelessChangeDetection(),\n          provideTanStackQuery(queryClient),\n          provideIsRestoring(signal(true).asReadonly()),\n        ],\n      })\n\n      const query = TestBed.runInInjectionContext(() =>\n        injectQuery(() => ({\n          queryKey: key,\n          queryFn,\n        })),\n      )\n\n      await vi.advanceTimersByTimeAsync(0)\n      expect(query.status()).toBe('pending')\n      expect(query.fetchStatus()).toBe('idle')\n      expect(query.data()).toBeUndefined()\n      expect(queryFn).toHaveBeenCalledTimes(0)\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(query.status()).toBe('pending')\n      expect(query.fetchStatus()).toBe('idle')\n      expect(query.data()).toBeUndefined()\n      expect(queryFn).toHaveBeenCalledTimes(0)\n    })\n  })\n\n  describe('injection context', () => {\n    test('throws NG0203 with descriptive error outside injection context', () => {\n      expect(() => {\n        injectQuery(() => ({\n          queryKey: ['injectionContextError'],\n          queryFn: () => sleep(0).then(() => 'Some data'),\n        }))\n      }).toThrowError(/NG0203(.*?)injectQuery/)\n    })\n\n    test('can be used outside injection context when passing an injector', () => {\n      const query = injectQuery(\n        () => ({\n          queryKey: ['manualInjector'],\n          queryFn: () => sleep(0).then(() => 'Some data'),\n        }),\n        {\n          injector: TestBed.inject(Injector),\n        },\n      )\n\n      expect(query.status()).toBe('pending')\n    })\n\n    test('should complete queries before whenStable() resolves', async () => {\n      const app = TestBed.inject(ApplicationRef)\n\n      const query = TestBed.runInInjectionContext(() =>\n        injectQuery(() => ({\n          queryKey: ['pendingTasksTest'],\n          queryFn: async () => {\n            await sleep(50)\n            return 'test data'\n          },\n        })),\n      )\n\n      expect(query.status()).toBe('pending')\n      expect(query.data()).toBeUndefined()\n\n      const stablePromise = app.whenStable()\n      await vi.advanceTimersByTimeAsync(60)\n      await stablePromise\n\n      expect(query.status()).toBe('success')\n      expect(query.data()).toBe('test data')\n    })\n\n    test('should complete HttpClient-based queries before whenStable() resolves', async () => {\n      TestBed.resetTestingModule()\n      TestBed.configureTestingModule({\n        providers: [\n          provideZonelessChangeDetection(),\n          provideTanStackQuery(queryClient),\n          provideHttpClient(),\n          provideHttpClientTesting(),\n        ],\n      })\n\n      const app = TestBed.inject(ApplicationRef)\n      const httpClient = TestBed.inject(HttpClient)\n      const httpTestingController = TestBed.inject(HttpTestingController)\n\n      // Create a query using HttpClient\n      const query = TestBed.runInInjectionContext(() =>\n        injectQuery(() => ({\n          queryKey: ['httpClientTest'],\n          queryFn: () =>\n            lastValueFrom(httpClient.get<{ message: string }>('/api/test')),\n        })),\n      )\n\n      // Schedule the HTTP response\n      setTimeout(() => {\n        const req = httpTestingController.expectOne('/api/test')\n        req.flush({ message: 'http test data' })\n      }, 10)\n\n      // Initial state\n      expect(query.status()).toBe('pending')\n\n      // Advance timers and wait for Angular to be \"stable\"\n      const stablePromise = app.whenStable()\n      await vi.advanceTimersByTimeAsync(20)\n      await stablePromise\n\n      // Query should be complete after whenStable() thanks to PendingTasks integration\n      expect(query.status()).toBe('success')\n      expect(query.data()).toEqual({ message: 'http test data' })\n\n      httpTestingController.verify()\n    })\n\n    test('should handle synchronous queryFn with staleTime', async () => {\n      TestBed.resetTestingModule()\n      TestBed.configureTestingModule({\n        providers: [\n          provideZonelessChangeDetection(),\n          provideTanStackQuery(queryClient),\n        ],\n      })\n\n      const app = TestBed.inject(ApplicationRef)\n      let callCount = 0\n\n      const query = TestBed.runInInjectionContext(() =>\n        injectQuery(() => ({\n          queryKey: ['sync-stale'],\n          staleTime: 1000,\n          queryFn: () => {\n            callCount++\n            return `sync-data-${callCount}`\n          },\n        })),\n      )\n\n      // Synchronize pending effects\n      TestBed.tick()\n\n      const stablePromise = app.whenStable()\n      await stablePromise\n\n      expect(query.status()).toBe('success')\n      expect(query.data()).toBe('sync-data-1')\n      expect(callCount).toBe(1)\n\n      await query.refetch()\n      await Promise.resolve()\n      await vi.runAllTimersAsync()\n      await app.whenStable()\n\n      expect(query.status()).toBe('success')\n      expect(query.data()).toBe('sync-data-2')\n      expect(callCount).toBe(2)\n    })\n\n    test('should handle enabled/disabled transitions with synchronous queryFn', async () => {\n      TestBed.resetTestingModule()\n      TestBed.configureTestingModule({\n        providers: [\n          provideZonelessChangeDetection(),\n          provideTanStackQuery(queryClient),\n        ],\n      })\n\n      const app = TestBed.inject(ApplicationRef)\n      const enabledSignal = signal(false)\n      let callCount = 0\n\n      const query = TestBed.runInInjectionContext(() =>\n        injectQuery(() => ({\n          queryKey: ['sync-enabled'],\n          enabled: enabledSignal(),\n          queryFn: () => {\n            callCount++\n            return `sync-data-${callCount}`\n          },\n        })),\n      )\n\n      // Initially disabled\n      TestBed.tick()\n      await app.whenStable()\n      expect(query.status()).toBe('pending')\n      expect(query.data()).toBeUndefined()\n      expect(callCount).toBe(0)\n\n      // Enable the query\n      enabledSignal.set(true)\n      TestBed.tick()\n\n      await app.whenStable()\n      expect(query.status()).toBe('success')\n      expect(query.data()).toBe('sync-data-1')\n      expect(callCount).toBe(1)\n    })\n\n    test('should handle query invalidation with synchronous data', async () => {\n      TestBed.resetTestingModule()\n      TestBed.configureTestingModule({\n        providers: [\n          provideZonelessChangeDetection(),\n          provideTanStackQuery(queryClient),\n        ],\n      })\n\n      const app = TestBed.inject(ApplicationRef)\n      const testKey = ['sync-invalidate']\n      let callCount = 0\n\n      const query = TestBed.runInInjectionContext(() =>\n        injectQuery(() => ({\n          queryKey: testKey,\n          queryFn: () => {\n            callCount++\n            return `sync-data-${callCount}`\n          },\n        })),\n      )\n\n      // Synchronize pending effects\n      TestBed.tick()\n\n      await app.whenStable()\n      expect(query.status()).toBe('success')\n      expect(query.data()).toBe('sync-data-1')\n      expect(callCount).toBe(1)\n\n      // Invalidate the query\n      queryClient.invalidateQueries({ queryKey: testKey })\n      TestBed.tick()\n\n      // Wait for the invalidation to trigger a refetch\n      await Promise.resolve()\n      await vi.advanceTimersByTimeAsync(10)\n      TestBed.tick()\n\n      await app.whenStable()\n      expect(query.status()).toBe('success')\n      expect(query.data()).toBe('sync-data-2')\n      expect(callCount).toBe(2)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/mutation-options.test-d.ts",
    "content": "import { assertType, describe, expectTypeOf, it } from 'vitest'\nimport { QueryClient } from '@tanstack/query-core'\nimport {\n  injectIsMutating,\n  injectMutation,\n  injectMutationState,\n  mutationOptions,\n} from '..'\nimport type {\n  DefaultError,\n  MutationFunctionContext,\n  MutationState,\n  WithRequired,\n} from '@tanstack/query-core'\nimport type { CreateMutationOptions, CreateMutationResult } from '../types'\n\ndescribe('mutationOptions', () => {\n  it('should not allow excess properties', () => {\n    // @ts-expect-error this is a good error, because onMutates does not exist!\n    mutationOptions({\n      mutationFn: () => Promise.resolve(5),\n      mutationKey: ['key'],\n      onMutates: 1000,\n      onSuccess: (data) => {\n        expectTypeOf(data).toEqualTypeOf<number>()\n      },\n    })\n  })\n\n  it('should infer types for callbacks', () => {\n    mutationOptions({\n      mutationFn: () => Promise.resolve(5),\n      mutationKey: ['key'],\n      onSuccess: (data) => {\n        expectTypeOf(data).toEqualTypeOf<number>()\n      },\n    })\n  })\n\n  it('should infer types for onError callback', () => {\n    mutationOptions({\n      mutationFn: () => {\n        throw new Error('fail')\n      },\n      mutationKey: ['key'],\n      onError: (error) => {\n        expectTypeOf(error).toEqualTypeOf<DefaultError>()\n      },\n    })\n  })\n\n  it('should infer types for variables', () => {\n    mutationOptions<number, DefaultError, { id: string }>({\n      mutationFn: (vars) => {\n        expectTypeOf(vars).toEqualTypeOf<{ id: string }>()\n        return Promise.resolve(5)\n      },\n      mutationKey: ['with-vars'],\n    })\n  })\n\n  it('should infer result type correctly', () => {\n    mutationOptions<number, DefaultError, void, { name: string }>({\n      mutationFn: () => Promise.resolve(5),\n      mutationKey: ['key'],\n      onMutate: () => {\n        return { name: 'onMutateResult' }\n      },\n      onSuccess: (_data, _variables, onMutateResult) => {\n        expectTypeOf(onMutateResult).toEqualTypeOf<{ name: string }>()\n      },\n    })\n  })\n\n  it('should infer context type correctly', () => {\n    mutationOptions<number>({\n      mutationFn: (_variables, context) => {\n        expectTypeOf(context).toEqualTypeOf<MutationFunctionContext>()\n        return Promise.resolve(5)\n      },\n      mutationKey: ['key'],\n      onMutate: (_variables, context) => {\n        expectTypeOf(context).toEqualTypeOf<MutationFunctionContext>()\n      },\n      onSuccess: (_data, _variables, _onMutateResult, context) => {\n        expectTypeOf(context).toEqualTypeOf<MutationFunctionContext>()\n      },\n      onError: (_error, _variables, _onMutateResult, context) => {\n        expectTypeOf(context).toEqualTypeOf<MutationFunctionContext>()\n      },\n      onSettled: (_data, _error, _variables, _onMutateResult, context) => {\n        expectTypeOf(context).toEqualTypeOf<MutationFunctionContext>()\n      },\n    })\n  })\n\n  it('should error if mutationFn return type mismatches TData', () => {\n    assertType(\n      mutationOptions<number>({\n        // @ts-expect-error this is a good error, because return type is string, not number\n        mutationFn: async () => Promise.resolve('wrong return'),\n      }),\n    )\n  })\n\n  it('should allow mutationKey to be omitted', () => {\n    return mutationOptions({\n      mutationFn: () => Promise.resolve(123),\n      onSuccess: (data) => {\n        expectTypeOf(data).toEqualTypeOf<number>()\n      },\n    })\n  })\n\n  it('should infer all types when not explicitly provided', () => {\n    expectTypeOf(\n      mutationOptions({\n        mutationFn: (id: string) => Promise.resolve(id.length),\n        mutationKey: ['key'],\n        onSuccess: (data) => {\n          expectTypeOf(data).toEqualTypeOf<number>()\n        },\n      }),\n    ).toEqualTypeOf<\n      WithRequired<\n        CreateMutationOptions<number, DefaultError, string>,\n        'mutationKey'\n      >\n    >()\n    expectTypeOf(\n      mutationOptions({\n        mutationFn: (id: string) => Promise.resolve(id.length),\n        onSuccess: (data) => {\n          expectTypeOf(data).toEqualTypeOf<number>()\n        },\n      }),\n    ).toEqualTypeOf<\n      Omit<CreateMutationOptions<number, DefaultError, string>, 'mutationKey'>\n    >()\n  })\n\n  it('should infer types when used with injectMutation', () => {\n    const mutation = injectMutation(() =>\n      mutationOptions({\n        mutationKey: ['key'],\n        mutationFn: () => Promise.resolve('data'),\n        onSuccess: (data) => {\n          expectTypeOf(data).toEqualTypeOf<string>()\n        },\n      }),\n    )\n    expectTypeOf(mutation).toEqualTypeOf<\n      CreateMutationResult<string, DefaultError, void, unknown>\n    >()\n\n    injectMutation(\n      // should allow when used with injectMutation without mutationKey\n      () =>\n        mutationOptions({\n          mutationFn: () => Promise.resolve('data'),\n          onSuccess: (data) => {\n            expectTypeOf(data).toEqualTypeOf<string>()\n          },\n        }),\n    )\n  })\n\n  it('should infer types when used with injectIsMutating', () => {\n    const isMutating = injectIsMutating(\n      mutationOptions({\n        mutationKey: ['key'],\n        mutationFn: () => Promise.resolve(5),\n      }),\n    )\n    expectTypeOf(isMutating()).toEqualTypeOf<number>()\n\n    injectIsMutating(\n      // @ts-expect-error filters should have mutationKey\n      mutationOptions({\n        mutationFn: () => Promise.resolve(5),\n      }),\n    )\n  })\n\n  it('should infer types when used with queryClient.isMutating', () => {\n    const queryClient = new QueryClient()\n\n    const isMutating = queryClient.isMutating(\n      mutationOptions({\n        mutationKey: ['key'],\n        mutationFn: () => Promise.resolve(5),\n      }),\n    )\n    expectTypeOf(isMutating).toEqualTypeOf<number>()\n\n    queryClient.isMutating(\n      // @ts-expect-error filters should have mutationKey\n      mutationOptions({\n        mutationFn: () => Promise.resolve(5),\n      }),\n    )\n  })\n\n  it('should infer types when used with injectMutationState', () => {\n    const mutationState = injectMutationState(() => ({\n      filters: mutationOptions({\n        mutationKey: ['key'],\n        mutationFn: () => Promise.resolve(5),\n      }),\n    }))\n    expectTypeOf(mutationState()).toEqualTypeOf<\n      Array<MutationState<unknown, Error, unknown, unknown>>\n    >()\n\n    injectMutationState({\n      // @ts-expect-error filters should have mutationKey\n      filters: mutationOptions({\n        mutationFn: () => Promise.resolve(5),\n      }),\n    })\n  })\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/mutation-options.test.ts",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { provideZonelessChangeDetection } from '@angular/core'\nimport { TestBed } from '@angular/core/testing'\nimport { QueryClient } from '@tanstack/query-core'\nimport { sleep } from '@tanstack/query-test-utils'\nimport {\n  injectIsMutating,\n  injectMutation,\n  injectMutationState,\n  mutationOptions,\n  provideTanStackQuery,\n} from '..'\nimport type { CreateMutationOptions } from '../types'\n\ndescribe('mutationOptions', () => {\n  let queryClient: QueryClient\n\n  beforeEach(() => {\n    vi.useFakeTimers()\n    queryClient = new QueryClient()\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(queryClient),\n      ],\n    })\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should return the object received as a parameter without any modification (with mutationKey in mutationOptions)', () => {\n    const object: CreateMutationOptions = {\n      mutationKey: ['key'],\n      mutationFn: () => sleep(10).then(() => 5),\n    } as const\n\n    expect(mutationOptions(object)).toBe(object)\n  })\n\n  it('should return the object received as a parameter without any modification (without mutationKey in mutationOptions)', () => {\n    const object: CreateMutationOptions = {\n      mutationFn: () => sleep(10).then(() => 5),\n    } as const\n\n    expect(mutationOptions(object)).toBe(object)\n  })\n\n  it('should return the number of fetching mutations when used with injectIsMutating (with mutationKey in mutationOptions)', async () => {\n    const mutationOpts = mutationOptions({\n      mutationKey: ['key'],\n      mutationFn: () => sleep(50).then(() => 'data'),\n    })\n\n    const [mutation, isMutating] = TestBed.runInInjectionContext(() => [\n      injectMutation(() => mutationOpts),\n      injectIsMutating(),\n    ])\n\n    expect(isMutating()).toBe(0)\n\n    mutation.mutate()\n    expect(isMutating()).toBe(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isMutating()).toBe(1)\n    await vi.advanceTimersByTimeAsync(51)\n    expect(isMutating()).toBe(0)\n  })\n\n  it('should return the number of fetching mutations when used with injectIsMutating (without mutationKey in mutationOptions)', async () => {\n    const mutationOpts = mutationOptions({\n      mutationFn: () => sleep(50).then(() => 'data'),\n    })\n\n    const [mutation, isMutating] = TestBed.runInInjectionContext(() => [\n      injectMutation(() => mutationOpts),\n      injectIsMutating(),\n    ])\n\n    expect(isMutating()).toBe(0)\n\n    mutation.mutate()\n    expect(isMutating()).toBe(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isMutating()).toBe(1)\n    await vi.advanceTimersByTimeAsync(51)\n    expect(isMutating()).toBe(0)\n  })\n\n  it('should return the number of fetching mutations when used with injectIsMutating', async () => {\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['key'],\n      mutationFn: () => sleep(50).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(50).then(() => 'data2'),\n    })\n\n    const [mutation1, mutation2, isMutating] = TestBed.runInInjectionContext(\n      () => [\n        injectMutation(() => mutationOpts1),\n        injectMutation(() => mutationOpts2),\n        injectIsMutating(),\n      ],\n    )\n\n    expect(isMutating()).toBe(0)\n\n    mutation1.mutate()\n    mutation2.mutate()\n    expect(isMutating()).toBe(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isMutating()).toBe(2)\n    await vi.advanceTimersByTimeAsync(51)\n    expect(isMutating()).toBe(0)\n  })\n\n  it('should return the number of fetching mutations when used with injectIsMutating (filter mutationOpts1.mutationKey)', async () => {\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['key'],\n      mutationFn: () => sleep(50).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(50).then(() => 'data2'),\n    })\n\n    const [mutation1, mutation2, isMutating] = TestBed.runInInjectionContext(\n      () => [\n        injectMutation(() => mutationOpts1),\n        injectMutation(() => mutationOpts2),\n        injectIsMutating({ mutationKey: mutationOpts1.mutationKey }),\n      ],\n    )\n\n    expect(isMutating()).toBe(0)\n\n    mutation1.mutate()\n    mutation2.mutate()\n    expect(isMutating()).toBe(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isMutating()).toBe(1)\n    await vi.advanceTimersByTimeAsync(51)\n    expect(isMutating()).toBe(0)\n  })\n\n  it('should return the number of fetching mutations when used with queryClient.isMutating (with mutationKey in mutationOptions)', async () => {\n    const mutationOpts = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(500).then(() => 'data'),\n    })\n\n    const mutation = TestBed.runInInjectionContext(() =>\n      injectMutation(() => mutationOpts),\n    )\n\n    expect(queryClient.isMutating(mutationOpts)).toBe(0)\n\n    mutation.mutate()\n    expect(queryClient.isMutating(mutationOpts)).toBe(1)\n    await vi.advanceTimersByTimeAsync(501)\n    expect(queryClient.isMutating(mutationOpts)).toBe(0)\n  })\n\n  it('should return the number of fetching mutations when used with queryClient.isMutating (without mutationKey in mutationOptions)', async () => {\n    const mutationOpts = mutationOptions({\n      mutationFn: () => sleep(500).then(() => 'data'),\n    })\n\n    const mutation = TestBed.runInInjectionContext(() =>\n      injectMutation(() => mutationOpts),\n    )\n\n    expect(queryClient.isMutating()).toBe(0)\n\n    mutation.mutate()\n    expect(queryClient.isMutating()).toBe(1)\n    await vi.advanceTimersByTimeAsync(501)\n    expect(queryClient.isMutating()).toBe(0)\n  })\n\n  it('should return the number of fetching mutations when used with queryClient.isMutating', async () => {\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(500).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(500).then(() => 'data2'),\n    })\n\n    const [mutation1, mutation2] = TestBed.runInInjectionContext(() => [\n      injectMutation(() => mutationOpts1),\n      injectMutation(() => mutationOpts2),\n    ])\n\n    expect(queryClient.isMutating()).toBe(0)\n\n    mutation1.mutate()\n    mutation2.mutate()\n    expect(queryClient.isMutating()).toBe(2)\n    await vi.advanceTimersByTimeAsync(501)\n    expect(queryClient.isMutating()).toBe(0)\n  })\n\n  it('should return the number of fetching mutations when used with queryClient.isMutating (filter mutationOpt1.mutationKey)', async () => {\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(500).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(500).then(() => 'data2'),\n    })\n\n    const [mutation1, mutation2] = TestBed.runInInjectionContext(() => [\n      injectMutation(() => mutationOpts1),\n      injectMutation(() => mutationOpts2),\n    ])\n\n    expect(\n      queryClient.isMutating({ mutationKey: mutationOpts1.mutationKey }),\n    ).toBe(0)\n\n    mutation1.mutate()\n    mutation2.mutate()\n    expect(\n      queryClient.isMutating({ mutationKey: mutationOpts1.mutationKey }),\n    ).toBe(1)\n    await vi.advanceTimersByTimeAsync(501)\n    expect(\n      queryClient.isMutating({ mutationKey: mutationOpts1.mutationKey }),\n    ).toBe(0)\n  })\n\n  it('should return the number of fetching mutations when used with injectMutationState (with mutationKey in mutationOptions)', async () => {\n    const mutationOpts = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(10).then(() => 'data'),\n    })\n\n    const [mutation, mutationState] = TestBed.runInInjectionContext(() => [\n      injectMutation(() => mutationOpts),\n      injectMutationState(() => ({\n        filters: { mutationKey: mutationOpts.mutationKey, status: 'success' },\n      })),\n    ])\n\n    expect(mutationState().length).toBe(0)\n\n    mutation.mutate()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(mutationState().length).toBe(1)\n    expect(mutationState()[0]?.data).toBe('data')\n  })\n\n  it('should return the number of fetching mutations when used with injectMutationState (without mutationKey in mutationOptions)', async () => {\n    const mutationOpts = mutationOptions({\n      mutationFn: () => sleep(10).then(() => 'data'),\n    })\n\n    const [mutation, mutationState] = TestBed.runInInjectionContext(() => [\n      injectMutation(() => mutationOpts),\n      injectMutationState(() => ({\n        filters: { status: 'success' },\n      })),\n    ])\n\n    expect(mutationState().length).toBe(0)\n\n    mutation.mutate()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(mutationState().length).toBe(1)\n    expect(mutationState()[0]?.data).toBe('data')\n  })\n\n  it('should return the number of fetching mutations when used with injectMutationState', async () => {\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(10).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(10).then(() => 'data2'),\n    })\n\n    const [mutation1, mutation2, mutationState] = TestBed.runInInjectionContext(\n      () => [\n        injectMutation(() => mutationOpts1),\n        injectMutation(() => mutationOpts2),\n        injectMutationState(() => ({\n          filters: { status: 'success' },\n        })),\n      ],\n    )\n\n    expect(mutationState().length).toBe(0)\n\n    mutation1.mutate()\n    mutation2.mutate()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(mutationState().length).toBe(2)\n    expect(mutationState()[0]?.data).toBe('data1')\n    expect(mutationState()[1]?.data).toBe('data2')\n  })\n\n  it('should return the number of fetching mutations when used with injectMutationState (filter mutationOpt1.mutationKey)', async () => {\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(10).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(10).then(() => 'data2'),\n    })\n\n    const [mutation1, mutation2, mutationState] = TestBed.runInInjectionContext(\n      () => [\n        injectMutation(() => mutationOpts1),\n        injectMutation(() => mutationOpts2),\n        injectMutationState(() => ({\n          filters: {\n            mutationKey: mutationOpts1.mutationKey,\n            status: 'success',\n          },\n        })),\n      ],\n    )\n\n    expect(mutationState().length).toBe(0)\n\n    mutation1.mutate()\n    mutation2.mutate()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(mutationState().length).toBe(1)\n    expect(mutationState()[0]?.data).toBe('data1')\n  })\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/pending-tasks.test.ts",
    "content": "import {\n  ApplicationRef,\n  Component,\n  provideZonelessChangeDetection,\n} from '@angular/core'\nimport { TestBed } from '@angular/core/testing'\nimport { HttpClient, provideHttpClient } from '@angular/common/http'\nimport {\n  HttpTestingController,\n  provideHttpClientTesting,\n} from '@angular/common/http/testing'\nimport { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { lastValueFrom } from 'rxjs'\nimport {\n  QueryClient,\n  injectMutation,\n  injectQuery,\n  onlineManager,\n  provideTanStackQuery,\n} from '..'\n\ndescribe('PendingTasks Integration', () => {\n  let queryClient: QueryClient\n\n  beforeEach(() => {\n    vi.useFakeTimers()\n\n    queryClient = new QueryClient({\n      defaultOptions: {\n        queries: {\n          retry: false,\n        },\n        mutations: {\n          retry: false,\n        },\n      },\n    })\n\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(queryClient),\n      ],\n    })\n  })\n\n  afterEach(() => {\n    onlineManager.setOnline(true)\n    vi.useRealTimers()\n    queryClient.clear()\n  })\n\n  describe('Synchronous Resolution', () => {\n    test('should handle synchronous queryFn with whenStable()', async () => {\n      const app = TestBed.inject(ApplicationRef)\n\n      const query = TestBed.runInInjectionContext(() =>\n        injectQuery(() => ({\n          queryKey: ['sync'],\n          queryFn: () => 'instant-data', // Resolves synchronously\n        })),\n      )\n\n      // Should start as pending even with synchronous data\n      expect(query.status()).toBe('pending')\n      expect(query.data()).toBeUndefined()\n\n      const stablePromise = app.whenStable()\n      // Flush microtasks to allow TanStack Query's scheduled notifications to process\n      await Promise.resolve()\n      await vi.advanceTimersByTimeAsync(10)\n      await stablePromise\n\n      // Should work correctly even though queryFn was synchronous\n      expect(query.status()).toBe('success')\n      expect(query.data()).toBe('instant-data')\n    })\n\n    test('should handle synchronous error with whenStable()', async () => {\n      const app = TestBed.inject(ApplicationRef)\n\n      const query = TestBed.runInInjectionContext(() =>\n        injectQuery(() => ({\n          queryKey: ['sync-error'],\n          queryFn: () => {\n            throw new Error('instant-error')\n          }, // Throws synchronously\n        })),\n      )\n\n      const stablePromise = app.whenStable()\n      // Flush microtasks to allow TanStack Query's scheduled notifications to process\n      await Promise.resolve()\n      await vi.advanceTimersByTimeAsync(10)\n      await stablePromise\n\n      expect(query.status()).toBe('error')\n      expect(query.error()).toEqual(new Error('instant-error'))\n    })\n\n    test('should handle synchronous mutationFn with whenStable()', async () => {\n      const app = TestBed.inject(ApplicationRef)\n      let mutationFnCalled = false\n\n      const mutation = TestBed.runInInjectionContext(() =>\n        injectMutation(() => ({\n          mutationFn: async (data: string) => {\n            mutationFnCalled = true\n            await Promise.resolve()\n            return `processed: ${data}`\n          },\n        })),\n      )\n\n      mutation.mutate('test')\n\n      TestBed.tick()\n\n      const stablePromise = app.whenStable()\n      await Promise.resolve()\n      await vi.advanceTimersByTimeAsync(10)\n      await stablePromise\n\n      expect(mutationFnCalled).toBe(true)\n      expect(mutation.isSuccess()).toBe(true)\n      expect(mutation.data()).toBe('processed: test')\n    })\n\n    test('should handle synchronous mutation error with whenStable()', async () => {\n      const app = TestBed.inject(ApplicationRef)\n\n      const mutation = TestBed.runInInjectionContext(() =>\n        injectMutation(() => ({\n          mutationFn: async () => {\n            await Promise.resolve()\n            throw new Error('sync-mutation-error')\n          },\n        })),\n      )\n\n      mutation.mutate()\n\n      TestBed.tick()\n\n      const stablePromise = app.whenStable()\n      await Promise.resolve()\n      await vi.advanceTimersByTimeAsync(10)\n      await stablePromise\n\n      expect(mutation.isError()).toBe(true)\n      expect(mutation.error()).toEqual(new Error('sync-mutation-error'))\n    })\n  })\n\n  describe('Race Conditions', () => {\n    test('should handle query that completes during initial subscription', async () => {\n      const app = TestBed.inject(ApplicationRef)\n      let resolveQuery: (value: string) => void\n\n      const queryPromise = new Promise<string>((resolve) => {\n        resolveQuery = resolve\n      })\n\n      const query = TestBed.runInInjectionContext(() =>\n        injectQuery(() => ({\n          queryKey: ['race-condition'],\n          queryFn: () => queryPromise,\n        })),\n      )\n\n      // Resolve immediately to create potential race condition\n      resolveQuery!('race-data')\n\n      const stablePromise = app.whenStable()\n      await Promise.resolve()\n      await vi.advanceTimersByTimeAsync(10)\n      await stablePromise\n\n      expect(query.status()).toBe('success')\n      expect(query.data()).toBe('race-data')\n    })\n\n    test('should handle rapid refetches without task leaks', async () => {\n      const app = TestBed.inject(ApplicationRef)\n      let callCount = 0\n\n      const query = TestBed.runInInjectionContext(() =>\n        injectQuery(() => ({\n          queryKey: ['rapid-refetch'],\n          queryFn: async () => {\n            callCount++\n            await sleep(10)\n            return `data-${callCount}`\n          },\n        })),\n      )\n\n      // Trigger multiple rapid refetches\n      query.refetch()\n      query.refetch()\n      query.refetch()\n\n      const stablePromise = app.whenStable()\n      await vi.advanceTimersByTimeAsync(20)\n      await stablePromise\n\n      expect(query.status()).toBe('success')\n      expect(query.data()).toMatch(/^data-\\d+$/)\n    })\n\n    test('should keep PendingTasks active while query retry is paused offline', async () => {\n      const app = TestBed.inject(ApplicationRef)\n      let attempt = 0\n\n      const query = TestBed.runInInjectionContext(() =>\n        injectQuery(() => ({\n          queryKey: ['paused-offline'],\n          retry: 1,\n          retryDelay: 50, // Longer delay to ensure we can go offline before retry\n          queryFn: async () => {\n            attempt++\n            if (attempt === 1) {\n              throw new Error('offline-fail')\n            }\n            await sleep(10)\n            return 'final-data'\n          },\n        })),\n      )\n\n      // Allow the initial attempt to start and fail\n      await vi.advanceTimersByTimeAsync(0)\n      await Promise.resolve()\n\n      // Wait for the first attempt to complete and start retry delay\n      await vi.advanceTimersByTimeAsync(10)\n      await Promise.resolve()\n\n      expect(query.status()).toBe('pending')\n      expect(query.fetchStatus()).toBe('fetching')\n\n      // Simulate the app going offline during retry delay\n      onlineManager.setOnline(false)\n\n      // Advance past the retry delay to trigger the pause\n      await vi.advanceTimersByTimeAsync(50)\n      await Promise.resolve()\n\n      expect(query.fetchStatus()).toBe('paused')\n\n      const stablePromise = app.whenStable()\n      let stableResolved = false\n      void stablePromise.then(() => {\n        stableResolved = true\n      })\n\n      await Promise.resolve()\n\n      // PendingTasks should continue blocking stability while the fetch is paused\n      expect(stableResolved).toBe(false)\n      expect(query.status()).toBe('pending')\n\n      // Bring the app back online so the retry can continue\n      onlineManager.setOnline(true)\n\n      // Give time for the retry to resume and complete\n      await vi.advanceTimersByTimeAsync(20)\n      await Promise.resolve()\n\n      await stablePromise\n\n      expect(stableResolved).toBe(true)\n      expect(query.status()).toBe('success')\n      expect(query.data()).toBe('final-data')\n    })\n  })\n\n  describe('Component Destruction', () => {\n    @Component({\n      template: '',\n    })\n    class TestComponent {\n      query = injectQuery(() => ({\n        queryKey: ['component-query'],\n        queryFn: async () => {\n          await sleep(100)\n          return 'component-data'\n        },\n      }))\n\n      mutation = injectMutation(() => ({\n        mutationFn: async (data: string) => {\n          await sleep(100)\n          return `processed: ${data}`\n        },\n      }))\n    }\n\n    test('should cleanup pending tasks when component with active query is destroyed', async () => {\n      const app = TestBed.inject(ApplicationRef)\n      const fixture = TestBed.createComponent(TestComponent)\n\n      // Start the query\n      expect(fixture.componentInstance.query.status()).toBe('pending')\n\n      // Destroy component while query is running\n      fixture.destroy()\n\n      // Angular should become stable even though component was destroyed\n      const stablePromise = app.whenStable()\n      await vi.advanceTimersByTimeAsync(150)\n\n      await expect(stablePromise).resolves.toEqual(undefined)\n    })\n\n    test('should cleanup pending tasks when component with active mutation is destroyed', async () => {\n      const app = TestBed.inject(ApplicationRef)\n      const fixture = TestBed.createComponent(TestComponent)\n\n      fixture.componentInstance.mutation.mutate('test')\n\n      // Destroy component while mutation is running\n      fixture.destroy()\n\n      // Angular should become stable even though component was destroyed\n      const stablePromise = app.whenStable()\n      await vi.advanceTimersByTimeAsync(150)\n\n      await expect(stablePromise).resolves.toEqual(undefined)\n    })\n  })\n\n  describe('Concurrent Operations', () => {\n    test('should handle multiple queries running simultaneously', async () => {\n      const app = TestBed.inject(ApplicationRef)\n\n      const query1 = TestBed.runInInjectionContext(() =>\n        injectQuery(() => ({\n          queryKey: ['concurrent-1'],\n          queryFn: async () => {\n            await sleep(30)\n            return 'data-1'\n          },\n        })),\n      )\n\n      const query2 = TestBed.runInInjectionContext(() =>\n        injectQuery(() => ({\n          queryKey: ['concurrent-2'],\n          queryFn: async () => {\n            await sleep(50)\n            return 'data-2'\n          },\n        })),\n      )\n\n      const query3 = TestBed.runInInjectionContext(() =>\n        injectQuery(() => ({\n          queryKey: ['concurrent-3'],\n          queryFn: () => 'instant-data', // Synchronous\n        })),\n      )\n\n      // All queries should start\n      expect(query1.status()).toBe('pending')\n      expect(query2.status()).toBe('pending')\n      expect(query3.status()).toBe('pending')\n\n      const stablePromise = app.whenStable()\n      await vi.advanceTimersByTimeAsync(60)\n      await stablePromise\n\n      // All queries should be complete\n      expect(query1.status()).toBe('success')\n      expect(query1.data()).toBe('data-1')\n      expect(query2.status()).toBe('success')\n      expect(query2.data()).toBe('data-2')\n      expect(query3.status()).toBe('success')\n      expect(query3.data()).toBe('instant-data')\n    })\n\n    test('should handle multiple mutations running simultaneously', async () => {\n      const app = TestBed.inject(ApplicationRef)\n\n      const mutation1 = TestBed.runInInjectionContext(() =>\n        injectMutation(() => ({\n          mutationFn: async (data: string) => {\n            await sleep(30)\n            return `processed-1: ${data}`\n          },\n        })),\n      )\n\n      const mutation2 = TestBed.runInInjectionContext(() =>\n        injectMutation(() => ({\n          mutationFn: async (data: string) => {\n            await sleep(50)\n            return `processed-2: ${data}`\n          },\n        })),\n      )\n\n      const mutation3 = TestBed.runInInjectionContext(() =>\n        injectMutation(() => ({\n          mutationFn: async (data: string) => {\n            await Promise.resolve()\n            return `processed-3: ${data}`\n          },\n        })),\n      )\n\n      // Start all mutations\n      mutation1.mutate('test1')\n      mutation2.mutate('test2')\n      mutation3.mutate('test3')\n\n      TestBed.tick()\n\n      const stablePromise = app.whenStable()\n      await vi.advanceTimersByTimeAsync(60)\n      await stablePromise\n\n      // All mutations should be complete\n      expect(mutation1.isSuccess()).toBe(true)\n      expect(mutation1.data()).toBe('processed-1: test1')\n      expect(mutation2.isSuccess()).toBe(true)\n      expect(mutation2.data()).toBe('processed-2: test2')\n      expect(mutation3.isSuccess()).toBe(true)\n      expect(mutation3.data()).toBe('processed-3: test3')\n    })\n\n    test('should handle mixed queries and mutations', async () => {\n      const app = TestBed.inject(ApplicationRef)\n\n      const query = TestBed.runInInjectionContext(() =>\n        injectQuery(() => ({\n          queryKey: ['mixed-query'],\n          queryFn: async () => {\n            await sleep(40)\n            return 'query-data'\n          },\n        })),\n      )\n\n      const mutation = TestBed.runInInjectionContext(() =>\n        injectMutation(() => ({\n          mutationFn: async (data: string) => {\n            await sleep(60)\n            return `mutation: ${data}`\n          },\n        })),\n      )\n\n      // Start both operations\n      mutation.mutate('test')\n\n      const stablePromise = app.whenStable()\n      await vi.advanceTimersByTimeAsync(70)\n      await stablePromise\n\n      // Both should be complete\n      expect(query.status()).toBe('success')\n      expect(query.data()).toBe('query-data')\n      expect(mutation.isSuccess()).toBe(true)\n      expect(mutation.data()).toBe('mutation: test')\n    })\n  })\n\n  describe('HttpClient Integration', () => {\n    beforeEach(() => {\n      TestBed.resetTestingModule()\n      TestBed.configureTestingModule({\n        providers: [\n          provideZonelessChangeDetection(),\n          provideTanStackQuery(queryClient),\n          provideHttpClient(),\n          provideHttpClientTesting(),\n        ],\n      })\n    })\n\n    test('should handle multiple HttpClient requests with lastValueFrom', async () => {\n      const app = TestBed.inject(ApplicationRef)\n      const httpClient = TestBed.inject(HttpClient)\n      const httpTestingController = TestBed.inject(HttpTestingController)\n\n      const query1 = TestBed.runInInjectionContext(() =>\n        injectQuery(() => ({\n          queryKey: ['http-1'],\n          queryFn: () =>\n            lastValueFrom(httpClient.get<{ id: number }>('/api/1')),\n        })),\n      )\n\n      const query2 = TestBed.runInInjectionContext(() =>\n        injectQuery(() => ({\n          queryKey: ['http-2'],\n          queryFn: () =>\n            lastValueFrom(httpClient.get<{ id: number }>('/api/2')),\n        })),\n      )\n\n      // Schedule HTTP responses\n      setTimeout(() => {\n        const req1 = httpTestingController.expectOne('/api/1')\n        req1.flush({ id: 1 })\n\n        const req2 = httpTestingController.expectOne('/api/2')\n        req2.flush({ id: 2 })\n      }, 10)\n\n      const stablePromise = app.whenStable()\n      await vi.advanceTimersByTimeAsync(20)\n      await stablePromise\n\n      expect(query1.status()).toBe('success')\n      expect(query1.data()).toEqual({ id: 1 })\n      expect(query2.status()).toBe('success')\n      expect(query2.data()).toEqual({ id: 2 })\n\n      httpTestingController.verify()\n    })\n\n    test('should handle HttpClient request cancellation', async () => {\n      const app = TestBed.inject(ApplicationRef)\n      const httpClient = TestBed.inject(HttpClient)\n      const httpTestingController = TestBed.inject(HttpTestingController)\n\n      const query = TestBed.runInInjectionContext(() =>\n        injectQuery(() => ({\n          queryKey: ['http-cancel'],\n          queryFn: () =>\n            lastValueFrom(httpClient.get<{ data: string }>('/api/cancel')),\n        })),\n      )\n\n      // Cancel the request before it completes\n      setTimeout(() => {\n        const req = httpTestingController.expectOne('/api/cancel')\n        req.error(new ProgressEvent('error'), {\n          status: 0,\n          statusText: 'Unknown Error',\n        })\n      }, 10)\n\n      const stablePromise = app.whenStable()\n      await vi.advanceTimersByTimeAsync(20)\n      await stablePromise\n\n      expect(query.status()).toBe('error')\n\n      httpTestingController.verify()\n    })\n  })\n\n  describe('Edge Cases', () => {\n    test('should handle query cancellation mid-flight', async () => {\n      const app = TestBed.inject(ApplicationRef)\n\n      const query = TestBed.runInInjectionContext(() =>\n        injectQuery(() => ({\n          queryKey: ['cancel-test'],\n          queryFn: async () => {\n            await sleep(100)\n            return 'data'\n          },\n        })),\n      )\n\n      // Cancel the query after a short delay\n      setTimeout(() => {\n        queryClient.cancelQueries({ queryKey: ['cancel-test'] })\n      }, 20)\n\n      // Advance to the cancellation point\n      await vi.advanceTimersByTimeAsync(20)\n\n      TestBed.tick()\n\n      const stablePromise = app.whenStable()\n      await vi.advanceTimersByTimeAsync(130)\n      await stablePromise\n\n      // Cancellation should restore the pre-fetch state\n      expect(query.status()).toBe('pending')\n      expect(query.fetchStatus()).toBe('idle')\n    })\n\n    test('should handle query retry and pending task tracking', async () => {\n      const app = TestBed.inject(ApplicationRef)\n      let attemptCount = 0\n\n      const query = TestBed.runInInjectionContext(() =>\n        injectQuery(() => ({\n          queryKey: ['retry-test'],\n          retry: 2,\n          retryDelay: 10,\n          queryFn: async () => {\n            attemptCount++\n            if (attemptCount <= 2) {\n              throw new Error(`Attempt ${attemptCount} failed`)\n            }\n            return 'success-data'\n          },\n        })),\n      )\n\n      const stablePromise = app.whenStable()\n      await vi.advanceTimersByTimeAsync(50)\n      await stablePromise\n\n      expect(query.status()).toBe('success')\n      expect(query.data()).toBe('success-data')\n      expect(attemptCount).toBe(3) // Initial + 2 retries\n    })\n\n    test('should handle mutation with optimistic updates', async () => {\n      const app = TestBed.inject(ApplicationRef)\n      const testQueryKey = ['optimistic-test']\n\n      queryClient.setQueryData(testQueryKey, 'initial-data')\n\n      const mutation = TestBed.runInInjectionContext(() =>\n        injectMutation(() => ({\n          mutationFn: async (newData: string) => {\n            await sleep(50)\n            return newData\n          },\n          onMutate: async (newData) => {\n            // Optimistic update\n            const previousData = queryClient.getQueryData(testQueryKey)\n            queryClient.setQueryData(testQueryKey, newData)\n            return { previousData }\n          },\n          onError: (_err, _newData, context) => {\n            // Rollback on error\n            if (context?.previousData) {\n              queryClient.setQueryData(testQueryKey, context.previousData)\n            }\n          },\n        })),\n      )\n\n      mutation.mutate('optimistic-data')\n\n      await Promise.resolve()\n\n      // Data should be optimistically updated immediately\n      expect(queryClient.getQueryData(testQueryKey)).toBe('optimistic-data')\n\n      const stablePromise = app.whenStable()\n      await vi.advanceTimersByTimeAsync(60)\n      await stablePromise\n\n      expect(mutation.isSuccess()).toBe(true)\n      expect(mutation.data()).toBe('optimistic-data')\n      expect(queryClient.getQueryData(testQueryKey)).toBe('optimistic-data')\n    })\n  })\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/provide-query-client.test.ts",
    "content": "import { TestBed } from '@angular/core/testing'\nimport { describe, expect, test } from 'vitest'\nimport { InjectionToken, provideZonelessChangeDetection } from '@angular/core'\nimport { QueryClient } from '@tanstack/query-core'\nimport { provideQueryClient } from '../providers'\n\ndescribe('provideQueryClient', () => {\n  test('should provide a QueryClient instance directly', () => {\n    const queryClient = new QueryClient()\n\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideQueryClient(queryClient),\n      ],\n    })\n\n    const providedQueryClient = TestBed.inject(QueryClient)\n    expect(providedQueryClient).toBe(queryClient)\n  })\n\n  test('should provide a QueryClient instance using an InjectionToken', () => {\n    const queryClient = new QueryClient()\n    const CUSTOM_QUERY_CLIENT = new InjectionToken<QueryClient>('', {\n      factory: () => queryClient,\n    })\n\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideQueryClient(CUSTOM_QUERY_CLIENT),\n      ],\n    })\n\n    const providedQueryClient = TestBed.inject(QueryClient)\n    expect(providedQueryClient).toBe(queryClient)\n  })\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/provide-tanstack-query.test.ts",
    "content": "import { TestBed } from '@angular/core/testing'\nimport { describe, expect, test } from 'vitest'\nimport { InjectionToken, provideZonelessChangeDetection } from '@angular/core'\nimport { QueryClient } from '@tanstack/query-core'\nimport { provideTanStackQuery } from '../providers'\n\ndescribe('provideTanStackQuery', () => {\n  test('should provide a QueryClient instance directly', () => {\n    const queryClient = new QueryClient()\n\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(queryClient),\n      ],\n    })\n\n    const providedQueryClient = TestBed.inject(QueryClient)\n    expect(providedQueryClient).toBe(queryClient)\n  })\n\n  test('should provide a QueryClient instance using an InjectionToken', () => {\n    const queryClient = new QueryClient()\n    const CUSTOM_QUERY_CLIENT = new InjectionToken<QueryClient>('', {\n      factory: () => queryClient,\n    })\n\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(CUSTOM_QUERY_CLIENT),\n      ],\n    })\n\n    const providedQueryClient = TestBed.inject(QueryClient)\n    expect(providedQueryClient).toBe(queryClient)\n  })\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/query-options.test-d.ts",
    "content": "import { assertType, describe, expectTypeOf, test } from 'vitest'\nimport { QueryClient, dataTagSymbol, injectQuery, queryOptions } from '..'\nimport type { Signal } from '@angular/core'\n\ndescribe('queryOptions', () => {\n  test('should not allow excess properties', () => {\n    expectTypeOf(queryOptions).parameter(0).not.toHaveProperty('stallTime')\n  })\n\n  test('should infer types for callbacks', () => {\n    queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n      staleTime: 1000,\n      select: (data) => {\n        expectTypeOf(data).toEqualTypeOf<number>()\n      },\n    })\n  })\n\n  test('should allow undefined response in initialData', () => {\n    const options = (id: string | null) =>\n      queryOptions({\n        queryKey: ['todo', id],\n        queryFn: () =>\n          Promise.resolve({\n            id: '1',\n            title: 'Do Laundry',\n          }),\n        initialData: () =>\n          !id\n            ? undefined\n            : {\n                id,\n                title: 'Initial Data',\n              },\n      })\n\n    expectTypeOf(options(null).initialData).returns.toEqualTypeOf<\n      { id: string; title: string } | undefined\n    >()\n  })\n})\n\ntest('should work when passed to injectQuery', () => {\n  const options = queryOptions({\n    queryKey: ['key'],\n    queryFn: () => Promise.resolve(5),\n  })\n\n  const { data } = injectQuery(() => options)\n  expectTypeOf(data).toEqualTypeOf<Signal<number | undefined>>()\n})\n\ntest('should work when passed to fetchQuery', () => {\n  const options = queryOptions({\n    queryKey: ['key'],\n    queryFn: () => Promise.resolve(5),\n  })\n\n  const data = new QueryClient().fetchQuery(options)\n  assertType<Promise<number>>(data)\n})\n\ntest('should tag the queryKey with the result type of the QueryFn', () => {\n  const { queryKey } = queryOptions({\n    queryKey: ['key'],\n    queryFn: () => Promise.resolve(5),\n  })\n  assertType<number>(queryKey[dataTagSymbol])\n})\n\ntest('should tag the queryKey even if no promise is returned', () => {\n  const { queryKey } = queryOptions({\n    queryKey: ['key'],\n    queryFn: () => 5,\n  })\n  assertType<number>(queryKey[dataTagSymbol])\n})\n\ntest('should tag the queryKey with unknown if there is no queryFn', () => {\n  const { queryKey } = queryOptions({\n    queryKey: ['key'],\n  })\n\n  assertType<unknown>(queryKey[dataTagSymbol])\n})\n\ntest('should tag the queryKey with the result type of the QueryFn if select is used', () => {\n  const { queryKey } = queryOptions({\n    queryKey: ['key'],\n    queryFn: () => Promise.resolve(5),\n    select: (data) => data.toString(),\n  })\n\n  assertType<number>(queryKey[dataTagSymbol])\n})\n\ntest('should return the proper type when passed to getQueryData', () => {\n  const { queryKey } = queryOptions({\n    queryKey: ['key'],\n    queryFn: () => Promise.resolve(5),\n  })\n\n  const queryClient = new QueryClient()\n  const data = queryClient.getQueryData(queryKey)\n\n  expectTypeOf(data).toEqualTypeOf<number | undefined>()\n})\n\ntest('should properly type updaterFn when passed to setQueryData', () => {\n  const { queryKey } = queryOptions({\n    queryKey: ['key'],\n    queryFn: () => Promise.resolve(5),\n  })\n\n  const queryClient = new QueryClient()\n  const data = queryClient.setQueryData(queryKey, (prev) => {\n    expectTypeOf(prev).toEqualTypeOf<number | undefined>()\n    return prev\n  })\n\n  expectTypeOf(data).toEqualTypeOf<number | undefined>()\n})\n\ntest('should properly type value when passed to setQueryData', () => {\n  const { queryKey } = queryOptions({\n    queryKey: ['key'],\n    queryFn: () => Promise.resolve(5),\n  })\n\n  const queryClient = new QueryClient()\n\n  // @ts-expect-error value should be a number\n  queryClient.setQueryData(queryKey, '5')\n  // @ts-expect-error value should be a number\n  queryClient.setQueryData(queryKey, () => '5')\n\n  const data = queryClient.setQueryData(queryKey, 5)\n\n  expectTypeOf(data).toEqualTypeOf<number | undefined>()\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/query-options.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\nimport { queryOptions } from '../query-options'\nimport type { CreateQueryOptions } from '../types'\n\ndescribe('queryOptions', () => {\n  it('should return the object received as a parameter without any modification.', () => {\n    const object: CreateQueryOptions = {\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    } as const\n\n    expect(queryOptions(object)).toBe(object)\n  })\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/signal-proxy.test.ts",
    "content": "import { isSignal, signal } from '@angular/core'\nimport { describe, expect, test } from 'vitest'\nimport { signalProxy } from '../signal-proxy'\n\ndescribe('signalProxy', () => {\n  const inputSignal = signal({ fn: () => 'bar', baz: 'qux' })\n  const proxy = signalProxy(inputSignal)\n\n  test('should have computed fields', () => {\n    expect(proxy.baz()).toEqual('qux')\n    expect(isSignal(proxy.baz)).toBe(true)\n  })\n\n  test('should pass through functions as-is', () => {\n    expect(proxy.fn()).toEqual('bar')\n    expect(isSignal(proxy.fn)).toBe(false)\n  })\n\n  test('supports \"in\" operator', () => {\n    expect('baz' in proxy).toBe(true)\n    expect('foo' in proxy).toBe(false)\n  })\n\n  test('supports \"Object.keys\"', () => {\n    expect(Object.keys(proxy)).toEqual(['fn', 'baz'])\n  })\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/test-utils.ts",
    "content": "import { isSignal, untracked } from '@angular/core'\nimport { SIGNAL, signalSetFn } from '@angular/core/primitives/signals'\nimport { expect } from 'vitest'\nimport type { InputSignal, Signal } from '@angular/core'\nimport type { ComponentFixture } from '@angular/core/testing'\n\n// Evaluate all signals on an object and return the result\nfunction evaluateSignals<T extends Record<string, any>>(\n  obj: T,\n): { [K in keyof T]: ReturnType<T[K]> } {\n  const result: Partial<{ [K in keyof T]: ReturnType<T[K]> }> = {}\n\n  untracked(() => {\n    for (const key in obj) {\n      if (\n        Object.prototype.hasOwnProperty.call(obj, key) &&\n        // Only evaluate signals, not normal functions\n        isSignal(obj[key])\n      ) {\n        const func = obj[key]\n        result[key] = func()\n      }\n    }\n  })\n\n  return result as { [K in keyof T]: ReturnType<T[K]> }\n}\n\nexport const expectSignals = <T extends Record<string, any>>(\n  obj: T,\n  expected: Partial<{\n    [K in keyof T]: T[K] extends Signal<any> ? ReturnType<T[K]> : never\n  }>,\n): void => {\n  expect(evaluateSignals(obj)).toMatchObject(expected)\n}\n\ntype ToSignalInputUpdatableMap<T> = {\n  [K in keyof T as T[K] extends InputSignal<any>\n    ? K\n    : never]: T[K] extends InputSignal<infer Value> ? Value : never\n}\n\nfunction componentHasSignalInputProperty<TProperty extends string>(\n  component: object,\n  property: TProperty,\n): component is { [key in TProperty]: InputSignal<unknown> } {\n  return (\n    component.hasOwnProperty(property) && (component as any)[property][SIGNAL]\n  )\n}\n\n/**\n * Set required signal input value to component fixture\n * @see https://github.com/angular/angular/issues/54013\n */\nexport function setSignalInputs<T extends NonNullable<unknown>>(\n  component: T,\n  inputs: ToSignalInputUpdatableMap<T>,\n) {\n  for (const inputKey in inputs) {\n    if (componentHasSignalInputProperty(component, inputKey)) {\n      signalSetFn(component[inputKey][SIGNAL], inputs[inputKey])\n    }\n  }\n}\n\nexport function setFixtureSignalInputs<T extends NonNullable<unknown>>(\n  componentFixture: ComponentFixture<T>,\n  inputs: ToSignalInputUpdatableMap<T>,\n  options: { detectChanges: boolean } = { detectChanges: true },\n) {\n  setSignalInputs(componentFixture.componentInstance, inputs)\n  if (options.detectChanges) {\n    componentFixture.detectChanges()\n  }\n}\n"
  },
  {
    "path": "packages/angular-query-experimental/src/__tests__/with-devtools.test.ts",
    "content": "import { afterEach, beforeEach, describe, expect, it, test, vi } from 'vitest'\nimport { QueryClient } from '@tanstack/query-core'\nimport { TestBed } from '@angular/core/testing'\nimport {\n  ENVIRONMENT_INITIALIZER,\n  EnvironmentInjector,\n  InjectionToken,\n  PLATFORM_ID,\n  createEnvironmentInjector,\n  isDevMode,\n  provideZonelessChangeDetection,\n  signal,\n} from '@angular/core'\nimport { provideTanStackQuery } from '../providers'\nimport { withDevtools } from '../devtools'\nimport type {\n  DevtoolsButtonPosition,\n  DevtoolsErrorType,\n  DevtoolsPosition,\n} from '@tanstack/query-devtools'\nimport type { DevtoolsOptions } from '../devtools'\n\nconst mockDevtoolsInstance = {\n  mount: vi.fn(),\n  unmount: vi.fn(),\n  setClient: vi.fn(),\n  setPosition: vi.fn(),\n  setErrorTypes: vi.fn(),\n  setButtonPosition: vi.fn(),\n  setInitialIsOpen: vi.fn(),\n}\n\nfunction MockTanstackQueryDevtools() {\n  return mockDevtoolsInstance\n}\n\nconst mockTanstackQueryDevtools = vi.fn(MockTanstackQueryDevtools)\n\nvi.mock('@tanstack/query-devtools', () => ({\n  TanstackQueryDevtools: mockTanstackQueryDevtools,\n}))\n\nvi.mock('@angular/core', async () => {\n  const actual = await vi.importActual('@angular/core')\n  return {\n    ...actual,\n    isDevMode: vi.fn(),\n  }\n})\n\nconst mockIsDevMode = vi.mocked(isDevMode)\n\ndescribe('withDevtools feature', () => {\n  beforeEach(() => {\n    vi.clearAllMocks()\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.restoreAllMocks()\n    vi.useRealTimers()\n    TestBed.resetTestingModule()\n  })\n\n  test.each([\n    {\n      description: 'should load devtools in development mode',\n      isDevMode: true,\n      expectedCalled: true,\n    },\n    {\n      description: 'should not load devtools in production mode',\n      isDevMode: false,\n      expectedCalled: false,\n    },\n    {\n      description: `should load devtools in development mode when 'loadDevtools' is set to 'auto'`,\n      isDevMode: true,\n      loadDevtools: 'auto',\n      expectedCalled: true,\n    },\n    {\n      description: `should not load devtools in production mode when 'loadDevtools' is set to 'auto'`,\n      isDevMode: false,\n      loadDevtools: 'auto',\n      expectedCalled: false,\n    },\n    {\n      description:\n        \"should load devtools in development mode when 'loadDevtools' is set to true\",\n      isDevMode: true,\n      loadDevtools: true,\n      expectedCalled: true,\n    },\n    {\n      description:\n        \"should load devtools in production mode when 'loadDevtools' is set to true\",\n      isDevMode: false,\n      loadDevtools: true,\n      expectedCalled: true,\n    },\n    {\n      description:\n        \"should not load devtools in development mode when 'loadDevtools' is set to false\",\n      isDevMode: true,\n      loadDevtools: false,\n      expectedCalled: false,\n    },\n    {\n      description:\n        \"should not load devtools in production mode when 'loadDevtools' is set to false\",\n      isDevMode: false,\n      loadDevtools: false,\n      expectedCalled: false,\n    },\n  ])(\n    '$description',\n    async ({ isDevMode: isDevModeValue, loadDevtools, expectedCalled }) => {\n      mockIsDevMode.mockReturnValue(isDevModeValue)\n\n      const providers = [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(\n          new QueryClient(),\n          loadDevtools !== undefined\n            ? withDevtools(\n                () =>\n                  ({\n                    loadDevtools,\n                  }) as DevtoolsOptions,\n              )\n            : withDevtools(),\n        ),\n      ]\n\n      TestBed.configureTestingModule({\n        providers,\n      })\n\n      TestBed.inject(ENVIRONMENT_INITIALIZER)\n      await vi.advanceTimersByTimeAsync(0)\n      TestBed.tick()\n      await vi.dynamicImportSettled()\n      TestBed.tick()\n      await vi.dynamicImportSettled()\n\n      expect(mockTanstackQueryDevtools).toHaveBeenCalledTimes(\n        expectedCalled ? 1 : 0,\n      )\n      expect(mockDevtoolsInstance.mount).toHaveBeenCalledTimes(\n        expectedCalled ? 1 : 0,\n      )\n    },\n  )\n\n  it('should not continue loading devtools after injector is destroyed', async () => {\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(\n          new QueryClient(),\n          withDevtools(() => ({\n            loadDevtools: true,\n          })),\n        ),\n      ],\n    })\n\n    TestBed.inject(ENVIRONMENT_INITIALIZER)\n    // Destroys injector\n    TestBed.resetTestingModule()\n    await vi.advanceTimersByTimeAsync(0)\n    await vi.dynamicImportSettled()\n\n    expect(mockTanstackQueryDevtools).not.toHaveBeenCalled()\n  })\n\n  it('should not create devtools again when already provided', async () => {\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(\n          new QueryClient(),\n          withDevtools(() => ({\n            loadDevtools: true,\n          })),\n        ),\n      ],\n    })\n\n    TestBed.inject(ENVIRONMENT_INITIALIZER)\n    await vi.advanceTimersByTimeAsync(0)\n    await vi.dynamicImportSettled()\n\n    expect(mockTanstackQueryDevtools).toHaveBeenCalledTimes(1)\n\n    const injector = TestBed.inject(EnvironmentInjector)\n\n    createEnvironmentInjector(\n      [\n        withDevtools(() => ({\n          loadDevtools: true,\n        })).ɵproviders,\n      ],\n      injector,\n    )\n\n    TestBed.inject(ENVIRONMENT_INITIALIZER)\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(mockTanstackQueryDevtools).toHaveBeenCalledTimes(1)\n  })\n\n  it('should not load devtools if platform is not browser', async () => {\n    TestBed.configureTestingModule({\n      providers: [\n        {\n          provide: PLATFORM_ID,\n          useValue: 'server',\n        },\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(\n          new QueryClient(),\n          withDevtools(() => ({\n            loadDevtools: true,\n          })),\n        ),\n      ],\n    })\n\n    TestBed.inject(ENVIRONMENT_INITIALIZER)\n    await vi.runAllTimersAsync()\n\n    expect(mockTanstackQueryDevtools).not.toHaveBeenCalled()\n  })\n\n  it('should update error types', async () => {\n    const errorTypes = signal([] as Array<DevtoolsErrorType>)\n\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(\n          new QueryClient(),\n          withDevtools(() => ({\n            loadDevtools: true,\n            errorTypes: errorTypes(),\n          })),\n        ),\n      ],\n    })\n\n    TestBed.inject(ENVIRONMENT_INITIALIZER)\n    await vi.advanceTimersByTimeAsync(0)\n    await vi.dynamicImportSettled()\n\n    TestBed.tick()\n\n    expect(mockDevtoolsInstance.setErrorTypes).toHaveBeenCalledTimes(0)\n\n    const newErrorTypes = [\n      {\n        name: '',\n        initializer: () => new Error(),\n      },\n    ]\n\n    errorTypes.set(newErrorTypes)\n\n    TestBed.tick()\n\n    expect(mockDevtoolsInstance.setErrorTypes).toHaveBeenCalledTimes(1)\n    expect(mockDevtoolsInstance.setErrorTypes).toHaveBeenCalledWith(\n      newErrorTypes,\n    )\n  })\n\n  it('should update client', async () => {\n    const client = signal(new QueryClient())\n\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(\n          new QueryClient(),\n          withDevtools(() => ({\n            loadDevtools: true,\n            client: client(),\n          })),\n        ),\n      ],\n    })\n\n    TestBed.inject(ENVIRONMENT_INITIALIZER)\n    await vi.advanceTimersByTimeAsync(0)\n    await vi.dynamicImportSettled()\n\n    TestBed.tick()\n\n    expect(mockDevtoolsInstance.setClient).toHaveBeenCalledTimes(0)\n\n    const newClient = new QueryClient()\n    client.set(newClient)\n\n    TestBed.tick()\n\n    expect(mockDevtoolsInstance.setClient).toHaveBeenCalledTimes(1)\n    expect(mockDevtoolsInstance.setClient).toHaveBeenCalledWith(newClient)\n  })\n\n  it('should update position', async () => {\n    const position = signal<DevtoolsPosition>('top')\n\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(\n          new QueryClient(),\n          withDevtools(() => ({\n            loadDevtools: true,\n            position: position(),\n          })),\n        ),\n      ],\n    })\n\n    TestBed.inject(ENVIRONMENT_INITIALIZER)\n    await vi.advanceTimersByTimeAsync(0)\n    await vi.dynamicImportSettled()\n\n    TestBed.tick()\n\n    expect(mockDevtoolsInstance.setPosition).toHaveBeenCalledTimes(0)\n\n    position.set('left')\n\n    TestBed.tick()\n\n    expect(mockDevtoolsInstance.setPosition).toHaveBeenCalledTimes(1)\n    expect(mockDevtoolsInstance.setPosition).toHaveBeenCalledWith('left')\n  })\n\n  it('should update button position', async () => {\n    const buttonPosition = signal<DevtoolsButtonPosition>('bottom-left')\n\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(\n          new QueryClient(),\n          withDevtools(() => ({\n            loadDevtools: true,\n            buttonPosition: buttonPosition(),\n          })),\n        ),\n      ],\n    })\n\n    TestBed.inject(ENVIRONMENT_INITIALIZER)\n    await vi.advanceTimersByTimeAsync(0)\n    await vi.dynamicImportSettled()\n\n    TestBed.tick()\n\n    expect(mockDevtoolsInstance.setButtonPosition).toHaveBeenCalledTimes(0)\n\n    buttonPosition.set('bottom-right')\n\n    TestBed.tick()\n\n    expect(mockDevtoolsInstance.setButtonPosition).toHaveBeenCalledTimes(1)\n    expect(mockDevtoolsInstance.setButtonPosition).toHaveBeenCalledWith(\n      'bottom-right',\n    )\n  })\n\n  it('should update initialIsOpen', async () => {\n    const initialIsOpen = signal(false)\n\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(\n          new QueryClient(),\n          withDevtools(() => ({\n            loadDevtools: true,\n            initialIsOpen: initialIsOpen(),\n          })),\n        ),\n      ],\n    })\n\n    TestBed.inject(ENVIRONMENT_INITIALIZER)\n    await vi.advanceTimersByTimeAsync(0)\n    await vi.dynamicImportSettled()\n\n    TestBed.tick()\n\n    expect(mockDevtoolsInstance.setInitialIsOpen).toHaveBeenCalledTimes(0)\n\n    initialIsOpen.set(true)\n\n    TestBed.tick()\n\n    expect(mockDevtoolsInstance.setInitialIsOpen).toHaveBeenCalledTimes(1)\n    expect(mockDevtoolsInstance.setInitialIsOpen).toHaveBeenCalledWith(true)\n  })\n\n  it('should destroy devtools', async () => {\n    const loadDevtools = signal(true)\n\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(\n          new QueryClient(),\n          withDevtools(() => ({\n            loadDevtools: loadDevtools(),\n          })),\n        ),\n      ],\n    })\n\n    TestBed.inject(ENVIRONMENT_INITIALIZER)\n    await vi.advanceTimersByTimeAsync(0)\n    await vi.dynamicImportSettled()\n\n    expect(mockDevtoolsInstance.mount).toHaveBeenCalledTimes(1)\n    expect(mockDevtoolsInstance.unmount).toHaveBeenCalledTimes(0)\n\n    loadDevtools.set(false)\n\n    TestBed.tick()\n\n    expect(mockDevtoolsInstance.unmount).toHaveBeenCalledTimes(1)\n  })\n\n  it('should unmount devtools when injector is destroyed', async () => {\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(\n          new QueryClient(),\n          withDevtools(() => ({\n            loadDevtools: true,\n          })),\n        ),\n      ],\n    })\n\n    TestBed.inject(ENVIRONMENT_INITIALIZER)\n    await vi.advanceTimersByTimeAsync(0)\n    TestBed.tick()\n    await vi.dynamicImportSettled()\n\n    expect(mockTanstackQueryDevtools).toHaveBeenCalled()\n    expect(mockDevtoolsInstance.mount).toHaveBeenCalledTimes(1)\n    expect(mockDevtoolsInstance.unmount).toHaveBeenCalledTimes(0)\n\n    // Destroy the injector\n    TestBed.resetTestingModule()\n\n    expect(mockDevtoolsInstance.unmount).toHaveBeenCalledTimes(1)\n  })\n\n  it('should remount devtools when toggled from false to true', async () => {\n    const loadDevtools = signal(false)\n\n    TestBed.configureTestingModule({\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(\n          new QueryClient(),\n          withDevtools(() => ({\n            loadDevtools: loadDevtools(),\n          })),\n        ),\n      ],\n    })\n\n    TestBed.inject(ENVIRONMENT_INITIALIZER)\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(mockTanstackQueryDevtools).not.toHaveBeenCalled()\n    expect(mockDevtoolsInstance.mount).not.toHaveBeenCalled()\n\n    loadDevtools.set(true)\n    TestBed.tick()\n    await vi.dynamicImportSettled()\n\n    expect(mockTanstackQueryDevtools).toHaveBeenCalledTimes(1)\n    expect(mockDevtoolsInstance.mount).toHaveBeenCalledTimes(1)\n    expect(mockDevtoolsInstance.unmount).not.toHaveBeenCalled()\n\n    loadDevtools.set(false)\n    TestBed.tick()\n\n    expect(mockDevtoolsInstance.unmount).toHaveBeenCalledTimes(1)\n    expect(mockDevtoolsInstance.mount).toHaveBeenCalledTimes(1)\n\n    loadDevtools.set(true)\n    TestBed.tick()\n    await vi.dynamicImportSettled()\n\n    // Should remount (mount called twice now)\n    expect(mockDevtoolsInstance.mount).toHaveBeenCalledTimes(2)\n    expect(mockDevtoolsInstance.unmount).toHaveBeenCalledTimes(1)\n  })\n\n  describe('deps parameter', () => {\n    it('should inject dependencies and pass them to withDevtoolsFn in correct order', async () => {\n      const mockService1 = { value: 'service1' }\n      const mockService2 = { value: 'service2' }\n      const mockService1Token = new InjectionToken('MockService1')\n      const mockService2Token = new InjectionToken('MockService2')\n      const withDevtoolsFn = vi.fn().mockReturnValue({ loadDevtools: true })\n\n      TestBed.configureTestingModule({\n        providers: [\n          provideZonelessChangeDetection(),\n          {\n            provide: mockService1Token,\n            useValue: mockService1,\n          },\n          {\n            provide: mockService2Token,\n            useValue: mockService2,\n          },\n          provideTanStackQuery(\n            new QueryClient(),\n            withDevtools(withDevtoolsFn, {\n              deps: [mockService1Token, mockService2Token],\n            }),\n          ),\n        ],\n      })\n\n      TestBed.inject(ENVIRONMENT_INITIALIZER)\n      await vi.advanceTimersByTimeAsync(0)\n\n      expect(withDevtoolsFn).toHaveBeenCalledWith(mockService1, mockService2)\n    })\n\n    it('should work with empty deps array', async () => {\n      const withDevtoolsFn = vi.fn().mockReturnValue({ loadDevtools: true })\n\n      TestBed.configureTestingModule({\n        providers: [\n          provideZonelessChangeDetection(),\n          provideTanStackQuery(\n            new QueryClient(),\n            withDevtools(withDevtoolsFn, {\n              deps: [],\n            }),\n          ),\n        ],\n      })\n\n      TestBed.inject(ENVIRONMENT_INITIALIZER)\n      await vi.advanceTimersByTimeAsync(0)\n\n      expect(withDevtoolsFn).toHaveBeenCalledWith()\n    })\n\n    it('should reactively update when injected services change', async () => {\n      class ReactiveService {\n        enabled = signal(false)\n        position = signal<DevtoolsPosition>('bottom')\n      }\n\n      const withDevtoolsFn = (service: ReactiveService) => ({\n        loadDevtools: service.enabled(),\n        position: service.position(),\n      })\n\n      TestBed.configureTestingModule({\n        providers: [\n          provideZonelessChangeDetection(),\n          ReactiveService,\n          provideTanStackQuery(\n            new QueryClient(),\n            withDevtools(withDevtoolsFn, {\n              deps: [ReactiveService],\n            }),\n          ),\n        ],\n      })\n\n      TestBed.inject(ENVIRONMENT_INITIALIZER)\n      await vi.advanceTimersByTimeAsync(0)\n\n      const service = TestBed.inject(ReactiveService)\n\n      expect(mockTanstackQueryDevtools).not.toHaveBeenCalled()\n\n      service.enabled.set(true)\n      TestBed.tick()\n      await vi.dynamicImportSettled()\n\n      expect(mockTanstackQueryDevtools).toHaveBeenCalledTimes(1)\n      expect(mockTanstackQueryDevtools).toHaveBeenCalledWith(\n        expect.objectContaining({\n          position: 'bottom',\n        }),\n      )\n\n      service.position.set('top')\n      TestBed.tick()\n\n      expect(mockDevtoolsInstance.setPosition).toHaveBeenCalledWith('top')\n    })\n  })\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/create-base-query.ts",
    "content": "import {\n  NgZone,\n  VERSION,\n  computed,\n  effect,\n  inject,\n  signal,\n  untracked,\n} from '@angular/core'\nimport {\n  QueryClient,\n  notifyManager,\n  shouldThrowError,\n} from '@tanstack/query-core'\nimport { signalProxy } from './signal-proxy'\nimport { injectIsRestoring } from './inject-is-restoring'\nimport { PENDING_TASKS } from './pending-tasks-compat'\nimport type { PendingTaskRef } from './pending-tasks-compat'\nimport type {\n  QueryKey,\n  QueryObserver,\n  QueryObserverResult,\n} from '@tanstack/query-core'\nimport type { CreateBaseQueryOptions } from './types'\n\n/**\n * Base implementation for `injectQuery` and `injectInfiniteQuery`.\n * @param optionsFn\n * @param Observer\n */\nexport function createBaseQuery<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryData,\n  TQueryKey extends QueryKey,\n>(\n  optionsFn: () => CreateBaseQueryOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryData,\n    TQueryKey\n  >,\n  Observer: typeof QueryObserver,\n) {\n  const ngZone = inject(NgZone)\n  const pendingTasks = inject(PENDING_TASKS)\n  const queryClient = inject(QueryClient)\n  const isRestoring = injectIsRestoring()\n\n  /**\n   * Signal that has the default options from query client applied\n   * computed() is used so signals can be inserted into the options\n   * making it reactive. Wrapping options in a function ensures embedded expressions\n   * are preserved and can keep being applied after signal changes\n   */\n  const defaultedOptionsSignal = computed(() => {\n    const defaultedOptions = queryClient.defaultQueryOptions(optionsFn())\n    defaultedOptions._optimisticResults = isRestoring()\n      ? 'isRestoring'\n      : 'optimistic'\n    return defaultedOptions\n  })\n\n  const observerSignal = (() => {\n    let instance: QueryObserver<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryData,\n      TQueryKey\n    > | null = null\n\n    return computed(() => {\n      return (instance ||= new Observer(queryClient, defaultedOptionsSignal()))\n    })\n  })()\n\n  const optimisticResultSignal = computed(() =>\n    observerSignal().getOptimisticResult(defaultedOptionsSignal()),\n  )\n\n  const resultFromSubscriberSignal = signal<QueryObserverResult<\n    TData,\n    TError\n  > | null>(null)\n\n  effect(\n    (onCleanup) => {\n      const observer = observerSignal()\n      const defaultedOptions = defaultedOptionsSignal()\n\n      untracked(() => {\n        observer.setOptions(defaultedOptions)\n      })\n      onCleanup(() => {\n        ngZone.run(() => resultFromSubscriberSignal.set(null))\n      })\n    },\n    {\n      // Set allowSignalWrites to support Angular < v19\n      // Set to undefined to avoid warning on newer versions\n      allowSignalWrites: VERSION.major < '19' || undefined,\n    },\n  )\n\n  effect((onCleanup) => {\n    // observer.trackResult is not used as this optimization is not needed for Angular\n    const observer = observerSignal()\n    let pendingTaskRef: PendingTaskRef | null = null\n\n    const unsubscribe = isRestoring()\n      ? () => undefined\n      : untracked(() =>\n          ngZone.runOutsideAngular(() => {\n            return observer.subscribe(\n              notifyManager.batchCalls((state) => {\n                ngZone.run(() => {\n                  if (state.fetchStatus === 'fetching' && !pendingTaskRef) {\n                    pendingTaskRef = pendingTasks.add()\n                  }\n\n                  if (state.fetchStatus === 'idle' && pendingTaskRef) {\n                    pendingTaskRef()\n                    pendingTaskRef = null\n                  }\n\n                  if (\n                    state.isError &&\n                    !state.isFetching &&\n                    shouldThrowError(observer.options.throwOnError, [\n                      state.error,\n                      observer.getCurrentQuery(),\n                    ])\n                  ) {\n                    ngZone.onError.emit(state.error)\n                    throw state.error\n                  }\n                  resultFromSubscriberSignal.set(state)\n                })\n              }),\n            )\n          }),\n        )\n\n    onCleanup(() => {\n      if (pendingTaskRef) {\n        pendingTaskRef()\n        pendingTaskRef = null\n      }\n      unsubscribe()\n    })\n  })\n\n  return signalProxy(\n    computed(() => {\n      const subscriberResult = resultFromSubscriberSignal()\n      const optimisticResult = optimisticResultSignal()\n      const result = subscriberResult ?? optimisticResult\n\n      // Wrap methods to ensure observer has latest options before execution\n      const observer = observerSignal()\n\n      const originalRefetch = result.refetch\n      return {\n        ...result,\n        refetch: ((...args: Parameters<typeof originalRefetch>) => {\n          observer.setOptions(defaultedOptionsSignal())\n          return originalRefetch(...args)\n        }) as typeof originalRefetch,\n      }\n    }),\n  )\n}\n"
  },
  {
    "path": "packages/angular-query-experimental/src/devtools/index.ts",
    "content": "export type {\n  DevtoolsOptions,\n  WithDevtools,\n  WithDevtoolsFn,\n  WithDevtoolsOptions,\n} from './types'\n\nexport { withDevtools } from './with-devtools'\n"
  },
  {
    "path": "packages/angular-query-experimental/src/devtools/production/index.ts",
    "content": "export * from '..'\n"
  },
  {
    "path": "packages/angular-query-experimental/src/devtools/stub.ts",
    "content": "import type { WithDevtools } from './types'\n\n// Stub which replaces `withDevtools` in production builds\nexport const withDevtools: WithDevtools = () => ({\n  ɵkind: 'Devtools',\n  ɵproviders: [],\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/devtools/types.ts",
    "content": "import type { QueryClient } from '@tanstack/query-core'\nimport type {\n  DevtoolsButtonPosition,\n  DevtoolsErrorType,\n  DevtoolsPosition,\n} from '@tanstack/query-devtools'\nimport type { DevtoolsFeature } from '../providers'\n\n/**\n * Options for configuring withDevtools.\n */\nexport interface WithDevtoolsOptions {\n  /**\n   * An array of dependencies to be injected and passed to the `withDevtoolsFn` function.\n   *\n   * **Example**\n   * ```ts\n   * export const appConfig: ApplicationConfig = {\n   *   providers: [\n   *     provideTanStackQuery(\n   *       new QueryClient(),\n   *       withDevtools(\n   *         (devToolsOptionsManager: DevtoolsOptionsManager) => ({\n   *           loadDevtools: devToolsOptionsManager.loadDevtools(),\n   *         }),\n   *         {\n   *           deps: [DevtoolsOptionsManager],\n   *         },\n   *       ),\n   *     ),\n   *   ],\n   * }\n   * ```\n   */\n  deps?: Array<any>\n}\n\n/**\n * Options for configuring the TanStack Query devtools.\n */\nexport interface DevtoolsOptions {\n  /**\n   * Set this true if you want the devtools to default to being open\n   */\n  initialIsOpen?: boolean\n  /**\n   * The position of the TanStack logo to open and close the devtools panel.\n   * `top-left` | `top-right` | `bottom-left` | `bottom-right` | `relative`\n   * Defaults to `bottom-right`.\n   */\n  buttonPosition?: DevtoolsButtonPosition\n  /**\n   * The position of the TanStack Query devtools panel.\n   * `top` | `bottom` | `left` | `right`\n   * Defaults to `bottom`.\n   */\n  position?: DevtoolsPosition\n  /**\n   * Custom instance of QueryClient\n   */\n  client?: QueryClient\n  /**\n   * Use this so you can define custom errors that can be shown in the devtools.\n   */\n  errorTypes?: Array<DevtoolsErrorType>\n  /**\n   * 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.\n   */\n  styleNonce?: string\n  /**\n   * Use this so you can attach the devtool's styles to a specific element in the DOM.\n   */\n  shadowDOMTarget?: ShadowRoot\n  /**\n   * Set this to true to hide disabled queries from the devtools panel.\n   */\n  hideDisabledQueries?: boolean\n\n  /**\n   * Whether the developer tools should load.\n   * - `auto`- (Default) Lazily loads devtools when in development mode. Skips loading in production mode.\n   * - `true`- Always load the devtools, regardless of the environment.\n   * - `false`- Never load the devtools, regardless of the environment.\n   *\n   * You can use `true` and `false` to override loading developer tools from an environment file.\n   * For example, a test environment might run in production mode but you may want to load developer tools.\n   *\n   * Additionally, you can use a signal in the callback to dynamically load the devtools based on a condition. For example,\n   * a signal created from a RxJS observable that listens for a keyboard shortcut.\n   *\n   * **Example**\n   * ```ts\n   *    withDevtools(() => ({\n   *      initialIsOpen: true,\n   *      loadDevtools: inject(ExampleService).loadDevtools()\n   *    }))\n   *  ```\n   */\n  loadDevtools?: 'auto' | boolean\n}\n\nexport type WithDevtoolsFn = (...deps: Array<any>) => DevtoolsOptions\n\nexport type WithDevtools = (\n  withDevtoolsFn?: WithDevtoolsFn,\n  options?: WithDevtoolsOptions,\n) => DevtoolsFeature\n"
  },
  {
    "path": "packages/angular-query-experimental/src/devtools/with-devtools.ts",
    "content": "import { isPlatformBrowser } from '@angular/common'\nimport {\n  DestroyRef,\n  ENVIRONMENT_INITIALIZER,\n  InjectionToken,\n  Injector,\n  PLATFORM_ID,\n  computed,\n  effect,\n  inject,\n  isDevMode,\n} from '@angular/core'\nimport { QueryClient, noop, onlineManager } from '@tanstack/query-core'\nimport { queryFeature } from '../providers'\nimport type { Signal } from '@angular/core'\nimport type {\n  DevtoolsOptions,\n  WithDevtools,\n  WithDevtoolsFn,\n  WithDevtoolsOptions,\n} from './types'\nimport type { TanstackQueryDevtools } from '@tanstack/query-devtools'\n\n/**\n * Internal token used to prevent double providing of devtools in child injectors\n */\nconst DEVTOOLS_PROVIDED = new InjectionToken('', {\n  factory: () => ({\n    isProvided: false,\n  }),\n})\n\n/**\n * Internal token for providing devtools options\n */\nconst DEVTOOLS_OPTIONS_SIGNAL = new InjectionToken<Signal<DevtoolsOptions>>('')\n\n/**\n * Enables developer tools in Angular development builds.\n *\n * **Example**\n *\n * ```ts\n * export const appConfig: ApplicationConfig = {\n *   providers: [\n *     provideTanStackQuery(new QueryClient(), withDevtools())\n *   ]\n * }\n * ```\n * The devtools will be rendered in `<body>`.\n *\n * If you need more control over when devtools are loaded, you can use the `loadDevtools` option.\n *\n * If you need more control over where devtools are rendered, consider `injectDevtoolsPanel`. This allows rendering devtools inside your own devtools for example.\n * @param withDevtoolsFn - A function that returns `DevtoolsOptions`.\n * @param options - Additional options for configuring `withDevtools`.\n * @returns A set of providers for use with `provideTanStackQuery`.\n * @see {@link provideTanStackQuery}\n * @see {@link DevtoolsOptions}\n */\nexport const withDevtools: WithDevtools = (\n  withDevtoolsFn?: WithDevtoolsFn,\n  options: WithDevtoolsOptions = {},\n) =>\n  queryFeature('Devtools', [\n    {\n      provide: DEVTOOLS_OPTIONS_SIGNAL,\n      useFactory: (...deps: Array<any>) =>\n        computed(() => withDevtoolsFn?.(...deps) ?? {}),\n      deps: options.deps || [],\n    },\n    {\n      // Do not use provideEnvironmentInitializer while Angular < v19 is supported\n      provide: ENVIRONMENT_INITIALIZER,\n      multi: true,\n      useFactory: () => {\n        const devtoolsProvided = inject(DEVTOOLS_PROVIDED)\n        if (\n          !isPlatformBrowser(inject(PLATFORM_ID)) ||\n          devtoolsProvided.isProvided\n        )\n          return noop\n\n        devtoolsProvided.isProvided = true\n        let injectorIsDestroyed = false\n        inject(DestroyRef).onDestroy(() => (injectorIsDestroyed = true))\n\n        return () => {\n          const injectedClient = inject(QueryClient, {\n            optional: true,\n          })\n          const destroyRef = inject(DestroyRef)\n          const devtoolsOptions = inject(DEVTOOLS_OPTIONS_SIGNAL)\n          const injector = inject(Injector)\n\n          let devtools: TanstackQueryDevtools | null = null\n          let el: HTMLElement | null = null\n\n          const shouldLoadToolsSignal = computed(() => {\n            const { loadDevtools } = devtoolsOptions()\n            return typeof loadDevtools === 'boolean'\n              ? loadDevtools\n              : isDevMode()\n          })\n\n          const getResolvedQueryClient = () => {\n            const client = devtoolsOptions().client ?? injectedClient\n            if (!client) {\n              throw new Error('No QueryClient found')\n            }\n            return client\n          }\n\n          const destroyDevtools = () => {\n            devtools?.unmount()\n            el?.remove()\n            devtools = null\n          }\n\n          effect(\n            () => {\n              const shouldLoadTools = shouldLoadToolsSignal()\n              const {\n                client,\n                position,\n                errorTypes,\n                buttonPosition,\n                initialIsOpen,\n              } = devtoolsOptions()\n\n              if (!shouldLoadTools) {\n                // Destroy or do nothing\n                devtools && destroyDevtools()\n                return\n              }\n\n              if (devtools) {\n                // Update existing devtools config\n                client && devtools.setClient(client)\n                position && devtools.setPosition(position)\n                errorTypes && devtools.setErrorTypes(errorTypes)\n                buttonPosition && devtools.setButtonPosition(buttonPosition)\n                typeof initialIsOpen === 'boolean' &&\n                  devtools.setInitialIsOpen(initialIsOpen)\n                return\n              }\n\n              // Create devtools\n              import('@tanstack/query-devtools')\n                .then((queryDevtools) => {\n                  // As this code runs async, the injector could have been destroyed\n                  if (injectorIsDestroyed) return\n\n                  devtools = new queryDevtools.TanstackQueryDevtools({\n                    ...devtoolsOptions(),\n                    client: getResolvedQueryClient(),\n                    queryFlavor: 'Angular Query',\n                    version: '5',\n                    onlineManager,\n                  })\n\n                  el = document.body.appendChild(document.createElement('div'))\n                  el.classList.add('tsqd-parent-container')\n                  devtools.mount(el)\n\n                  destroyRef.onDestroy(destroyDevtools)\n                })\n                .catch((error) => {\n                  console.error(\n                    'Install @tanstack/query-devtools or reinstall without --omit=optional.',\n                    error,\n                  )\n                })\n            },\n            { injector },\n          )\n        }\n      },\n    },\n  ])\n"
  },
  {
    "path": "packages/angular-query-experimental/src/devtools-panel/index.ts",
    "content": "export type {\n  InjectDevtoolsPanel,\n  DevtoolsPanelOptions,\n  InjectDevtoolsPanelOptions,\n  DevtoolsPanelRef,\n} from './types'\n\nexport { injectDevtoolsPanel } from './inject-devtools-panel'\n"
  },
  {
    "path": "packages/angular-query-experimental/src/devtools-panel/inject-devtools-panel.ts",
    "content": "import {\n  DestroyRef,\n  Injector,\n  PLATFORM_ID,\n  assertInInjectionContext,\n  computed,\n  effect,\n  inject,\n  runInInjectionContext,\n  untracked,\n} from '@angular/core'\nimport { QueryClient, onlineManager } from '@tanstack/query-core'\nimport { isPlatformBrowser } from '@angular/common'\nimport type { TanstackQueryDevtoolsPanel } from '@tanstack/query-devtools'\nimport type {\n  DevtoolsPanelOptions,\n  InjectDevtoolsPanel,\n  InjectDevtoolsPanelOptions,\n} from './types'\n\n/**\n * Inject a TanStack Query devtools panel and render it in the DOM.\n *\n * Devtools panel allows programmatic control over the devtools, for example if you want to render\n * the devtools as part of your own devtools.\n *\n * Consider `withDevtools` instead if you don't need this.\n * @param injectDevtoolsPanelFn - A function that returns devtools panel options.\n * @param options - Additional configuration\n * @returns DevtoolsPanelRef\n * @see https://tanstack.com/query/v5/docs/framework/angular/devtools\n */\nexport const injectDevtoolsPanel: InjectDevtoolsPanel = (\n  injectDevtoolsPanelFn: () => DevtoolsPanelOptions,\n  options?: InjectDevtoolsPanelOptions,\n) => {\n  !options?.injector && assertInInjectionContext(injectDevtoolsPanel)\n  const currentInjector = options?.injector ?? inject(Injector)\n\n  return runInInjectionContext(currentInjector, () => {\n    const destroyRef = inject(DestroyRef)\n    const isBrowser = isPlatformBrowser(inject(PLATFORM_ID))\n    const injectedClient = inject(QueryClient, { optional: true })\n\n    const queryOptions = computed(injectDevtoolsPanelFn)\n    let devtools: TanstackQueryDevtoolsPanel | null = null\n\n    const destroy = () => {\n      devtools?.unmount()\n      devtools = null\n    }\n\n    if (!isBrowser)\n      return {\n        destroy,\n      }\n\n    effect(() => {\n      const {\n        client = injectedClient,\n        errorTypes = [],\n        styleNonce,\n        shadowDOMTarget,\n        onClose,\n        hostElement,\n      } = queryOptions()\n\n      untracked(() => {\n        if (!client) throw new Error('No QueryClient found')\n        if (!devtools && hostElement) {\n          import('@tanstack/query-devtools')\n            .then((queryDevtools) => {\n              devtools = new queryDevtools.TanstackQueryDevtoolsPanel({\n                client,\n                queryFlavor: 'Angular Query',\n                version: '5',\n                buttonPosition: 'bottom-left',\n                position: 'bottom',\n                initialIsOpen: true,\n                errorTypes,\n                styleNonce,\n                shadowDOMTarget,\n                onClose,\n                onlineManager,\n              })\n              devtools.mount(hostElement.nativeElement)\n            })\n            .catch((error) => {\n              console.error(\n                'Install @tanstack/query-devtools or reinstall without --omit=optional.',\n                error,\n              )\n            })\n        } else if (devtools && hostElement) {\n          devtools.setClient(client)\n          devtools.setErrorTypes(errorTypes)\n          onClose && devtools.setOnClose(onClose)\n        } else if (devtools && !hostElement) {\n          destroy()\n        }\n      })\n    })\n\n    destroyRef.onDestroy(destroy)\n\n    return {\n      destroy,\n    }\n  })\n}\n"
  },
  {
    "path": "packages/angular-query-experimental/src/devtools-panel/production/index.ts",
    "content": "export * from '..'\n"
  },
  {
    "path": "packages/angular-query-experimental/src/devtools-panel/stub.ts",
    "content": "import { noop } from '@tanstack/query-core'\nimport type { InjectDevtoolsPanel } from './types'\n\n// Stub which replaces `injectDevtoolsPanel` in production builds\nexport const injectDevtoolsPanel: InjectDevtoolsPanel = () => ({\n  destroy: noop,\n})\n"
  },
  {
    "path": "packages/angular-query-experimental/src/devtools-panel/types.ts",
    "content": "import type { DevtoolsErrorType } from '@tanstack/query-devtools'\nimport type { ElementRef, Injector } from '@angular/core'\nimport type { QueryClient } from '@tanstack/query-core'\n\nexport interface InjectDevtoolsPanelOptions {\n  /**\n   * The `Injector` in which to create the devtools panel.\n   *\n   * If this is not provided, the current injection context will be used instead (via `inject`).\n   */\n  injector?: Injector\n}\n\n/**\n * A devtools panel, which can be manually destroyed.\n */\nexport interface DevtoolsPanelRef {\n  /**\n   * Destroy the panel, removing it from the DOM and stops listening to signal changes.\n   */\n  destroy: () => void\n}\n\nexport interface DevtoolsPanelOptions {\n  /**\n   * Custom instance of QueryClient\n   */\n  client?: QueryClient\n  /**\n   * Use this so you can define custom errors that can be shown in the devtools.\n   */\n  errorTypes?: Array<DevtoolsErrorType>\n  /**\n   * 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.\n   */\n  styleNonce?: string\n  /**\n   * Use this so you can attach the devtool's styles to specific element in the DOM.\n   */\n  shadowDOMTarget?: ShadowRoot\n\n  /**\n   * Callback function that is called when the devtools panel is closed\n   */\n  onClose?: () => unknown\n\n  /**\n   * Element where to render the devtools panel. When set to undefined or null, the devtools panel will not be created, or destroyed if existing.\n   * If changed from undefined to a ElementRef, the devtools panel will be created.\n   */\n  hostElement?: ElementRef\n}\n\nexport type InjectDevtoolsPanel = (\n  injectDevtoolsPanelFn: () => DevtoolsPanelOptions,\n  options?: InjectDevtoolsPanelOptions,\n) => DevtoolsPanelRef\n"
  },
  {
    "path": "packages/angular-query-experimental/src/index.ts",
    "content": "/* istanbul ignore file */\n\n// Re-export core\nexport * from '@tanstack/query-core'\n\nexport * from './types'\n\nexport type {\n  DefinedInitialDataOptions,\n  UndefinedInitialDataOptions,\n  UnusedSkipTokenOptions,\n} from './query-options'\nexport { queryOptions } from './query-options'\n\nexport type { CreateMutationOptions } from './types'\nexport { mutationOptions } from './mutation-options'\n\nexport type {\n  DefinedInitialDataInfiniteOptions,\n  UndefinedInitialDataInfiniteOptions,\n  UnusedSkipTokenInfiniteOptions,\n} from './infinite-query-options'\nexport { infiniteQueryOptions } from './infinite-query-options'\n\nexport type { InjectInfiniteQueryOptions } from './inject-infinite-query'\nexport { injectInfiniteQuery } from './inject-infinite-query'\n\nexport type { InjectIsFetchingOptions } from './inject-is-fetching'\nexport { injectIsFetching } from './inject-is-fetching'\n\nexport type { InjectIsMutatingOptions } from './inject-is-mutating'\nexport { injectIsMutating } from './inject-is-mutating'\n\nexport { injectIsRestoring, provideIsRestoring } from './inject-is-restoring'\n\nexport type { InjectMutationOptions } from './inject-mutation'\nexport { injectMutation } from './inject-mutation'\n\nexport type { InjectMutationStateOptions } from './inject-mutation-state'\nexport { injectMutationState } from './inject-mutation-state'\n\nexport type { QueriesOptions, QueriesResults } from './inject-queries'\n\nexport type { InjectQueryOptions } from './inject-query'\nexport { injectQuery } from './inject-query'\n\nexport { injectQueryClient } from './inject-query-client'\n\nexport type {\n  DevtoolsFeature,\n  PersistQueryClientFeature,\n  QueryFeature,\n  QueryFeatures,\n} from './providers'\nexport {\n  provideAngularQuery,\n  provideQueryClient,\n  provideTanStackQuery,\n  queryFeature,\n} from './providers'\n"
  },
  {
    "path": "packages/angular-query-experimental/src/infinite-query-options.ts",
    "content": "import type {\n  DataTag,\n  DefaultError,\n  InfiniteData,\n  InitialDataFunction,\n  NonUndefinedGuard,\n  OmitKeyof,\n  QueryKey,\n  SkipToken,\n} from '@tanstack/query-core'\nimport type { CreateInfiniteQueryOptions } from './types'\n\nexport type UndefinedInitialDataInfiniteOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> = CreateInfiniteQueryOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey,\n  TPageParam\n> & {\n  initialData?:\n    | undefined\n    | NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>\n    | InitialDataFunction<\n        NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>\n      >\n}\n\nexport type UnusedSkipTokenInfiniteOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> = OmitKeyof<\n  CreateInfiniteQueryOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n  'queryFn'\n> & {\n  queryFn?: Exclude<\n    CreateInfiniteQueryOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey,\n      TPageParam\n    >['queryFn'],\n    SkipToken | undefined\n  >\n}\n\nexport type DefinedInitialDataInfiniteOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> = CreateInfiniteQueryOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey,\n  TPageParam\n> & {\n  initialData:\n    | NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>\n    | (() => NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>)\n    | undefined\n}\n\n/**\n * Allows to share and re-use infinite query options in a type-safe way.\n *\n * The `queryKey` will be tagged with the type from `queryFn`.\n * @param options - The infinite query options to tag with the type from `queryFn`.\n * @returns The tagged infinite query options.\n */\nexport function infiniteQueryOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: DefinedInitialDataInfiniteOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n): DefinedInitialDataInfiniteOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey,\n  TPageParam\n> & {\n  queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>\n}\n\n/**\n * Allows to share and re-use infinite query options in a type-safe way.\n *\n * The `queryKey` will be tagged with the type from `queryFn`.\n * @param options - The infinite query options to tag with the type from `queryFn`.\n * @returns The tagged infinite query options.\n */\nexport function infiniteQueryOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: UnusedSkipTokenInfiniteOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n): UnusedSkipTokenInfiniteOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey,\n  TPageParam\n> & {\n  queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>\n}\n\n/**\n * Allows to share and re-use infinite query options in a type-safe way.\n *\n * The `queryKey` will be tagged with the type from `queryFn`.\n * @param options - The infinite query options to tag with the type from `queryFn`.\n * @returns The tagged infinite query options.\n */\nexport function infiniteQueryOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: UndefinedInitialDataInfiniteOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n): UndefinedInitialDataInfiniteOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey,\n  TPageParam\n> & {\n  queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>\n}\n\n/**\n * Allows to share and re-use infinite query options in a type-safe way.\n *\n * The `queryKey` will be tagged with the type from `queryFn`.\n * @param options - The infinite query options to tag with the type from `queryFn`.\n * @returns The tagged infinite query options.\n */\nexport function infiniteQueryOptions(options: unknown) {\n  return options\n}\n"
  },
  {
    "path": "packages/angular-query-experimental/src/inject-infinite-query.ts",
    "content": "import { InfiniteQueryObserver } from '@tanstack/query-core'\nimport {\n  Injector,\n  assertInInjectionContext,\n  inject,\n  runInInjectionContext,\n} from '@angular/core'\nimport { createBaseQuery } from './create-base-query'\nimport type {\n  DefaultError,\n  InfiniteData,\n  QueryKey,\n  QueryObserver,\n} from '@tanstack/query-core'\nimport type {\n  CreateInfiniteQueryOptions,\n  CreateInfiniteQueryResult,\n  DefinedCreateInfiniteQueryResult,\n} from './types'\nimport type {\n  DefinedInitialDataInfiniteOptions,\n  UndefinedInitialDataInfiniteOptions,\n} from './infinite-query-options'\n\nexport interface InjectInfiniteQueryOptions {\n  /**\n   * The `Injector` in which to create the infinite query.\n   *\n   * If this is not provided, the current injection context will be used instead (via `inject`).\n   */\n  injector?: Injector\n}\n\n/**\n * Injects an infinite query: a declarative dependency on an asynchronous source of data that is tied to a unique key.\n * Infinite queries can additively \"load more\" data onto an existing set of data or \"infinite scroll\"\n * @param injectInfiniteQueryFn - A function that returns infinite query options.\n * @param options - Additional configuration.\n * @returns The infinite query result.\n */\nexport function injectInfiniteQuery<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  injectInfiniteQueryFn: () => DefinedInitialDataInfiniteOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n  options?: InjectInfiniteQueryOptions,\n): DefinedCreateInfiniteQueryResult<TData, TError>\n\n/**\n * Injects an infinite query: a declarative dependency on an asynchronous source of data that is tied to a unique key.\n * Infinite queries can additively \"load more\" data onto an existing set of data or \"infinite scroll\"\n * @param injectInfiniteQueryFn - A function that returns infinite query options.\n * @param options - Additional configuration.\n * @returns The infinite query result.\n */\nexport function injectInfiniteQuery<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  injectInfiniteQueryFn: () => UndefinedInitialDataInfiniteOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n  options?: InjectInfiniteQueryOptions,\n): CreateInfiniteQueryResult<TData, TError>\n\n/**\n * Injects an infinite query: a declarative dependency on an asynchronous source of data that is tied to a unique key.\n * Infinite queries can additively \"load more\" data onto an existing set of data or \"infinite scroll\"\n * @param injectInfiniteQueryFn - A function that returns infinite query options.\n * @param options - Additional configuration.\n * @returns The infinite query result.\n */\nexport function injectInfiniteQuery<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  injectInfiniteQueryFn: () => CreateInfiniteQueryOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n  options?: InjectInfiniteQueryOptions,\n): CreateInfiniteQueryResult<TData, TError>\n\n/**\n * Injects an infinite query: a declarative dependency on an asynchronous source of data that is tied to a unique key.\n * Infinite queries can additively \"load more\" data onto an existing set of data or \"infinite scroll\"\n * @param injectInfiniteQueryFn - A function that returns infinite query options.\n * @param options - Additional configuration.\n * @returns The infinite query result.\n */\nexport function injectInfiniteQuery(\n  injectInfiniteQueryFn: () => CreateInfiniteQueryOptions,\n  options?: InjectInfiniteQueryOptions,\n) {\n  !options?.injector && assertInInjectionContext(injectInfiniteQuery)\n  const injector = options?.injector ?? inject(Injector)\n  return runInInjectionContext(injector, () =>\n    createBaseQuery(\n      injectInfiniteQueryFn,\n      InfiniteQueryObserver as typeof QueryObserver,\n    ),\n  )\n}\n"
  },
  {
    "path": "packages/angular-query-experimental/src/inject-is-fetching.ts",
    "content": "import {\n  DestroyRef,\n  Injector,\n  NgZone,\n  assertInInjectionContext,\n  inject,\n  signal,\n} from '@angular/core'\nimport { QueryClient, notifyManager } from '@tanstack/query-core'\nimport type { QueryFilters } from '@tanstack/query-core'\nimport type { Signal } from '@angular/core'\n\nexport interface InjectIsFetchingOptions {\n  /**\n   * The `Injector` in which to create the isFetching signal.\n   *\n   * If this is not provided, the current injection context will be used instead (via `inject`).\n   */\n  injector?: Injector\n}\n\n/**\n * Injects a signal that tracks the number of queries that your application is loading or\n * fetching in the background.\n *\n * Can be used for app-wide loading indicators\n * @param filters - The filters to apply to the query.\n * @param options - Additional configuration\n * @returns signal with number of loading or fetching queries.\n */\nexport function injectIsFetching(\n  filters?: QueryFilters,\n  options?: InjectIsFetchingOptions,\n): Signal<number> {\n  !options?.injector && assertInInjectionContext(injectIsFetching)\n  const injector = options?.injector ?? inject(Injector)\n  const destroyRef = injector.get(DestroyRef)\n  const ngZone = injector.get(NgZone)\n  const queryClient = injector.get(QueryClient)\n\n  const cache = queryClient.getQueryCache()\n  // isFetching is the prev value initialized on mount *\n  let isFetching = queryClient.isFetching(filters)\n\n  const result = signal(isFetching)\n\n  const unsubscribe = ngZone.runOutsideAngular(() =>\n    cache.subscribe(\n      notifyManager.batchCalls(() => {\n        const newIsFetching = queryClient.isFetching(filters)\n        if (isFetching !== newIsFetching) {\n          // * and update with each change\n          isFetching = newIsFetching\n          ngZone.run(() => {\n            result.set(isFetching)\n          })\n        }\n      }),\n    ),\n  )\n\n  destroyRef.onDestroy(unsubscribe)\n\n  return result\n}\n"
  },
  {
    "path": "packages/angular-query-experimental/src/inject-is-mutating.ts",
    "content": "import {\n  DestroyRef,\n  Injector,\n  NgZone,\n  assertInInjectionContext,\n  inject,\n  signal,\n} from '@angular/core'\nimport { QueryClient, notifyManager } from '@tanstack/query-core'\nimport type { MutationFilters } from '@tanstack/query-core'\nimport type { Signal } from '@angular/core'\n\nexport interface InjectIsMutatingOptions {\n  /**\n   * The `Injector` in which to create the isMutating signal.\n   *\n   * If this is not provided, the current injection context will be used instead (via `inject`).\n   */\n  injector?: Injector\n}\n\n/**\n * Injects a signal that tracks the number of mutations that your application is fetching.\n *\n * Can be used for app-wide loading indicators\n * @param filters - The filters to apply to the query.\n * @param options - Additional configuration\n * @returns A read-only signal with the number of fetching mutations.\n */\nexport function injectIsMutating(\n  filters?: MutationFilters,\n  options?: InjectIsMutatingOptions,\n): Signal<number> {\n  !options?.injector && assertInInjectionContext(injectIsMutating)\n  const injector = options?.injector ?? inject(Injector)\n  const destroyRef = injector.get(DestroyRef)\n  const ngZone = injector.get(NgZone)\n  const queryClient = injector.get(QueryClient)\n\n  const cache = queryClient.getMutationCache()\n  // isMutating is the prev value initialized on mount *\n  let isMutating = queryClient.isMutating(filters)\n\n  const result = signal(isMutating)\n\n  const unsubscribe = ngZone.runOutsideAngular(() =>\n    cache.subscribe(\n      notifyManager.batchCalls(() => {\n        const newIsMutating = queryClient.isMutating(filters)\n        if (isMutating !== newIsMutating) {\n          // * and update with each change\n          isMutating = newIsMutating\n          ngZone.run(() => {\n            result.set(isMutating)\n          })\n        }\n      }),\n    ),\n  )\n\n  destroyRef.onDestroy(unsubscribe)\n\n  return result.asReadonly()\n}\n"
  },
  {
    "path": "packages/angular-query-experimental/src/inject-is-restoring.ts",
    "content": "import {\n  InjectionToken,\n  Injector,\n  assertInInjectionContext,\n  inject,\n  signal,\n} from '@angular/core'\nimport type { Provider, Signal } from '@angular/core'\n\n/**\n * Internal token used to track isRestoring state, accessible in public API through `injectIsRestoring` and set via `provideIsRestoring`\n */\nconst IS_RESTORING = new InjectionToken('', {\n  // Default value when not provided\n  factory: () => signal(false).asReadonly(),\n})\n\ninterface InjectIsRestoringOptions {\n  /**\n   * The `Injector` to use to get the isRestoring signal.\n   *\n   * If this is not provided, the current injection context will be used instead (via `inject`).\n   */\n  injector?: Injector\n}\n\n/**\n * 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.\n * @param options - Options for injectIsRestoring.\n * @returns readonly signal with boolean that indicates whether a restore is in progress.\n */\nexport function injectIsRestoring(options?: InjectIsRestoringOptions) {\n  !options?.injector && assertInInjectionContext(injectIsRestoring)\n  const injector = options?.injector ?? inject(Injector)\n  return injector.get(IS_RESTORING)\n}\n\n/**\n * Used by TanStack Query Angular persist client plugin to provide the signal that tracks the restore state\n * @param isRestoring - a readonly signal that returns a boolean\n * @returns Provider for the `isRestoring` signal\n */\nexport function provideIsRestoring(isRestoring: Signal<boolean>): Provider {\n  return {\n    provide: IS_RESTORING,\n    useValue: isRestoring,\n  }\n}\n"
  },
  {
    "path": "packages/angular-query-experimental/src/inject-mutation-state.ts",
    "content": "import {\n  DestroyRef,\n  Injector,\n  NgZone,\n  assertInInjectionContext,\n  computed,\n  inject,\n  signal,\n} from '@angular/core'\nimport {\n  QueryClient,\n  notifyManager,\n  replaceEqualDeep,\n} from '@tanstack/query-core'\nimport type { Signal } from '@angular/core'\nimport type {\n  Mutation,\n  MutationCache,\n  MutationFilters,\n  MutationState,\n} from '@tanstack/query-core'\n\ntype MutationStateOptions<TResult = MutationState> = {\n  filters?: MutationFilters\n  select?: (mutation: Mutation) => TResult\n}\n\n/**\n *\n * @param mutationCache\n * @param options\n */\nfunction getResult<TResult = MutationState>(\n  mutationCache: MutationCache,\n  options: MutationStateOptions<TResult>,\n): Array<TResult> {\n  return mutationCache\n    .findAll(options.filters)\n    .map(\n      (mutation): TResult =>\n        (options.select ? options.select(mutation) : mutation.state) as TResult,\n    )\n}\n\nexport interface InjectMutationStateOptions {\n  /**\n   * The `Injector` in which to create the mutation state signal.\n   *\n   * If this is not provided, the current injection context will be used instead (via `inject`).\n   */\n  injector?: Injector\n}\n\n/**\n * Injects a signal that tracks the state of all mutations.\n * @param injectMutationStateFn - A function that returns mutation state options.\n * @param options - The Angular injector to use.\n * @returns The signal that tracks the state of all mutations.\n */\nexport function injectMutationState<TResult = MutationState>(\n  injectMutationStateFn: () => MutationStateOptions<TResult> = () => ({}),\n  options?: InjectMutationStateOptions,\n): Signal<Array<TResult>> {\n  !options?.injector && assertInInjectionContext(injectMutationState)\n  const injector = options?.injector ?? inject(Injector)\n  const destroyRef = injector.get(DestroyRef)\n  const ngZone = injector.get(NgZone)\n  const queryClient = injector.get(QueryClient)\n  const mutationCache = queryClient.getMutationCache()\n\n  /**\n   * Computed signal that gets result from mutation cache based on passed options\n   * First element is the result, second element is the time when the result was set\n   */\n  const resultFromOptionsSignal = computed(() => {\n    return [\n      getResult(mutationCache, injectMutationStateFn()),\n      performance.now(),\n    ] as const\n  })\n\n  /**\n   * Signal that contains result set by subscriber\n   * First element is the result, second element is the time when the result was set\n   */\n  const resultFromSubscriberSignal = signal<[Array<TResult>, number] | null>(\n    null,\n  )\n\n  /**\n   * Returns the last result by either subscriber or options\n   */\n  const effectiveResultSignal = computed(() => {\n    const optionsResult = resultFromOptionsSignal()\n    const subscriberResult = resultFromSubscriberSignal()\n    return subscriberResult && subscriberResult[1] > optionsResult[1]\n      ? subscriberResult[0]\n      : optionsResult[0]\n  })\n\n  const unsubscribe = ngZone.runOutsideAngular(() =>\n    mutationCache.subscribe(\n      notifyManager.batchCalls(() => {\n        const [lastResult] = effectiveResultSignal()\n        const nextResult = replaceEqualDeep(\n          lastResult,\n          getResult(mutationCache, injectMutationStateFn()),\n        )\n        if (lastResult !== nextResult) {\n          ngZone.run(() => {\n            resultFromSubscriberSignal.set([nextResult, performance.now()])\n          })\n        }\n      }),\n    ),\n  )\n\n  destroyRef.onDestroy(unsubscribe)\n\n  return effectiveResultSignal\n}\n"
  },
  {
    "path": "packages/angular-query-experimental/src/inject-mutation.ts",
    "content": "import {\n  Injector,\n  NgZone,\n  assertInInjectionContext,\n  computed,\n  effect,\n  inject,\n  signal,\n  untracked,\n} from '@angular/core'\nimport {\n  MutationObserver,\n  QueryClient,\n  noop,\n  notifyManager,\n  shouldThrowError,\n} from '@tanstack/query-core'\nimport { signalProxy } from './signal-proxy'\nimport { PENDING_TASKS } from './pending-tasks-compat'\nimport type { PendingTaskRef } from './pending-tasks-compat'\nimport type { DefaultError, MutationObserverResult } from '@tanstack/query-core'\nimport type {\n  CreateMutateFunction,\n  CreateMutationOptions,\n  CreateMutationResult,\n} from './types'\n\nexport interface InjectMutationOptions {\n  /**\n   * The `Injector` in which to create the mutation.\n   *\n   * If this is not provided, the current injection context will be used instead (via `inject`).\n   */\n  injector?: Injector\n}\n\n/**\n * Injects a mutation: an imperative function that can be invoked which typically performs server side effects.\n *\n * Unlike queries, mutations are not run automatically.\n * @param injectMutationFn - A function that returns mutation options.\n * @param options - Additional configuration\n * @returns The mutation.\n */\nexport function injectMutation<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n>(\n  injectMutationFn: () => CreateMutationOptions<\n    TData,\n    TError,\n    TVariables,\n    TOnMutateResult\n  >,\n  options?: InjectMutationOptions,\n): CreateMutationResult<TData, TError, TVariables, TOnMutateResult> {\n  !options?.injector && assertInInjectionContext(injectMutation)\n  const injector = options?.injector ?? inject(Injector)\n  const ngZone = injector.get(NgZone)\n  const pendingTasks = injector.get(PENDING_TASKS)\n  const queryClient = injector.get(QueryClient)\n\n  /**\n   * computed() is used so signals can be inserted into the options\n   * making it reactive. Wrapping options in a function ensures embedded expressions\n   * are preserved and can keep being applied after signal changes\n   */\n  const optionsSignal = computed(injectMutationFn)\n\n  const observerSignal = (() => {\n    let instance: MutationObserver<\n      TData,\n      TError,\n      TVariables,\n      TOnMutateResult\n    > | null = null\n\n    return computed(() => {\n      return (instance ||= new MutationObserver(queryClient, optionsSignal()))\n    })\n  })()\n\n  const mutateFnSignal = computed<\n    CreateMutateFunction<TData, TError, TVariables, TOnMutateResult>\n  >(() => {\n    const observer = observerSignal()\n    return (variables, mutateOptions) => {\n      observer.mutate(variables, mutateOptions).catch(noop)\n    }\n  })\n\n  /**\n   * Computed signal that gets result from mutation cache based on passed options\n   */\n  const resultFromInitialOptionsSignal = computed(() => {\n    const observer = observerSignal()\n    return observer.getCurrentResult()\n  })\n\n  /**\n   * Signal that contains result set by subscriber\n   */\n  const resultFromSubscriberSignal = signal<MutationObserverResult<\n    TData,\n    TError,\n    TVariables,\n    TOnMutateResult\n  > | null>(null)\n\n  effect(\n    () => {\n      const observer = observerSignal()\n      const observerOptions = optionsSignal()\n\n      untracked(() => {\n        observer.setOptions(observerOptions)\n      })\n    },\n    {\n      injector,\n    },\n  )\n\n  effect(\n    (onCleanup) => {\n      // observer.trackResult is not used as this optimization is not needed for Angular\n      const observer = observerSignal()\n      let pendingTaskRef: PendingTaskRef | null = null\n\n      untracked(() => {\n        const unsubscribe = ngZone.runOutsideAngular(() =>\n          observer.subscribe(\n            notifyManager.batchCalls((state) => {\n              ngZone.run(() => {\n                // Track pending task when mutation is pending\n                if (state.isPending && !pendingTaskRef) {\n                  pendingTaskRef = pendingTasks.add()\n                }\n\n                // Clear pending task when mutation is no longer pending\n                if (!state.isPending && pendingTaskRef) {\n                  pendingTaskRef()\n                  pendingTaskRef = null\n                }\n\n                if (\n                  state.isError &&\n                  shouldThrowError(observer.options.throwOnError, [state.error])\n                ) {\n                  ngZone.onError.emit(state.error)\n                  throw state.error\n                }\n\n                resultFromSubscriberSignal.set(state)\n              })\n            }),\n          ),\n        )\n        onCleanup(() => {\n          // Clean up any pending task on destroy\n          if (pendingTaskRef) {\n            pendingTaskRef()\n            pendingTaskRef = null\n          }\n          unsubscribe()\n        })\n      })\n    },\n    {\n      injector,\n    },\n  )\n\n  const resultSignal = computed(() => {\n    const resultFromSubscriber = resultFromSubscriberSignal()\n    const resultFromInitialOptions = resultFromInitialOptionsSignal()\n\n    const result = resultFromSubscriber ?? resultFromInitialOptions\n\n    return {\n      ...result,\n      mutate: mutateFnSignal(),\n      mutateAsync: result.mutate,\n    }\n  })\n\n  return signalProxy(resultSignal) as CreateMutationResult<\n    TData,\n    TError,\n    TVariables,\n    TOnMutateResult\n  >\n}\n"
  },
  {
    "path": "packages/angular-query-experimental/src/inject-queries-experimental/index.ts",
    "content": "export * from '../inject-queries'\n"
  },
  {
    "path": "packages/angular-query-experimental/src/inject-queries.ts",
    "content": "import {\n  QueriesObserver,\n  QueryClient,\n  notifyManager,\n} from '@tanstack/query-core'\nimport {\n  DestroyRef,\n  Injector,\n  NgZone,\n  assertInInjectionContext,\n  computed,\n  effect,\n  inject,\n  runInInjectionContext,\n  signal,\n  untracked,\n} from '@angular/core'\nimport { signalProxy } from './signal-proxy'\nimport { injectIsRestoring } from './inject-is-restoring'\nimport type {\n  DefaultError,\n  OmitKeyof,\n  QueriesObserverOptions,\n  QueriesPlaceholderDataFunction,\n  QueryFunction,\n  QueryKey,\n  QueryObserverOptions,\n  ThrowOnError,\n} from '@tanstack/query-core'\nimport type {\n  CreateQueryOptions,\n  CreateQueryResult,\n  DefinedCreateQueryResult,\n} from './types'\nimport type { Signal } from '@angular/core'\n\n// This defines the `CreateQueryOptions` that are accepted in `QueriesOptions` & `GetOptions`.\n// `placeholderData` function always gets undefined passed\ntype QueryObserverOptionsForCreateQueries<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = OmitKeyof<\n  CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  'placeholderData'\n> & {\n  placeholderData?: TQueryFnData | QueriesPlaceholderDataFunction<TQueryFnData>\n}\n\n// Avoid TS depth-limit error in case of large array literal\ntype MAXIMUM_DEPTH = 20\n\n// Widen the type of the symbol to enable type inference even if skipToken is not immutable.\ntype SkipTokenForCreateQueries = symbol\n\ntype GetCreateQueryOptionsForCreateQueries<T> =\n  // Part 1: responsible for applying explicit type parameter to function arguments, if object { queryFnData: TQueryFnData, error: TError, data: TData }\n  T extends {\n    queryFnData: infer TQueryFnData\n    error?: infer TError\n    data: infer TData\n  }\n    ? QueryObserverOptionsForCreateQueries<TQueryFnData, TError, TData>\n    : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n      ? QueryObserverOptionsForCreateQueries<TQueryFnData, TError>\n      : T extends { data: infer TData; error?: infer TError }\n        ? QueryObserverOptionsForCreateQueries<unknown, TError, TData>\n        : // Part 2: responsible for applying explicit type parameter to function arguments, if tuple [TQueryFnData, TError, TData]\n          T extends [infer TQueryFnData, infer TError, infer TData]\n          ? QueryObserverOptionsForCreateQueries<TQueryFnData, TError, TData>\n          : T extends [infer TQueryFnData, infer TError]\n            ? QueryObserverOptionsForCreateQueries<TQueryFnData, TError>\n            : T extends [infer TQueryFnData]\n              ? QueryObserverOptionsForCreateQueries<TQueryFnData>\n              : // Part 3: responsible for inferring and enforcing type if no explicit parameter was provided\n                T extends {\n                    queryFn?:\n                      | QueryFunction<infer TQueryFnData, infer TQueryKey>\n                      | SkipTokenForCreateQueries\n                    select?: (data: any) => infer TData\n                    throwOnError?: ThrowOnError<any, infer TError, any, any>\n                  }\n                ? QueryObserverOptionsForCreateQueries<\n                    TQueryFnData,\n                    unknown extends TError ? DefaultError : TError,\n                    unknown extends TData ? TQueryFnData : TData,\n                    TQueryKey\n                  >\n                : // Fallback\n                  QueryObserverOptionsForCreateQueries\n\n// A defined initialData setting should return a DefinedCreateQueryResult rather than CreateQueryResult\ntype GetDefinedOrUndefinedQueryResult<T, TData, TError = unknown> = T extends {\n  initialData?: infer TInitialData\n}\n  ? unknown extends TInitialData\n    ? CreateQueryResult<TData, TError>\n    : TInitialData extends TData\n      ? DefinedCreateQueryResult<TData, TError>\n      : TInitialData extends () => infer TInitialDataResult\n        ? unknown extends TInitialDataResult\n          ? CreateQueryResult<TData, TError>\n          : TInitialDataResult extends TData\n            ? DefinedCreateQueryResult<TData, TError>\n            : CreateQueryResult<TData, TError>\n        : CreateQueryResult<TData, TError>\n  : CreateQueryResult<TData, TError>\n\ntype GetCreateQueryResult<T> =\n  // Part 1: responsible for mapping explicit type parameter to function result, if object\n  T extends { queryFnData: any; error?: infer TError; data: infer TData }\n    ? GetDefinedOrUndefinedQueryResult<T, TData, TError>\n    : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n      ? GetDefinedOrUndefinedQueryResult<T, TQueryFnData, TError>\n      : T extends { data: infer TData; error?: infer TError }\n        ? GetDefinedOrUndefinedQueryResult<T, TData, TError>\n        : // Part 2: responsible for mapping explicit type parameter to function result, if tuple\n          T extends [any, infer TError, infer TData]\n          ? GetDefinedOrUndefinedQueryResult<T, TData, TError>\n          : T extends [infer TQueryFnData, infer TError]\n            ? GetDefinedOrUndefinedQueryResult<T, TQueryFnData, TError>\n            : T extends [infer TQueryFnData]\n              ? GetDefinedOrUndefinedQueryResult<T, TQueryFnData>\n              : // Part 3: responsible for mapping inferred type to results, if no explicit parameter was provided\n                T extends {\n                    queryFn?:\n                      | QueryFunction<infer TQueryFnData, any>\n                      | SkipTokenForCreateQueries\n                    select?: (data: any) => infer TData\n                    throwOnError?: ThrowOnError<any, infer TError, any, any>\n                  }\n                ? GetDefinedOrUndefinedQueryResult<\n                    T,\n                    unknown extends TData ? TQueryFnData : TData,\n                    unknown extends TError ? DefaultError : TError\n                  >\n                : // Fallback\n                  CreateQueryResult\n\n/**\n * QueriesOptions reducer recursively unwraps function arguments to infer/enforce type param\n */\nexport type QueriesOptions<\n  T extends Array<any>,\n  TResults extends Array<any> = [],\n  TDepth extends ReadonlyArray<number> = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n  ? Array<QueryObserverOptionsForCreateQueries>\n  : T extends []\n    ? []\n    : T extends [infer Head]\n      ? [...TResults, GetCreateQueryOptionsForCreateQueries<Head>]\n      : T extends [infer Head, ...infer Tails]\n        ? QueriesOptions<\n            [...Tails],\n            [...TResults, GetCreateQueryOptionsForCreateQueries<Head>],\n            [...TDepth, 1]\n          >\n        : ReadonlyArray<unknown> extends T\n          ? T\n          : // If T is *some* array but we couldn't assign unknown[] to it, then it must hold some known/homogenous type!\n            // use this to infer the param types in the case of Array.map() argument\n            T extends Array<\n                QueryObserverOptionsForCreateQueries<\n                  infer TQueryFnData,\n                  infer TError,\n                  infer TData,\n                  infer TQueryKey\n                >\n              >\n            ? Array<\n                QueryObserverOptionsForCreateQueries<\n                  TQueryFnData,\n                  TError,\n                  TData,\n                  TQueryKey\n                >\n              >\n            : // Fallback\n              Array<QueryObserverOptionsForCreateQueries>\n\n/**\n * QueriesResults reducer recursively maps type param to results\n */\nexport type QueriesResults<\n  T extends Array<any>,\n  TResults extends Array<any> = [],\n  TDepth extends ReadonlyArray<number> = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n  ? Array<CreateQueryResult>\n  : T extends []\n    ? []\n    : T extends [infer Head]\n      ? [...TResults, GetCreateQueryResult<Head>]\n      : T extends [infer Head, ...infer Tails]\n        ? QueriesResults<\n            [...Tails],\n            [...TResults, GetCreateQueryResult<Head>],\n            [...TDepth, 1]\n          >\n        : { [K in keyof T]: GetCreateQueryResult<T[K]> }\n\nexport interface InjectQueriesOptions<\n  T extends Array<any>,\n  TCombinedResult = QueriesResults<T>,\n> {\n  queries:\n    | readonly [...QueriesOptions<T>]\n    | readonly [\n        ...{ [K in keyof T]: GetCreateQueryOptionsForCreateQueries<T[K]> },\n      ]\n  combine?: (result: QueriesResults<T>) => TCombinedResult\n}\n\n/**\n * @param optionsFn - A function that returns queries' options.\n * @param injector - The Angular injector to use.\n */\nexport function injectQueries<\n  T extends Array<any>,\n  TCombinedResult = QueriesResults<T>,\n>(\n  optionsFn: () => InjectQueriesOptions<T, TCombinedResult>,\n  injector?: Injector,\n): Signal<TCombinedResult> {\n  !injector && assertInInjectionContext(injectQueries)\n  return runInInjectionContext(injector ?? inject(Injector), () => {\n    const destroyRef = inject(DestroyRef)\n    const ngZone = inject(NgZone)\n    const queryClient = inject(QueryClient)\n    const isRestoring = injectIsRestoring()\n\n    /**\n     * Signal that has the default options from query client applied\n     * computed() is used so signals can be inserted into the options\n     * making it reactive. Wrapping options in a function ensures embedded expressions\n     * are preserved and can keep being applied after signal changes\n     */\n    const optionsSignal = computed(() => {\n      return optionsFn()\n    })\n\n    const defaultedQueries = computed(() => {\n      return optionsSignal().queries.map((opts) => {\n        const defaultedOptions = queryClient.defaultQueryOptions(\n          opts as QueryObserverOptions,\n        )\n        // Make sure the results are already in fetching state before subscribing or updating options\n        defaultedOptions._optimisticResults = isRestoring()\n          ? 'isRestoring'\n          : 'optimistic'\n\n        return defaultedOptions as QueryObserverOptions\n      })\n    })\n\n    const observerSignal = (() => {\n      let instance: QueriesObserver<TCombinedResult> | null = null\n\n      return computed(() => {\n        return (instance ||= new QueriesObserver<TCombinedResult>(\n          queryClient,\n          defaultedQueries(),\n          optionsSignal() as QueriesObserverOptions<TCombinedResult>,\n        ))\n      })\n    })()\n\n    const optimisticResultSignal = computed(() =>\n      observerSignal().getOptimisticResult(\n        defaultedQueries(),\n        (optionsSignal() as QueriesObserverOptions<TCombinedResult>).combine,\n      ),\n    )\n\n    // Do not notify on updates because of changes in the options because\n    // these changes should already be reflected in the optimistic result.\n    effect(() => {\n      observerSignal().setQueries(\n        defaultedQueries(),\n        optionsSignal() as QueriesObserverOptions<TCombinedResult>,\n      )\n    })\n\n    const optimisticCombinedResultSignal = computed(() => {\n      const [_optimisticResult, getCombinedResult, trackResult] =\n        optimisticResultSignal()\n      return getCombinedResult(trackResult())\n    })\n\n    const resultFromSubscriberSignal = signal<TCombinedResult | null>(null)\n\n    effect(() => {\n      const observer = observerSignal()\n      const [_optimisticResult, getCombinedResult] = optimisticResultSignal()\n\n      untracked(() => {\n        const unsubscribe = isRestoring()\n          ? () => undefined\n          : ngZone.runOutsideAngular(() =>\n              observer.subscribe(\n                notifyManager.batchCalls((state) => {\n                  resultFromSubscriberSignal.set(getCombinedResult(state))\n                }),\n              ),\n            )\n\n        destroyRef.onDestroy(unsubscribe)\n      })\n    })\n\n    const resultSignal = computed(() => {\n      const subscriberResult = resultFromSubscriberSignal()\n      const optimisticResult = optimisticCombinedResultSignal()\n      return subscriberResult ?? optimisticResult\n    })\n\n    return computed(() => {\n      const result = resultSignal()\n      const { combine } = optionsSignal()\n\n      return combine\n        ? result\n        : (result as QueriesResults<T>).map((query) =>\n            signalProxy(signal(query)),\n          )\n    })\n  }) as unknown as Signal<TCombinedResult>\n}\n"
  },
  {
    "path": "packages/angular-query-experimental/src/inject-query-client.ts",
    "content": "import { Injector, inject } from '@angular/core'\nimport { QueryClient } from '@tanstack/query-core'\nimport type { InjectOptions } from '@angular/core'\n\n/**\n * Injects a `QueryClient` instance and allows passing a custom injector.\n * @param injectOptions - Type of the options argument to inject and optionally a custom injector.\n * @returns The `QueryClient` instance.\n * @deprecated Use `inject(QueryClient)` instead.\n * If you need to get a `QueryClient` from a custom injector, use `injector.get(QueryClient)`.\n *\n *\n * **Example**\n * ```ts\n * const queryClient = injectQueryClient();\n * ```\n */\nexport function injectQueryClient(\n  injectOptions: InjectOptions & { injector?: Injector } = {},\n) {\n  return (injectOptions.injector ?? inject(Injector)).get(QueryClient)\n}\n"
  },
  {
    "path": "packages/angular-query-experimental/src/inject-query.ts",
    "content": "import { QueryObserver } from '@tanstack/query-core'\nimport {\n  Injector,\n  assertInInjectionContext,\n  inject,\n  runInInjectionContext,\n} from '@angular/core'\nimport { createBaseQuery } from './create-base-query'\nimport type { DefaultError, QueryKey } from '@tanstack/query-core'\nimport type {\n  CreateQueryOptions,\n  CreateQueryResult,\n  DefinedCreateQueryResult,\n} from './types'\nimport type {\n  DefinedInitialDataOptions,\n  UndefinedInitialDataOptions,\n} from './query-options'\n\nexport interface InjectQueryOptions {\n  /**\n   * The `Injector` in which to create the query.\n   *\n   * If this is not provided, the current injection context will be used instead (via `inject`).\n   */\n  injector?: Injector\n}\n\n/**\n * Injects a query: a declarative dependency on an asynchronous source of data that is tied to a unique key.\n *\n * **Basic example**\n * ```ts\n * class ServiceOrComponent {\n *   query = injectQuery(() => ({\n *     queryKey: ['repoData'],\n *     queryFn: () =>\n *       this.#http.get<Response>('https://api.github.com/repos/tanstack/query'),\n *   }))\n * }\n * ```\n *\n * Similar to `computed` from Angular, the function passed to `injectQuery` will be run in the reactive context.\n * In the example below, the query will be automatically enabled and executed when the filter signal changes\n * to a truthy value. When the filter signal changes back to a falsy value, the query will be disabled.\n *\n * **Reactive example**\n * ```ts\n * class ServiceOrComponent {\n *   filter = signal('')\n *\n *   todosQuery = injectQuery(() => ({\n *     queryKey: ['todos', this.filter()],\n *     queryFn: () => fetchTodos(this.filter()),\n *     // Signals can be combined with expressions\n *     enabled: !!this.filter(),\n *   }))\n * }\n * ```\n * @param injectQueryFn - A function that returns query options.\n * @param options - Additional configuration\n * @returns The query result.\n * @see https://tanstack.com/query/latest/docs/framework/angular/guides/queries\n */\nexport function injectQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  injectQueryFn: () => DefinedInitialDataOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey\n  >,\n  options?: InjectQueryOptions,\n): DefinedCreateQueryResult<TData, TError>\n\n/**\n * Injects a query: a declarative dependency on an asynchronous source of data that is tied to a unique key.\n *\n * **Basic example**\n * ```ts\n * class ServiceOrComponent {\n *   query = injectQuery(() => ({\n *     queryKey: ['repoData'],\n *     queryFn: () =>\n *       this.#http.get<Response>('https://api.github.com/repos/tanstack/query'),\n *   }))\n * }\n * ```\n *\n * Similar to `computed` from Angular, the function passed to `injectQuery` will be run in the reactive context.\n * In the example below, the query will be automatically enabled and executed when the filter signal changes\n * to a truthy value. When the filter signal changes back to a falsy value, the query will be disabled.\n *\n * **Reactive example**\n * ```ts\n * class ServiceOrComponent {\n *   filter = signal('')\n *\n *   todosQuery = injectQuery(() => ({\n *     queryKey: ['todos', this.filter()],\n *     queryFn: () => fetchTodos(this.filter()),\n *     // Signals can be combined with expressions\n *     enabled: !!this.filter(),\n *   }))\n * }\n * ```\n * @param injectQueryFn - A function that returns query options.\n * @param options - Additional configuration\n * @returns The query result.\n * @see https://tanstack.com/query/latest/docs/framework/angular/guides/queries\n */\nexport function injectQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  injectQueryFn: () => UndefinedInitialDataOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey\n  >,\n  options?: InjectQueryOptions,\n): CreateQueryResult<TData, TError>\n\n/**\n * Injects a query: a declarative dependency on an asynchronous source of data that is tied to a unique key.\n *\n * **Basic example**\n * ```ts\n * class ServiceOrComponent {\n *   query = injectQuery(() => ({\n *     queryKey: ['repoData'],\n *     queryFn: () =>\n *       this.#http.get<Response>('https://api.github.com/repos/tanstack/query'),\n *   }))\n * }\n * ```\n *\n * Similar to `computed` from Angular, the function passed to `injectQuery` will be run in the reactive context.\n * In the example below, the query will be automatically enabled and executed when the filter signal changes\n * to a truthy value. When the filter signal changes back to a falsy value, the query will be disabled.\n *\n * **Reactive example**\n * ```ts\n * class ServiceOrComponent {\n *   filter = signal('')\n *\n *   todosQuery = injectQuery(() => ({\n *     queryKey: ['todos', this.filter()],\n *     queryFn: () => fetchTodos(this.filter()),\n *     // Signals can be combined with expressions\n *     enabled: !!this.filter(),\n *   }))\n * }\n * ```\n * @param injectQueryFn - A function that returns query options.\n * @param options - Additional configuration\n * @returns The query result.\n * @see https://tanstack.com/query/latest/docs/framework/angular/guides/queries\n */\nexport function injectQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  injectQueryFn: () => CreateQueryOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey\n  >,\n  options?: InjectQueryOptions,\n): CreateQueryResult<TData, TError>\n\n/**\n * Injects a query: a declarative dependency on an asynchronous source of data that is tied to a unique key.\n *\n * **Basic example**\n * ```ts\n * class ServiceOrComponent {\n *   query = injectQuery(() => ({\n *     queryKey: ['repoData'],\n *     queryFn: () =>\n *       this.#http.get<Response>('https://api.github.com/repos/tanstack/query'),\n *   }))\n * }\n * ```\n *\n * Similar to `computed` from Angular, the function passed to `injectQuery` will be run in the reactive context.\n * In the example below, the query will be automatically enabled and executed when the filter signal changes\n * to a truthy value. When the filter signal changes back to a falsy value, the query will be disabled.\n *\n * **Reactive example**\n * ```ts\n * class ServiceOrComponent {\n *   filter = signal('')\n *\n *   todosQuery = injectQuery(() => ({\n *     queryKey: ['todos', this.filter()],\n *     queryFn: () => fetchTodos(this.filter()),\n *     // Signals can be combined with expressions\n *     enabled: !!this.filter(),\n *   }))\n * }\n * ```\n * @param injectQueryFn - A function that returns query options.\n * @param options - Additional configuration\n * @returns The query result.\n * @see https://tanstack.com/query/latest/docs/framework/angular/guides/queries\n */\nexport function injectQuery(\n  injectQueryFn: () => CreateQueryOptions,\n  options?: InjectQueryOptions,\n) {\n  !options?.injector && assertInInjectionContext(injectQuery)\n  return runInInjectionContext(options?.injector ?? inject(Injector), () =>\n    createBaseQuery(injectQueryFn, QueryObserver),\n  ) as unknown as CreateQueryResult\n}\n"
  },
  {
    "path": "packages/angular-query-experimental/src/mutation-options.ts",
    "content": "import type { DefaultError, WithRequired } from '@tanstack/query-core'\nimport type { CreateMutationOptions } from './types'\n\n/**\n * Allows to share and re-use mutation options in a type-safe way.\n *\n * **Example**\n *\n * ```ts\n * export class QueriesService {\n *   private http = inject(HttpClient)\n *   private queryClient = inject(QueryClient)\n *\n *   updatePost(id: number) {\n *     return mutationOptions({\n *       mutationFn: (post: Post) => Promise.resolve(post),\n *       mutationKey: [\"updatePost\", id],\n *       onSuccess: (newPost) => {\n *         //           ^? newPost: Post\n *         this.queryClient.setQueryData([\"posts\", id], newPost)\n *       },\n *     });\n *   }\n * }\n *\n * class ComponentOrService {\n *   queries = inject(QueriesService)\n *   id = signal(0)\n *   mutation = injectMutation(() => this.queries.updatePost(this.id()))\n *\n *   save() {\n *     this.mutation.mutate({ title: 'New Title' })\n *   }\n * }\n * ```\n * @param options - The mutation options.\n * @returns Mutation options.\n */\nexport function mutationOptions<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n>(\n  options: WithRequired<\n    CreateMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n    'mutationKey'\n  >,\n): WithRequired<\n  CreateMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n  'mutationKey'\n>\nexport function mutationOptions<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n>(\n  options: Omit<\n    CreateMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n    'mutationKey'\n  >,\n): Omit<\n  CreateMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n  'mutationKey'\n>\n\n/**\n * Allows to share and re-use mutation options in a type-safe way.\n *\n * **Example**\n *\n * ```ts\n * export class QueriesService {\n *   private http = inject(HttpClient)\n *   private queryClient = inject(QueryClient)\n *\n *   updatePost(id: number) {\n *     return mutationOptions({\n *       mutationFn: (post: Post) => Promise.resolve(post),\n *       mutationKey: [\"updatePost\", id],\n *       onSuccess: (newPost) => {\n *         //           ^? newPost: Post\n *         this.queryClient.setQueryData([\"posts\", id], newPost)\n *       },\n *     });\n *   }\n * }\n *\n * class ComponentOrService {\n *   queries = inject(QueriesService)\n *   id = signal(0)\n *   mutation = injectMutation(() => this.queries.updatePost(this.id()))\n *\n *   save() {\n *     this.mutation.mutate({ title: 'New Title' })\n *   }\n * }\n * ```\n * @param options - The mutation options.\n * @returns Mutation options.\n */\nexport function mutationOptions<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n>(\n  options: CreateMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n): CreateMutationOptions<TData, TError, TVariables, TOnMutateResult> {\n  return options\n}\n"
  },
  {
    "path": "packages/angular-query-experimental/src/pending-tasks-compat.ts",
    "content": "import { InjectionToken, inject } from '@angular/core'\nimport * as ng from '@angular/core'\nimport { noop } from '@tanstack/query-core'\n\ntype PendingTasksCompat = { add: () => PendingTaskRef }\n\nexport type PendingTaskRef = () => void\n\nexport const PENDING_TASKS = new InjectionToken<PendingTasksCompat>(\n  'PENDING_TASKS',\n  {\n    factory: (): PendingTasksCompat => {\n      // Access via Reflect so bundlers stay quiet when the token is absent (Angular < 19).\n      const token = Reflect.get(ng, 'PendingTasks') as unknown as\n        | Parameters<typeof inject>[0]\n        | undefined\n\n      const svc: PendingTasksCompat | null = token\n        ? (inject(token, { optional: true }) as PendingTasksCompat | null)\n        : null\n\n      // Without PendingTasks we fall back to a stable no-op shim.\n      return {\n        add: svc ? () => svc.add() : () => noop,\n      }\n    },\n  },\n)\n"
  },
  {
    "path": "packages/angular-query-experimental/src/providers.ts",
    "content": "import { DestroyRef, InjectionToken, inject } from '@angular/core'\nimport { QueryClient } from '@tanstack/query-core'\nimport type { Provider } from '@angular/core'\n\n/**\n * Usually {@link provideTanStackQuery} is used once to set up TanStack Query and the\n * {@link https://tanstack.com/query/latest/docs/reference/QueryClient|QueryClient}\n * for the entire application. Internally it calls `provideQueryClient`.\n * You can use `provideQueryClient` to provide a different `QueryClient` instance for a part\n * of the application or for unit testing purposes.\n * @param queryClient - A `QueryClient` instance, or an `InjectionToken` which provides a `QueryClient`.\n * @returns a provider object that can be used to provide the `QueryClient` instance.\n */\nexport function provideQueryClient(\n  queryClient: QueryClient | InjectionToken<QueryClient>,\n): Provider {\n  return {\n    provide: QueryClient,\n    useFactory: () => {\n      const client =\n        queryClient instanceof InjectionToken\n          ? inject(queryClient)\n          : queryClient\n      // Unmount the query client on injector destroy\n      inject(DestroyRef).onDestroy(() => client.unmount())\n      client.mount()\n      return client\n    },\n  }\n}\n\n/**\n * Sets up providers necessary to enable TanStack Query functionality for Angular applications.\n *\n * Allows to configure a `QueryClient` and optional features such as developer tools.\n *\n * **Example - standalone**\n *\n * ```ts\n * import {\n *   provideTanStackQuery,\n *   QueryClient,\n * } from '@tanstack/angular-query-experimental'\n *\n * bootstrapApplication(AppComponent, {\n *   providers: [provideTanStackQuery(new QueryClient())],\n * })\n * ```\n *\n * **Example - NgModule-based**\n *\n * ```ts\n * import {\n *   provideTanStackQuery,\n *   QueryClient,\n * } from '@tanstack/angular-query-experimental'\n *\n * @NgModule({\n *   declarations: [AppComponent],\n *   imports: [BrowserModule],\n *   providers: [provideTanStackQuery(new QueryClient())],\n *   bootstrap: [AppComponent],\n * })\n * export class AppModule {}\n * ```\n *\n * You can also enable optional developer tools by adding `withDevtools`. By\n * default the tools will then be loaded when your app is in development mode.\n * ```ts\n * import {\n *   provideTanStackQuery,\n *   withDevtools\n *   QueryClient,\n * } from '@tanstack/angular-query-experimental'\n *\n * bootstrapApplication(AppComponent,\n *   {\n *     providers: [\n *       provideTanStackQuery(new QueryClient(), withDevtools())\n *     ]\n *   }\n * )\n * ```\n *\n * **Example: using an InjectionToken**\n *\n * ```ts\n * export const MY_QUERY_CLIENT = new InjectionToken('', {\n *   factory: () => new QueryClient(),\n * })\n *\n * // In a lazy loaded route or lazy loaded component's providers array:\n * providers: [provideTanStackQuery(MY_QUERY_CLIENT)]\n * ```\n * Using an InjectionToken for the QueryClient is an advanced optimization which allows TanStack Query to be absent from the main application bundle.\n * This can be beneficial if you want to include TanStack Query on lazy loaded routes only while still sharing a `QueryClient`.\n *\n * Note that this is a small optimization and for most applications it's preferable to provide the `QueryClient` in the main application config.\n * @param queryClient - A `QueryClient` instance, or an `InjectionToken` which provides a `QueryClient`.\n * @param features - Optional features to configure additional Query functionality.\n * @returns A set of providers to set up TanStack Query.\n * @see https://tanstack.com/query/v5/docs/framework/angular/quick-start\n * @see withDevtools\n */\nexport function provideTanStackQuery(\n  queryClient: QueryClient | InjectionToken<QueryClient>,\n  ...features: Array<QueryFeatures>\n): Array<Provider> {\n  return [\n    provideQueryClient(queryClient),\n    features.map((feature) => feature.ɵproviders),\n  ]\n}\n\n/**\n * Sets up providers necessary to enable TanStack Query functionality for Angular applications.\n *\n * Allows to configure a `QueryClient`.\n * @param queryClient - A `QueryClient` instance.\n * @returns A set of providers to set up TanStack Query.\n * @see https://tanstack.com/query/v5/docs/framework/angular/quick-start\n * @deprecated Use `provideTanStackQuery` instead.\n */\nexport function provideAngularQuery(queryClient: QueryClient): Array<Provider> {\n  return provideTanStackQuery(queryClient)\n}\n\nconst queryFeatures = ['Devtools', 'PersistQueryClient'] as const\n\ntype QueryFeatureKind = (typeof queryFeatures)[number]\n\n/**\n * Helper type to represent a Query feature.\n */\nexport interface QueryFeature<TFeatureKind extends QueryFeatureKind> {\n  ɵkind: TFeatureKind\n  ɵproviders: Array<Provider>\n}\n\n/**\n * Helper function to create an object that represents a Query feature.\n * @param kind -\n * @param providers -\n * @returns A Query feature.\n */\nexport function queryFeature<TFeatureKind extends QueryFeatureKind>(\n  kind: TFeatureKind,\n  providers: Array<Provider>,\n): QueryFeature<TFeatureKind> {\n  return { ɵkind: kind, ɵproviders: providers }\n}\n\n/**\n * A type alias that represents a feature which enables developer tools.\n * The type is used to describe the return value of the `withDevtools` function.\n * @see {@link withDevtools}\n */\nexport type DevtoolsFeature = QueryFeature<'Devtools'>\n\n/**\n * A type alias that represents a feature which enables persistence.\n * The type is used to describe the return value of the `withPersistQueryClient` function.\n */\nexport type PersistQueryClientFeature = QueryFeature<'PersistQueryClient'>\n\n/**\n * A type alias that represents all Query features available for use with `provideTanStackQuery`.\n * Features can be enabled by adding special functions to the `provideTanStackQuery` call.\n * See documentation for each symbol to find corresponding function name. See also `provideTanStackQuery`\n * documentation on how to use those functions.\n * @see {@link provideTanStackQuery}\n */\nexport type QueryFeatures = DevtoolsFeature | PersistQueryClientFeature\n"
  },
  {
    "path": "packages/angular-query-experimental/src/query-options.ts",
    "content": "import type {\n  DataTag,\n  DefaultError,\n  InitialDataFunction,\n  NonUndefinedGuard,\n  OmitKeyof,\n  QueryFunction,\n  QueryKey,\n  SkipToken,\n} from '@tanstack/query-core'\nimport type { CreateQueryOptions } from './types'\n\nexport type UndefinedInitialDataOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey> & {\n  initialData?:\n    | undefined\n    | InitialDataFunction<NonUndefinedGuard<TQueryFnData>>\n    | NonUndefinedGuard<TQueryFnData>\n}\n\nexport type UnusedSkipTokenOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = OmitKeyof<\n  CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  'queryFn'\n> & {\n  queryFn?: Exclude<\n    CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>['queryFn'],\n    SkipToken | undefined\n  >\n}\n\nexport type DefinedInitialDataOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = Omit<\n  CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  'queryFn'\n> & {\n  initialData:\n    | NonUndefinedGuard<TQueryFnData>\n    | (() => NonUndefinedGuard<TQueryFnData>)\n  queryFn?: QueryFunction<TQueryFnData, TQueryKey>\n}\n\n/**\n * Allows to share and re-use query options in a type-safe way.\n *\n * The `queryKey` will be tagged with the type from `queryFn`.\n *\n * **Example**\n *\n * ```ts\n *  const { queryKey } = queryOptions({\n *     queryKey: ['key'],\n *     queryFn: () => Promise.resolve(5),\n *     //  ^?  Promise<number>\n *   })\n *\n *   const queryClient = new QueryClient()\n *   const data = queryClient.getQueryData(queryKey)\n *   //    ^?  number | undefined\n * ```\n * @param options - The query options to tag with the type from `queryFn`.\n * @returns The tagged query options.\n */\nexport function queryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,\n): DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> & {\n  queryKey: DataTag<TQueryKey, TQueryFnData, TError>\n}\n\n/**\n * Allows to share and re-use query options in a type-safe way.\n *\n * The `queryKey` will be tagged with the type from `queryFn`.\n *\n * **Example**\n *\n * ```ts\n *  const { queryKey } = queryOptions({\n *     queryKey: ['key'],\n *     queryFn: () => Promise.resolve(5),\n *     //  ^?  Promise<number>\n *   })\n *\n *   const queryClient = new QueryClient()\n *   const data = queryClient.getQueryData(queryKey)\n *   //    ^?  number | undefined\n * ```\n * @param options - The query options to tag with the type from `queryFn`.\n * @returns The tagged query options.\n */\nexport function queryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: UnusedSkipTokenOptions<TQueryFnData, TError, TData, TQueryKey>,\n): UnusedSkipTokenOptions<TQueryFnData, TError, TData, TQueryKey> & {\n  queryKey: DataTag<TQueryKey, TQueryFnData, TError>\n}\n\n/**\n * Allows to share and re-use query options in a type-safe way.\n *\n * The `queryKey` will be tagged with the type from `queryFn`.\n *\n * **Example**\n *\n * ```ts\n *  const { queryKey } = queryOptions({\n *     queryKey: ['key'],\n *     queryFn: () => Promise.resolve(5),\n *     //  ^?  Promise<number>\n *   })\n *\n *   const queryClient = new QueryClient()\n *   const data = queryClient.getQueryData(queryKey)\n *   //    ^?  number | undefined\n * ```\n * @param options - The query options to tag with the type from `queryFn`.\n * @returns The tagged query options.\n */\nexport function queryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,\n): UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> & {\n  queryKey: DataTag<TQueryKey, TQueryFnData, TError>\n}\n\n/**\n * Allows to share and re-use query options in a type-safe way.\n *\n * The `queryKey` will be tagged with the type from `queryFn`.\n *\n * **Example**\n *\n * ```ts\n *  const { queryKey } = queryOptions({\n *     queryKey: ['key'],\n *     queryFn: () => Promise.resolve(5),\n *     //  ^?  Promise<number>\n *   })\n *\n *   const queryClient = new QueryClient()\n *   const data = queryClient.getQueryData(queryKey)\n *   //    ^?  number | undefined\n * ```\n * @param options - The query options to tag with the type from `queryFn`.\n * @returns The tagged query options.\n */\nexport function queryOptions(options: unknown) {\n  return options\n}\n"
  },
  {
    "path": "packages/angular-query-experimental/src/signal-proxy.ts",
    "content": "import { computed, untracked } from '@angular/core'\nimport type { Signal } from '@angular/core'\n\nexport type MapToSignals<T> = {\n  [K in keyof T]: T[K] extends Function ? T[K] : Signal<T[K]>\n}\n\n/**\n * Exposes fields of an object passed via an Angular `Signal` as `Computed` signals.\n * Functions on the object are passed through as-is.\n * @param inputSignal - `Signal` that must return an object.\n * @returns A proxy object with the same fields as the input object, but with each field wrapped in a `Computed` signal.\n */\nexport function signalProxy<TInput extends Record<string | symbol, any>>(\n  inputSignal: Signal<TInput>,\n) {\n  const internalState = {} as MapToSignals<TInput>\n\n  return new Proxy<MapToSignals<TInput>>(internalState, {\n    get(target, prop) {\n      // first check if we have it in our internal state and return it\n      const computedField = target[prop]\n      if (computedField) return computedField\n\n      // then, check if it's a function on the resultState and return it\n      const targetField = untracked(inputSignal)[prop]\n      if (typeof targetField === 'function') return targetField\n\n      // finally, create a computed field, store it and return it\n      // @ts-expect-error\n      return (target[prop] = computed(() => inputSignal()[prop]))\n    },\n    has(_, prop) {\n      return !!untracked(inputSignal)[prop]\n    },\n    ownKeys() {\n      return Reflect.ownKeys(untracked(inputSignal))\n    },\n    getOwnPropertyDescriptor() {\n      return {\n        enumerable: true,\n        configurable: true,\n      }\n    },\n  })\n}\n"
  },
  {
    "path": "packages/angular-query-experimental/src/types.ts",
    "content": "/* istanbul ignore file */\n\nimport type {\n  DefaultError,\n  DefinedInfiniteQueryObserverResult,\n  DefinedQueryObserverResult,\n  InfiniteQueryObserverOptions,\n  InfiniteQueryObserverResult,\n  MutateFunction,\n  MutationObserverOptions,\n  MutationObserverResult,\n  OmitKeyof,\n  Override,\n  QueryKey,\n  QueryObserverOptions,\n  QueryObserverResult,\n} from '@tanstack/query-core'\nimport type { Signal } from '@angular/core'\nimport type { MapToSignals } from './signal-proxy'\n\nexport interface CreateBaseQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> extends QueryObserverOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryData,\n  TQueryKey\n> {}\n\nexport interface CreateQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> extends OmitKeyof<\n  CreateBaseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>,\n  'suspense'\n> {}\n\ntype CreateStatusBasedQueryResult<\n  TStatus extends QueryObserverResult['status'],\n  TData = unknown,\n  TError = DefaultError,\n> = Extract<QueryObserverResult<TData, TError>, { status: TStatus }>\n\nexport interface BaseQueryNarrowing<TData = unknown, TError = DefaultError> {\n  isSuccess: (\n    this: CreateBaseQueryResult<TData, TError>,\n  ) => this is CreateBaseQueryResult<\n    TData,\n    TError,\n    CreateStatusBasedQueryResult<'success', TData, TError>\n  >\n  isError: (\n    this: CreateBaseQueryResult<TData, TError>,\n  ) => this is CreateBaseQueryResult<\n    TData,\n    TError,\n    CreateStatusBasedQueryResult<'error', TData, TError>\n  >\n  isPending: (\n    this: CreateBaseQueryResult<TData, TError>,\n  ) => this is CreateBaseQueryResult<\n    TData,\n    TError,\n    CreateStatusBasedQueryResult<'pending', TData, TError>\n  >\n}\n\nexport interface CreateInfiniteQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> extends OmitKeyof<\n  InfiniteQueryObserverOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n  'suspense'\n> {}\n\nexport type CreateBaseQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n  TState = QueryObserverResult<TData, TError>,\n> = BaseQueryNarrowing<TData, TError> &\n  MapToSignals<OmitKeyof<TState, keyof BaseQueryNarrowing, 'safely'>>\n\nexport type CreateQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = CreateBaseQueryResult<TData, TError>\n\nexport type DefinedCreateQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n  TState = DefinedQueryObserverResult<TData, TError>,\n> = BaseQueryNarrowing<TData, TError> &\n  MapToSignals<OmitKeyof<TState, keyof BaseQueryNarrowing, 'safely'>>\n\nexport type CreateInfiniteQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = BaseQueryNarrowing<TData, TError> &\n  MapToSignals<InfiniteQueryObserverResult<TData, TError>>\n\nexport type DefinedCreateInfiniteQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n  TDefinedInfiniteQueryObserver = DefinedInfiniteQueryObserverResult<\n    TData,\n    TError\n  >,\n> = MapToSignals<TDefinedInfiniteQueryObserver>\n\nexport interface CreateMutationOptions<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> extends OmitKeyof<\n  MutationObserverOptions<TData, TError, TVariables, TOnMutateResult>,\n  '_defaulted'\n> {}\n\nexport type CreateMutateFunction<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> = (\n  ...args: Parameters<\n    MutateFunction<TData, TError, TVariables, TOnMutateResult>\n  >\n) => void\n\nexport type CreateMutateAsyncFunction<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> = MutateFunction<TData, TError, TVariables, TOnMutateResult>\n\nexport type CreateBaseMutationResult<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = unknown,\n  TOnMutateResult = unknown,\n> = Override<\n  MutationObserverResult<TData, TError, TVariables, TOnMutateResult>,\n  { mutate: CreateMutateFunction<TData, TError, TVariables, TOnMutateResult> }\n> & {\n  mutateAsync: CreateMutateAsyncFunction<\n    TData,\n    TError,\n    TVariables,\n    TOnMutateResult\n  >\n}\n\ntype CreateStatusBasedMutationResult<\n  TStatus extends CreateBaseMutationResult['status'],\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = unknown,\n  TOnMutateResult = unknown,\n> = Extract<\n  CreateBaseMutationResult<TData, TError, TVariables, TOnMutateResult>,\n  { status: TStatus }\n>\n\ntype SignalFunction<T extends () => any> = T & Signal<ReturnType<T>>\n\nexport interface BaseMutationNarrowing<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = unknown,\n  TOnMutateResult = unknown,\n> {\n  isSuccess: SignalFunction<\n    (\n      this: CreateMutationResult<TData, TError, TVariables, TOnMutateResult>,\n    ) => this is CreateMutationResult<\n      TData,\n      TError,\n      TVariables,\n      TOnMutateResult,\n      CreateStatusBasedMutationResult<\n        'success',\n        TData,\n        TError,\n        TVariables,\n        TOnMutateResult\n      >\n    >\n  >\n  isError: SignalFunction<\n    (\n      this: CreateMutationResult<TData, TError, TVariables, TOnMutateResult>,\n    ) => this is CreateMutationResult<\n      TData,\n      TError,\n      TVariables,\n      TOnMutateResult,\n      CreateStatusBasedMutationResult<\n        'error',\n        TData,\n        TError,\n        TVariables,\n        TOnMutateResult\n      >\n    >\n  >\n  isPending: SignalFunction<\n    (\n      this: CreateMutationResult<TData, TError, TVariables, TOnMutateResult>,\n    ) => this is CreateMutationResult<\n      TData,\n      TError,\n      TVariables,\n      TOnMutateResult,\n      CreateStatusBasedMutationResult<\n        'pending',\n        TData,\n        TError,\n        TVariables,\n        TOnMutateResult\n      >\n    >\n  >\n  isIdle: SignalFunction<\n    (\n      this: CreateMutationResult<TData, TError, TVariables, TOnMutateResult>,\n    ) => this is CreateMutationResult<\n      TData,\n      TError,\n      TVariables,\n      TOnMutateResult,\n      CreateStatusBasedMutationResult<\n        'idle',\n        TData,\n        TError,\n        TVariables,\n        TOnMutateResult\n      >\n    >\n  >\n}\n\nexport type CreateMutationResult<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = unknown,\n  TOnMutateResult = unknown,\n  TState = CreateStatusBasedMutationResult<\n    CreateBaseMutationResult['status'],\n    TData,\n    TError,\n    TVariables,\n    TOnMutateResult\n  >,\n> = BaseMutationNarrowing<TData, TError, TVariables, TOnMutateResult> &\n  MapToSignals<OmitKeyof<TState, keyof BaseMutationNarrowing, 'safely'>>\n"
  },
  {
    "path": "packages/angular-query-experimental/test-setup.ts",
    "content": "import '@testing-library/jest-dom/vitest'\nimport { getTestBed } from '@angular/core/testing'\nimport {\n  BrowserTestingModule,\n  platformBrowserTesting,\n} from '@angular/platform-browser/testing'\n\ngetTestBed().initTestEnvironment(BrowserTestingModule, platformBrowserTesting())\n"
  },
  {
    "path": "packages/angular-query-experimental/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\",\n    \"noFallthroughCasesInSwitch\": true,\n    \"useDefineForClassFields\": false,\n    \"target\": \"ES2022\"\n  },\n  \"angularCompilerOptions\": {\n    \"enableI18nLegacyMessageIdFormat\": false,\n    \"strictInjectionParameters\": true,\n    \"strictInputAccessModifiers\": true,\n    \"strictStandalone\": true,\n    \"strictTemplates\": true\n  },\n  \"include\": [\"src\", \"scripts\", \"test-setup.ts\", \"*.config.*\", \"package.json\"],\n  \"references\": [{ \"path\": \"../query-core\" }, { \"path\": \"../query-devtools\" }]\n}\n"
  },
  {
    "path": "packages/angular-query-experimental/tsconfig.prod.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"incremental\": false,\n    \"composite\": false,\n    \"rootDir\": \"../../\",\n    \"customConditions\": null\n  }\n}\n"
  },
  {
    "path": "packages/angular-query-experimental/vite.config.ts",
    "content": "import { defineConfig, mergeConfig } from 'vitest/config'\nimport { externalizeDeps } from 'vite-plugin-externalize-deps'\nimport tsconfigPaths from 'vite-tsconfig-paths'\nimport dts from 'vite-plugin-dts'\nimport packageJson from './package.json'\nimport type { Options } from '@tanstack/vite-config'\n\nfunction ensureImportFileExtension({\n  content,\n  extension,\n}: {\n  content: string\n  extension: string\n}) {\n  // replace e.g. `import { foo } from './foo'` with `import { foo } from './foo.js'`\n  content = content.replace(\n    /(im|ex)port\\s[\\w{}/*\\s,]+from\\s['\"](?:\\.\\.?\\/)+?[^.'\"]+(?=['\"];?)/gm,\n    `$&.${extension}`,\n  )\n\n  // replace e.g. `import('./foo')` with `import('./foo.js')`\n  content = content.replace(\n    /import\\(['\"](?:\\.\\.?\\/)+?[^.'\"]+(?=['\"];?)/gm,\n    `$&.${extension}`,\n  )\n  return content\n}\n\nconst config = defineConfig({\n  // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660\n  resolve: {\n    conditions: ['@tanstack/custom-condition'],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        conditions: ['@tanstack/custom-condition'],\n      },\n    },\n  },\n  test: {\n    name: packageJson.name,\n    dir: './src',\n    watch: false,\n    environment: 'jsdom',\n    setupFiles: ['test-setup.ts'],\n    coverage: {\n      enabled: true,\n      provider: 'istanbul',\n      include: ['src/**/*'],\n      exclude: ['src/__tests__/**'],\n    },\n    typecheck: { enabled: true },\n    globals: true,\n    restoreMocks: true,\n  },\n})\n\n// copy from @tanstack/config/vite with changes:\n// - build - lib - fileName: [name.mjs]\n// - rollup - output - preserveModulesRoot: src\nexport const tanstackViteConfig = (options: Options) => {\n  const outDir = options.outDir ?? 'dist'\n  const cjs = options.cjs ?? true\n\n  return defineConfig({\n    plugins: [\n      externalizeDeps({ include: options.externalDeps ?? [] }),\n      tsconfigPaths({\n        projects: options.tsconfigPath ? [options.tsconfigPath] : undefined,\n      }),\n      dts({\n        outDir,\n        entryRoot: options.srcDir,\n        include: options.srcDir,\n        exclude: options.exclude,\n        tsconfigPath: options.tsconfigPath,\n        compilerOptions: {\n          module: 99, // ESNext\n          declarationMap: false,\n        },\n        beforeWriteFile: (filePath, content) => {\n          return {\n            filePath,\n            content: ensureImportFileExtension({ content, extension: 'js' }),\n          }\n        },\n        afterDiagnostic: (diagnostics) => {\n          if (diagnostics.length > 0) {\n            console.error('Please fix the above type errors')\n            process.exit(1)\n          }\n        },\n      }),\n    ],\n    build: {\n      outDir,\n      minify: false,\n      sourcemap: true,\n      lib: {\n        entry: options.entry,\n        formats: cjs ? ['es', 'cjs'] : ['es'],\n        fileName: () => '[name].mjs',\n      },\n      rollupOptions: {\n        output: {\n          preserveModules: true,\n          preserveModulesRoot: 'src',\n        },\n      },\n    },\n  })\n}\n\nexport default mergeConfig(\n  config,\n  tanstackViteConfig({\n    cjs: false,\n    entry: [\n      './src/index.ts',\n      './src/inject-queries-experimental/index.ts',\n      './src/devtools-panel/index.ts',\n      './src/devtools-panel/stub.ts',\n      './src/devtools/index.ts',\n      './src/devtools/stub.ts',\n    ],\n    exclude: ['src/__tests__'],\n    srcDir: './src',\n    tsconfigPath: 'tsconfig.prod.json',\n  }),\n)\n"
  },
  {
    "path": "packages/angular-query-persist-client/.attw.json",
    "content": "{\n  \"ignoreRules\": [\"cjs-resolves-to-esm\"]\n}\n"
  },
  {
    "path": "packages/angular-query-persist-client/CHANGELOG.md",
    "content": "# @tanstack/angular-query-persist-client\n\n## 5.62.32\n\n### Patch Changes\n\n- fix(streamedQuery): maintain error state on reset refetch with initialData defined ([#10287](https://github.com/TanStack/query/pull/10287))\n\n- Updated dependencies [[`248975e`](https://github.com/TanStack/query/commit/248975e896f585f6eaa505c796e73fcf7bfd1eec)]:\n  - @tanstack/angular-query-experimental@5.90.28\n  - @tanstack/query-persist-client-core@5.92.4\n\n## 5.62.31\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/angular-query-experimental@5.90.27\n  - @tanstack/query-persist-client-core@5.92.3\n\n## 5.62.30\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/angular-query-experimental@5.90.26\n  - @tanstack/query-persist-client-core@5.92.2\n\n## 5.62.29\n\n### Patch Changes\n\n- Updated dependencies [[`e505568`](https://github.com/TanStack/query/commit/e505568f4d51c8281d38e9687091094b7d32a405)]:\n  - @tanstack/query-persist-client-core@5.92.1\n\n## 5.62.28\n\n### Patch Changes\n\n- Updated dependencies [[`978fc52`](https://github.com/TanStack/query/commit/978fc52728a8b9eb33f0a82f4ddf42a95815bd7f)]:\n  - @tanstack/query-persist-client-core@5.92.0\n\n## 5.62.27\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/angular-query-experimental@5.90.24\n  - @tanstack/query-persist-client-core@5.91.19\n\n## 5.62.26\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/angular-query-experimental@5.90.23\n  - @tanstack/query-persist-client-core@5.91.18\n\n## 5.62.25\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/angular-query-experimental@5.90.22\n  - @tanstack/query-persist-client-core@5.91.17\n\n## 5.62.24\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/angular-query-experimental@5.90.21\n  - @tanstack/query-persist-client-core@5.91.16\n\n## 5.62.23\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/angular-query-experimental@5.90.20\n  - @tanstack/query-persist-client-core@5.91.15\n\n## 5.62.22\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/angular-query-experimental@5.90.19\n  - @tanstack/query-persist-client-core@5.91.14\n\n## 5.62.21\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/angular-query-experimental@5.90.18\n  - @tanstack/query-persist-client-core@5.91.13\n\n## 5.62.20\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/angular-query-experimental@5.90.17\n  - @tanstack/query-persist-client-core@5.91.12\n\n## 5.62.19\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/angular-query-experimental@5.90.16\n  - @tanstack/query-persist-client-core@5.91.11\n\n## 5.62.18\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/angular-query-experimental@5.90.15\n  - @tanstack/query-persist-client-core@5.91.10\n\n## 5.62.17\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/angular-query-experimental@5.90.12\n  - @tanstack/query-persist-client-core@5.91.9\n\n## 5.62.16\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/angular-query-experimental@5.90.11\n  - @tanstack/query-persist-client-core@5.91.8\n\n## 5.62.15\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/angular-query-experimental@5.90.10\n  - @tanstack/query-persist-client-core@5.91.7\n\n## 5.62.14\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/angular-query-experimental@5.90.9\n  - @tanstack/query-persist-client-core@5.91.6\n\n## 5.62.13\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/angular-query-experimental@5.90.8\n  - @tanstack/query-persist-client-core@5.91.5\n\n## 5.62.12\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/angular-query-experimental@5.90.5\n  - @tanstack/query-persist-client-core@5.91.4\n\n## 5.62.11\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/angular-query-experimental@5.90.4\n  - @tanstack/query-persist-client-core@5.91.3\n\n## 5.62.10\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/angular-query-experimental@5.90.3\n  - @tanstack/query-persist-client-core@5.91.2\n\n## 5.62.9\n\n### Patch Changes\n\n- Updated dependencies [[`846d53d`](https://github.com/TanStack/query/commit/846d53d98992d50606c40634efa43dea9965b787)]:\n  - @tanstack/query-persist-client-core@5.91.1\n\n## 5.62.8\n\n### Patch Changes\n\n- Updated dependencies [[`5cd86c6`](https://github.com/TanStack/query/commit/5cd86c6ef1720b87b13e1ab70ee823616f1f029a)]:\n  - @tanstack/query-persist-client-core@5.91.0\n"
  },
  {
    "path": "packages/angular-query-persist-client/eslint.config.js",
    "content": "// @ts-check\n\nimport pluginJsdoc from 'eslint-plugin-jsdoc'\nimport rootConfig from './root.eslint.config.js'\n\nexport default [\n  ...rootConfig,\n  pluginJsdoc.configs['flat/recommended-typescript'],\n  {\n    rules: {\n      'cspell/spellchecker': [\n        'warn',\n        {\n          cspell: {\n            ignoreRegExpList: ['\\\\ɵ.+'],\n          },\n        },\n      ],\n      'jsdoc/require-hyphen-before-param-description': 1,\n      'jsdoc/sort-tags': 1,\n      'jsdoc/require-throws': 1,\n      'jsdoc/check-tag-names': [\n        'warn',\n        {\n          // Not compatible with Api Extractor @public\n          typed: false,\n        },\n      ],\n    },\n  },\n]\n"
  },
  {
    "path": "packages/angular-query-persist-client/package.json",
    "content": "{\n  \"name\": \"@tanstack/angular-query-persist-client\",\n  \"private\": true,\n  \"version\": \"5.62.32\",\n  \"description\": \"Angular bindings to work with persisters in TanStack/angular-query\",\n  \"author\": \"Omer Gronich\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/angular-query-persist-client\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"scripts\": {\n    \"clean\": \"premove ./build ./coverage ./dist-ts\",\n    \"compile\": \"tsc --build\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:types\": \"npm-run-all --serial test:types:*\",\n    \"test:types:ts54\": \"node ../../node_modules/typescript54/lib/tsc.js --build\",\n    \"test:types:ts55\": \"node ../../node_modules/typescript55/lib/tsc.js --build\",\n    \"test:types:ts56\": \"node ../../node_modules/typescript56/lib/tsc.js --build\",\n    \"test:types:ts57\": \"node ../../node_modules/typescript57/lib/tsc.js --build\",\n    \"test:types:ts58\": \"node ../../node_modules/typescript58/lib/tsc.js --build\",\n    \"test:types:ts59\": \"node ../../node_modules/typescript59/lib/tsc.js --build\",\n    \"test:types:tscurrent\": \"tsc --build\",\n    \"test:types:ts60\": \"node ../../node_modules/typescript60/lib/tsc.js --build\",\n    \"test:lib\": \"vitest\",\n    \"test:lib:dev\": \"pnpm run test:lib --watch\",\n    \"test:build\": \"publint --strict && attw --pack\",\n    \"build\": \"pnpm build:tsup\",\n    \"build:tsup\": \"tsup --tsconfig tsconfig.prod.json\"\n  },\n  \"type\": \"module\",\n  \"types\": \"build/index.d.ts\",\n  \"module\": \"build/index.mjs\",\n  \"exports\": {\n    \".\": {\n      \"types\": \"./build/index.d.ts\",\n      \"default\": \"./build/index.mjs\"\n    },\n    \"./package.json\": {\n      \"default\": \"./package.json\"\n    }\n  },\n  \"sideEffects\": false,\n  \"files\": [\n    \"build\",\n    \"src\",\n    \"!src/__tests__\"\n  ],\n  \"dependencies\": {\n    \"@tanstack/query-persist-client-core\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"@angular/animations\": \"^20.0.0\",\n    \"@angular/common\": \"^20.0.0\",\n    \"@angular/compiler\": \"^20.0.0\",\n    \"@angular/core\": \"^20.0.0\",\n    \"@angular/platform-browser\": \"^20.0.0\",\n    \"@tanstack/angular-query-experimental\": \"workspace:*\",\n    \"@tanstack/query-test-utils\": \"workspace:*\",\n    \"@testing-library/angular\": \"^18.0.0\",\n    \"@testing-library/dom\": \"^10.4.0\",\n    \"eslint-plugin-jsdoc\": \"^50.5.0\",\n    \"npm-run-all2\": \"^5.0.0\"\n  },\n  \"peerDependencies\": {\n    \"@angular/common\": \">=16.0.0\",\n    \"@angular/core\": \">=16.0.0\",\n    \"@tanstack/angular-query-experimental\": \"workspace:^\"\n  }\n}\n"
  },
  {
    "path": "packages/angular-query-persist-client/src/__tests__/with-persist-query-client.test.ts",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport {\n  QueryClient,\n  injectQuery,\n  provideTanStackQuery,\n} from '@tanstack/angular-query-experimental'\nimport { persistQueryClientSave } from '@tanstack/query-persist-client-core'\nimport {\n  Component,\n  effect,\n  provideZonelessChangeDetection,\n} from '@angular/core'\nimport { render } from '@testing-library/angular'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { withPersistQueryClient } from '../with-persist-query-client'\nimport type {\n  PersistedClient,\n  Persister,\n} from '@tanstack/query-persist-client-core'\n\nbeforeEach(() => {\n  vi.useFakeTimers()\n})\n\nafterEach(() => {\n  vi.useRealTimers()\n})\n\nconst createMockPersister = (): Persister => {\n  let storedState: PersistedClient | undefined\n\n  return {\n    persistClient(persistClient: PersistedClient) {\n      storedState = persistClient\n    },\n    async restoreClient() {\n      return sleep(10).then(() => storedState)\n    },\n    removeClient() {\n      storedState = undefined\n    },\n  }\n}\n\nconst createMockErrorPersister = (\n  removeClient: Persister['removeClient'],\n): [Error, Persister] => {\n  const error = new Error('restore failed')\n  return [\n    error,\n    {\n      async persistClient() {\n        // noop\n      },\n      async restoreClient() {\n        await sleep(10)\n        throw error\n      },\n      removeClient,\n    },\n  ]\n}\n\ndescribe('withPersistQueryClient', () => {\n  test('restores cache from persister', async () => {\n    const key = queryKey()\n    const states: Array<{\n      status: string\n      fetchStatus: string\n      data: string | undefined\n    }> = []\n\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createMockPersister()\n\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    @Component({\n      template: `\n        <div>\n          <h1>{{ state.data() }}</h1>\n          <h2>fetchStatus: {{ state.fetchStatus() }}</h2>\n        </div>\n      `,\n    })\n    class Page {\n      state = injectQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'fetched'),\n      }))\n      _ = effect(() => {\n        states.push({\n          status: this.state.status(),\n          fetchStatus: this.state.fetchStatus(),\n          data: this.state.data(),\n        })\n      })\n    }\n\n    const rendered = await render(Page, {\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(\n          queryClient,\n          withPersistQueryClient({ persistOptions: { persister } }),\n        ),\n      ],\n    })\n\n    expect(rendered.getByText('fetchStatus: idle')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    rendered.fixture.detectChanges()\n    expect(rendered.getByText('hydrated')).toBeInTheDocument()\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.fixture.detectChanges()\n    expect(rendered.getByText('fetched')).toBeInTheDocument()\n\n    expect(states).toHaveLength(3)\n\n    expect(states[0]).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'idle',\n      data: undefined,\n    })\n\n    expect(states[1]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: 'hydrated',\n    })\n\n    expect(states[2]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: 'fetched',\n    })\n  })\n\n  test.todo(\n    '(Once injectQueries is functional) verify that injectQueries transitions to an idle state',\n  )\n\n  test('should show initialData while restoring', async () => {\n    const key = queryKey()\n    const states: Array<{\n      status: string\n      fetchStatus: string\n      data: string | undefined\n    }> = []\n\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createMockPersister()\n\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    @Component({\n      template: `\n        <div>\n          <h1>{{ state.data() }}</h1>\n          <h2>fetchStatus: {{ state.fetchStatus() }}</h2>\n        </div>\n      `,\n    })\n    class Page {\n      state = injectQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'fetched'),\n        initialData: 'initial',\n        // make sure that initial data is older than the hydration data\n        // otherwise initialData would be newer and takes precedence\n        initialDataUpdatedAt: 1,\n      }))\n      _ = effect(() => {\n        states.push({\n          status: this.state.status(),\n          fetchStatus: this.state.fetchStatus(),\n          data: this.state.data(),\n        })\n      })\n    }\n\n    const rendered = await render(Page, {\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(\n          queryClient,\n          withPersistQueryClient({ persistOptions: { persister } }),\n        ),\n      ],\n    })\n\n    expect(rendered.getByText('initial')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    rendered.fixture.detectChanges()\n    expect(rendered.getByText('hydrated')).toBeInTheDocument()\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.fixture.detectChanges()\n    expect(rendered.getByText('fetched')).toBeInTheDocument()\n\n    expect(states).toHaveLength(3)\n\n    expect(states[0]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: 'initial',\n    })\n\n    expect(states[1]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: 'hydrated',\n    })\n\n    expect(states[2]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: 'fetched',\n    })\n  })\n\n  test('should not refetch after restoring when data is fresh', async () => {\n    const key = queryKey()\n    const states: Array<{\n      status: string\n      fetchStatus: string\n      data: string | undefined\n    }> = []\n\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createMockPersister()\n\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    let fetched = false\n\n    @Component({\n      template: `\n        <div>\n          <h1>data: {{ state.data() ?? 'null' }}</h1>\n          <h2>fetchStatus: {{ state.fetchStatus() }}</h2>\n        </div>\n      `,\n    })\n    class Page {\n      state = injectQuery(() => ({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          fetched = true\n          return 'fetched'\n        },\n        staleTime: Infinity,\n      }))\n      _ = effect(() => {\n        states.push({\n          status: this.state.status(),\n          fetchStatus: this.state.fetchStatus(),\n          data: this.state.data(),\n        })\n      })\n    }\n\n    const rendered = await render(Page, {\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(\n          queryClient,\n          withPersistQueryClient({ persistOptions: { persister } }),\n        ),\n      ],\n    })\n\n    expect(rendered.getByText('data: null')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    rendered.fixture.detectChanges()\n    expect(rendered.getByText('data: hydrated')).toBeInTheDocument()\n\n    expect(states).toHaveLength(2)\n\n    expect(fetched).toBe(false)\n\n    expect(states[0]).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'idle',\n      data: undefined,\n    })\n\n    expect(states[1]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: 'hydrated',\n    })\n  })\n\n  test('should call onSuccess after successful restoring', async () => {\n    const key = queryKey()\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createMockPersister()\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    @Component({\n      template: `\n        <div>\n          <h1>{{ state.data() }}</h1>\n          <h2>fetchStatus: {{ state.fetchStatus() }}</h2>\n        </div>\n      `,\n    })\n    class Page {\n      state = injectQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'fetched'),\n      }))\n    }\n\n    const onSuccess = vi.fn()\n\n    const rendered = await render(Page, {\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(\n          queryClient,\n          withPersistQueryClient({\n            persistOptions: { persister },\n            onSuccess,\n          }),\n        ),\n      ],\n    })\n\n    expect(onSuccess).toHaveBeenCalledTimes(0)\n    await vi.advanceTimersByTimeAsync(10)\n    rendered.fixture.detectChanges()\n    expect(rendered.getByText('hydrated')).toBeInTheDocument()\n    expect(onSuccess).toHaveBeenCalledTimes(1)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.fixture.detectChanges()\n    expect(rendered.getByText('fetched')).toBeInTheDocument()\n  })\n\n  test('should remove cache after non-successful restoring', async () => {\n    const key = queryKey()\n    const onErrorMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const queryClient = new QueryClient()\n    const removeClient = vi.fn()\n    const [error, persister] = createMockErrorPersister(removeClient)\n    const onSuccess = vi.fn()\n    const onError = vi.fn()\n\n    @Component({\n      template: `\n        <div>\n          <h1>{{ state.data() }}</h1>\n          <h2>fetchStatus: {{ state.fetchStatus() }}</h2>\n        </div>\n      `,\n    })\n    class Page {\n      state = injectQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'fetched'),\n      }))\n    }\n\n    const rendered = await render(Page, {\n      providers: [\n        provideZonelessChangeDetection(),\n        provideTanStackQuery(\n          queryClient,\n          withPersistQueryClient({\n            persistOptions: { persister },\n            onSuccess,\n            onError,\n          }),\n        ),\n      ],\n    })\n\n    await vi.advanceTimersByTimeAsync(10)\n    rendered.fixture.detectChanges()\n    expect(removeClient).toHaveBeenCalledTimes(1)\n    expect(onSuccess).toHaveBeenCalledTimes(0)\n    expect(onError).toHaveBeenCalledTimes(1)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.fixture.detectChanges()\n    expect(rendered.getByText('fetched')).toBeInTheDocument()\n\n    expect(onErrorMock).toHaveBeenCalledTimes(1)\n    expect(onErrorMock).toHaveBeenNthCalledWith(1, error)\n    onErrorMock.mockRestore()\n  })\n})\n"
  },
  {
    "path": "packages/angular-query-persist-client/src/index.ts",
    "content": "// Re-export core\nexport * from '@tanstack/query-persist-client-core'\n\nexport * from './with-persist-query-client'\n"
  },
  {
    "path": "packages/angular-query-persist-client/src/with-persist-query-client.ts",
    "content": "import {\n  QueryClient,\n  provideIsRestoring,\n  queryFeature,\n} from '@tanstack/angular-query-experimental'\nimport {\n  DestroyRef,\n  ENVIRONMENT_INITIALIZER,\n  PLATFORM_ID,\n  inject,\n  signal,\n} from '@angular/core'\nimport { isPlatformBrowser } from '@angular/common'\nimport {\n  persistQueryClientRestore,\n  persistQueryClientSubscribe,\n} from '@tanstack/query-persist-client-core'\nimport type { PersistQueryClientOptions as PersistQueryClientOptionsCore } from '@tanstack/query-persist-client-core'\nimport type { PersistQueryClientFeature } from '@tanstack/angular-query-experimental'\n\ntype PersistQueryClientOptions = {\n  persistOptions: Omit<PersistQueryClientOptionsCore, 'queryClient'>\n  onSuccess?: () => Promise<unknown> | unknown\n  onError?: () => Promise<unknown> | unknown\n}\n\n/**\n * Enables persistence.\n *\n * **Example**\n *\n * ```ts\n * const localStoragePersister = createAsyncStoragePersister({\n *  storage: window.localStorage,\n * })\n *\n * export const appConfig: ApplicationConfig = {\n *   providers: [\n *     provideTanStackQuery(\n *       new QueryClient(),\n *       withPersistQueryClient({\n *         persistOptions: {\n *           persister: localStoragePersister,\n *         },\n *         onSuccess: () => console.log('Restoration completed successfully.'),\n *       })\n *     ),\n *   ],\n * };\n * ```\n * @param persistQueryClientOptions - persistence options and optional onSuccess and onError callbacks which get called when the restoration process is complete.\n * @returns A set of providers for use with `provideTanStackQuery`.\n * @public\n */\nexport function withPersistQueryClient(\n  persistQueryClientOptions: PersistQueryClientOptions,\n): PersistQueryClientFeature {\n  const isRestoring = signal(true)\n  const providers = [\n    provideIsRestoring(isRestoring.asReadonly()),\n    {\n      // Do not use provideEnvironmentInitializer while Angular < v19 is supported\n      provide: ENVIRONMENT_INITIALIZER,\n      multi: true,\n      useValue: () => {\n        if (!isPlatformBrowser(inject(PLATFORM_ID))) return\n        const destroyRef = inject(DestroyRef)\n        const queryClient = inject(QueryClient)\n\n        const { onSuccess, onError, persistOptions } = persistQueryClientOptions\n        const options = { queryClient, ...persistOptions }\n        persistQueryClientRestore(options)\n          .then(() => {\n            onSuccess?.()\n          })\n          .catch(() => {\n            onError?.()\n          })\n          .finally(() => {\n            isRestoring.set(false)\n            const cleanup = persistQueryClientSubscribe(options)\n            destroyRef.onDestroy(cleanup)\n          })\n      },\n    },\n  ]\n  return queryFeature('PersistQueryClient', providers)\n}\n"
  },
  {
    "path": "packages/angular-query-persist-client/test-setup.ts",
    "content": "import '@testing-library/jest-dom/vitest'\nimport { getTestBed } from '@angular/core/testing'\nimport {\n  BrowserTestingModule,\n  platformBrowserTesting,\n} from '@angular/platform-browser/testing'\n\ngetTestBed().initTestEnvironment(BrowserTestingModule, platformBrowserTesting())\n"
  },
  {
    "path": "packages/angular-query-persist-client/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\",\n    \"noFallthroughCasesInSwitch\": true,\n    \"useDefineForClassFields\": false,\n    \"target\": \"ES2022\"\n  },\n  \"include\": [\"src\", \"test-setup.ts\", \"*.config.*\", \"package.json\"],\n  \"references\": [\n    { \"path\": \"../angular-query-experimental\" },\n    { \"path\": \"../query-persist-client-core\" }\n  ]\n}\n"
  },
  {
    "path": "packages/angular-query-persist-client/tsconfig.prod.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"incremental\": false,\n    \"composite\": false,\n    \"rootDir\": \"../../\"\n  }\n}\n"
  },
  {
    "path": "packages/angular-query-persist-client/tsup.config.ts",
    "content": "import { defineConfig } from 'tsup'\n\nexport default defineConfig({\n  entry: ['src/index.ts'],\n  sourcemap: true,\n  clean: true,\n  format: ['esm'],\n  experimentalDts: true,\n  outDir: 'build',\n  outExtension({ format }) {\n    return format === 'esm' ? { js: '.mjs' } : { js: '.js' }\n  },\n})\n"
  },
  {
    "path": "packages/angular-query-persist-client/vite.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nimport packageJson from './package.json'\n\nexport default defineConfig({\n  // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660\n  resolve: {\n    conditions: ['@tanstack/custom-condition'],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        conditions: ['@tanstack/custom-condition'],\n      },\n    },\n  },\n  test: {\n    name: packageJson.name,\n    dir: './src',\n    watch: false,\n    environment: 'jsdom',\n    setupFiles: ['test-setup.ts'],\n    coverage: {\n      enabled: true,\n      provider: 'istanbul',\n      include: ['src/**/*'],\n      exclude: ['src/__tests__/**'],\n    },\n    typecheck: { enabled: true },\n    globals: true,\n    restoreMocks: true,\n  },\n})\n"
  },
  {
    "path": "packages/eslint-plugin-query/.attw.json",
    "content": "{\n  \"ignoreRules\": [\"false-export-default\"]\n}\n"
  },
  {
    "path": "packages/eslint-plugin-query/CHANGELOG.md",
    "content": "# @tanstack/eslint-plugin-query\n\n## 5.91.5\n\n### Patch Changes\n\n- Fix `exhaustive-deps` to detect dependencies used inside nested `queryFn` callbacks/control flow, and avoid false positives when those dependencies are already present in complex `queryKey` expressions. ([#10258](https://github.com/TanStack/query/pull/10258))\n\n## 5.91.4\n\n### Patch Changes\n\n- fix(eslint-plugin-query): declare typescript as optional peer dependency ([#10007](https://github.com/TanStack/query/pull/10007))\n\n## 5.91.3\n\n### Patch Changes\n\n- exhaustive-deps rule fixed for vue files ([#10011](https://github.com/TanStack/query/pull/10011))\n\n## 5.91.2\n\n### Patch Changes\n\n- fix: allow useQueries with combine property in no-unstable-deps rule ([#9720](https://github.com/TanStack/query/pull/9720))\n\n## 5.91.1\n\n### Patch Changes\n\n- avoid typescript import in no-void-query-fn rule ([#9759](https://github.com/TanStack/query/pull/9759))\n\n## 5.91.0\n\n### Minor Changes\n\n- feat: improve type of exported plugin ([#9700](https://github.com/TanStack/query/pull/9700))\n\n## 5.90.2\n\n### Patch Changes\n\n- fix: exhaustive-deps with variables and type assertions ([#9687](https://github.com/TanStack/query/pull/9687))\n"
  },
  {
    "path": "packages/eslint-plugin-query/eslint.config.js",
    "content": "// @ts-check\n\nimport vitest from '@vitest/eslint-plugin'\nimport rootConfig from './root.eslint.config.js'\n\nexport default [\n  ...rootConfig,\n  {\n    plugins: { vitest },\n    rules: {\n      ...vitest.configs.recommended.rules,\n      'vitest/expect-expect': [\n        'warn',\n        {\n          assertFunctionNames: ['expect', 'expectArrayEqualIgnoreOrder'],\n        },\n      ],\n    },\n  },\n]\n"
  },
  {
    "path": "packages/eslint-plugin-query/package.json",
    "content": "{\n  \"name\": \"@tanstack/eslint-plugin-query\",\n  \"version\": \"5.91.5\",\n  \"description\": \"ESLint plugin for TanStack Query\",\n  \"author\": \"Eliya Cohen\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/eslint-plugin-query\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"scripts\": {\n    \"clean\": \"premove ./dist ./coverage ./dist-ts\",\n    \"compile\": \"tsc --build\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:types\": \"npm-run-all --serial test:types:*\",\n    \"test:types:ts54\": \"node ../../node_modules/typescript54/lib/tsc.js --build\",\n    \"test:types:ts55\": \"node ../../node_modules/typescript55/lib/tsc.js --build\",\n    \"test:types:ts56\": \"node ../../node_modules/typescript56/lib/tsc.js --build\",\n    \"test:types:ts57\": \"node ../../node_modules/typescript57/lib/tsc.js --build\",\n    \"test:types:ts58\": \"node ../../node_modules/typescript58/lib/tsc.js --build\",\n    \"test:types:ts59\": \"node ../../node_modules/typescript59/lib/tsc.js --build\",\n    \"test:types:tscurrent\": \"tsc --build\",\n    \"test:types:ts60\": \"node ../../node_modules/typescript60/lib/tsc.js --build\",\n    \"test:lib\": \"vitest\",\n    \"test:lib:dev\": \"pnpm run test:lib --watch\",\n    \"test:build\": \"publint --strict && attw --pack\",\n    \"build\": \"tsup --tsconfig tsconfig.prod.json\"\n  },\n  \"type\": \"module\",\n  \"types\": \"build/legacy/index.d.ts\",\n  \"main\": \"build/legacy/index.cjs\",\n  \"module\": \"build/legacy/index.js\",\n  \"react-native\": \"src/index.ts\",\n  \"exports\": {\n    \".\": {\n      \"@tanstack/custom-condition\": \"./src/index.ts\",\n      \"import\": {\n        \"types\": \"./build/modern/index.d.ts\",\n        \"default\": \"./build/modern/index.js\"\n      },\n      \"require\": {\n        \"types\": \"./build/modern/index.d.cts\",\n        \"default\": \"./build/modern/index.cjs\"\n      }\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"sideEffects\": false,\n  \"files\": [\n    \"build\",\n    \"src\",\n    \"!src/__tests__\"\n  ],\n  \"dependencies\": {\n    \"@typescript-eslint/utils\": \"^8.48.0\"\n  },\n  \"devDependencies\": {\n    \"@typescript-eslint/parser\": \"^8.48.0\",\n    \"@typescript-eslint/rule-tester\": \"^8.48.0\",\n    \"combinate\": \"^1.1.11\",\n    \"eslint\": \"^9.36.0\",\n    \"npm-run-all2\": \"^5.0.0\"\n  },\n  \"peerDependencies\": {\n    \"eslint\": \"^8.57.0 || ^9.0.0\",\n    \"typescript\": \"^5.4.0\"\n  },\n  \"peerDependenciesMeta\": {\n    \"typescript\": {\n      \"optional\": true\n    }\n  }\n}\n"
  },
  {
    "path": "packages/eslint-plugin-query/root.tsup.config.js",
    "content": "// @ts-check\n\n/**\n * @param {Object} opts - Options for building configurations.\n * @param {string[]} opts.entry - The entry array.\n * @returns {import('tsup').Options}\n */\nexport function modernConfig(opts) {\n  return {\n    entry: opts.entry,\n    format: ['cjs', 'esm'],\n    target: ['chrome91', 'firefox90', 'edge91', 'safari15', 'ios15', 'opera77'],\n    outDir: 'build/modern',\n    experimentalDts: true,\n    sourcemap: true,\n    clean: true,\n    external: ['typescript'],\n    footer: ({ format }) => {\n      if (format === 'cjs') {\n        // workaround for CJS default export\n        // @see https://github.com/evanw/esbuild/issues/1182#issuecomment-1011414271\n        return { js: `module.exports = module.exports.default` }\n      }\n\n      return\n    },\n  }\n}\n\n/**\n * @param {Object} opts - Options for building configurations.\n * @param {string[]} opts.entry - The entry array.\n * @returns {import('tsup').Options}\n */\nexport function legacyConfig(opts) {\n  return {\n    entry: opts.entry,\n    format: ['cjs', 'esm'],\n    target: ['es2020', 'node16'],\n    outDir: 'build/legacy',\n    experimentalDts: true,\n    sourcemap: true,\n    clean: true,\n    external: ['typescript'],\n  }\n}\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/__tests__/exhaustive-deps.test.ts",
    "content": "import { RuleTester } from '@typescript-eslint/rule-tester'\nimport { rule } from '../rules/exhaustive-deps/exhaustive-deps.rule'\nimport { normalizeIndent } from './test-utils'\n\nconst ruleTester = new RuleTester()\n\nruleTester.run('exhaustive-deps', rule, {\n  valid: [\n    {\n      name: 'should pass when deps are passed in array (react)',\n      code: 'useQuery({ queryKey: [\"todos\"], queryFn: fetchTodos });',\n    },\n    {\n      name: 'should pass when deps are passed in array (solid)',\n      code: 'createQuery({ queryKey: [\"todos\"], queryFn: fetchTodos });',\n    },\n    {\n      name: 'should pass when deps are passed in array',\n      code: 'useQuery({ queryKey: [\"entity\", id], queryFn: () => api.getEntity(id) });',\n    },\n    {\n      name: 'should pass when deps are passed in template literal',\n      code: 'useQuery({ queryKey: [`entity/${id}`], queryFn: () => api.getEntity(id) });',\n    },\n    {\n      name: 'should not pass fetch',\n      code: 'useQuery({ queryKey: [\"entity\", id], queryFn: () => fetch(id) });',\n    },\n    {\n      name: 'should not pass axios.get',\n      code: 'useQuery({ queryKey: [\"entity\", id], queryFn: () => axios.get(id) });',\n    },\n    {\n      name: 'should not pass api.entity.get',\n      code: 'useQuery({ queryKey: [\"entity\", id], queryFn: () => api.entity.get(id) });',\n    },\n    {\n      name: 'should pass props.src',\n      code: `\n        function MyComponent(props) {\n            useQuery({ queryKey: [\"entity\", props.src], queryFn: () => api.entity.get(props.src) });\n        }\n      `,\n    },\n    {\n      name: 'identify !!props.id (unary expression)',\n      code: `\n        function MyComponent(props) {\n            useQuery({ queryKey: [\"entity\", !!props.id], queryFn: () => api.entity.get(props.id) });\n        }\n      `,\n    },\n    {\n      name: 'identify props?.id (chain expression)',\n      code: `\n        function MyComponent(props) {\n            useQuery({ queryKey: [\"entity\", props?.id], queryFn: () => api.entity.get(props?.id) });\n        }\n      `,\n    },\n    {\n      name: 'identify props!.id (ts non null expression)',\n      code: `\n        function MyComponent(props) {\n            useQuery({ queryKey: [\"entity\", props!.id], queryFn: () => api.entity.get(props!.id) });\n        }\n      `,\n    },\n    {\n      name: 'should ignore keys from callback',\n      code: `\n        function MyComponent(props) {\n            useQuery({\n              queryKey: [\"foo\", dep1],\n              queryFn: ({ queryKey: [, dep] }) => fetch(dep),\n            });\n        }\n      `,\n    },\n    {\n      name: 'should ignore type identifiers',\n      code: `\n        type Result = {};\n        function MyComponent(props) {\n            useQuery({\n              queryKey: [\"foo\", dep],\n              queryFn: () => api.get<Result>(dep),\n            });\n        }\n      `,\n    },\n    {\n      name: 'should add \"...args\" to deps',\n      code: `\n        function foo(...args) {}\n        function useData(arg, ...args) {\n          return useQuery({\n            queryKey: ['foo', arg, ...args],\n            queryFn: async () => foo([arg, ...args])\n          });\n        }\n      `,\n    },\n    {\n      name: 'should not add class to deps',\n      code: `\n        class Foo {}\n        useQuery({ queryKey: ['foo'], queryFn: async () => new Foo() });\n      `,\n    },\n    {\n      name: 'should not add `undefined` to deps',\n      code: `\n        useQuery({\n          queryKey: [],\n          queryFn: async () => {\n            if (undefined) {\n              return null;\n            }\n            return 1\n          },\n        });\n      `,\n    },\n    {\n      name: 'should not fail when queryKey is a queryKeyFactory while having a dep as first arg',\n      code: normalizeIndent`\n        const fooQueryKeyFactory = {\n          foo: () => ['foo'] as const,\n          num: (num: number) => [...fooQueryKeyFactory.foo(), num] as const,\n        }\n\n        const useFoo = (num: number) =>\n          useQuery({\n            queryKey: fooQueryKeyFactory.foo(num),\n            queryFn: () => Promise.resolve(num),\n          })\n      `,\n    },\n    {\n      name: 'should not fail when queryKey is a queryKeyFactory while having a dep in object',\n      code: normalizeIndent`\n        const fooQueryKeyFactory = {\n          foo: () => ['foo'] as const,\n          num: (num: number) => [...fooQueryKeyFactory.foo(), num] as const,\n        }\n\n        const useFoo = (num: number) =>\n          useQuery({\n            queryKey: fooQueryKeyFactory.foo({ x: num }),\n            queryFn: () => Promise.resolve(num),\n          })\n      `,\n    },\n    {\n      name: 'should not fail when queryKey is a queryKeyFactory while having a dep in object 2',\n      code: normalizeIndent`\n        const fooQueryKeyFactory = {\n          foo: () => ['foo'] as const,\n          num: (num: number) => [...fooQueryKeyFactory.foo(), num] as const,\n        }\n\n        const useFoo = (num: number) =>\n          useQuery({\n            queryKey: fooQueryKeyFactory.foo({ num }),\n            queryFn: () => Promise.resolve(num),\n          })\n      `,\n    },\n    {\n      name: 'should not fail when queryKey is a queryKeyFactory while having a dep in array',\n      code: normalizeIndent`\n        const fooQueryKeyFactory = {\n          foo: () => ['foo'] as const,\n          num: (num: number) => [...fooQueryKeyFactory.foo(), num] as const,\n        }\n\n        const useFoo = (num: number) =>\n          useQuery({\n              queryKey: fooQueryKeyFactory.foo([num]),\n              queryFn: () => Promise.resolve(num),\n          })\n      `,\n    },\n    {\n      name: 'should not fail when queryKey is a queryKeyFactory while having a dep in second arg',\n      code: normalizeIndent`\n        const fooQueryKeyFactory = {\n          foo: () => ['foo'] as const,\n          num: (num: number) => [...fooQueryKeyFactory.foo(), num] as const,\n        }\n\n        const useFoo = (num: number) =>\n          useQuery({\n              queryKey: fooQueryKeyFactory.foo(1, num),\n              queryFn: () => Promise.resolve(num),\n          })\n      `,\n    },\n    {\n      name: 'should not fail when queryKey is a queryKeyFactory while having a dep is object prop',\n      code: normalizeIndent`\n        const fooQueryKeyFactory = {\n          foo: () => ['foo'] as const,\n          num: (num: number) => [...fooQueryKeyFactory.foo(), num] as const,\n        }\n\n        const useFoo = (obj: { num: number }) =>\n          useQuery({\n              queryKey: fooQueryKeyFactory.foo(obj.num),\n              queryFn: () => Promise.resolve(obj.num),\n          })\n      `,\n    },\n    {\n      name: 'should pass with queryKeyFactory result assigned to a variable',\n      code: `\n        function fooQueryKeyFactory(dep: string) {\n            return [\"foo\", dep];\n        }\n\n        const useFoo = (dep: string) => {\n          const queryKey = fooQueryKeyFactory(dep);\n          return useQuery({\n              queryKey,\n              queryFn: () => Promise.resolve(dep),\n            })\n          }\n      `,\n    },\n    {\n      name: 'should pass with queryKeyFactory result assigned to a variable 2',\n      code: `\n        function fooQueryKeyFactory(dep: string) {\n            const x = [\"foo\", dep] as const;\n            return x as const;\n        }\n\n        const useFoo = (dep: string) => {\n          const queryKey = fooQueryKeyFactory(dep);\n          return useQuery({\n              queryKey,\n              queryFn: () => Promise.resolve(dep),\n            })\n          }\n      `,\n    },\n    {\n      name: 'should pass when queryKey is a chained queryKeyFactory while having deps in nested calls',\n      code: normalizeIndent`\n        const fooQueryKeyFactory = {\n          foo: (num: number) => ({\n            detail: (flag: boolean) => ['foo', num, flag] as const,\n          }),\n        }\n\n        const useFoo = (num: number, flag: boolean) =>\n          useQuery({\n            queryKey: fooQueryKeyFactory.foo(num).detail(flag),\n            queryFn: () => Promise.resolve({ num, flag }),\n          })\n      `,\n    },\n    {\n      name: 'should not treat new Error as missing dependency',\n      code: normalizeIndent`\n        useQuery({\n          queryKey: ['foo'],\n          queryFn: () => Promise.reject(new Error('1')),\n        })\n      `,\n    },\n    {\n      name: 'should see id when there is a const assertion',\n      code: normalizeIndent`\n        const useX = (id: number) => {\n          return useQuery({\n            queryKey: ['foo', id] as const,\n            queryFn: async () => id,\n          })\n        }\n      `,\n    },\n    {\n      name: 'should see id when there is a const assertion of a variable dereference',\n      code: normalizeIndent`\n        const useX = (id: number) => {\n          const queryKey = ['foo', id]\n          return useQuery({\n            queryKey: queryKey as const,\n            queryFn: async () => id,\n          })\n        }\n      `,\n    },\n    {\n      name: 'should see id when there is a const assertion assigned to a variable',\n      code: normalizeIndent`\n        const useX = (id: number) => {\n          const queryKey = ['foo', id] as const\n          return useQuery({\n            queryKey,\n            queryFn: async () => id,\n          })\n        }\n      `,\n    },\n    {\n      name: 'should not fail if queryKey is having the whole object while queryFn uses some props of it',\n      code: normalizeIndent`\n        const state = { foo: 'foo', bar: 'bar' }\n\n        useQuery({\n            queryKey: ['state', state],\n            queryFn: () => Promise.resolve({ foo: state.foo, bar: state.bar })\n        })\n      `,\n    },\n    {\n      name: 'should not fail if queryKey does not include an internal dependency',\n      code: normalizeIndent`\n        useQuery({\n          queryKey: [\"api\"],\n          queryFn: async () => {\n            const response = Promise.resolve([]);\n            const data = await response.json();\n            return data[0].name;\n          },\n        });\n      `,\n    },\n    {\n      name: 'should ignore constants defined out of scope (react component, function declaration)',\n      code: `\n        const CONST_VAL = 1\n        function MyComponent() {\n          useQuery({\n            queryKey: [\"foo\"],\n            queryFn: () => CONST_VAL\n          });\n        }\n      `,\n    },\n    {\n      name: 'should ignore constants defined out of scope (react component, function expression)',\n      code: `\n        const CONST_VAL = 1\n        const MyComponent = () => {\n          useQuery({\n            queryKey: [\"foo\"],\n            queryFn: () => CONST_VAL\n          });\n        }\n      `,\n    },\n    {\n      name: 'should ignore constants defined out of scope (react component, anonymous function)',\n      code: `\n        const CONST_VAL = 1\n        const MyComponent = function () {\n          useQuery({\n            queryKey: [\"foo\"],\n            queryFn: () => CONST_VAL\n          });\n        }\n      `,\n    },\n    {\n      name: 'should ignore constants defined out of scope (non react component/hook function)',\n      code: `\n          const CONST_VAL = 1\n          function fn() {\n            return {\n              queryKey: [\"foo\"],\n              queryFn: () => CONST_VAL\n            }\n          }\n        `,\n    },\n    {\n      name: 'should ignore constants defined out of scope (react hook, function declaration)',\n      code: `\n        const CONST_VAL = 1\n        function useHook() {\n          useQuery({\n            queryKey: [\"foo\"],\n            queryFn: () => CONST_VAL\n          });\n        }\n      `,\n    },\n    {\n      name: 'should ignore constants defined out of scope (react hook, function expression)',\n      code: `\n        const CONST_VAL = 1\n        const useHook = () => {\n          useQuery({\n            queryKey: [\"foo\"],\n            queryFn: () => CONST_VAL\n          });\n        }\n      `,\n    },\n    {\n      name: 'should ignore constants defined out of scope (react hook, anonymous function)',\n      code: `\n        const CONST_VAL = 1\n        const useHook = function () {\n          useQuery({\n            queryKey: [\"foo\"],\n            queryFn: () => CONST_VAL\n          });\n        }\n      `,\n    },\n    {\n      name: 'query key with nullish coalescing operator',\n      code: `\n        const factory = (id: number) => ['foo', id];\n        function Component({ id }) {\n          useQuery({\n            queryKey: factory(id ?? -1),\n            queryFn: () => Promise.resolve({ id })\n          });\n        }\n        `,\n    },\n    {\n      name: 'should pass when queryKey uses a direct conditional expression',\n      code: normalizeIndent`\n        function Component(cond, a, b) {\n          useQuery({\n            queryKey: ['thing', cond ? a : b],\n            queryFn: () => (cond ? a : b),\n          })\n        }\n      `,\n    },\n    {\n      name: 'should pass when queryKey uses a direct binary expression',\n      code: normalizeIndent`\n        function Component(a, b) {\n          useQuery({\n            queryKey: ['thing', a + b],\n            queryFn: () => a + b,\n          })\n        }\n      `,\n    },\n    {\n      name: 'should pass when queryKey uses a nested type assertion',\n      code: normalizeIndent`\n        function Component(dep) {\n          useQuery({\n            queryKey: ['thing', dep as string],\n            queryFn: () => dep,\n          })\n        }\n      `,\n    },\n    {\n      name: 'should pass when queryKey derives values inside a callback',\n      code: normalizeIndent`\n        function Component(ids, prefix) {\n          useQuery({\n            queryKey: ['thing', ids.map((id) => prefix + '-' + id)],\n            queryFn: () => ({ ids, prefix }),\n          })\n        }\n      `,\n    },\n    {\n      name: 'instanceof value should not be in query key',\n      code: `\n        class SomeClass {}\n\n        function Component({ value }) {\n            useQuery({\n                queryKey: ['foo'],\n                queryFn: () => {\n                    return value instanceof SomeClass;\n                }\n            });\n        }\n        `,\n    },\n    {\n      name: 'queryFn as a ternary expression with dep and a skipToken',\n      code: normalizeIndent`\n        import { useQuery, skipToken } from \"@tanstack/react-query\";\n        const fetch = true\n\n        function Component({ id }) {\n          useQuery({\n              queryKey: [id],\n              queryFn: fetch ? () => Promise.resolve(id) : skipToken\n          })\n        }\n      `,\n    },\n    {\n      name: 'should not fail when queryFn uses nullish coalescing operator',\n      code: normalizeIndent`\n        useQuery({\n          queryKey: [\"foo\", options],\n          queryFn: () => options?.params ?? options\n        });\n      `,\n    },\n    {\n      name: 'should not fail when queryKey uses arrow function to produce a key',\n      code: normalizeIndent`\n      const obj = reactive<{ boo?: string }>({});\n\n      const query = useQuery({\n        queryKey: ['foo', () => obj.boo],\n        queryFn: () => fetch(\\`/mock/getSomething/\\${obj.boo}\\`),\n        enable: () => !!obj.boo,\n      });\n      `,\n    },\n    {\n      name: 'should not fail when queryKey uses arrow function to produce a key as the body return',\n      code: normalizeIndent`\n      const obj = reactive<{ boo?: string }>({});\n\n      const query = useQuery({\n        queryKey: ['foo', () => { return obj.boo }],\n        queryFn: () => fetch(\\`/mock/getSomething/\\${obj.boo}\\`),\n        enable: () => !!obj.boo,\n      });\n      `,\n    },\n    {\n      name: 'should not fail when queryKey uses function expression to produce a key as the body return',\n      code: normalizeIndent`\n      const obj = reactive<{ boo?: string }>({});\n\n      const query = useQuery({\n        queryKey: ['foo', function() {\n          return obj.boo\n        }],\n        queryFn: () => fetch(\\`/mock/getSomething/\\${obj.boo}\\`),\n        enable: () => !!obj.boo,\n      });\n      `,\n    },\n    {\n      name: 'should not fail when queryFn inside queryOptions contains a reference to an external variable',\n      code: normalizeIndent`\n      const EXTERNAL = 1;\n\n      export const queries = {\n        foo: queryOptions({\n          queryKey: ['foo'],\n          queryFn: () => Promise.resolve(EXTERNAL),\n        }),\n      };\n      `,\n    },\n    {\n      name: 'should pass with optional chaining as key',\n      code: `\n        function useTest(data?: any) {\n          return useQuery({\n            queryKey: ['query-name', data?.address],\n            queryFn: async () => sendQuery(data.address),\n            enabled: !!data?.address,\n          })\n        }\n      `,\n    },\n    {\n      name: 'should pass with optional chaining as key and non-null assertion in queryFn',\n      code: `\n        function useTest(data?: any) {\n          return useQuery({\n            queryKey: ['query-name', data?.address],\n            queryFn: async () => sendQuery(data!.address),\n            enabled: !!data?.address,\n          })\n        }\n      `,\n    },\n    {\n      name: 'should pass with optional chaining as key and non-null assertion at the end of the variable in queryFn',\n      code: `\n        function useTest(data?: any) {\n          return useQuery({\n            queryKey: ['query-name', data?.address],\n            queryFn: async () => sendQuery(data!.address!),\n            enabled: !!data?.address,\n          })\n        }\n      `,\n    },\n    {\n      name: 'should pass in Vue file when deps are correctly included (script setup)',\n      filename: 'Component.vue',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/vue-query'\n\n        const id = 1\n        useQuery({\n          queryKey: ['entity', id],\n          queryFn: () => fetchEntity(id),\n        })\n      `,\n    },\n    {\n      name: 'should not require imports in queryKey for Vue files',\n      filename: 'Component.vue',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/vue-query'\n        import { fetchTodos } from './api'\n\n        useQuery({\n          queryKey: ['todos'],\n          queryFn: () => fetchTodos(),\n        })\n      `,\n    },\n    {\n      name: 'should not require global fetch in queryKey for Vue files',\n      filename: 'Component.vue',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/vue-query'\n\n        const id = 1\n        useQuery({\n          queryKey: ['entity', id],\n          queryFn: () => fetch('/api/entity/' + id),\n        })\n      `,\n    },\n    {\n      name: 'should ignore callback locals in Vue file queryFn',\n      filename: 'Component.vue',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/vue-query'\n\n        const ids = [1, 2, 3]\n        useQuery({\n          queryKey: ['entities', ids],\n          queryFn: () => ids.map((id) => fetchEntity(id)),\n        })\n      `,\n    },\n    {\n      name: 'should pass when dep used in then/catch is listed in queryKey',\n      code: normalizeIndent`\n        function Component() {\n          const id = 1\n          useQuery({\n            queryKey: ['foo', id],\n            queryFn: () =>\n              Promise.resolve(null)\n                .then(() => id)\n                .catch(() => id),\n          })\n        }\n      `,\n    },\n    {\n      name: 'should pass when dep used in try/catch/finally is listed in queryKey',\n      code: normalizeIndent`\n        function Component() {\n          const id = 1\n          useQuery({\n            queryKey: ['foo', id],\n            queryFn: () => {\n              try {\n                return fetch(id)\n              } catch (error) {\n                console.error(error)\n                return id\n              } finally {\n                console.log('done')\n              }\n            },\n          })\n        }\n      `,\n    },\n  ],\n  invalid: [\n    {\n      name: 'should fail when api from hook is used for calling a function',\n      code: normalizeIndent`\n        import useApi from './useApi'\n\n        const useFoo = () => {\n          const api = useApi();\n          return useQuery({\n            queryKey: ['foo'],\n            queryFn: () => api.fetchFoo(),\n          })\n        }\n      `,\n      errors: [\n        {\n          messageId: 'missingDeps',\n          data: { deps: 'api' },\n          suggestions: [\n            {\n              messageId: 'fixTo',\n              data: { result: \"['foo', api]\" },\n              output: normalizeIndent`\n                import useApi from './useApi'\n\n                const useFoo = () => {\n                  const api = useApi();\n                  return useQuery({\n                    queryKey: ['foo', api],\n                    queryFn: () => api.fetchFoo(),\n                  })\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      name: 'should fail when deps are missing in query factory',\n      code: normalizeIndent`\n        const todoQueries = {\n          list: () => ({ queryKey: ['entity'], queryFn: fetchEntities }),\n          detail: (id) => ({ queryKey: ['entity'], queryFn: () => fetchEntity(id) })\n        }\n        `,\n      errors: [\n        {\n          messageId: 'missingDeps',\n          data: { deps: 'id' },\n          suggestions: [\n            {\n              messageId: 'fixTo',\n              data: { result: \"['entity', id]\" },\n              output: normalizeIndent`\n                const todoQueries = {\n                  list: () => ({ queryKey: ['entity'], queryFn: fetchEntities }),\n                  detail: (id) => ({ queryKey: ['entity', id], queryFn: () => fetchEntity(id) })\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      name: 'should fail when no deps are passed (react)',\n      code: normalizeIndent`\n        function Component() {\n          const id = 1;\n          useQuery({ queryKey: [\"entity\"], queryFn: () => api.getEntity(id) });\n        }\n      `,\n      errors: [\n        {\n          messageId: 'missingDeps',\n          data: { deps: 'id' },\n          suggestions: [\n            {\n              messageId: 'fixTo',\n              data: { result: '[\"entity\", id]' },\n              output: normalizeIndent`\n                function Component() {\n                  const id = 1;\n                  useQuery({ queryKey: [\"entity\", id], queryFn: () => api.getEntity(id) });\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      name: 'should fail when no deps are passed (solid)',\n      code: normalizeIndent`\n        function Component() {\n          const id = 1;\n          createQuery({ queryKey: [\"entity\"], queryFn: () => api.getEntity(id) });\n        }\n      `,\n      errors: [\n        {\n          messageId: 'missingDeps',\n          data: { deps: 'id' },\n          suggestions: [\n            {\n              messageId: 'fixTo',\n              data: { result: '[\"entity\", id]' },\n              output: normalizeIndent`\n                function Component() {\n                  const id = 1;\n                  createQuery({ queryKey: [\"entity\", id], queryFn: () => api.getEntity(id) });\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      name: 'should fail when deps are passed incorrectly',\n      code: normalizeIndent`\n        function Component() {\n          const id = 1;\n          useQuery({ queryKey: [\"entity/\\${id}\"], queryFn: () => api.getEntity(id) });\n        }\n      `,\n      errors: [\n        {\n          messageId: 'missingDeps',\n          data: { deps: 'id' },\n          suggestions: [\n            {\n              messageId: 'fixTo',\n              data: { result: '[\"entity/${id}\", id]' },\n              output: normalizeIndent`\n                function Component() {\n                  const id = 1;\n                  useQuery({ queryKey: [\"entity/\\${id}\", id], queryFn: () => api.getEntity(id) });\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      name: 'should pass missing dep while key has a template literal',\n      code: normalizeIndent`\n        function Component() {\n          const a = 1;\n          const b = 2;\n          useQuery({ queryKey: [\\`entity/\\${a}\\`], queryFn: () => api.getEntity(a, b) });\n        }\n      `,\n      errors: [\n        {\n          messageId: 'missingDeps',\n          data: { deps: 'b' },\n          suggestions: [\n            {\n              messageId: 'fixTo',\n              data: { result: '[`entity/${a}`, b]' },\n              output: normalizeIndent`\n                function Component() {\n                  const a = 1;\n                  const b = 2;\n                  useQuery({ queryKey: [\\`entity/\\${a}\\`, b], queryFn: () => api.getEntity(a, b) });\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      name: 'should fail when dep exists inside setter and missing in queryKey',\n      code: normalizeIndent`\n        function Component() {\n          const [id] = React.useState(1);\n          useQuery({\n            queryKey: [\"entity\"],\n            queryFn: () => {\n              const { data } = axios.get(\\`.../\\${id}\\`);\n              return data;\n            }\n          });\n        }\n      `,\n      errors: [\n        {\n          messageId: 'missingDeps',\n          data: { deps: 'id' },\n          suggestions: [\n            {\n              messageId: 'fixTo',\n              data: { result: '[\"entity\", id]' },\n              output: normalizeIndent`\n                function Component() {\n                  const [id] = React.useState(1);\n                  useQuery({\n                    queryKey: [\"entity\", id],\n                    queryFn: () => {\n                      const { data } = axios.get(\\`.../\\${id}\\`);\n                      return data;\n                    }\n                  });\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      name: 'should fail when dep does not exist while having a complex queryKey',\n      code: normalizeIndent`\n        const todoQueries = {\n          key: (a, b, c, d, e) => ({\n            queryKey: [\"entity\", a, [b], { c }, 1, true],\n            queryFn: () => api.getEntity(a, b, c, d, e)\n          })\n        }\n      `,\n      errors: [\n        {\n          messageId: 'missingDeps',\n          data: { deps: 'd, e' },\n          suggestions: [\n            {\n              messageId: 'fixTo',\n              data: { result: '[\"entity\", a, [b], { c }, 1, true, d, e]' },\n              output: normalizeIndent`\n                const todoQueries = {\n                  key: (a, b, c, d, e) => ({\n                    queryKey: [\"entity\", a, [b], { c }, 1, true, d, e],\n                    queryFn: () => api.getEntity(a, b, c, d, e)\n                  })\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      name: 'should fail when dep does not exist while having a complex queryKey #2',\n      code: normalizeIndent`\n        const todoQueries = {\n          key: (dep1, dep2, dep3, dep4, dep5, dep6, dep7, dep8) => ({\n            queryKey: ['foo', {dep1, dep2: dep2, bar: dep3, baz: [dep4, dep5]}, [dep6, dep7]],\n            queryFn: () => api.getEntity(dep1, dep2, dep3, dep4, dep5, dep6, dep7, dep8),\n          }),\n        };\n      `,\n      errors: [\n        {\n          messageId: 'missingDeps',\n          data: { deps: 'dep8' },\n          suggestions: [\n            {\n              messageId: 'fixTo',\n              data: {\n                result:\n                  \"['foo', {dep1, dep2: dep2, bar: dep3, baz: [dep4, dep5]}, [dep6, dep7], dep8]\",\n              },\n              output: normalizeIndent`\n                const todoQueries = {\n                  key: (dep1, dep2, dep3, dep4, dep5, dep6, dep7, dep8) => ({\n                    queryKey: ['foo', {dep1, dep2: dep2, bar: dep3, baz: [dep4, dep5]}, [dep6, dep7], dep8],\n                    queryFn: () => api.getEntity(dep1, dep2, dep3, dep4, dep5, dep6, dep7, dep8),\n                  }),\n                };\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      name: 'should fail when two deps that depend on each other are missing',\n      code: normalizeIndent`\n        function Component({ map, key }) {\n          useQuery({ queryKey: [\"key\"], queryFn: () => api.get(map[key]) });\n        }\n      `,\n      errors: [\n        {\n          messageId: 'missingDeps',\n          data: { deps: 'map[key]' },\n          suggestions: [\n            {\n              messageId: 'fixTo',\n              data: {\n                result: '[\"key\", map[key]]',\n              },\n              output: normalizeIndent`\n                function Component({ map, key }) {\n                  useQuery({ queryKey: [\"key\", map[key]], queryFn: () => api.get(map[key]) });\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      name: 'should fail when a queryKey is a reference of an array expression with a missing dep',\n      code: normalizeIndent`\n        function Component() {\n          const x = 5;\n          const queryKey = ['foo']\n          useQuery({ queryKey, queryFn: () => x })\n        }\n      `,\n      errors: [\n        {\n          messageId: 'missingDeps',\n          data: { deps: 'x' },\n          suggestions: [\n            {\n              messageId: 'fixTo',\n              data: {\n                result: \"['foo', x]\",\n              },\n              output: normalizeIndent`\n                function Component() {\n                  const x = 5;\n                  const queryKey = ['foo', x]\n                  useQuery({ queryKey, queryFn: () => x })\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      name: 'should fail when alias of props used in queryFn is missing in queryKey',\n      code: normalizeIndent`\n        function Component(props) {\n          const entities = props.entities;\n\n          const q = useQuery({\n            queryKey: ['get-stuff'],\n            queryFn: () => {\n              return api.fetchStuff({\n                ids: entities.map((o) => o.id)\n              });\n            }\n          });\n        }\n      `,\n      errors: [\n        {\n          messageId: 'missingDeps',\n          data: { deps: 'entities' },\n          suggestions: [\n            {\n              messageId: 'fixTo',\n              data: { result: \"['get-stuff', entities]\" },\n              output: normalizeIndent`\n                function Component(props) {\n                  const entities = props.entities;\n\n                  const q = useQuery({\n                    queryKey: ['get-stuff', entities],\n                    queryFn: () => {\n                      return api.fetchStuff({\n                        ids: entities.map((o) => o.id)\n                      });\n                    }\n                  });\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      name: 'should fail when queryKey is a queryKeyFactory while having missing dep',\n      code: normalizeIndent`\n        const fooQueryKeyFactory = { foo: () => ['foo'] as const }\n\n        const useFoo = (num: number) =>\n          useQuery({\n              queryKey: fooQueryKeyFactory.foo(),\n              queryFn: () => Promise.resolve(num),\n          })\n      `,\n      errors: [\n        {\n          messageId: 'missingDeps',\n          data: { deps: 'num' },\n        },\n      ],\n    },\n    {\n      name: 'should fail when queryKey is a chained queryKeyFactory while having missing dep in earlier call',\n      code: normalizeIndent`\n        const fooQueryKeyFactory = {\n          foo: (num: number) => ({\n            detail: (flag: boolean) => ['foo', num, flag] as const,\n          }),\n        }\n\n        const useFoo = (num: number, flag: boolean) =>\n          useQuery({\n            queryKey: fooQueryKeyFactory.foo(1).detail(flag),\n            queryFn: () => Promise.resolve({ num, flag }),\n          })\n      `,\n      errors: [\n        {\n          messageId: 'missingDeps',\n          data: { deps: 'num' },\n        },\n      ],\n    },\n    {\n      name: 'should fail if queryFn is using multiple object props when only one of them is in the queryKey',\n      code: normalizeIndent`\n        function Component() {\n          const state = { foo: 'foo', bar: 'bar' }\n\n          useQuery({\n            queryKey: ['state', state.foo],\n            queryFn: () => Promise.resolve({ foo: state.foo, bar: state.bar })\n          })\n        }\n      `,\n      errors: [\n        {\n          suggestions: [\n            {\n              messageId: 'fixTo',\n              output: normalizeIndent`\n              function Component() {\n                const state = { foo: 'foo', bar: 'bar' }\n\n                useQuery({\n                  queryKey: ['state', state.foo, state.bar],\n                  queryFn: () => Promise.resolve({ foo: state.foo, bar: state.bar })\n                })\n              }\n            `,\n            },\n          ],\n          messageId: 'missingDeps',\n          data: { deps: 'state.bar' },\n        },\n      ],\n    },\n    {\n      name: 'should fail if queryFn is invalid while using FunctionExpression syntax',\n      code: normalizeIndent`\n        function Component() {\n          const id = 1;\n\n          useQuery({\n            queryKey: [],\n            queryFn() {\n              Promise.resolve(id)\n            }\n          });\n        }\n      `,\n      errors: [\n        {\n          suggestions: [\n            {\n              messageId: 'fixTo',\n              output: normalizeIndent`\n                function Component() {\n                  const id = 1;\n\n                  useQuery({\n                    queryKey: [id],\n                    queryFn() {\n                      Promise.resolve(id)\n                    }\n                  });\n                }\n              `,\n            },\n          ],\n          messageId: 'missingDeps',\n          data: { deps: 'id' },\n        },\n      ],\n    },\n    {\n      name: 'should fail if queryFn is a ternary expression with missing dep and a skipToken',\n      code: normalizeIndent`\n        import { useQuery, skipToken } from \"@tanstack/react-query\";\n        const fetch = true\n\n        function Component({ id }) {\n          useQuery({\n              queryKey: [],\n              queryFn: fetch ? () => Promise.resolve(id) : skipToken\n          })\n        }\n      `,\n      errors: [\n        {\n          suggestions: [\n            {\n              messageId: 'fixTo',\n              output: normalizeIndent`\n                import { useQuery, skipToken } from \"@tanstack/react-query\";\n                const fetch = true\n\n                function Component({ id }) {\n                  useQuery({\n                      queryKey: [id],\n                      queryFn: fetch ? () => Promise.resolve(id) : skipToken\n                  })\n                }\n              `,\n            },\n          ],\n          messageId: 'missingDeps',\n          data: { deps: 'id' },\n        },\n      ],\n    },\n    {\n      name: 'should fail in Vue file when deps are missing (script setup)',\n      filename: 'Component.vue',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/vue-query'\n\n        const id = 1\n        useQuery({\n          queryKey: ['entity'],\n          queryFn: () => fetchEntity(id),\n        })\n      `,\n      errors: [\n        {\n          messageId: 'missingDeps',\n          data: { deps: 'id' },\n          suggestions: [\n            {\n              messageId: 'fixTo',\n              data: { result: \"['entity', id]\" },\n              output: normalizeIndent`\n                import { useQuery } from '@tanstack/vue-query'\n\n                const id = 1\n                useQuery({\n                  queryKey: ['entity', id],\n                  queryFn: () => fetchEntity(id),\n                })\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      name: 'should fail in Vue file when multiple deps are missing',\n      filename: 'Component.vue',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/vue-query'\n\n        const userId = 1\n        const orgId = 2\n        useQuery({\n          queryKey: ['users'],\n          queryFn: () => fetchUser(userId, orgId),\n        })\n      `,\n      errors: [\n        {\n          messageId: 'missingDeps',\n          data: { deps: 'userId, orgId' },\n          suggestions: [\n            {\n              messageId: 'fixTo',\n              data: { result: \"['users', userId, orgId]\" },\n              output: normalizeIndent`\n                import { useQuery } from '@tanstack/vue-query'\n\n                const userId = 1\n                const orgId = 2\n                useQuery({\n                  queryKey: ['users', userId, orgId],\n                  queryFn: () => fetchUser(userId, orgId),\n                })\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      name: 'should fail when dep used in then/catch is missing in queryKey',\n      code: normalizeIndent`\n        function Component() {\n          const id = 1\n          useQuery({\n            queryKey: ['foo'],\n            queryFn: () =>\n              Promise.resolve(null)\n                .then(() => id)\n                .catch(() => id),\n          })\n        }\n      `,\n      errors: [\n        {\n          messageId: 'missingDeps',\n          data: { deps: 'id' },\n          suggestions: [\n            {\n              messageId: 'fixTo',\n              output: normalizeIndent`\n                function Component() {\n                  const id = 1\n                  useQuery({\n                    queryKey: ['foo', id],\n                    queryFn: () =>\n                      Promise.resolve(null)\n                        .then(() => id)\n                        .catch(() => id),\n                  })\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      name: 'should fail when queryKey callback only references a shadowing local',\n      code: normalizeIndent`\n        function Component(id, ids) {\n          useQuery({\n            queryKey: ['thing', ids.map((id) => id)],\n            queryFn: () => id,\n          })\n        }\n      `,\n      errors: [\n        {\n          messageId: 'missingDeps',\n          data: { deps: 'id' },\n          suggestions: [\n            {\n              messageId: 'fixTo',\n              output: normalizeIndent`\n                function Component(id, ids) {\n                  useQuery({\n                    queryKey: ['thing', ids.map((id) => id), id],\n                    queryFn: () => id,\n                  })\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      name: 'should fail when dep used in try/catch/finally is missing in queryKey',\n      code: normalizeIndent`\n        function Component() {\n          const id = 1\n          useQuery({\n            queryKey: ['foo'],\n            queryFn: () => {\n              try {\n                return fetch(id)\n              } catch (error) {\n                console.error(error)\n                return id\n              } finally {\n                console.log('done')\n              }\n            },\n          })\n        }\n      `,\n      errors: [\n        {\n          messageId: 'missingDeps',\n          data: { deps: 'id' },\n          suggestions: [\n            {\n              messageId: 'fixTo',\n              output: normalizeIndent`\n                function Component() {\n                  const id = 1\n                  useQuery({\n                    queryKey: ['foo', id],\n                    queryFn: () => {\n                      try {\n                        return fetch(id)\n                      } catch (error) {\n                        console.error(error)\n                        return id\n                      } finally {\n                        console.log('done')\n                      }\n                    },\n                  })\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n  ],\n})\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/__tests__/infinite-query-property-order.rule.test.ts",
    "content": "import { RuleTester } from '@typescript-eslint/rule-tester'\nimport combinate from 'combinate'\n\nimport {\n  checkedProperties,\n  infiniteQueryFunctions,\n} from '../rules/infinite-query-property-order/constants'\nimport {\n  name,\n  rule,\n} from '../rules/infinite-query-property-order/infinite-query-property-order.rule'\nimport {\n  generateInterleavedCombinations,\n  generatePartialCombinations,\n  generatePermutations,\n  normalizeIndent,\n} from './test-utils'\nimport type { InfiniteQueryFunctions } from '../rules/infinite-query-property-order/constants'\n\nconst ruleTester = new RuleTester()\n\ntype CheckedProperties = (typeof checkedProperties)[number]\nconst orderIndependentProps = [\n  'queryKey',\n  '...objectExpressionSpread',\n  '...callExpressionSpread',\n  '...memberCallExpressionSpread',\n] as const\ntype OrderIndependentProps = (typeof orderIndependentProps)[number]\n\ninterface TestCase {\n  infiniteQueryFunction: InfiniteQueryFunctions\n  properties: Array<CheckedProperties | OrderIndependentProps>\n}\n\nconst validTestMatrix = combinate({\n  infiniteQueryFunction: [...infiniteQueryFunctions],\n  properties: generatePartialCombinations(checkedProperties, 2),\n})\n\nexport function generateInvalidPermutations(\n  arr: ReadonlyArray<CheckedProperties>,\n): Array<{\n  invalid: Array<CheckedProperties>\n  valid: Array<CheckedProperties>\n}> {\n  const combinations = generatePartialCombinations(arr, 2)\n  const allPermutations: Array<{\n    invalid: Array<CheckedProperties>\n    valid: Array<CheckedProperties>\n  }> = []\n\n  for (const combination of combinations) {\n    const permutations = generatePermutations(combination)\n    // skip the first permutation as it matches the original combination\n    const invalidPermutations = permutations.slice(1)\n\n    if (\n      combination.includes('getNextPageParam') &&\n      combination.includes('getPreviousPageParam')\n    ) {\n      if (\n        combination.indexOf('getNextPageParam') <\n        combination.indexOf('getPreviousPageParam')\n      ) {\n        // since we ignore the relative order of 'getPreviousPageParam' and 'getNextPageParam', we skip this combination (but keep the other one where `getPreviousPageParam` is before `getNextPageParam`)\n\n        continue\n      }\n    }\n\n    allPermutations.push(\n      ...invalidPermutations\n        .map((p) => {\n          // ignore the relative order of 'getPreviousPageParam' and 'getNextPageParam'\n          const correctedValid = [...combination].sort((a, b) => {\n            if (\n              (a === 'getNextPageParam' && b === 'getPreviousPageParam') ||\n              (a === 'getPreviousPageParam' && b === 'getNextPageParam')\n            ) {\n              return p.indexOf(a) - p.indexOf(b)\n            }\n            return checkedProperties.indexOf(a) - checkedProperties.indexOf(b)\n          })\n          return { invalid: p, valid: correctedValid }\n        })\n        .filter(\n          ({ invalid }) =>\n            // if `getPreviousPageParam` and `getNextPageParam` are next to each other and `queryFn` is not present, we skip this invalid permutation\n            Math.abs(\n              invalid.indexOf('getNextPageParam') -\n                invalid.indexOf('getPreviousPageParam'),\n            ) !== 1,\n        ),\n    )\n  }\n\n  return allPermutations\n}\n\nconst invalidPermutations = generateInvalidPermutations(checkedProperties)\n\ntype Interleaved = CheckedProperties | OrderIndependentProps\nconst interleavedInvalidPermutations: Array<{\n  invalid: Array<Interleaved>\n  valid: Array<Interleaved>\n}> = []\nfor (const invalidPermutation of invalidPermutations) {\n  const invalid = generateInterleavedCombinations(\n    invalidPermutation.invalid,\n    orderIndependentProps,\n  )\n  const valid = generateInterleavedCombinations(\n    invalidPermutation.valid,\n    orderIndependentProps,\n  )\n\n  for (let i = 0; i < invalid.length; i++) {\n    interleavedInvalidPermutations.push({\n      invalid: invalid[i]!,\n      valid: valid[i]!,\n    })\n  }\n}\n\nconst invalidTestMatrix = combinate({\n  infiniteQueryFunction: [...infiniteQueryFunctions],\n  properties: interleavedInvalidPermutations,\n})\n\nconst callExpressionSpread = normalizeIndent`\n        ...communitiesQuery({\n          filters: {\n            ...fieldValues,\n            placementFormats: [],\n          },\n        })`\n\nfunction getCode({\n  infiniteQueryFunction: infiniteQueryFunction,\n  properties,\n}: TestCase) {\n  function getPropertyCode(\n    property: CheckedProperties | OrderIndependentProps,\n  ) {\n    switch (property) {\n      case '...objectExpressionSpread':\n        return `...objectExpressionSpread`\n      case '...callExpressionSpread':\n        return callExpressionSpread\n      case '...memberCallExpressionSpread':\n        return '...myOptions.infiniteQueryOptions()'\n      case 'queryKey':\n        return `queryKey: ['projects']`\n      case 'queryFn':\n        return 'queryFn: async ({ pageParam }) => { \\n await fetch(`/api/projects?cursor=${pageParam}`) \\n return await response.json() \\n }'\n      case 'getPreviousPageParam':\n        return 'getPreviousPageParam: (firstPage) => firstPage.previousId ?? undefined'\n      case 'getNextPageParam':\n        return 'getNextPageParam: (lastPage) => lastPage.nextId ?? undefined'\n    }\n  }\n  return `\n    import { ${infiniteQueryFunction} } from '@tanstack/react-query'\n\n    ${infiniteQueryFunction}({\n        ${properties.map(getPropertyCode).join(',\\n        ')}\n    })\n  `\n}\n\nconst validTestCases = validTestMatrix.map(\n  ({ infiniteQueryFunction, properties }) => ({\n    name: `should pass when order is correct for ${infiniteQueryFunction} with order: ${properties.join(', ')}`,\n    code: getCode({ infiniteQueryFunction, properties }),\n  }),\n)\n\nconst invalidTestCases = invalidTestMatrix.map(\n  ({ infiniteQueryFunction, properties }) => ({\n    name: `incorrect property order is detected for ${infiniteQueryFunction} with invalid order: ${properties.invalid.join(', ')}, valid order: ${properties.valid.join(', ')}`,\n    code: getCode({\n      infiniteQueryFunction: infiniteQueryFunction,\n      properties: properties.invalid,\n    }),\n    errors: [{ messageId: 'invalidOrder' }],\n    output: getCode({\n      infiniteQueryFunction: infiniteQueryFunction,\n      properties: properties.valid,\n    }),\n  }),\n)\n\nruleTester.run(name, rule, {\n  valid: validTestCases,\n  invalid: invalidTestCases,\n})\n\n// regression tests\n\nconst regressionTestCases = {\n  valid: [\n    {\n      name: 'should pass with call expression spread',\n      code: normalizeIndent`\n      import { useInfiniteQuery } from '@tanstack/react-query'\n      const { data, isFetching, isLoading, hasNextPage, fetchNextPage } =\n      useInfiniteQuery({\n        ...communitiesQuery({\n          filters: {\n            ...fieldValues,\n            placementFormats: [],\n          },\n        }),\n        refetchOnMount: false,\n      })`,\n    },\n  ],\n  invalid: [],\n}\n\nruleTester.run(name, rule, regressionTestCases)\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/__tests__/mutation-property-order.rule.test.ts",
    "content": "import { RuleTester } from '@typescript-eslint/rule-tester'\nimport combinate from 'combinate'\n\nimport {\n  checkedProperties,\n  mutationFunctions,\n} from '../rules/mutation-property-order/constants'\nimport {\n  name,\n  rule,\n} from '../rules/mutation-property-order/mutation-property-order.rule'\nimport {\n  generateInterleavedCombinations,\n  generatePartialCombinations,\n  generatePermutations,\n  normalizeIndent,\n} from './test-utils'\nimport type { MutationFunctions } from '../rules/mutation-property-order/constants'\n\nconst ruleTester = new RuleTester()\n\ntype CheckedProperties = (typeof checkedProperties)[number]\nconst orderIndependentProps = [\n  'gcTime',\n  '...objectExpressionSpread',\n  '...callExpressionSpread',\n  '...memberCallExpressionSpread',\n] as const\ntype OrderIndependentProps = (typeof orderIndependentProps)[number]\n\ninterface TestCase {\n  mutationFunction: MutationFunctions\n  properties: Array<CheckedProperties | OrderIndependentProps>\n}\n\nconst validTestMatrix = combinate({\n  mutationFunction: [...mutationFunctions],\n  properties: generatePartialCombinations(checkedProperties, 2),\n})\n\nexport function generateInvalidPermutations(\n  arr: ReadonlyArray<CheckedProperties>,\n): Array<{\n  invalid: Array<CheckedProperties>\n  valid: Array<CheckedProperties>\n}> {\n  const combinations = generatePartialCombinations(arr, 2)\n  const allPermutations: Array<{\n    invalid: Array<CheckedProperties>\n    valid: Array<CheckedProperties>\n  }> = []\n\n  for (const combination of combinations) {\n    const permutations = generatePermutations(combination)\n    // skip the first permutation as it matches the original combination\n    const invalidPermutations = permutations.slice(1)\n\n    if (combination.includes('onError') && combination.includes('onSettled')) {\n      if (combination.indexOf('onError') < combination.indexOf('onSettled')) {\n        // since we ignore the relative order of 'onError' and 'onSettled', we skip this combination (but keep the other one where `onSettled` is before `onError`)\n\n        continue\n      }\n    }\n\n    allPermutations.push(\n      ...invalidPermutations\n        .map((p) => {\n          // ignore the relative order of 'onError' and 'onSettled'\n          const correctedValid = [...combination].sort((a, b) => {\n            if (\n              (a === 'onSettled' && b === 'onError') ||\n              (a === 'onError' && b === 'onSettled')\n            ) {\n              return p.indexOf(a) - p.indexOf(b)\n            }\n            return checkedProperties.indexOf(a) - checkedProperties.indexOf(b)\n          })\n          return { invalid: p, valid: correctedValid }\n        })\n        .filter(\n          ({ invalid }) =>\n            // if `onError` and `onSettled` are next to each other and `onMutate` is not present, we skip this invalid permutation\n            Math.abs(\n              invalid.indexOf('onSettled') - invalid.indexOf('onError'),\n            ) !== 1,\n        ),\n    )\n  }\n\n  return allPermutations\n}\n\nconst invalidPermutations = generateInvalidPermutations(checkedProperties)\n\ntype Interleaved = CheckedProperties | OrderIndependentProps\nconst interleavedInvalidPermutations: Array<{\n  invalid: Array<Interleaved>\n  valid: Array<Interleaved>\n}> = []\nfor (const invalidPermutation of invalidPermutations) {\n  const invalid = generateInterleavedCombinations(\n    invalidPermutation.invalid,\n    orderIndependentProps,\n  )\n  const valid = generateInterleavedCombinations(\n    invalidPermutation.valid,\n    orderIndependentProps,\n  )\n\n  for (let i = 0; i < invalid.length; i++) {\n    interleavedInvalidPermutations.push({\n      invalid: invalid[i]!,\n      valid: valid[i]!,\n    })\n  }\n}\n\nconst invalidTestMatrix = combinate({\n  mutationFunction: [...mutationFunctions],\n  properties: interleavedInvalidPermutations,\n})\n\nconst callExpressionSpread = normalizeIndent`\n        ...mutationOptions({\n            onSuccess: () => {},\n            retry: 3,\n        })`\n\nfunction getCode({ mutationFunction: mutationFunction, properties }: TestCase) {\n  function getPropertyCode(\n    property: CheckedProperties | OrderIndependentProps,\n  ) {\n    switch (property) {\n      case '...objectExpressionSpread':\n        return `...objectExpressionSpread`\n      case '...callExpressionSpread':\n        return callExpressionSpread\n      case '...memberCallExpressionSpread':\n        return '...myOptions.mutationOptions()'\n      case 'gcTime':\n        return 'gcTime: 5 * 60 * 1000'\n      case 'onMutate':\n        return 'onMutate: (data) => {\\n return { foo: data }\\n}'\n      case 'onError':\n        return 'onError: (error, variables, onMutateResult) => {\\n  console.log(\"error:\", error, \"onMutateResult:\", scope)\\n}'\n      case 'onSettled':\n        return 'onSettled: (data, error, variables, onMutateResult) => {\\n  console.log(\"settled\", onMutateResult)\\n}'\n    }\n  }\n  return `\n    import { ${mutationFunction} } from '@tanstack/react-query'\n\n    ${mutationFunction}({\n        ${properties.map(getPropertyCode).join(',\\n        ')}\n    })\n  `\n}\n\nconst validTestCases = validTestMatrix.map(\n  ({ mutationFunction, properties }) => ({\n    name: `should pass when order is correct for ${mutationFunction} with order: ${properties.join(', ')}`,\n    code: getCode({\n      mutationFunction: mutationFunction,\n      properties,\n    }),\n  }),\n)\n\nconst invalidTestCases = invalidTestMatrix.map(\n  ({ mutationFunction, properties }) => ({\n    name: `incorrect property order id detected for ${mutationFunction} with invalid order: ${properties.invalid.join(', ')}, valid order ${properties.valid.join(', ')}`,\n    code: getCode({\n      mutationFunction: mutationFunction,\n      properties: properties.invalid,\n    }),\n    errors: [{ messageId: 'invalidOrder' }],\n    output: getCode({\n      mutationFunction: mutationFunction,\n      properties: properties.valid,\n    }),\n  }),\n)\n\nruleTester.run(name, rule, {\n  valid: validTestCases,\n  invalid: invalidTestCases,\n})\n\nconst regressionTestCases = {\n  valid: [\n    {\n      name: 'should pass with call expression spread in useMutation',\n      code: normalizeIndent`\n      import { useMutation } from '@tanstack/react-query'\n\n      const { mutate } = useMutation({\n        ...mutationOptions({\n          retry: 3,\n          onSuccess: () => console.log('success'),\n        }),\n        onMutate: (data) => {\n          return { foo: data }\n        },\n        onError: (error, variables, onMutateResult) => {\n          console.log(error, onMutateResult)\n        },\n        onSettled: (data, error, variables, onMutateResult) => {\n          console.log('settled', onMutateResult)\n        },\n      })\n      `,\n    },\n  ],\n  invalid: [],\n}\n\nruleTester.run(name, rule, regressionTestCases)\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/__tests__/no-rest-destructuring.test.ts",
    "content": "import { RuleTester } from '@typescript-eslint/rule-tester'\nimport { rule } from '../rules/no-rest-destructuring/no-rest-destructuring.rule'\nimport { normalizeIndent } from './test-utils'\n\nconst ruleTester = new RuleTester()\n\nruleTester.run('no-rest-destructuring', rule, {\n  valid: [\n    {\n      name: 'useQuery is not captured',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/react-query'\n\n        function Component() {\n          useQuery()\n          return\n        }\n      `,\n    },\n    {\n      name: 'useQuery is not destructured',\n      code: normalizeIndent`\n          import { useQuery } from '@tanstack/react-query'\n\n          function Component() {\n            const query = useQuery()\n            return\n          }\n        `,\n    },\n    {\n      name: 'useQuery is destructured without rest',\n      code: normalizeIndent`\n          import { useQuery } from '@tanstack/react-query'\n\n          function Component() {\n            const { data, isLoading, isError } = useQuery()\n            return\n          }\n        `,\n    },\n    {\n      name: 'useInfiniteQuery is not captured',\n      code: normalizeIndent`\n        import { useInfiniteQuery } from '@tanstack/react-query'\n\n        function Component() {\n          useInfiniteQuery()\n          return\n        }\n      `,\n    },\n    {\n      name: 'useInfiniteQuery is not destructured',\n      code: normalizeIndent`\n          import { useInfiniteQuery } from '@tanstack/react-query'\n\n          function Component() {\n            const query = useInfiniteQuery()\n            return\n          }\n        `,\n    },\n    {\n      name: 'useInfiniteQuery is destructured without rest',\n      code: normalizeIndent`\n          import { useInfiniteQuery } from '@tanstack/react-query'\n\n          function Component() {\n            const { data, isLoading, isError } = useInfiniteQuery()\n            return\n          }\n        `,\n    },\n    {\n      name: 'useQueries is not captured',\n      code: normalizeIndent`\n        import { useQueries } from '@tanstack/react-query'\n\n        function Component() {\n          useQueries([])\n          return\n        }\n      `,\n    },\n    {\n      name: 'useQueries is not destructured',\n      code: normalizeIndent`\n          import { useQueries } from '@tanstack/react-query'\n\n          function Component() {\n            const queries = useQueries([])\n            return\n          }\n        `,\n    },\n    {\n      name: 'useQueries array has no rest destructured element',\n      code: normalizeIndent`\n          import { useQueries } from '@tanstack/react-query'\n\n          function Component() {\n            const [query1, { data, isLoading },, ...others] = useQueries([\n              { queryKey: ['key1'], queryFn: () => {} },\n              { queryKey: ['key2'], queryFn: () => {} },\n              { queryKey: ['key3'], queryFn: () => {} },\n              { queryKey: ['key4'], queryFn: () => {} },\n              { queryKey: ['key5'], queryFn: () => {} },\n            ])\n            return\n          }\n        `,\n    },\n    {\n      name: 'useQuery is destructured with rest but not from tanstack query',\n      code: normalizeIndent`\n        import { useQuery } from 'other-package'\n\n        function Component() {\n          const { data, ...rest } = useQuery()\n          return\n        }\n      `,\n    },\n    {\n      name: 'useInfiniteQuery is destructured with rest but not from tanstack query',\n      code: normalizeIndent`\n        import { useInfiniteQuery } from 'other-package'\n\n        function Component() {\n          const { data, ...rest } = useInfiniteQuery()\n          return\n        }\n      `,\n    },\n    {\n      name: 'useQueries array has rest destructured element but not from tanstack query',\n      code: normalizeIndent`\n          import { useQueries } from 'other-package'\n\n          function Component() {\n            const [query1, { data, ...rest }] = useQueries([\n              { queryKey: ['key1'], queryFn: () => {} },\n              { queryKey: ['key2'], queryFn: () => {} },\n            ])\n            return\n          }\n        `,\n    },\n    {\n      name: 'useSuspenseQuery is not captured',\n      code: normalizeIndent`\n        import { useSuspenseQuery } from '@tanstack/react-query'\n\n        function Component() {\n          useSuspenseQuery()\n          return\n        }\n      `,\n    },\n    {\n      name: 'useSuspenseQuery is not destructured',\n      code: normalizeIndent`\n        import { useSuspenseQuery } from '@tanstack/react-query'\n\n        function Component() {\n          const query = useSuspenseQuery()\n          return\n        }\n      `,\n    },\n    {\n      name: 'useSuspenseQuery is destructured without rest',\n      code: normalizeIndent`\n        import { useSuspenseQuery } from '@tanstack/react-query'\n\n        function Component() {\n          const { data, isLoading, isError } = useSuspenseQuery()\n          return\n        }\n      `,\n    },\n    {\n      name: 'useSuspenseInfiniteQuery is not captured',\n      code: normalizeIndent`\n        import { useSuspenseInfiniteQuery } from '@tanstack/react-query'\n\n        function Component() {\n          useSuspenseInfiniteQuery()\n          return\n        }\n      `,\n    },\n    {\n      name: 'useSuspenseInfiniteQuery is not destructured',\n      code: normalizeIndent`\n        import { useSuspenseInfiniteQuery } from '@tanstack/react-query'\n\n        function Component() {\n          const query = useSuspenseInfiniteQuery()\n          return\n        }\n      `,\n    },\n    {\n      name: 'useSuspenseInfiniteQuery is destructured without rest',\n      code: normalizeIndent`\n        import { useSuspenseInfiniteQuery } from '@tanstack/react-query'\n\n        function Component() {\n          const { data, isLoading, isError } = useSuspenseInfiniteQuery()\n          return\n        }\n      `,\n    },\n    {\n      name: 'useSuspenseQueries is not captured',\n      code: normalizeIndent`\n        import { useSuspenseQueries } from '@tanstack/react-query'\n\n        function Component() {\n          useSuspenseQueries([])\n          return\n        }\n      `,\n    },\n    {\n      name: 'useSuspenseQueries is not destructured',\n      code: normalizeIndent`\n        import { useSuspenseQueries } from '@tanstack/react-query'\n\n        function Component() {\n          const queries = useSuspenseQueries([])\n          return\n        }\n      `,\n    },\n    {\n      name: 'useSuspenseQueries array has no rest destructured element',\n      code: normalizeIndent`\n        import { useSuspenseQueries } from '@tanstack/react-query'\n\n        function Component() {\n          const [query1, { data, isLoading }] = useSuspenseQueries([\n            { queryKey: ['key1'], queryFn: () => {} },\n            { queryKey: ['key2'], queryFn: () => {} },\n          ])\n          return\n        }\n      `,\n    },\n    {\n      name: 'useSuspenseQuery is destructured with rest but not from tanstack query',\n      code: normalizeIndent`\n        import { useSuspenseQuery } from 'other-package'\n\n        function Component() {\n          const { data, ...rest } = useSuspenseQuery()\n          return\n        }\n      `,\n    },\n    {\n      name: 'useSuspenseInfiniteQuery is destructured with rest but not from tanstack query',\n      code: normalizeIndent`\n        import { useSuspenseInfiniteQuery } from 'other-package'\n\n        function Component() {\n          const { data, ...rest } = useSuspenseInfiniteQuery()\n          return\n        }\n      `,\n    },\n    {\n      name: 'useSuspenseQueries array has rest destructured element but not from tanstack query',\n      code: normalizeIndent`\n        import { useSuspenseQueries } from 'other-package'\n\n        function Component() {\n          const [query1, { data, ...rest }] = useSuspenseQueries([\n            { queryKey: ['key1'], queryFn: () => {} },\n            { queryKey: ['key2'], queryFn: () => {} },\n          ])\n          return\n        }\n      `,\n    },\n  ],\n  invalid: [\n    {\n      name: 'useQuery is destructured with rest',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/react-query'\n\n        function Component() {\n          const { data, ...rest } = useQuery()\n          return\n        }\n      `,\n      errors: [{ messageId: 'objectRestDestructure' }],\n    },\n    {\n      name: 'useInfiniteQuery is destructured with rest',\n      code: normalizeIndent`\n        import { useInfiniteQuery } from '@tanstack/react-query'\n\n        function Component() {\n          const { data, ...rest } = useInfiniteQuery()\n          return\n        }\n      `,\n      errors: [{ messageId: 'objectRestDestructure' }],\n    },\n    {\n      name: 'useQueries array has rest destructured element',\n      code: normalizeIndent`\n          import { useQueries } from '@tanstack/react-query'\n\n          function Component() {\n            const [query1, { data, ...rest }] = useQueries([\n              { queryKey: ['key1'], queryFn: () => {} },\n              { queryKey: ['key2'], queryFn: () => {} },\n            ])\n            return\n          }\n        `,\n      errors: [{ messageId: 'objectRestDestructure' }],\n    },\n    {\n      name: 'useSuspenseQuery is destructured with rest',\n      code: normalizeIndent`\n        import { useSuspenseQuery } from '@tanstack/react-query'\n\n        function Component() {\n          const { data, ...rest } = useSuspenseQuery()\n          return\n        }\n      `,\n      errors: [{ messageId: 'objectRestDestructure' }],\n    },\n    {\n      name: 'useSuspenseInfiniteQuery is destructured with rest',\n      code: normalizeIndent`\n        import { useSuspenseInfiniteQuery } from '@tanstack/react-query'\n\n        function Component() {\n          const { data, ...rest } = useSuspenseInfiniteQuery()\n          return\n        }\n      `,\n      errors: [{ messageId: 'objectRestDestructure' }],\n    },\n    {\n      name: 'useSuspenseQueries is destructured with rest',\n      code: normalizeIndent`\n        import { useSuspenseQueries } from '@tanstack/react-query'\n\n        function Component() {\n          const [query1, { data, ...rest }] = useSuspenseQueries([\n            { queryKey: ['key1'], queryFn: () => {} },\n            { queryKey: ['key2'], queryFn: () => {} },\n          ])\n          return\n        }\n      `,\n      errors: [{ messageId: 'objectRestDestructure' }],\n    },\n    {\n      name: 'useQuery result is spread in return statement',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/react-query'\n\n        function Component() {\n          const query = useQuery()\n          return { ...query, data: query.data[0] }\n        }\n      `,\n      errors: [{ messageId: 'objectRestDestructure' }],\n    },\n    {\n      name: 'useQuery result is spread in object expression',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/react-query'\n\n        function Component() {\n          const query = useQuery()\n          const result = { ...query, data: query.data[0] }\n          return result\n        }\n      `,\n      errors: [{ messageId: 'objectRestDestructure' }],\n    },\n  ],\n})\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/__tests__/no-unstable-deps.test.ts",
    "content": "import { RuleTester } from '@typescript-eslint/rule-tester'\nimport {\n  reactHookNames,\n  rule,\n  useQueryHookNames,\n} from '../rules/no-unstable-deps/no-unstable-deps.rule'\n\nconst ruleTester = new RuleTester()\n\ninterface TestCase {\n  reactHookImport: string\n  reactHookInvocation: string\n  reactHookAlias: string\n}\nconst baseTestCases = {\n  valid: ({ reactHookImport, reactHookInvocation, reactHookAlias }: TestCase) =>\n    [\n      {\n        name: `should pass when destructured mutate is passed to ${reactHookAlias} as dependency`,\n        code: `\n            ${reactHookImport}\n            import { useMutation } from \"@tanstack/react-query\";\n\n            function Component() {\n                const { mutate } = useMutation({ mutationFn: (value: string) => value });\n                const callback = ${reactHookInvocation}(() => { mutate('hello') }, [mutate]);\n                return;\n            }\n              `,\n      },\n    ]\n      .concat(\n        useQueryHookNames.map((queryHook) => ({\n          name: `should pass result of ${queryHook} is passed to ${reactHookInvocation} as dependency`,\n          code: `\n            ${reactHookImport}\n            import { ${queryHook} } from \"@tanstack/react-query\";\n\n            function Component() {\n              const { refetch } = ${queryHook}({ queryFn: (value: string) => value });\n              const callback = ${reactHookInvocation}(() => { query.refetch() }, [refetch]);\n              return;\n            }\n          `,\n        })),\n      )\n      .concat([\n        {\n          name: `should pass when useQueries with combine is passed to ${reactHookAlias} as dependency`,\n          code: `\n            ${reactHookImport}\n            import { useQueries } from \"@tanstack/react-query\";\n\n            function Component() {\n              const queries = useQueries({\n                queries: [\n                  { queryKey: ['test'], queryFn: () => 'test' }\n                ],\n                combine: (results) => ({ data: results[0]?.data })\n              });\n              const callback = ${reactHookInvocation}(() => { queries.data }, [queries]);\n              return;\n            }\n          `,\n        },\n      ])\n      .concat([\n        {\n          name: `should pass when useQuery is imported from non-TanStack source and used with ${reactHookAlias}`,\n          code: `\n            ${reactHookImport}\n            import { useQuery } from \"./router\";\n\n            function Component() {\n              const query = useQuery();\n              const callback = ${reactHookInvocation}(() => { query.refetch() }, [query]);\n              return;\n            }\n          `,\n        },\n        {\n          name: `should pass when useMutation is imported from non-TanStack source and used with ${reactHookAlias}`,\n          code: `\n            ${reactHookImport}\n            import { useMutation } from \"./api\";\n\n            function Component() {\n              const mutation = useMutation();\n              const callback = ${reactHookInvocation}(() => { mutation.mutate() }, [mutation]);\n              return;\n            }\n          `,\n        },\n      ]),\n  invalid: ({\n    reactHookImport,\n    reactHookInvocation,\n    reactHookAlias,\n  }: TestCase) =>\n    [\n      {\n        name: `result of useMutation is passed to ${reactHookInvocation} as dependency `,\n        code: `\n            ${reactHookImport}\n            import { useMutation } from \"@tanstack/react-query\";\n\n            function Component() {\n              const mutation = useMutation({ mutationFn: (value: string) => value });\n              const callback = ${reactHookInvocation}(() => { mutation.mutate('hello') }, [mutation]);\n              return;\n            }\n          `,\n        errors: [\n          {\n            messageId: 'noUnstableDeps',\n            data: { reactHook: reactHookAlias, queryHook: 'useMutation' },\n          },\n        ],\n      },\n    ]\n      .concat(\n        useQueryHookNames.map((queryHook) => ({\n          name: `result of ${queryHook} is passed to ${reactHookInvocation} as dependency`,\n          code: `\n            ${reactHookImport}\n            import { ${queryHook} } from \"@tanstack/react-query\";\n\n            function Component() {\n              const query = ${queryHook}({ queryFn: (value: string) => value });\n              const callback = ${reactHookInvocation}(() => { query.refetch() }, [query]);\n              return;\n            }\n          `,\n          errors: [\n            {\n              messageId: 'noUnstableDeps',\n              data: { reactHook: reactHookAlias, queryHook },\n            },\n          ],\n        })),\n      )\n      .concat([\n        {\n          name: `result of useQueries without combine is passed to ${reactHookInvocation} as dependency`,\n          code: `\n            ${reactHookImport}\n            import { useQueries } from \"@tanstack/react-query\";\n\n            function Component() {\n              const queries = useQueries({\n                queries: [\n                  { queryKey: ['test'], queryFn: () => 'test' }\n                ]\n              });\n              const callback = ${reactHookInvocation}(() => { queries[0]?.data }, [queries]);\n              return;\n            }\n          `,\n          errors: [\n            {\n              messageId: 'noUnstableDeps',\n              data: { reactHook: reactHookAlias, queryHook: 'useQueries' },\n            },\n          ],\n        },\n      ]),\n}\n\nconst testCases = (reactHookName: string) => [\n  {\n    reactHookImport: 'import * as React from \"React\";',\n    reactHookInvocation: `React.${reactHookName}`,\n    reactHookAlias: reactHookName,\n  },\n  {\n    reactHookImport: `import { ${reactHookName} } from \"React\";`,\n    reactHookInvocation: reactHookName,\n    reactHookAlias: reactHookName,\n  },\n  {\n    reactHookImport: `import { ${reactHookName} as useAlias } from \"React\";`,\n    reactHookInvocation: 'useAlias',\n    reactHookAlias: 'useAlias',\n  },\n]\n\nreactHookNames.forEach((reactHookName) => {\n  testCases(reactHookName).forEach(\n    ({ reactHookInvocation, reactHookAlias, reactHookImport }) => {\n      ruleTester.run('no-unstable-deps', rule, {\n        valid: baseTestCases.valid({\n          reactHookImport,\n          reactHookInvocation,\n          reactHookAlias,\n        }),\n        invalid: baseTestCases.invalid({\n          reactHookImport,\n          reactHookInvocation,\n          reactHookAlias,\n        }),\n      })\n    },\n  )\n})\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/__tests__/no-void-query-fn.test.ts",
    "content": "import path from 'node:path'\nimport { RuleTester } from '@typescript-eslint/rule-tester'\nimport { afterAll, describe, it } from 'vitest'\nimport { rule } from '../rules/no-void-query-fn/no-void-query-fn.rule'\nimport { normalizeIndent } from './test-utils'\n\nRuleTester.afterAll = afterAll\nRuleTester.describe = describe\nRuleTester.it = it\n\nconst ruleTester = new RuleTester({\n  languageOptions: {\n    parser: await import('@typescript-eslint/parser'),\n    parserOptions: {\n      project: true,\n      tsconfigRootDir: path.resolve(__dirname, './ts-fixture'),\n    },\n  },\n})\n\nruleTester.run('no-void-query-fn', rule, {\n  valid: [\n    {\n      name: 'queryFn returns a value',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/react-query'\n\n        function Component() {\n          const query = useQuery({\n            queryKey: ['test'],\n            queryFn: () => ({ data: 'test' }),\n          })\n          return null\n        }\n      `,\n    },\n    {\n      name: 'queryFn returns a Promise',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/react-query'\n\n        function Component() {\n          const query = useQuery({\n            queryKey: ['test'],\n            queryFn: async () => ({ data: 'test' }),\n          })\n          return null\n        }\n      `,\n    },\n    {\n      name: 'queryFn returns Promise.resolve',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/react-query'\n\n        function Component() {\n          const query = useQuery({\n            queryKey: ['test'],\n            queryFn: () => Promise.resolve({ data: 'test' }),\n          })\n          return null\n        }\n      `,\n    },\n    {\n      name: 'queryFn with explicit Promise type',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/react-query'\n\n        interface Data {\n          value: string\n        }\n\n        function Component() {\n          const query = useQuery({\n            queryKey: ['test'],\n            queryFn: async (): Promise<Data> => {\n              return { value: 'test' }\n            },\n          })\n          return null\n        }\n      `,\n    },\n    {\n      name: 'queryFn with generic Promise type',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/react-query'\n\n        interface Response<T> {\n          data: T\n        }\n\n        function Component() {\n          const query = useQuery({\n            queryKey: ['test'],\n            queryFn: async (): Promise<Response<string>> => {\n              return { data: 'test' }\n            },\n          })\n          return null\n        }\n      `,\n    },\n    {\n      name: 'queryFn with external async function',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/react-query'\n\n        async function fetchData(): Promise<{ data: string }> {\n          return { data: 'test' }\n        }\n\n        function Component() {\n          const query = useQuery({\n            queryKey: ['test'],\n            queryFn: fetchData,\n          })\n          return null\n        }\n      `,\n    },\n    {\n      name: 'queryFn returns null',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/react-query'\n\n        function Component() {\n          const query = useQuery({\n            queryKey: ['test'],\n            queryFn: () => null,\n          })\n          return null\n        }\n      `,\n    },\n    {\n      name: 'queryFn returns 0',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/react-query'\n\n        function Component() {\n          const query = useQuery({\n            queryKey: ['test'],\n            queryFn: () => 0,\n          })\n          return null\n        }\n      `,\n    },\n    {\n      name: 'queryFn returns false',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/react-query'\n\n        function Component() {\n          const query = useQuery({\n            queryKey: ['test'],\n            queryFn: () => false,\n          })\n          return null\n        }\n      `,\n    },\n  ],\n  invalid: [\n    {\n      name: 'queryFn returns void',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/react-query'\n\n        function Component() {\n          const query = useQuery({\n            queryKey: ['test'],\n            queryFn: () => {\n              console.log('test')\n            },\n          })\n          return null\n        }\n      `,\n      errors: [{ messageId: 'noVoidReturn' }],\n    },\n    {\n      name: 'queryFn returns undefined',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/react-query'\n\n        function Component() {\n          const query = useQuery({\n            queryKey: ['test'],\n            queryFn: () => undefined,\n          })\n          return null\n        }\n      `,\n      errors: [{ messageId: 'noVoidReturn' }],\n    },\n    {\n      name: 'async queryFn returns void',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/react-query'\n\n        function Component() {\n          const query = useQuery({\n            queryKey: ['test'],\n            queryFn: async () => {\n              await someOperation()\n            },\n          })\n          return null\n        }\n      `,\n      errors: [{ messageId: 'noVoidReturn' }],\n    },\n    {\n      name: 'queryFn with explicit void Promise',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/react-query'\n\n        function Component() {\n          const query = useQuery({\n            queryKey: ['test'],\n            queryFn: async (): Promise<void> => {\n              await someOperation()\n            },\n          })\n          return null\n        }\n      `,\n      errors: [{ messageId: 'noVoidReturn' }],\n    },\n    {\n      name: 'queryFn with Promise.resolve(undefined)',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/react-query'\n\n        function Component() {\n          const query = useQuery({\n            queryKey: ['test'],\n            queryFn: () => Promise.resolve(undefined),\n          })\n          return null\n        }\n      `,\n      errors: [{ messageId: 'noVoidReturn' }],\n    },\n    {\n      name: 'queryFn with external void async function',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/react-query'\n\n        async function voidOperation(): Promise<void> {\n          await someOperation()\n        }\n\n        function Component() {\n          const query = useQuery({\n            queryKey: ['test'],\n            queryFn: voidOperation,\n          })\n          return null\n        }\n      `,\n      errors: [{ messageId: 'noVoidReturn' }],\n    },\n    {\n      name: 'queryFn with conditional return (one branch missing)',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/react-query'\n\n        function Component() {\n          const query = useQuery({\n            queryKey: ['test'],\n            queryFn: () => {\n              if (Math.random() > 0.5) {\n                return { data: 'test' }\n              }\n              // Missing return in the else case\n            },\n          })\n          return null\n        }\n      `,\n      errors: [{ messageId: 'noVoidReturn' }],\n    },\n    {\n      name: 'queryFn with ternary operator returning undefined',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/react-query'\n\n        function Component() {\n          const query = useQuery({\n            queryKey: ['test'],\n            queryFn: () => Math.random() > 0.5 ? { data: 'test' } : undefined,\n          })\n          return null\n        }\n      `,\n      errors: [{ messageId: 'noVoidReturn' }],\n    },\n    {\n      name: 'async queryFn with try/catch missing return in catch',\n      code: normalizeIndent`\n        import { useQuery } from '@tanstack/react-query'\n\n        function Component() {\n          const query = useQuery({\n            queryKey: ['test'],\n            queryFn: async () => {\n              try {\n                return { data: 'test' }\n              } catch (error) {\n                console.error(error)\n                // No return here results in an implicit undefined\n              }\n            },\n          })\n          return null\n        }\n      `,\n      errors: [{ messageId: 'noVoidReturn' }],\n    },\n  ],\n})\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/__tests__/sort-data-by-order.utils.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { sortDataByOrder } from '../utils/sort-data-by-order'\n\ndescribe('create-route-property-order utils', () => {\n  describe('sortDataByOrder', () => {\n    const testCases = [\n      {\n        data: [{ key: 'a' }, { key: 'c' }, { key: 'b' }],\n        orderArray: [\n          [['a'], ['b']],\n          [['b'], ['c']],\n        ],\n        key: 'key',\n        expected: [{ key: 'a' }, { key: 'b' }, { key: 'c' }],\n      },\n      {\n        data: [{ key: 'b' }, { key: 'a' }, { key: 'c' }],\n        orderArray: [\n          [['a'], ['b']],\n          [['b'], ['c']],\n        ],\n        key: 'key',\n        expected: [{ key: 'a' }, { key: 'b' }, { key: 'c' }],\n      },\n      {\n        data: [{ key: 'a' }, { key: 'b' }, { key: 'c' }],\n        orderArray: [\n          [['a'], ['b']],\n          [['b'], ['c']],\n        ],\n        key: 'key',\n        expected: null,\n      },\n      {\n        data: [{ key: 'a' }, { key: 'b' }, { key: 'c' }, { key: 'd' }],\n        orderArray: [\n          [['a'], ['b']],\n          [['b'], ['c']],\n        ],\n        key: 'key',\n        expected: null,\n      },\n      {\n        data: [{ key: 'a' }, { key: 'b' }, { key: 'd' }, { key: 'c' }],\n        orderArray: [\n          [['a'], ['b']],\n          [['b'], ['c']],\n        ],\n        key: 'key',\n        expected: null,\n      },\n      {\n        data: [{ key: 'd' }, { key: 'a' }, { key: 'b' }, { key: 'c' }],\n        orderArray: [\n          [['a'], ['b']],\n          [['b'], ['c']],\n        ],\n        key: 'key',\n        expected: null,\n      },\n      {\n        data: [{ key: 'd' }, { key: 'b' }, { key: 'a' }, { key: 'c' }],\n        orderArray: [\n          [['a'], ['b']],\n          [['b'], ['c']],\n        ],\n        key: 'key',\n        expected: [{ key: 'd' }, { key: 'a' }, { key: 'b' }, { key: 'c' }],\n      },\n    ] as const\n    test.each(testCases)(\n      '$data $orderArray $key $expected',\n      ({ data, orderArray, key, expected }) => {\n        const sortedData = sortDataByOrder(data, orderArray, key)\n        expect(sortedData).toEqual(expected)\n      },\n    )\n  })\n})\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/__tests__/stable-query-client.test.ts",
    "content": "import { RuleTester } from '@typescript-eslint/rule-tester'\nimport { rule } from '../rules/stable-query-client/stable-query-client.rule'\nimport { normalizeIndent } from './test-utils'\n\nconst ruleTester = new RuleTester()\n\nruleTester.run('stable-query-client', rule, {\n  valid: [\n    {\n      name: 'QueryClient is stable when wrapped in React.useState',\n      code: normalizeIndent`\n        import { QueryClient } from \"@tanstack/react-query\";\n\n        function Component() {\n          const [queryClient] = React.useState(() => new QueryClient());\n          return;\n        }\n      `,\n    },\n    {\n      name: 'QueryClient is stable when wrapped in useState',\n      code: normalizeIndent`\n        import { QueryClient } from \"@tanstack/react-query\";\n\n        function Component() {\n          const [queryClient] = useState(() => new QueryClient());\n          return;\n        }\n      `,\n    },\n    {\n      name: 'QueryClient is stable when wrapped in React.useMemo',\n      code: normalizeIndent`\n          import { QueryClient } from \"@tanstack/react-query\";\n\n          function Component() {\n            const [queryClient] = React.useMemo(() => new QueryClient(), []);\n            return;\n          }\n        `,\n    },\n    {\n      name: 'QueryClient is stable when wrapped in useAnything',\n      code: normalizeIndent`\n          import { QueryClient } from \"@tanstack/react-query\";\n\n          function Component() {\n            const [queryClient] = useAnything(() => new QueryClient());\n            return;\n          }\n        `,\n    },\n    {\n      name: 'QueryClient is imported from a non-tanstack package',\n      code: normalizeIndent`\n        import { QueryClient } from \"other-library\";\n\n        function Component() {\n          const queryClient = new QueryClient();\n          return;\n        }\n      `,\n    },\n    {\n      name: 'QueryClient is not imported from @tanstack/react-query',\n      code: normalizeIndent`\n        import { QueryClient } from \"@tanstack/solid-query\";\n\n        function Component() {\n          const queryClient = new QueryClient();\n          return;\n        }\n      `,\n    },\n    {\n      name: 'QueryClient is invoked outside of a function',\n      code: normalizeIndent`\n        import { QueryClient } from \"@tanstack/solid-query\";\n\n        const queryClient = new QueryClient();\n\n        function Component() {\n          return;\n        }\n      `,\n    },\n    {\n      name: 'QueryClient is invoked in a non-component function',\n      code: normalizeIndent`\n        import { QueryClient } from \"@tanstack/solid-query\";\n\n        function someFn() {\n          const queryClient = new QueryClient();\n          return;\n        }\n      `,\n    },\n    {\n      name: 'QueryClient is invoked in an async (react server) component',\n      code: normalizeIndent`\n        import { QueryClient } from \"@tanstack/solid-query\";\n\n        async function AsyncComponent() {\n          const queryClient = new QueryClient();\n          return;\n        }\n      `,\n    },\n  ],\n  invalid: [\n    {\n      name: 'QueryClient is not stable when it is not wrapped in React.useState in component',\n      code: normalizeIndent`\n        import { QueryClient } from \"@tanstack/react-query\";\n\n        function Component() {\n          const queryClient = new QueryClient();\n          return;\n        }\n      `,\n      output: normalizeIndent`\n        import { QueryClient } from \"@tanstack/react-query\";\n\n        function Component() {\n          const [queryClient] = React.useState(() => new QueryClient());\n          return;\n        }\n      `,\n      errors: [{ messageId: 'unstable' }],\n    },\n    {\n      name: 'QueryClient is not stable when it is not wrapped in React.useState in custom hook',\n      code: normalizeIndent`\n        import { QueryClient } from \"@tanstack/react-query\";\n\n        function useHook() {\n          const queryClient = new QueryClient();\n          return;\n        }\n      `,\n      output: normalizeIndent`\n        import { QueryClient } from \"@tanstack/react-query\";\n\n        function useHook() {\n          const [queryClient] = React.useState(() => new QueryClient());\n          return;\n        }\n      `,\n      errors: [{ messageId: 'unstable' }],\n    },\n    {\n      name: 'preserve QueryClient options',\n      code: normalizeIndent`\n        import { QueryClient } from \"@tanstack/react-query\";\n\n        function Component() {\n          const queryClient = new QueryClient({ defaultOptions: { /* */ } });\n          return;\n        }\n      `,\n      output: normalizeIndent`\n        import { QueryClient } from \"@tanstack/react-query\";\n\n        function Component() {\n          const [queryClient] = React.useState(() => new QueryClient({ defaultOptions: { /* */ } }));\n          return;\n        }\n      `,\n      errors: [{ messageId: 'unstable' }],\n    },\n    {\n      name: 'preserve QueryClient variable declarator name',\n      code: normalizeIndent`\n        import { QueryClient } from \"@tanstack/react-query\";\n\n        function Component() {\n          const customName = new QueryClient();\n          return;\n        }\n      `,\n      output: normalizeIndent`\n        import { QueryClient } from \"@tanstack/react-query\";\n\n        function Component() {\n          const [customName] = React.useState(() => new QueryClient());\n          return;\n        }\n      `,\n      errors: [{ messageId: 'unstable' }],\n    },\n  ],\n})\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/__tests__/test-utils.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport {\n  expectArrayEqualIgnoreOrder,\n  generateInterleavedCombinations,\n  generatePartialCombinations,\n  generatePermutations,\n} from './test-utils'\n\ndescribe('test-utils', () => {\n  describe('generatePermutations', () => {\n    const testCases = [\n      {\n        input: ['a', 'b', 'c'],\n        expected: [\n          ['a', 'b', 'c'],\n          ['a', 'c', 'b'],\n          ['b', 'a', 'c'],\n          ['b', 'c', 'a'],\n          ['c', 'a', 'b'],\n          ['c', 'b', 'a'],\n        ],\n      },\n      {\n        input: ['a', 'b'],\n        expected: [\n          ['a', 'b'],\n          ['b', 'a'],\n        ],\n      },\n      {\n        input: ['a'],\n        expected: [['a']],\n      },\n    ]\n    test.each(testCases)('$input $expected', ({ input, expected }) => {\n      const permutations = generatePermutations(input)\n      expect(permutations).toEqual(expected)\n    })\n  })\n\n  describe('generatePartialCombinations', () => {\n    const testCases = [\n      {\n        input: ['a', 'b', 'c'],\n        minLength: 2,\n        expected: [\n          ['a', 'b'],\n          ['a', 'c'],\n          ['b', 'c'],\n          ['a', 'b', 'c'],\n        ],\n      },\n      {\n        input: ['a', 'b'],\n        expected: [['a', 'b']],\n        minLength: 2,\n      },\n      {\n        input: ['a'],\n        expected: [],\n        minLength: 2,\n      },\n      {\n        input: ['a'],\n        expected: [['a']],\n        minLength: 1,\n      },\n      {\n        input: ['a'],\n        expected: [[], ['a']],\n        minLength: 0,\n      },\n    ]\n    test.each(testCases)(\n      '$input $minLength $expected',\n      ({ input, minLength, expected }) => {\n        const combinations = generatePartialCombinations(input, minLength)\n        expectArrayEqualIgnoreOrder(combinations, expected)\n      },\n    )\n  })\n\n  describe('generateInterleavedCombinations', () => {\n    const testCases = [\n      {\n        data: ['a', 'b'],\n        additional: ['x'],\n        expected: [\n          ['a', 'b'],\n          ['x', 'a', 'b'],\n          ['a', 'x', 'b'],\n          ['a', 'b', 'x'],\n        ],\n      },\n    ]\n    test.each(testCases)(\n      '$input $expected',\n      ({ data, additional, expected }) => {\n        const combinations = generateInterleavedCombinations(data, additional)\n        expectArrayEqualIgnoreOrder(combinations, expected)\n      },\n    )\n  })\n})\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/__tests__/test-utils.ts",
    "content": "import { expect } from 'vitest'\n\nexport function normalizeIndent(template: TemplateStringsArray) {\n  const codeLines = template[0]?.split('\\n') ?? ['']\n  const leftPadding = codeLines[1]?.match(/\\s+/)?.[0] ?? ''\n  return codeLines.map((line) => line.slice(leftPadding.length)).join('\\n')\n}\n\nexport function generatePermutations<T>(arr: Array<T>): Array<Array<T>> {\n  if (arr.length <= 1) {\n    return [arr]\n  }\n\n  const result: Array<Array<T>> = []\n  for (let i = 0; i < arr.length; i++) {\n    const rest = arr.slice(0, i).concat(arr.slice(i + 1))\n    const restPermutations = generatePermutations(rest)\n    for (const perm of restPermutations) {\n      result.push([arr[i]!, ...perm])\n    }\n  }\n\n  return result\n}\n\nexport function generatePartialCombinations<T>(\n  arr: ReadonlyArray<T>,\n  minLength: number,\n): Array<Array<T>> {\n  const result: Array<Array<T>> = []\n\n  function backtrack(start: number, current: Array<T>) {\n    if (current.length > minLength - 1) {\n      result.push([...current])\n    }\n    for (let i = start; i < arr.length; i++) {\n      current.push(arr[i]!)\n      backtrack(i + 1, current)\n      current.pop()\n    }\n  }\n  backtrack(0, [])\n  return result\n}\n\nexport function expectArrayEqualIgnoreOrder<T>(a: Array<T>, b: Array<T>) {\n  expect([...a].sort()).toEqual([...b].sort())\n}\n\nexport function generateInterleavedCombinations<\n  TData,\n  TAdditional,\n  TResult extends TData | TAdditional,\n>(\n  data: Array<TData> | ReadonlyArray<TData>,\n  additional: Array<TAdditional> | ReadonlyArray<TAdditional>,\n): Array<Array<TResult>> {\n  const result: Array<Array<TResult>> = []\n\n  function getSubsets(array: Array<TAdditional>): Array<Array<TAdditional>> {\n    return array.reduce(\n      (subsets, value) => {\n        return subsets.concat(subsets.map((set) => [...set, value]))\n      },\n      [[]] as Array<Array<TAdditional>>,\n    )\n  }\n\n  function insertAtPositions(\n    baseData: Array<TResult>,\n    subset: Array<TResult>,\n  ): Array<Array<TResult>> {\n    const combinations: Array<Array<TResult>> = []\n\n    const recurse = (\n      currentData: Array<TResult>,\n      currentSubset: Array<TResult>,\n      start: number,\n    ): void => {\n      if (currentSubset.length === 0) {\n        combinations.push([...currentData])\n        return\n      }\n\n      for (let i = start; i <= currentData.length; i++) {\n        const newData = [\n          ...currentData.slice(0, i),\n          currentSubset[0]!,\n          ...currentData.slice(i),\n        ]\n        recurse(newData, currentSubset.slice(1), i + 1)\n      }\n    }\n\n    recurse(baseData, subset, 0)\n    return combinations\n  }\n\n  const subsets = getSubsets(additional as Array<TAdditional>)\n\n  subsets.forEach((subset) => {\n    result.push(\n      ...insertAtPositions(data as Array<TResult>, subset as Array<TResult>),\n    )\n  })\n\n  return result\n}\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/__tests__/ts-fixture/file.ts",
    "content": "// File needs to exists\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/__tests__/ts-fixture/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ESNext\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"strict\": true,\n    \"skipLibCheck\": true\n  },\n  \"include\": [\"**/*\"]\n}\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/index.ts",
    "content": "import { rules } from './rules'\nimport type { ESLint, Linter } from 'eslint'\nimport type { RuleModule } from '@typescript-eslint/utils/ts-eslint'\n\ntype RuleKey = keyof typeof rules\n\nexport interface Plugin extends Omit<ESLint.Plugin, 'rules'> {\n  rules: Record<RuleKey, RuleModule<any, any, any>>\n  configs: {\n    recommended: ESLint.ConfigData\n    'flat/recommended': Array<Linter.Config>\n  }\n}\n\nexport const plugin = {\n  meta: {\n    name: '@tanstack/eslint-plugin-query',\n  },\n  configs: {\n    recommended: {\n      plugins: ['@tanstack/query'],\n      rules: {\n        '@tanstack/query/exhaustive-deps': 'error',\n        '@tanstack/query/no-rest-destructuring': 'warn',\n        '@tanstack/query/stable-query-client': 'error',\n        '@tanstack/query/no-unstable-deps': 'error',\n        '@tanstack/query/infinite-query-property-order': 'error',\n        '@tanstack/query/no-void-query-fn': 'error',\n        '@tanstack/query/mutation-property-order': 'error',\n      },\n    },\n    'flat/recommended': [\n      {\n        name: 'tanstack/query/flat/recommended',\n        plugins: {\n          '@tanstack/query': {}, // Assigned after plugin object created\n        },\n        rules: {\n          '@tanstack/query/exhaustive-deps': 'error',\n          '@tanstack/query/no-rest-destructuring': 'warn',\n          '@tanstack/query/stable-query-client': 'error',\n          '@tanstack/query/no-unstable-deps': 'error',\n          '@tanstack/query/infinite-query-property-order': 'error',\n          '@tanstack/query/no-void-query-fn': 'error',\n          '@tanstack/query/mutation-property-order': 'error',\n        },\n      },\n    ],\n  },\n  rules,\n} satisfies Plugin\n\nplugin.configs['flat/recommended'][0]!.plugins['@tanstack/query'] = plugin\n\nexport default plugin\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.rule.ts",
    "content": "import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils'\nimport { ASTUtils } from '../../utils/ast-utils'\nimport { getDocsUrl } from '../../utils/get-docs-url'\nimport { uniqueBy } from '../../utils/unique-by'\nimport { detectTanstackQueryImports } from '../../utils/detect-react-query-imports'\nimport { ExhaustiveDepsUtils } from './exhaustive-deps.utils'\nimport type { TSESLint, TSESTree } from '@typescript-eslint/utils'\nimport type { ExtraRuleDocs } from '../../types'\n\nconst QUERY_KEY = 'queryKey'\nconst QUERY_FN = 'queryFn'\n\nexport const name = 'exhaustive-deps'\n\nconst createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)\n\nexport const rule = createRule({\n  name,\n  meta: {\n    type: 'problem',\n    docs: {\n      description: 'Exhaustive deps rule for useQuery',\n      recommended: 'error',\n    },\n    messages: {\n      missingDeps: `The following dependencies are missing in your queryKey: {{deps}}`,\n      fixTo: 'Fix to {{result}}',\n    },\n    hasSuggestions: true,\n    fixable: 'code',\n    schema: [],\n  },\n  defaultOptions: [],\n\n  create: detectTanstackQueryImports((context) => {\n    return {\n      Property: (node) => {\n        if (\n          !ASTUtils.isObjectExpression(node.parent) ||\n          !ASTUtils.isIdentifierWithName(node.key, QUERY_KEY)\n        ) {\n          return\n        }\n\n        const scopeManager = context.sourceCode.scopeManager\n        const queryKey = ASTUtils.findPropertyWithIdentifierKey(\n          node.parent.properties,\n          QUERY_KEY,\n        )\n        const queryFn = ASTUtils.findPropertyWithIdentifierKey(\n          node.parent.properties,\n          QUERY_FN,\n        )\n\n        if (\n          scopeManager === null ||\n          queryKey === undefined ||\n          queryFn === undefined ||\n          !ASTUtils.isNodeOfOneOf(queryFn.value, [\n            AST_NODE_TYPES.ArrowFunctionExpression,\n            AST_NODE_TYPES.FunctionExpression,\n            AST_NODE_TYPES.ConditionalExpression,\n          ])\n        ) {\n          return\n        }\n\n        const queryKeyNode = dereferenceVariablesAndTypeAssertions(\n          queryKey.value,\n          context,\n        )\n\n        const externalRefs = ASTUtils.getExternalRefs({\n          scopeManager,\n          sourceCode: context.sourceCode,\n          node: getQueryFnRelevantNode(queryFn),\n        })\n\n        const relevantRefs = externalRefs.filter((reference) =>\n          ExhaustiveDepsUtils.isRelevantReference({\n            sourceCode: context.sourceCode,\n            reference,\n            scopeManager,\n            node: getQueryFnRelevantNode(queryFn),\n            filename: context.filename,\n          }),\n        )\n\n        const queryKeyDeps = ExhaustiveDepsUtils.collectQueryKeyDeps({\n          sourceCode: context.sourceCode,\n          scopeManager,\n          queryKeyNode,\n        })\n\n        const missingRefs = relevantRefs\n          .map((ref) => ({\n            ref: ref,\n            text: ASTUtils.isAncestorIsCallee(ref.identifier)\n              ? ref.identifier.name\n              : ASTUtils.mapKeyNodeToBaseText(\n                  ref.identifier,\n                  context.sourceCode,\n                ),\n          }))\n          .filter(({ ref, text }) => {\n            return (\n              !ref.isTypeReference &&\n              !queryKeyDeps.has(text) &&\n              !queryKeyDeps.has(text.split(/[?.]/)[0] ?? '')\n            )\n          })\n          .map(({ ref, text }) => ({\n            identifier: ref.identifier,\n            text: text,\n          }))\n\n        const uniqueMissingRefs = uniqueBy(missingRefs, (x) => x.text)\n\n        if (uniqueMissingRefs.length > 0) {\n          const missingAsText = uniqueMissingRefs\n            .map((ref) => ref.text)\n            .join(', ')\n\n          const queryKeyValue = context.sourceCode.getText(queryKeyNode)\n\n          const existingWithMissing =\n            queryKeyValue === '[]'\n              ? `[${missingAsText}]`\n              : queryKeyValue.replace(/\\]$/, `, ${missingAsText}]`)\n\n          const suggestions: TSESLint.ReportSuggestionArray<string> = []\n\n          if (queryKeyNode.type === AST_NODE_TYPES.ArrayExpression) {\n            suggestions.push({\n              messageId: 'fixTo',\n              data: { result: existingWithMissing },\n              fix(fixer) {\n                return fixer.replaceText(queryKeyNode, existingWithMissing)\n              },\n            })\n          }\n\n          context.report({\n            node: node,\n            messageId: 'missingDeps',\n            data: {\n              deps: uniqueMissingRefs.map((ref) => ref.text).join(', '),\n            },\n            suggest: suggestions,\n          })\n        }\n      },\n    }\n  }),\n})\n\nfunction getQueryFnRelevantNode(queryFn: TSESTree.Property) {\n  if (queryFn.value.type !== AST_NODE_TYPES.ConditionalExpression) {\n    return queryFn.value\n  }\n\n  if (\n    queryFn.value.consequent.type === AST_NODE_TYPES.Identifier &&\n    queryFn.value.consequent.name === 'skipToken'\n  ) {\n    return queryFn.value.alternate\n  }\n\n  return queryFn.value.consequent\n}\n\nfunction dereferenceVariablesAndTypeAssertions(\n  queryKeyNode: TSESTree.Node,\n  context: Readonly<TSESLint.RuleContext<string, ReadonlyArray<unknown>>>,\n) {\n  const visitedNodes = new Set<TSESTree.Node>()\n\n  for (let i = 0; i < 1 << 8; ++i) {\n    if (visitedNodes.has(queryKeyNode)) {\n      return queryKeyNode\n    }\n    visitedNodes.add(queryKeyNode)\n\n    switch (queryKeyNode.type) {\n      case AST_NODE_TYPES.TSAsExpression:\n        queryKeyNode = queryKeyNode.expression\n        break\n      case AST_NODE_TYPES.Identifier: {\n        const expression = ASTUtils.getReferencedExpressionByIdentifier({\n          context,\n          node: queryKeyNode,\n        })\n\n        if (expression == null) {\n          return queryKeyNode\n        }\n        queryKeyNode = expression\n        break\n      }\n      default:\n        return queryKeyNode\n    }\n  }\n  return queryKeyNode\n}\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.utils.ts",
    "content": "import { AST_NODE_TYPES } from '@typescript-eslint/utils'\nimport { ASTUtils } from '../../utils/ast-utils'\nimport type { TSESLint, TSESTree } from '@typescript-eslint/utils'\n\nexport const ExhaustiveDepsUtils = {\n  isRelevantReference(params: {\n    sourceCode: Readonly<TSESLint.SourceCode>\n    reference: TSESLint.Scope.Reference\n    scopeManager: TSESLint.Scope.ScopeManager\n    node: TSESTree.Node\n    filename: string\n  }) {\n    const { sourceCode, reference, scopeManager, node, filename } = params\n    const component = ASTUtils.getFunctionAncestor(sourceCode, node)\n    const queryFnScope = scopeManager.acquire(node)\n\n    if (queryFnScope === null) {\n      return false\n    }\n\n    let currentScope = reference.resolved?.scope ?? null\n    while (currentScope !== null) {\n      if (currentScope === queryFnScope) {\n        return false\n      }\n\n      currentScope = currentScope.upper\n    }\n\n    if (component !== undefined) {\n      if (\n        !ASTUtils.isDeclaredInNode({\n          scopeManager,\n          reference,\n          functionNode: component,\n        })\n      ) {\n        return false\n      }\n    } else {\n      const isVueFile = filename.endsWith('.vue')\n\n      if (!isVueFile) {\n        return false\n      }\n\n      const definition = reference.resolved?.defs[0]\n      const isGlobalVariable = definition === undefined\n      const isImport = definition?.type === 'ImportBinding'\n\n      if (isGlobalVariable || isImport) {\n        return false\n      }\n    }\n\n    return (\n      reference.identifier.name !== 'undefined' &&\n      reference.identifier.parent.type !== AST_NODE_TYPES.NewExpression &&\n      !ExhaustiveDepsUtils.isInstanceOfKind(reference.identifier.parent)\n    )\n  },\n  isInstanceOfKind(node: TSESTree.Node) {\n    return (\n      node.type === AST_NODE_TYPES.BinaryExpression &&\n      node.operator === 'instanceof'\n    )\n  },\n\n  collectQueryKeyDeps(params: {\n    sourceCode: Readonly<TSESLint.SourceCode>\n    scopeManager: TSESLint.Scope.ScopeManager\n    queryKeyNode: TSESTree.Node\n  }): Set<string> {\n    const { sourceCode, scopeManager, queryKeyNode } = params\n    const deps = new Set<string>()\n    const visitorKeys = sourceCode.visitorKeys\n\n    function add(identifier: TSESTree.Identifier) {\n      deps.add(ASTUtils.mapKeyNodeToBaseText(identifier, sourceCode))\n    }\n\n    function visitChildren(node: TSESTree.Node): void {\n      const keys = (visitorKeys[node.type] ?? []) as ReadonlyArray<\n        keyof TSESTree.Node\n      >\n\n      for (const key of keys) {\n        const value = node[key]\n\n        if (Array.isArray(value)) {\n          for (const item of value) {\n            if (ExhaustiveDepsUtils.isNode(item)) {\n              visit(item)\n            }\n          }\n          continue\n        }\n\n        if (ExhaustiveDepsUtils.isNode(value)) {\n          visit(value)\n        }\n      }\n    }\n\n    function visit(node: TSESTree.Node | null | undefined): void {\n      if (!node) return\n\n      switch (node.type) {\n        case AST_NODE_TYPES.Identifier:\n          add(node)\n          return\n        case AST_NODE_TYPES.ArrowFunctionExpression:\n        case AST_NODE_TYPES.FunctionExpression:\n          for (const reference of ExhaustiveDepsUtils.collectExternalRefsInFunction(\n            {\n              functionNode: node,\n              scopeManager: scopeManager,\n            },\n          )) {\n            if (reference.identifier.type === AST_NODE_TYPES.Identifier) {\n              add(reference.identifier)\n            }\n          }\n          return\n        case AST_NODE_TYPES.Property:\n          visit(node.value)\n          return\n        case AST_NODE_TYPES.MemberExpression:\n          if (\n            node.parent.type === AST_NODE_TYPES.CallExpression &&\n            node.parent.callee === node &&\n            node.object.type === AST_NODE_TYPES.Identifier\n          ) {\n            deps.add(node.object.name)\n          } else {\n            visit(node.object)\n          }\n          return\n        case AST_NODE_TYPES.CallExpression:\n          node.arguments.forEach((argument) => visit(argument))\n          if (\n            node.callee.type === AST_NODE_TYPES.MemberExpression ||\n            node.callee.type === AST_NODE_TYPES.ChainExpression ||\n            node.callee.type === AST_NODE_TYPES.TSNonNullExpression\n          ) {\n            visit(node.callee)\n          }\n          return\n      }\n\n      visitChildren(node)\n    }\n\n    visit(queryKeyNode)\n\n    return deps\n  },\n\n  isNode(value: unknown): value is TSESTree.Node {\n    return (\n      typeof value === 'object' &&\n      value !== null &&\n      'type' in value &&\n      typeof value.type === 'string'\n    )\n  },\n\n  collectExternalRefsInFunction(params: {\n    functionNode: TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression\n    scopeManager: TSESLint.Scope.ScopeManager\n  }): Array<TSESLint.Scope.Reference> {\n    const { functionNode, scopeManager } = params\n    const functionScope = scopeManager.acquire(functionNode)\n\n    if (functionScope === null) {\n      return []\n    }\n\n    const externalRefs: Array<TSESLint.Scope.Reference> = []\n\n    function collect(scope: TSESLint.Scope.Scope) {\n      for (const reference of scope.references) {\n        if (!reference.isRead() || reference.resolved === null) {\n          continue\n        }\n\n        let currentScope: TSESLint.Scope.Scope | null = reference.resolved.scope\n        let declaredInsideFunction = false\n\n        while (currentScope !== null) {\n          if (currentScope === functionScope) {\n            declaredInsideFunction = true\n            break\n          }\n\n          currentScope = currentScope.upper\n        }\n\n        if (!declaredInsideFunction) {\n          externalRefs.push(reference)\n        }\n      }\n\n      for (const childScope of scope.childScopes) {\n        collect(childScope)\n      }\n    }\n\n    collect(functionScope)\n\n    return externalRefs\n  },\n}\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/rules/infinite-query-property-order/constants.ts",
    "content": "export const infiniteQueryFunctions = [\n  'infiniteQueryOptions',\n  'useInfiniteQuery',\n  'useSuspenseInfiniteQuery',\n] as const\n\nexport type InfiniteQueryFunctions = (typeof infiniteQueryFunctions)[number]\n\nexport const checkedProperties = [\n  'queryFn',\n  'getPreviousPageParam',\n  'getNextPageParam',\n] as const\n\nexport type InfiniteQueryProperties = (typeof checkedProperties)[number]\n\nexport const sortRules = [\n  [['queryFn'], ['getPreviousPageParam', 'getNextPageParam']],\n] as const\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/rules/infinite-query-property-order/infinite-query-property-order.rule.ts",
    "content": "import { createPropertyOrderRule } from '../../utils/create-property-order-rule'\nimport { infiniteQueryFunctions, sortRules } from './constants'\nimport type {\n  InfiniteQueryFunctions,\n  InfiniteQueryProperties,\n} from './constants'\n\nexport const name = 'infinite-query-property-order'\n\nexport const rule = createPropertyOrderRule<\n  InfiniteQueryFunctions,\n  InfiniteQueryProperties\n>(\n  {\n    name,\n    meta: {\n      type: 'problem',\n      docs: {\n        description:\n          'Ensure correct order of inference sensitive properties for infinite queries',\n        recommended: 'error',\n      },\n      messages: {\n        invalidOrder: 'Invalid order of properties for `{{function}}`.',\n      },\n      schema: [],\n      hasSuggestions: true,\n      fixable: 'code',\n    },\n    defaultOptions: [],\n  },\n  infiniteQueryFunctions,\n  sortRules,\n)\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/rules/mutation-property-order/constants.ts",
    "content": "export const mutationFunctions = ['useMutation'] as const\n\nexport type MutationFunctions = (typeof mutationFunctions)[number]\n\nexport const checkedProperties = ['onMutate', 'onError', 'onSettled'] as const\n\nexport type MutationProperties = (typeof checkedProperties)[number]\n\nexport const sortRules = [[['onMutate'], ['onError', 'onSettled']]] as const\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/rules/mutation-property-order/mutation-property-order.rule.ts",
    "content": "import { createPropertyOrderRule } from '../../utils/create-property-order-rule'\nimport { mutationFunctions, sortRules } from './constants'\nimport type { MutationFunctions, MutationProperties } from './constants'\n\nexport const name = 'mutation-property-order'\n\nexport const rule = createPropertyOrderRule<\n  MutationFunctions,\n  MutationProperties\n>(\n  {\n    name,\n    meta: {\n      type: 'problem',\n      docs: {\n        description:\n          'Ensure correct order of inference-sensitive properties in useMutation()',\n        recommended: 'error',\n      },\n      messages: {\n        invalidOrder: 'Invalid order of properties for `{{function}}`.',\n      },\n      schema: [],\n      hasSuggestions: true,\n      fixable: 'code',\n    },\n    defaultOptions: [],\n  },\n  mutationFunctions,\n  sortRules,\n)\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/rules/no-rest-destructuring/no-rest-destructuring.rule.ts",
    "content": "import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils'\nimport { getDocsUrl } from '../../utils/get-docs-url'\nimport { ASTUtils } from '../../utils/ast-utils'\nimport { detectTanstackQueryImports } from '../../utils/detect-react-query-imports'\nimport { NoRestDestructuringUtils } from './no-rest-destructuring.utils'\nimport type { ExtraRuleDocs } from '../../types'\n\nexport const name = 'no-rest-destructuring'\n\nconst queryHooks = [\n  'useQuery',\n  'useQueries',\n  'useInfiniteQuery',\n  'useSuspenseQuery',\n  'useSuspenseQueries',\n  'useSuspenseInfiniteQuery',\n]\n\nconst createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)\n\nexport const rule = createRule({\n  name,\n  meta: {\n    type: 'problem',\n    docs: {\n      description: 'Disallows rest destructuring in queries',\n      recommended: 'warn',\n    },\n    messages: {\n      objectRestDestructure: `Object rest destructuring on a query will observe all changes to the query, leading to excessive re-renders.`,\n    },\n    schema: [],\n  },\n  defaultOptions: [],\n\n  create: detectTanstackQueryImports((context, _, helpers) => {\n    const queryResultVariables = new Set<string>()\n\n    return {\n      CallExpression: (node) => {\n        if (\n          !ASTUtils.isIdentifierWithOneOfNames(node.callee, queryHooks) ||\n          node.parent.type !== AST_NODE_TYPES.VariableDeclarator ||\n          !helpers.isTanstackQueryImport(node.callee)\n        ) {\n          return\n        }\n\n        const returnValue = node.parent.id\n\n        if (\n          node.callee.name !== 'useQueries' &&\n          node.callee.name !== 'useSuspenseQueries'\n        ) {\n          if (NoRestDestructuringUtils.isObjectRestDestructuring(returnValue)) {\n            return context.report({\n              node: node.parent,\n              messageId: 'objectRestDestructure',\n            })\n          }\n\n          if (returnValue.type === AST_NODE_TYPES.Identifier) {\n            queryResultVariables.add(returnValue.name)\n          }\n\n          return\n        }\n\n        if (returnValue.type !== AST_NODE_TYPES.ArrayPattern) {\n          if (returnValue.type === AST_NODE_TYPES.Identifier) {\n            queryResultVariables.add(returnValue.name)\n          }\n          return\n        }\n\n        returnValue.elements.forEach((queryResult) => {\n          if (queryResult === null) {\n            return\n          }\n          if (NoRestDestructuringUtils.isObjectRestDestructuring(queryResult)) {\n            context.report({\n              node: queryResult,\n              messageId: 'objectRestDestructure',\n            })\n          }\n        })\n      },\n\n      VariableDeclarator: (node) => {\n        if (\n          node.init?.type === AST_NODE_TYPES.Identifier &&\n          queryResultVariables.has(node.init.name) &&\n          NoRestDestructuringUtils.isObjectRestDestructuring(node.id)\n        ) {\n          context.report({\n            node,\n            messageId: 'objectRestDestructure',\n          })\n        }\n      },\n\n      SpreadElement: (node) => {\n        if (\n          node.argument.type === AST_NODE_TYPES.Identifier &&\n          queryResultVariables.has(node.argument.name)\n        ) {\n          context.report({\n            node,\n            messageId: 'objectRestDestructure',\n          })\n        }\n      },\n    }\n  }),\n})\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/rules/no-rest-destructuring/no-rest-destructuring.utils.ts",
    "content": "import { AST_NODE_TYPES } from '@typescript-eslint/utils'\nimport type { TSESTree } from '@typescript-eslint/utils'\n\nexport const NoRestDestructuringUtils = {\n  isObjectRestDestructuring(node: TSESTree.Node): boolean {\n    if (node.type !== AST_NODE_TYPES.ObjectPattern) {\n      return false\n    }\n    return node.properties.some((p) => p.type === AST_NODE_TYPES.RestElement)\n  },\n}\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/rules/no-unstable-deps/no-unstable-deps.rule.ts",
    "content": "import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils'\nimport { getDocsUrl } from '../../utils/get-docs-url'\nimport { detectTanstackQueryImports } from '../../utils/detect-react-query-imports'\nimport type { TSESTree } from '@typescript-eslint/utils'\nimport type { ExtraRuleDocs } from '../../types'\n\nexport const name = 'no-unstable-deps'\n\nexport const reactHookNames = ['useEffect', 'useCallback', 'useMemo']\nexport const useQueryHookNames = [\n  'useQuery',\n  'useSuspenseQuery',\n  'useQueries',\n  'useSuspenseQueries',\n  'useInfiniteQuery',\n  'useSuspenseInfiniteQuery',\n]\nconst allHookNames = ['useMutation', ...useQueryHookNames]\nconst createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)\n\nexport const rule = createRule({\n  name,\n  meta: {\n    type: 'problem',\n    docs: {\n      description:\n        'Disallow putting the result of query hooks directly in a React hook dependency array',\n      recommended: 'error',\n    },\n    messages: {\n      noUnstableDeps: `The result of {{queryHook}} is not referentially stable, so don't pass it directly into the dependencies array of {{reactHook}}. Instead, destructure the return value of {{queryHook}} and pass the destructured values into the dependency array of {{reactHook}}.`,\n    },\n    schema: [],\n  },\n  defaultOptions: [],\n\n  create: detectTanstackQueryImports((context, _options, helpers) => {\n    const trackedVariables: Record<string, string> = {}\n    const hookAliasMap: Record<string, string> = {}\n\n    function getReactHook(node: TSESTree.CallExpression): string | undefined {\n      if (node.callee.type === 'Identifier') {\n        const calleeName = node.callee.name\n        // Check if the identifier is a known React hook or an alias\n        if (reactHookNames.includes(calleeName) || calleeName in hookAliasMap) {\n          return calleeName\n        }\n      } else if (\n        node.callee.type === 'MemberExpression' &&\n        node.callee.object.type === 'Identifier' &&\n        node.callee.object.name === 'React' &&\n        node.callee.property.type === 'Identifier' &&\n        reactHookNames.includes(node.callee.property.name)\n      ) {\n        // Member expression case: `React.useCallback`\n        return node.callee.property.name\n      }\n      return undefined\n    }\n\n    function collectVariableNames(\n      pattern: TSESTree.BindingName,\n      queryHook: string,\n    ) {\n      if (pattern.type === AST_NODE_TYPES.Identifier) {\n        trackedVariables[pattern.name] = queryHook\n      }\n    }\n\n    function hasCombineProperty(\n      callExpression: TSESTree.CallExpression,\n    ): boolean {\n      if (callExpression.arguments.length === 0) return false\n\n      const firstArg = callExpression.arguments[0]\n      if (!firstArg || firstArg.type !== AST_NODE_TYPES.ObjectExpression)\n        return false\n\n      return firstArg.properties.some(\n        (prop) =>\n          prop.type === AST_NODE_TYPES.Property &&\n          prop.key.type === AST_NODE_TYPES.Identifier &&\n          prop.key.name === 'combine',\n      )\n    }\n\n    return {\n      ImportDeclaration(node: TSESTree.ImportDeclaration) {\n        if (\n          node.specifiers.length > 0 &&\n          node.importKind === 'value' &&\n          node.source.value === 'React'\n        ) {\n          node.specifiers.forEach((specifier) => {\n            if (\n              specifier.type === AST_NODE_TYPES.ImportSpecifier &&\n              specifier.imported.type === AST_NODE_TYPES.Identifier &&\n              reactHookNames.includes(specifier.imported.name)\n            ) {\n              // Track alias or direct import\n              hookAliasMap[specifier.local.name] = specifier.imported.name\n            }\n          })\n        }\n      },\n\n      VariableDeclarator(node) {\n        if (\n          node.init !== null &&\n          node.init.type === AST_NODE_TYPES.CallExpression &&\n          node.init.callee.type === AST_NODE_TYPES.Identifier &&\n          allHookNames.includes(node.init.callee.name) &&\n          helpers.isTanstackQueryImport(node.init.callee)\n        ) {\n          // Special case for useQueries with combine property - it's stable\n          if (\n            node.init.callee.name === 'useQueries' &&\n            hasCombineProperty(node.init)\n          ) {\n            // Don't track useQueries with combine as unstable\n            return\n          }\n          collectVariableNames(node.id, node.init.callee.name)\n        }\n      },\n      CallExpression: (node) => {\n        const reactHook = getReactHook(node)\n        if (\n          reactHook !== undefined &&\n          node.arguments.length > 1 &&\n          node.arguments[1]?.type === AST_NODE_TYPES.ArrayExpression\n        ) {\n          const depsArray = node.arguments[1].elements\n          depsArray.forEach((dep) => {\n            if (\n              dep !== null &&\n              dep.type === AST_NODE_TYPES.Identifier &&\n              trackedVariables[dep.name] !== undefined\n            ) {\n              const queryHook = trackedVariables[dep.name]\n              context.report({\n                node: dep,\n                messageId: 'noUnstableDeps',\n                data: {\n                  queryHook,\n                  reactHook,\n                },\n              })\n            }\n          })\n        }\n      },\n    }\n  }),\n})\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/rules/no-void-query-fn/no-void-query-fn.rule.ts",
    "content": "import { ESLintUtils } from '@typescript-eslint/utils'\nimport { ASTUtils } from '../../utils/ast-utils'\nimport { detectTanstackQueryImports } from '../../utils/detect-react-query-imports'\nimport { getDocsUrl } from '../../utils/get-docs-url'\nimport type { ParserServicesWithTypeInformation } from '@typescript-eslint/utils'\nimport type { ExtraRuleDocs } from '../../types'\n\nconst TypeFlags = {\n  Void: 16384,\n  Undefined: 32768,\n} as const\n\nexport const name = 'no-void-query-fn'\n\nconst createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)\n\nexport const rule = createRule({\n  name,\n  meta: {\n    type: 'problem',\n    docs: {\n      description: 'Ensures queryFn returns a non-undefined value',\n      recommended: 'error',\n    },\n    messages: {\n      noVoidReturn: 'queryFn must return a non-undefined value',\n    },\n    schema: [],\n  },\n  defaultOptions: [],\n\n  create: detectTanstackQueryImports((context) => {\n    return {\n      Property(node) {\n        if (\n          !ASTUtils.isObjectExpression(node.parent) ||\n          !ASTUtils.isIdentifierWithName(node.key, 'queryFn')\n        ) {\n          return\n        }\n\n        const parserServices = context.sourceCode.parserServices\n\n        if (\n          !parserServices ||\n          !parserServices.esTreeNodeToTSNodeMap ||\n          !parserServices.program\n        ) {\n          return\n        }\n\n        const checker = parserServices.program.getTypeChecker()\n        const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node.value)\n        const type = checker.getTypeAtLocation(tsNode)\n\n        // Get the return type of the function\n        if (type.getCallSignatures().length > 0) {\n          const returnType = type.getCallSignatures()[0]?.getReturnType()\n\n          if (!returnType) {\n            return\n          }\n\n          // Check if return type is void or undefined\n          if (isIllegalReturn(checker, returnType)) {\n            context.report({\n              node: node.value,\n              messageId: 'noVoidReturn',\n            })\n          }\n        }\n      },\n    }\n  }),\n})\n\ntype Program = ParserServicesWithTypeInformation['program']\ntype TypeChecker = ReturnType<Program['getTypeChecker']>\ntype Type = ReturnType<TypeChecker['getTypeAtLocation']>\n\nfunction isIllegalReturn(checker: TypeChecker, type: Type): boolean {\n  const awaited = checker.getAwaitedType(type)\n\n  if (!awaited) return false\n\n  if (awaited.isUnion()) {\n    return awaited.types.some((t) => isIllegalReturn(checker, t))\n  }\n\n  return awaited.flags & (TypeFlags.Void | TypeFlags.Undefined) ? true : false\n}\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/rules/stable-query-client/stable-query-client.rule.ts",
    "content": "import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils'\nimport { ASTUtils } from '../../utils/ast-utils'\nimport { getDocsUrl } from '../../utils/get-docs-url'\nimport { detectTanstackQueryImports } from '../../utils/detect-react-query-imports'\nimport type { TSESLint } from '@typescript-eslint/utils'\nimport type { ExtraRuleDocs } from '../../types'\n\nexport const name = 'stable-query-client'\n\nconst createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)\n\nexport const rule = createRule({\n  name,\n  meta: {\n    type: 'problem',\n    docs: {\n      description: 'Makes sure that QueryClient is stable',\n      recommended: 'error',\n    },\n    messages: {\n      unstable: [\n        'QueryClient is not stable. It should be either extracted from the component or wrapped in React.useState.',\n        'See https://tkdodo.eu/blog/react-query-fa-qs#2-the-queryclient-is-not-stable',\n      ].join('\\n'),\n      fixTo: 'Fix to {{result}}',\n    },\n    hasSuggestions: true,\n    fixable: 'code',\n    schema: [],\n  },\n  defaultOptions: [],\n\n  create: detectTanstackQueryImports((context, _, helpers) => {\n    return {\n      NewExpression: (node) => {\n        if (\n          node.callee.type !== AST_NODE_TYPES.Identifier ||\n          node.callee.name !== 'QueryClient' ||\n          node.parent.type !== AST_NODE_TYPES.VariableDeclarator ||\n          !helpers.isSpecificTanstackQueryImport(\n            node.callee,\n            '@tanstack/react-query',\n          )\n        ) {\n          return\n        }\n\n        const fnAncestor = ASTUtils.getFunctionAncestor(\n          context.sourceCode,\n          node,\n        )\n        const isReactServerComponent = fnAncestor?.async === true\n\n        if (\n          !ASTUtils.isValidReactComponentOrHookName(fnAncestor?.id) ||\n          isReactServerComponent\n        ) {\n          return\n        }\n\n        context.report({\n          node: node.parent,\n          messageId: 'unstable',\n          fix: (() => {\n            const { parent } = node\n\n            if (parent.id.type !== AST_NODE_TYPES.Identifier) {\n              return\n            }\n\n            // we need the fallbacks for backwards compat with eslint < 8.37.0\n            // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n            const sourceCode = context.sourceCode ?? context.getSourceCode()\n            const nodeText = sourceCode.getText(node)\n            const variableName = parent.id.name\n\n            return (fixer: TSESLint.RuleFixer) => {\n              return fixer.replaceTextRange(\n                [parent.range[0], parent.range[1]],\n                `[${variableName}] = React.useState(() => ${nodeText})`,\n              )\n            }\n          })(),\n        })\n      },\n    }\n  }),\n})\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/rules.ts",
    "content": "import * as exhaustiveDeps from './rules/exhaustive-deps/exhaustive-deps.rule'\nimport * as stableQueryClient from './rules/stable-query-client/stable-query-client.rule'\nimport * as noRestDestructuring from './rules/no-rest-destructuring/no-rest-destructuring.rule'\nimport * as noUnstableDeps from './rules/no-unstable-deps/no-unstable-deps.rule'\nimport * as infiniteQueryPropertyOrder from './rules/infinite-query-property-order/infinite-query-property-order.rule'\nimport * as noVoidQueryFn from './rules/no-void-query-fn/no-void-query-fn.rule'\nimport * as mutationPropertyOrder from './rules/mutation-property-order/mutation-property-order.rule'\nimport type { ESLintUtils } from '@typescript-eslint/utils'\nimport type { ExtraRuleDocs } from './types'\n\nexport const rules: Record<\n  string,\n  ESLintUtils.RuleModule<\n    string,\n    ReadonlyArray<unknown>,\n    ExtraRuleDocs,\n    ESLintUtils.RuleListener\n  >\n> = {\n  [exhaustiveDeps.name]: exhaustiveDeps.rule,\n  [stableQueryClient.name]: stableQueryClient.rule,\n  [noRestDestructuring.name]: noRestDestructuring.rule,\n  [noUnstableDeps.name]: noUnstableDeps.rule,\n  [infiniteQueryPropertyOrder.name]: infiniteQueryPropertyOrder.rule,\n  [noVoidQueryFn.name]: noVoidQueryFn.rule,\n  [mutationPropertyOrder.name]: mutationPropertyOrder.rule,\n}\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/types.ts",
    "content": "export type ExtraRuleDocs = {\n  recommended: 'strict' | 'error' | 'warn'\n}\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/utils/ast-utils.ts",
    "content": "import { AST_NODE_TYPES } from '@typescript-eslint/utils'\nimport { uniqueBy } from './unique-by'\nimport type { TSESLint, TSESTree } from '@typescript-eslint/utils'\n\nexport const ASTUtils = {\n  isNodeOfOneOf<T extends AST_NODE_TYPES>(\n    node: TSESTree.Node,\n    types: ReadonlyArray<T>,\n  ): node is TSESTree.Node & { type: T } {\n    return types.includes(node.type as T)\n  },\n  isIdentifier(node: TSESTree.Node): node is TSESTree.Identifier {\n    return node.type === AST_NODE_TYPES.Identifier\n  },\n  isIdentifierWithName(\n    node: TSESTree.Node,\n    name: string,\n  ): node is TSESTree.Identifier {\n    return ASTUtils.isIdentifier(node) && node.name === name\n  },\n  isIdentifierWithOneOfNames<T extends Array<string>>(\n    node: TSESTree.Node,\n    name: T,\n  ): node is TSESTree.Identifier & { name: T[number] } {\n    return ASTUtils.isIdentifier(node) && name.includes(node.name)\n  },\n  isProperty(node: TSESTree.Node): node is TSESTree.Property {\n    return node.type === AST_NODE_TYPES.Property\n  },\n  isObjectExpression(node: TSESTree.Node): node is TSESTree.ObjectExpression {\n    return node.type === AST_NODE_TYPES.ObjectExpression\n  },\n  isPropertyWithIdentifierKey(\n    node: TSESTree.Node,\n    key: string,\n  ): node is TSESTree.Property {\n    return (\n      ASTUtils.isProperty(node) && ASTUtils.isIdentifierWithName(node.key, key)\n    )\n  },\n  findPropertyWithIdentifierKey(\n    properties: Array<TSESTree.ObjectLiteralElement>,\n    key: string,\n  ): TSESTree.Property | undefined {\n    // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n    return properties.find((x) =>\n      ASTUtils.isPropertyWithIdentifierKey(x, key),\n    ) as TSESTree.Property | undefined\n  },\n  getNestedIdentifiers(node: TSESTree.Node): Array<TSESTree.Identifier> {\n    const identifiers: Array<TSESTree.Identifier> = []\n\n    if (ASTUtils.isIdentifier(node)) {\n      identifiers.push(node)\n    }\n\n    if ('arguments' in node) {\n      node.arguments.forEach((x) => {\n        identifiers.push(...ASTUtils.getNestedIdentifiers(x))\n      })\n    }\n\n    if ('elements' in node) {\n      node.elements.forEach((x) => {\n        if (x !== null) {\n          identifiers.push(...ASTUtils.getNestedIdentifiers(x))\n        }\n      })\n    }\n\n    if ('properties' in node) {\n      node.properties.forEach((x) => {\n        identifiers.push(...ASTUtils.getNestedIdentifiers(x))\n      })\n    }\n\n    if ('expressions' in node) {\n      node.expressions.forEach((x) => {\n        identifiers.push(...ASTUtils.getNestedIdentifiers(x))\n      })\n    }\n\n    if ('left' in node) {\n      identifiers.push(...ASTUtils.getNestedIdentifiers(node.left))\n    }\n\n    if ('right' in node) {\n      identifiers.push(...ASTUtils.getNestedIdentifiers(node.right))\n    }\n\n    if (node.type === AST_NODE_TYPES.Property) {\n      identifiers.push(...ASTUtils.getNestedIdentifiers(node.value))\n    }\n\n    if (node.type === AST_NODE_TYPES.SpreadElement) {\n      identifiers.push(...ASTUtils.getNestedIdentifiers(node.argument))\n    }\n\n    if (node.type === AST_NODE_TYPES.MemberExpression) {\n      identifiers.push(...ASTUtils.getNestedIdentifiers(node.object))\n    }\n\n    if (node.type === AST_NODE_TYPES.UnaryExpression) {\n      identifiers.push(...ASTUtils.getNestedIdentifiers(node.argument))\n    }\n\n    if (node.type === AST_NODE_TYPES.ChainExpression) {\n      identifiers.push(...ASTUtils.getNestedIdentifiers(node.expression))\n    }\n\n    if (node.type === AST_NODE_TYPES.TSNonNullExpression) {\n      identifiers.push(...ASTUtils.getNestedIdentifiers(node.expression))\n    }\n\n    if (node.type === AST_NODE_TYPES.ArrowFunctionExpression) {\n      identifiers.push(...ASTUtils.getNestedIdentifiers(node.body))\n    }\n\n    if (node.type === AST_NODE_TYPES.FunctionExpression) {\n      identifiers.push(...ASTUtils.getNestedIdentifiers(node.body))\n    }\n\n    if (node.type === AST_NODE_TYPES.BlockStatement) {\n      identifiers.push(\n        ...node.body.map((body) => ASTUtils.getNestedIdentifiers(body)).flat(),\n      )\n    }\n\n    if (node.type === AST_NODE_TYPES.ReturnStatement && node.argument) {\n      identifiers.push(...ASTUtils.getNestedIdentifiers(node.argument))\n    }\n\n    return identifiers\n  },\n  isAncestorIsCallee(identifier: TSESTree.Node) {\n    let previousNode = identifier\n    let currentNode = identifier.parent\n\n    while (currentNode !== undefined) {\n      if (\n        currentNode.type === AST_NODE_TYPES.CallExpression &&\n        currentNode.callee === previousNode\n      ) {\n        return true\n      }\n\n      if (currentNode.type !== AST_NODE_TYPES.MemberExpression) {\n        return false\n      }\n\n      previousNode = currentNode\n      currentNode = currentNode.parent\n    }\n\n    return false\n  },\n  traverseUpOnly(\n    identifier: TSESTree.Node,\n    allowedNodeTypes: Array<AST_NODE_TYPES>,\n  ): TSESTree.Node {\n    const parent = identifier.parent\n\n    if (parent !== undefined && allowedNodeTypes.includes(parent.type)) {\n      return ASTUtils.traverseUpOnly(parent, allowedNodeTypes)\n    }\n\n    return identifier\n  },\n  isDeclaredInNode(params: {\n    functionNode: TSESTree.Node\n    reference: TSESLint.Scope.Reference\n    scopeManager: TSESLint.Scope.ScopeManager\n  }) {\n    const { functionNode, reference, scopeManager } = params\n    const scope = scopeManager.acquire(functionNode)\n\n    if (scope === null) {\n      return false\n    }\n\n    return scope.set.has(reference.identifier.name)\n  },\n  getExternalRefs(params: {\n    scopeManager: TSESLint.Scope.ScopeManager\n    sourceCode: Readonly<TSESLint.SourceCode>\n    node: TSESTree.Node\n  }): Array<TSESLint.Scope.Reference> {\n    const { scopeManager, sourceCode, node } = params\n    const scope = scopeManager.acquire(node)\n\n    if (scope === null) {\n      return []\n    }\n\n    const collectReferences = (\n      currentScope: TSESLint.Scope.Scope,\n    ): Array<TSESLint.Scope.Reference> => {\n      const references = [...currentScope.references]\n\n      for (const childScope of currentScope.childScopes) {\n        references.push(...collectReferences(childScope))\n      }\n\n      return references\n    }\n\n    const references = collectReferences(scope)\n      .filter((x) => x.isRead() && !scope.set.has(x.identifier.name))\n      .map((x) => {\n        const referenceNode = ASTUtils.traverseUpOnly(x.identifier, [\n          AST_NODE_TYPES.MemberExpression,\n          AST_NODE_TYPES.Identifier,\n        ])\n\n        return {\n          variable: x,\n          node: referenceNode,\n          text: sourceCode.getText(referenceNode),\n        }\n      })\n\n    const localRefIds = new Set(\n      [...scope.set.values()].map((x) => sourceCode.getText(x.identifiers[0])),\n    )\n\n    const externalRefs = references.filter(\n      (x) => x.variable.resolved === null || !localRefIds.has(x.text),\n    )\n\n    return uniqueBy(externalRefs, (x) => x.text).map((x) => x.variable)\n  },\n  mapKeyNodeToText(\n    node: TSESTree.Node,\n    sourceCode: Readonly<TSESLint.SourceCode>,\n  ) {\n    return sourceCode.getText(\n      ASTUtils.traverseUpOnly(node, [\n        AST_NODE_TYPES.MemberExpression,\n        AST_NODE_TYPES.TSNonNullExpression,\n        AST_NODE_TYPES.Identifier,\n      ]),\n    )\n  },\n  mapKeyNodeToBaseText(\n    node: TSESTree.Node,\n    sourceCode: Readonly<TSESLint.SourceCode>,\n  ) {\n    return ASTUtils.mapKeyNodeToText(node, sourceCode).replace(\n      /(?:\\?(\\.)|!)/g,\n      '$1',\n    )\n  },\n  isValidReactComponentOrHookName(\n    identifier: TSESTree.Identifier | null | undefined,\n  ) {\n    return (\n      identifier !== null &&\n      identifier !== undefined &&\n      /^(use|[A-Z])/.test(identifier.name)\n    )\n  },\n  getFunctionAncestor(\n    sourceCode: Readonly<TSESLint.SourceCode>,\n    node: TSESTree.Node,\n  ) {\n    for (const ancestor of sourceCode.getAncestors(node)) {\n      if (\n        ASTUtils.isNodeOfOneOf(ancestor, [\n          AST_NODE_TYPES.FunctionDeclaration,\n          AST_NODE_TYPES.FunctionExpression,\n          AST_NODE_TYPES.ArrowFunctionExpression,\n        ])\n      ) {\n        return ancestor\n      }\n\n      if (\n        ancestor.parent?.type === AST_NODE_TYPES.VariableDeclarator &&\n        ancestor.parent.id.type === AST_NODE_TYPES.Identifier &&\n        ASTUtils.isNodeOfOneOf(ancestor, [\n          AST_NODE_TYPES.FunctionDeclaration,\n          AST_NODE_TYPES.FunctionExpression,\n          AST_NODE_TYPES.ArrowFunctionExpression,\n        ])\n      ) {\n        return ancestor\n      }\n    }\n\n    return undefined\n  },\n  getReferencedExpressionByIdentifier(params: {\n    node: TSESTree.Node\n    context: Readonly<TSESLint.RuleContext<string, ReadonlyArray<unknown>>>\n  }) {\n    const { node, context } = params\n\n    // we need the fallbacks for backwards compat with eslint < 8.37.0\n    // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n    const sourceCode = context.sourceCode ?? context.getSourceCode()\n    // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n    const scope = context.sourceCode.getScope(node)\n      ? sourceCode.getScope(node)\n      : context.getScope()\n\n    const resolvedNode = scope.references.find((ref) => ref.identifier === node)\n      ?.resolved?.defs[0]?.node\n\n    if (resolvedNode?.type !== AST_NODE_TYPES.VariableDeclarator) {\n      return null\n    }\n\n    return resolvedNode.init\n  },\n  getClosestVariableDeclarator(node: TSESTree.Node) {\n    let currentNode: TSESTree.Node | undefined = node\n\n    while (currentNode.type !== AST_NODE_TYPES.Program) {\n      if (currentNode.type === AST_NODE_TYPES.VariableDeclarator) {\n        return currentNode\n      }\n\n      currentNode = currentNode.parent\n    }\n\n    return undefined\n  },\n  getNestedReturnStatements(\n    node: TSESTree.Node,\n  ): Array<TSESTree.ReturnStatement> {\n    const returnStatements: Array<TSESTree.ReturnStatement> = []\n\n    if (node.type === AST_NODE_TYPES.ReturnStatement) {\n      returnStatements.push(node)\n    }\n\n    if ('body' in node && node.body !== undefined && node.body !== null) {\n      Array.isArray(node.body)\n        ? node.body.forEach((x) => {\n            returnStatements.push(...ASTUtils.getNestedReturnStatements(x))\n          })\n        : returnStatements.push(\n            ...ASTUtils.getNestedReturnStatements(node.body),\n          )\n    }\n\n    if ('consequent' in node) {\n      Array.isArray(node.consequent)\n        ? node.consequent.forEach((x) => {\n            returnStatements.push(...ASTUtils.getNestedReturnStatements(x))\n          })\n        : returnStatements.push(\n            ...ASTUtils.getNestedReturnStatements(node.consequent),\n          )\n    }\n\n    if ('alternate' in node && node.alternate !== null) {\n      Array.isArray(node.alternate)\n        ? node.alternate.forEach((x) => {\n            returnStatements.push(...ASTUtils.getNestedReturnStatements(x))\n          })\n        : returnStatements.push(\n            ...ASTUtils.getNestedReturnStatements(node.alternate),\n          )\n    }\n\n    if ('cases' in node) {\n      node.cases.forEach((x) => {\n        returnStatements.push(...ASTUtils.getNestedReturnStatements(x))\n      })\n    }\n\n    if ('block' in node) {\n      returnStatements.push(...ASTUtils.getNestedReturnStatements(node.block))\n    }\n\n    if ('handler' in node && node.handler !== null) {\n      returnStatements.push(...ASTUtils.getNestedReturnStatements(node.handler))\n    }\n\n    if ('finalizer' in node && node.finalizer !== null) {\n      returnStatements.push(\n        ...ASTUtils.getNestedReturnStatements(node.finalizer),\n      )\n    }\n\n    if (\n      'expression' in node &&\n      node.expression !== true &&\n      node.expression !== false\n    ) {\n      returnStatements.push(\n        ...ASTUtils.getNestedReturnStatements(node.expression),\n      )\n    }\n\n    if ('test' in node && node.test !== null) {\n      returnStatements.push(...ASTUtils.getNestedReturnStatements(node.test))\n    }\n\n    return returnStatements\n  },\n}\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/utils/create-property-order-rule.ts",
    "content": "import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils'\n\nimport { getDocsUrl } from './get-docs-url'\nimport { detectTanstackQueryImports } from './detect-react-query-imports'\nimport { sortDataByOrder } from './sort-data-by-order'\nimport type { ExtraRuleDocs } from '../types'\n\nconst createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)\n\nexport function createPropertyOrderRule<\n  TFunc extends string,\n  TProp extends string,\n>(\n  options: Omit<Parameters<typeof createRule>[0], 'create'>,\n  targetFunctions: ReadonlyArray<TFunc> | Array<TFunc>,\n  orderRules: ReadonlyArray<\n    Readonly<[ReadonlyArray<TProp>, ReadonlyArray<TProp>]>\n  >,\n) {\n  const targetFunctionSet = new Set(targetFunctions)\n  function isTargetFunction(node: any): node is TFunc {\n    return targetFunctionSet.has(node)\n  }\n\n  return createRule({\n    ...options,\n    create: detectTanstackQueryImports((context) => {\n      return {\n        CallExpression(node) {\n          if (node.callee.type !== AST_NODE_TYPES.Identifier) {\n            return\n          }\n          const functions = node.callee.name\n          if (!isTargetFunction(functions)) {\n            return\n          }\n          const argument = node.arguments[0]\n          if (argument === undefined || argument.type !== 'ObjectExpression') {\n            return\n          }\n\n          const allProperties = argument.properties\n\n          // no need to sort if there is at max 1 property\n          if (allProperties.length < 2) {\n            return\n          }\n\n          const properties = allProperties.flatMap((p, index) => {\n            if (\n              p.type === AST_NODE_TYPES.Property &&\n              p.key.type === AST_NODE_TYPES.Identifier\n            ) {\n              return { name: p.key.name, property: p }\n            } else return { name: `_property_${index}`, property: p }\n          })\n\n          const sortedProperties = sortDataByOrder(\n            properties,\n            orderRules,\n            'name',\n          )\n          if (sortedProperties === null) {\n            return\n          }\n\n          context.report({\n            node: argument,\n            data: { function: node.callee.name },\n            messageId: 'invalidOrder',\n            fix(fixer) {\n              const sourceCode = context.sourceCode\n\n              const reorderedText = sortedProperties.reduce(\n                (sourceText, specifier, index) => {\n                  let textBetweenProperties = ''\n                  if (index < allProperties.length - 1) {\n                    textBetweenProperties = sourceCode\n                      .getText()\n                      .slice(\n                        allProperties[index]!.range[1],\n                        allProperties[index + 1]!.range[0],\n                      )\n                  }\n                  return (\n                    sourceText +\n                    sourceCode.getText(specifier.property) +\n                    textBetweenProperties\n                  )\n                },\n                '',\n              )\n              return fixer.replaceTextRange(\n                [allProperties[0]!.range[0], allProperties.at(-1)!.range[1]],\n                reorderedText,\n              )\n            },\n          })\n        },\n      }\n    }),\n  })\n}\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/utils/detect-react-query-imports.ts",
    "content": "import { TSESTree } from '@typescript-eslint/utils'\nimport type { ESLintUtils, TSESLint } from '@typescript-eslint/utils'\n\ntype Create = Parameters<\n  ReturnType<typeof ESLintUtils.RuleCreator>\n>[0]['create']\n\ntype Context = Parameters<Create>[0]\ntype Options = Parameters<Create>[1]\ntype Helpers = {\n  isSpecificTanstackQueryImport: (\n    node: TSESTree.Identifier,\n    source: string,\n  ) => boolean\n  isTanstackQueryImport: (node: TSESTree.Identifier) => boolean\n}\n\ntype EnhancedCreate = (\n  context: Context,\n  options: Options,\n  helpers: Helpers,\n) => ReturnType<Create>\n\nexport function detectTanstackQueryImports(create: EnhancedCreate): Create {\n  return (context, optionsWithDefault) => {\n    const tanstackQueryImportSpecifiers: Array<TSESTree.ImportClause> = []\n\n    const helpers: Helpers = {\n      isSpecificTanstackQueryImport(node, source) {\n        return !!tanstackQueryImportSpecifiers.find((specifier) => {\n          if (\n            specifier.type === TSESTree.AST_NODE_TYPES.ImportSpecifier &&\n            specifier.parent.type ===\n              TSESTree.AST_NODE_TYPES.ImportDeclaration &&\n            specifier.parent.source.value === source\n          ) {\n            return node.name === specifier.local.name\n          }\n\n          return false\n        })\n      },\n      isTanstackQueryImport(node) {\n        return !!tanstackQueryImportSpecifiers.find((specifier) => {\n          if (specifier.type === TSESTree.AST_NODE_TYPES.ImportSpecifier) {\n            return node.name === specifier.local.name\n          }\n\n          return false\n        })\n      },\n    }\n\n    const detectionInstructions: TSESLint.RuleListener = {\n      ImportDeclaration(node) {\n        if (\n          node.specifiers.length > 0 &&\n          // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n          (node.importKind === 'value' || node.importKind === undefined) &&\n          node.source.value.startsWith('@tanstack/') &&\n          node.source.value.endsWith('-query')\n        ) {\n          tanstackQueryImportSpecifiers.push(...node.specifiers)\n        }\n      },\n    }\n\n    // Call original rule definition\n    const ruleInstructions = create(context, optionsWithDefault, helpers)\n    const enhancedRuleInstructions: TSESLint.RuleListener = {}\n\n    const allKeys = new Set(\n      Object.keys(detectionInstructions).concat(Object.keys(ruleInstructions)),\n    )\n\n    // Iterate over ALL instructions keys so we can override original rule instructions\n    // to prevent their execution if conditions to report errors are not met.\n    allKeys.forEach((instruction) => {\n      enhancedRuleInstructions[instruction] = (node) => {\n        if (instruction in detectionInstructions) {\n          detectionInstructions[instruction]?.(node)\n        }\n\n        const ruleInstruction = ruleInstructions[instruction]\n\n        // TODO: canReportErrors()\n        if (ruleInstruction) {\n          return ruleInstruction(node)\n        }\n\n        return undefined\n      }\n    })\n\n    return enhancedRuleInstructions\n  }\n}\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/utils/get-docs-url.ts",
    "content": "export const getDocsUrl = (ruleName: string): string =>\n  `https://tanstack.com/query/latest/docs/eslint/${ruleName}`\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/utils/sort-data-by-order.ts",
    "content": "export function sortDataByOrder<T, TKey extends keyof T>(\n  data: Array<T> | ReadonlyArray<T>,\n  orderRules: ReadonlyArray<\n    Readonly<[ReadonlyArray<T[TKey]>, ReadonlyArray<T[TKey]>]>\n  >,\n  key: TKey,\n): Array<T> | null {\n  const getSubsetIndex = (\n    item: T[TKey],\n    subsets: ReadonlyArray<ReadonlyArray<T[TKey]> | Array<T[TKey]>>,\n  ): number | null => {\n    for (let i = 0; i < subsets.length; i++) {\n      if (subsets[i]?.includes(item)) {\n        return i\n      }\n    }\n    return null\n  }\n\n  const orderSets = orderRules.reduce(\n    (sets, [A, B]) => [...sets, A, B],\n    [] as Array<ReadonlyArray<T[TKey]> | Array<T[TKey]>>,\n  )\n\n  const inOrderArray = data.filter(\n    (item) => getSubsetIndex(item[key], orderSets) !== null,\n  )\n\n  let wasResorted = false as boolean\n\n  // Sort by the relative order defined by the rules\n  const sortedArray = inOrderArray.sort((a, b) => {\n    const aKey = a[key],\n      bKey = b[key]\n    const aSubsetIndex = getSubsetIndex(aKey, orderSets)\n    const bSubsetIndex = getSubsetIndex(bKey, orderSets)\n\n    // If both items belong to different subsets, sort by their subset order\n    if (\n      aSubsetIndex !== null &&\n      bSubsetIndex !== null &&\n      aSubsetIndex !== bSubsetIndex\n    ) {\n      return aSubsetIndex - bSubsetIndex\n    }\n\n    // If both items belong to the same subset or neither is in the subset, keep their relative order\n    return 0\n  })\n\n  const inOrderIterator = sortedArray.values()\n  const result = data.map((item) => {\n    if (getSubsetIndex(item[key], orderSets) !== null) {\n      const sortedItem = inOrderIterator.next().value!\n      if (sortedItem[key] !== item[key]) {\n        wasResorted = true\n      }\n      return sortedItem\n    }\n    return item\n  })\n\n  if (!wasResorted) {\n    return null\n  }\n  return result\n}\n"
  },
  {
    "path": "packages/eslint-plugin-query/src/utils/unique-by.ts",
    "content": "export function uniqueBy<T>(arr: Array<T>, fn: (x: T) => unknown): Array<T> {\n  return arr.filter((x, i, a) => a.findIndex((y) => fn(x) === fn(y)) === i)\n}\n"
  },
  {
    "path": "packages/eslint-plugin-query/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\"\n  },\n  \"include\": [\"src\", \"*.config.*\", \"package.json\"]\n}\n"
  },
  {
    "path": "packages/eslint-plugin-query/tsconfig.prod.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"incremental\": false,\n    \"composite\": false,\n    \"rootDir\": \"../../\"\n  }\n}\n"
  },
  {
    "path": "packages/eslint-plugin-query/tsup.config.ts",
    "content": "import { defineConfig } from 'tsup'\nimport { legacyConfig, modernConfig } from './root.tsup.config.js'\n\nexport default defineConfig([\n  modernConfig({ entry: ['src/*.ts'] }),\n  legacyConfig({ entry: ['src/*.ts'] }),\n])\n"
  },
  {
    "path": "packages/eslint-plugin-query/vite.config.ts",
    "content": "import { defineConfig, mergeConfig } from 'vitest/config'\nimport { tanstackViteConfig } from '@tanstack/vite-config'\n\nimport packageJson from './package.json'\n\nconst config = defineConfig({\n  // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660\n  resolve: {\n    conditions: ['@tanstack/custom-condition'],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        conditions: ['@tanstack/custom-condition'],\n      },\n    },\n  },\n  test: {\n    name: packageJson.name,\n    dir: './src',\n    watch: false,\n    globals: true,\n    coverage: {\n      enabled: true,\n      provider: 'istanbul',\n      include: ['src/**/*'],\n      exclude: ['src/__tests__/**'],\n    },\n    typecheck: { enabled: true },\n    restoreMocks: true,\n  },\n})\n\nexport default mergeConfig(\n  config,\n  tanstackViteConfig({\n    entry: './src/index.ts',\n    srcDir: './src',\n    exclude: ['./src/__tests__'],\n  }),\n)\n"
  },
  {
    "path": "packages/preact-query/CHANGELOG.md",
    "content": "# @tanstack/preact-query\n\n## 5.94.2\n\n### Patch Changes\n\n- fix(streamedQuery): maintain error state on reset refetch with initialData defined ([#10287](https://github.com/TanStack/query/pull/10287))\n\n- Updated dependencies [[`248975e`](https://github.com/TanStack/query/commit/248975e896f585f6eaa505c796e73fcf7bfd1eec)]:\n  - @tanstack/query-core@5.91.2\n\n## 5.94.1\n\n### Patch Changes\n\n- fix(core): cancel paused initial fetch when last observer unsubscribes ([#10291](https://github.com/TanStack/query/pull/10291))\n\n- Updated dependencies [[`a89aab9`](https://github.com/TanStack/query/commit/a89aab975581c25c113a26c8af486b4cafad272a)]:\n  - @tanstack/query-core@5.91.1\n\n## 5.94.0\n\n### Minor Changes\n\n- feat: environmentManager ([#10199](https://github.com/TanStack/query/pull/10199))\n\n### Patch Changes\n\n- Updated dependencies [[`6fa901b`](https://github.com/TanStack/query/commit/6fa901b97a22a80d0fca3f6ed86237ff0cbdd13b)]:\n  - @tanstack/query-core@5.91.0\n\n## 5.93.0\n\n### Minor Changes\n\n- feat: Add preact persist plugin ([#10120](https://github.com/TanStack/query/pull/10120))\n\n## 5.92.0\n\n### Minor Changes\n\n- feat: Add preact query devtools ([#10119](https://github.com/TanStack/query/pull/10119))\n\n## 5.91.1\n\n### Patch Changes\n\n- refactor(preact-query/useQueries): remove unreachable 'willFetch' branch in suspense promise collection ([#10188](https://github.com/TanStack/query/pull/10188))\n\n## 5.91.0\n\n### Minor Changes\n\n- feat: Preact Adapter ([#9935](https://github.com/TanStack/query/pull/9935))\n"
  },
  {
    "path": "packages/preact-query/README.md",
    "content": "<img src=\"https://static.scarf.sh/a.png?x-pxid=be2d8a11-9712-4c1d-9963-580b2d4fb133\" />\n\n![TanStack Query Header](https://github.com/TanStack/query/raw/main/media/repo-header.png)\n\nHooks for fetching, caching and updating asynchronous data in Preact\n\n<a href=\"https://twitter.com/intent/tweet?button_hashtag=TanStack\" target=\"\\_parent\">\n  <img alt=\"#TanStack\" src=\"https://img.shields.io/twitter/url?color=%2308a0e9&label=%23TanStack&style=social&url=https%3A%2F%2Ftwitter.com%2Fintent%2Ftweet%3Fbutton_hashtag%3DTanStack\">\n</a><a href=\"https://discord.com/invite/WrRKjPJ\" target=\"\\_parent\">\n  <img alt=\"\" src=\"https://img.shields.io/badge/Discord-TanStack-%235865F2\" />\n</a><a href=\"https://github.com/TanStack/query/actions?query=workflow%3A%22preact-query+tests%22\">\n<img src=\"https://github.com/TanStack/query/workflows/preact-query%20tests/badge.svg\" />\n</a><a href=\"https://www.npmjs.com/package/@tanstack/query-core\" target=\"\\_parent\">\n  <img alt=\"\" src=\"https://img.shields.io/npm/dm/@tanstack/query-core.svg\" />\n</a><a href=\"https://bundlejs.com/?q=%40tanstack%2Fpreact-query&config=%7B%22esbuild%22%3A%7B%22external%22%3A%5B%22react%22%2C%22react-dom%22%5D%7D%7D&badge=\" target=\"\\_parent\">\n  <img alt=\"\" src=\"https://deno.bundlejs.com/?q=@tanstack/preact-query&config={%22esbuild%22:{%22external%22:[%22react%22,%22react-dom%22]}}&badge=detailed\" />\n</a><a href=\"#badge\">\n    <img alt=\"semantic-release\" src=\"https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg\">\n  </a><a href=\"https://github.com/TanStack/query/discussions\">\n  <img alt=\"Join the discussion on Github\" src=\"https://img.shields.io/badge/Github%20Discussions%20%26%20Support-Chat%20now!-blue\" />\n</a><a href=\"https://bestofjs.org/projects/tanstack-query\"><img alt=\"Best of JS\" src=\"https://img.shields.io/endpoint?url=https://bestofjs-serverless.now.sh/api/project-badge?fullName=TanStack%2Fquery%26since=daily\" /></a><a href=\"https://github.com/TanStack/query/\" target=\"\\_parent\">\n  <img alt=\"\" src=\"https://img.shields.io/github/stars/TanStack/query.svg?style=social&label=Star\" />\n</a><a href=\"https://twitter.com/tannerlinsley\" target=\"\\_parent\">\n  <img alt=\"\" src=\"https://img.shields.io/twitter/follow/tannerlinsley.svg?style=social&label=Follow\" />\n</a> <a href=\"https://gitpod.io/from-referrer/\">\n  <img src=\"https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod\" alt=\"Gitpod Ready-to-Code\"/>\n</a>\n\nEnjoy this library? Try the entire [TanStack](https://tanstack.com)! [TanStack Table](https://github.com/TanStack/table), [TanStack Router](https://github.com/tanstack/router), [TanStack Virtual](https://github.com/tanstack/virtual), [React Charts](https://github.com/TanStack/react-charts), [React Ranger](https://github.com/TanStack/ranger)\n\n## Visit [tanstack.com/query](https://tanstack.com/query) for docs, guides, API and more!\n\n## Quick Features\n\n- Transport/protocol/backend agnostic data fetching (REST, GraphQL, promises, whatever!)\n- Auto Caching + Refetching (stale-while-revalidate, Window Refocus, Polling/Realtime)\n- Parallel + Dependent Queries\n- Mutations + Reactive Query Refetching\n- Multi-layer Cache + Automatic Garbage Collection\n- Paginated + Cursor-based Queries\n- Load-More + Infinite Scroll Queries w/ Scroll Recovery\n- Request Cancellation\n- [Preact Suspense](https://preactjs.com/guide/v10/api-reference/#suspense) + Fetch-As-You-Render Query Prefetching -- Though not recommended because of the bulk preact/compat adds\n- Dedicated Devtools\n\n### [Become a Sponsor!](https://github.com/sponsors/tannerlinsley/)\n\n<!-- Use the force, Luke -->\n"
  },
  {
    "path": "packages/preact-query/eslint.config.js",
    "content": "// @ts-check\n// @ts-ignore: no types for eslint-config-preact\nimport preact from 'eslint-config-preact'\n// eslint-config-preact uses typescript-eslint under the hood\nimport tseslint from 'typescript-eslint'\n\nimport rootConfig from './root.eslint.config.js'\n\nexport default [\n  ...rootConfig,\n  ...preact,\n  {\n    files: ['**/*.{ts,tsx}'],\n    languageOptions: {\n      parser: tseslint.parser,\n      parserOptions: {\n        project: true,\n      },\n    },\n    plugins: {\n      'typescript-eslint': tseslint.plugin,\n    },\n    rules: {\n      // Disable base rule to prevent overload false positives\n      'no-redeclare': 'off',\n      'no-duplicate-imports': 'off',\n      'no-unused-vars': 'off',\n      'import/order': 'off',\n      'sort-imports': 'off',\n      'no-import-assign': 'off',\n      // TS-aware version handles overloads correctly\n      '@typescript-eslint/no-redeclare': 'error',\n      '@typescript-eslint/array-type': 'off',\n      '@typescript-eslint/no-unnecessary-type-assertion': 'off',\n      '@typescript-eslint/no-unnecessary-condition': 'off',\n    },\n  },\n]\n"
  },
  {
    "path": "packages/preact-query/package.json",
    "content": "{\n  \"name\": \"@tanstack/preact-query\",\n  \"version\": \"5.94.2\",\n  \"description\": \"Hooks for managing, caching and syncing asynchronous and remote data in preact\",\n  \"author\": \"tannerlinsley\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/preact-query\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"scripts\": {\n    \"clean\": \"premove ./build ./coverage ./dist-ts\",\n    \"compile\": \"tsc --build\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:types\": \"npm-run-all --serial test:types:*\",\n    \"test:types:ts54\": \"node ../../node_modules/typescript54/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts55\": \"node ../../node_modules/typescript55/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts56\": \"node ../../node_modules/typescript56/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts57\": \"node ../../node_modules/typescript57/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts58\": \"node ../../node_modules/typescript58/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts59\": \"node ../../node_modules/typescript59/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:tscurrent\": \"tsc --build\",\n    \"test:types:ts60\": \"node ../../node_modules/typescript60/lib/tsc.js --build\",\n    \"test:lib\": \"vitest\",\n    \"test:lib:dev\": \"pnpm run test:lib --watch\",\n    \"test:build\": \"publint --strict && attw --pack\",\n    \"build\": \"pnpm build:tsup && pnpm build:codemods\",\n    \"build:tsup\": \"tsup --tsconfig tsconfig.prod.json\",\n    \"build:codemods\": \"cpy ../query-codemods/* ./build/codemods\"\n  },\n  \"type\": \"module\",\n  \"types\": \"build/legacy/index.d.ts\",\n  \"main\": \"build/legacy/index.cjs\",\n  \"module\": \"build/legacy/index.js\",\n  \"exports\": {\n    \".\": {\n      \"@tanstack/custom-condition\": \"./src/index.ts\",\n      \"import\": {\n        \"types\": \"./build/modern/index.d.ts\",\n        \"default\": \"./build/modern/index.js\"\n      },\n      \"require\": {\n        \"types\": \"./build/modern/index.d.cts\",\n        \"default\": \"./build/modern/index.cjs\"\n      }\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"sideEffects\": false,\n  \"files\": [\n    \"build\",\n    \"src\",\n    \"!src/__tests__\",\n    \"!build/codemods/node_modules\",\n    \"!build/codemods/vite.config.ts\",\n    \"!build/codemods/**/__testfixtures__\",\n    \"!build/codemods/**/__tests__\"\n  ],\n  \"dependencies\": {\n    \"@tanstack/query-core\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"@preact/preset-vite\": \"^2.10.2\",\n    \"@tanstack/query-persist-client-core\": \"workspace:*\",\n    \"@tanstack/query-test-utils\": \"workspace:*\",\n    \"@testing-library/preact\": \"^3.2.4\",\n    \"cpy-cli\": \"^5.0.0\",\n    \"eslint-config-preact\": \"^2.0.0\",\n    \"npm-run-all2\": \"^5.0.0\",\n    \"preact\": \"^10.28.0\",\n    \"preact-render-to-string\": \"^6.6.4\",\n    \"typescript\": \"5.9.3\",\n    \"typescript-eslint\": \"^8.54.0\"\n  },\n  \"peerDependencies\": {\n    \"preact\": \"^10.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/preact-query/src/HydrationBoundary.tsx",
    "content": "import { hydrate } from '@tanstack/query-core'\nimport type {\n  DehydratedState,\n  HydrateOptions,\n  OmitKeyof,\n  QueryClient,\n} from '@tanstack/query-core'\nimport { Fragment } from 'preact'\nimport type { ComponentChildren } from 'preact'\nimport { useEffect, useMemo, useRef } from 'preact/hooks'\n\nimport { useQueryClient } from './QueryClientProvider'\n\nexport interface HydrationBoundaryProps {\n  state: DehydratedState | null | undefined\n  options?: OmitKeyof<HydrateOptions, 'defaultOptions'> & {\n    defaultOptions?: OmitKeyof<\n      Exclude<HydrateOptions['defaultOptions'], undefined>,\n      'mutations'\n    >\n  }\n  children?: ComponentChildren\n  queryClient?: QueryClient\n}\n\nexport const HydrationBoundary = ({\n  children,\n  options = {},\n  state,\n  queryClient,\n}: HydrationBoundaryProps) => {\n  const client = useQueryClient(queryClient)\n\n  const optionsRef = useRef(options)\n  useEffect(() => {\n    optionsRef.current = options\n  })\n\n  // This useMemo is for performance reasons only, everything inside it must\n  // be safe to run in every render and code here should be read as \"in render\".\n  //\n  // This code needs to happen during the render phase, because after initial\n  // SSR, hydration needs to happen _before_ children render. Also, if hydrating\n  // during a transition, we want to hydrate as much as is safe in render so\n  // we can prerender as much as possible.\n  //\n  // For any queries that already exist in the cache, we want to hold back on\n  // hydrating until _after_ the render phase. The reason for this is that during\n  // transitions, we don't want the existing queries and observers to update to\n  // the new data on the current page, only _after_ the transition is committed.\n  // If the transition is aborted, we will have hydrated any _new_ queries, but\n  // we throw away the fresh data for any existing ones to avoid unexpectedly\n  // updating the UI.\n  const hydrationQueue: DehydratedState['queries'] | undefined = useMemo(() => {\n    if (state) {\n      if (typeof state !== 'object') {\n        return\n      }\n\n      const queryCache = client.getQueryCache()\n      // State is supplied from the outside and we might as well fail\n      // gracefully if it has the wrong shape, so while we type `queries`\n      // as required, we still provide a fallback.\n      // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n      const queries = state.queries || []\n\n      const newQueries: DehydratedState['queries'] = []\n      const existingQueries: DehydratedState['queries'] = []\n      for (const dehydratedQuery of queries) {\n        const existingQuery = queryCache.get(dehydratedQuery.queryHash)\n\n        if (!existingQuery) {\n          newQueries.push(dehydratedQuery)\n        } else {\n          const hydrationIsNewer =\n            dehydratedQuery.state.dataUpdatedAt >\n              existingQuery.state.dataUpdatedAt ||\n            (dehydratedQuery.promise &&\n              existingQuery.state.status !== 'pending' &&\n              existingQuery.state.fetchStatus !== 'fetching' &&\n              dehydratedQuery.dehydratedAt !== undefined &&\n              dehydratedQuery.dehydratedAt > existingQuery.state.dataUpdatedAt)\n\n          if (hydrationIsNewer) {\n            existingQueries.push(dehydratedQuery)\n          }\n        }\n      }\n\n      if (newQueries.length > 0) {\n        // It's actually fine to call this with queries/state that already exists\n        // in the cache, or is older. hydrate() is idempotent for queries.\n        hydrate(client, { queries: newQueries }, optionsRef.current)\n      }\n      if (existingQueries.length > 0) {\n        return existingQueries\n      }\n    }\n    return undefined\n  }, [client, state])\n\n  useEffect(() => {\n    if (hydrationQueue) {\n      hydrate(client, { queries: hydrationQueue }, optionsRef.current)\n    }\n  }, [client, hydrationQueue])\n\n  return <Fragment>{children}</Fragment>\n}\n"
  },
  {
    "path": "packages/preact-query/src/IsRestoringProvider.ts",
    "content": "import { createContext } from 'preact'\nimport { useContext } from 'preact/hooks'\n\nconst IsRestoringContext = createContext(false)\n\nexport const useIsRestoring = () => useContext(IsRestoringContext)\nexport const IsRestoringProvider = IsRestoringContext.Provider\n"
  },
  {
    "path": "packages/preact-query/src/QueryClientProvider.tsx",
    "content": "import type { QueryClient } from '@tanstack/query-core'\nimport { createContext } from 'preact'\nimport type { ComponentChildren, VNode } from 'preact'\nimport { useContext, useEffect } from 'preact/hooks'\n\nexport const QueryClientContext = createContext<QueryClient | undefined>(\n  undefined,\n)\n\nexport const useQueryClient = (queryClient?: QueryClient) => {\n  const client = useContext(QueryClientContext)\n\n  if (queryClient) {\n    return queryClient\n  }\n\n  if (!client) {\n    throw new Error('No QueryClient set, use QueryClientProvider to set one')\n  }\n\n  return client\n}\n\nexport type QueryClientProviderProps = {\n  client: QueryClient\n  children?: ComponentChildren\n}\n\nexport const QueryClientProvider = ({\n  client,\n  children,\n}: QueryClientProviderProps): VNode => {\n  useEffect(() => {\n    client.mount()\n    return () => {\n      client.unmount()\n    }\n  }, [client])\n\n  return (\n    <QueryClientContext.Provider value={client}>\n      {children}\n    </QueryClientContext.Provider>\n  )\n}\n"
  },
  {
    "path": "packages/preact-query/src/QueryErrorResetBoundary.tsx",
    "content": "import { createContext } from 'preact'\nimport type { ComponentChildren } from 'preact'\nimport { useContext, useState } from 'preact/hooks'\n\n// CONTEXT\nexport type QueryErrorResetFunction = () => void\nexport type QueryErrorIsResetFunction = () => boolean\nexport type QueryErrorClearResetFunction = () => void\n\nexport interface QueryErrorResetBoundaryValue {\n  clearReset: QueryErrorClearResetFunction\n  isReset: QueryErrorIsResetFunction\n  reset: QueryErrorResetFunction\n}\n\nfunction createValue(): QueryErrorResetBoundaryValue {\n  let isReset = false\n  return {\n    clearReset: () => {\n      isReset = false\n    },\n    reset: () => {\n      isReset = true\n    },\n    isReset: () => {\n      return isReset\n    },\n  }\n}\n\nconst QueryErrorResetBoundaryContext = createContext(createValue())\n\n// HOOK\n\nexport const useQueryErrorResetBoundary = () =>\n  useContext(QueryErrorResetBoundaryContext)\n\n// COMPONENT\n\nexport type QueryErrorResetBoundaryFunction = (\n  value: QueryErrorResetBoundaryValue,\n) => ComponentChildren\n\nexport interface QueryErrorResetBoundaryProps {\n  children: QueryErrorResetBoundaryFunction | ComponentChildren\n}\n\nexport const QueryErrorResetBoundary = ({\n  children,\n}: QueryErrorResetBoundaryProps) => {\n  const [value] = useState(() => createValue())\n  return (\n    <QueryErrorResetBoundaryContext.Provider value={value}>\n      {typeof children === 'function' ? children(value) : children}\n    </QueryErrorResetBoundaryContext.Provider>\n  )\n}\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/ErrorBoundary/ErrorBoundary.ts",
    "content": "import { createElement, Component } from 'preact'\nimport type { ErrorInfo } from 'preact'\n\nimport { ErrorBoundaryContext } from './ErrorBoundaryContext'\nimport type { ErrorBoundaryProps, FallbackProps } from './types'\n\ntype ErrorBoundaryState =\n  | {\n      didCatch: true\n      error: any\n    }\n  | {\n      didCatch: false\n      error: null\n    }\n\nconst initialState: ErrorBoundaryState = {\n  didCatch: false,\n  error: null,\n}\n\nexport class ErrorBoundary extends Component<\n  ErrorBoundaryProps,\n  ErrorBoundaryState\n> {\n  constructor(props: ErrorBoundaryProps) {\n    super(props)\n\n    this.resetErrorBoundary = this.resetErrorBoundary.bind(this)\n    this.state = initialState\n  }\n\n  static getDerivedStateFromError(error: Error) {\n    return { didCatch: true, error }\n  }\n\n  resetErrorBoundary(...args: any[]) {\n    const { error } = this.state\n\n    if (error !== null) {\n      this.props.onReset?.({\n        args,\n        reason: 'imperative-api',\n      })\n\n      this.setState(initialState)\n    }\n  }\n\n  componentDidCatch(error: Error, info: ErrorInfo) {\n    /**\n     * To emulate the react behaviour of console.error\n     * we add one here to show that the errors bubble up\n     * to the system and can be seen in the console\n     */\n    console.error('%o\\n\\n%s', error, info)\n    this.props.onError?.(error, info)\n  }\n\n  componentDidUpdate(\n    prevProps: ErrorBoundaryProps,\n    prevState: ErrorBoundaryState,\n  ) {\n    const { didCatch } = this.state\n    const { resetKeys } = this.props\n\n    // There's an edge case where if the thing that triggered the error happens to *also* be in the resetKeys array,\n    // we'd end up resetting the error boundary immediately.\n    // This would likely trigger a second error to be thrown.\n    // So we make sure that we don't check the resetKeys on the first call of cDU after the error is set.\n\n    if (\n      didCatch &&\n      prevState.error !== null &&\n      hasArrayChanged(prevProps.resetKeys, resetKeys)\n    ) {\n      this.props.onReset?.({\n        next: resetKeys,\n        prev: prevProps.resetKeys,\n        reason: 'keys',\n      })\n\n      // eslint-disable-next-line\n      this.setState(initialState)\n    }\n  }\n\n  render() {\n    const { children, fallbackRender, FallbackComponent, fallback } = this.props\n    const { didCatch, error } = this.state\n\n    let childToRender = children\n\n    if (didCatch) {\n      const props: FallbackProps = {\n        error,\n        resetErrorBoundary: this.resetErrorBoundary,\n      }\n\n      if (typeof fallbackRender === 'function') {\n        childToRender = fallbackRender(props)\n      } else if (FallbackComponent) {\n        childToRender = createElement(FallbackComponent, props)\n      } else if (fallback !== undefined) {\n        childToRender = fallback\n      } else {\n        console.error(\n          'preact-error-boundary requires either a fallback, fallbackRender, or FallbackComponent prop',\n        )\n\n        throw error\n      }\n    }\n\n    return createElement(\n      ErrorBoundaryContext.Provider,\n      {\n        value: {\n          didCatch,\n          error,\n          resetErrorBoundary: this.resetErrorBoundary,\n        },\n      },\n      childToRender,\n    )\n  }\n}\n\nfunction hasArrayChanged(a: any[] = [], b: any[] = []) {\n  return (\n    a.length !== b.length || a.some((item, index) => !Object.is(item, b[index]))\n  )\n}\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/ErrorBoundary/ErrorBoundaryContext.ts",
    "content": "import { createContext } from 'preact'\n\ntype ErrorBoundaryContextType = {\n  didCatch: boolean\n  error: any\n  resetErrorBoundary: (...args: any[]) => void\n}\n\nexport const ErrorBoundaryContext =\n  createContext<ErrorBoundaryContextType | null>(null)\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/ErrorBoundary/index.ts",
    "content": "/**\n * Custom Error Boundary port from 'react-error-boundary'\n * Taken directly from https://github.com/bvaughn/react-error-boundary/\n * and modified to server a preact use case\n */\n\nexport * from './ErrorBoundary'\nexport * from './ErrorBoundaryContext'\nexport * from './types'\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/ErrorBoundary/types.ts",
    "content": "import type {\n  ComponentChild,\n  ComponentChildren,\n  ComponentType,\n  ErrorInfo,\n} from 'preact'\n\nexport type FallbackProps = {\n  error: any\n  resetErrorBoundary: (...args: any[]) => void\n}\n\ntype PropsWithChildren<TProps = {}> = TProps & {\n  children?: ComponentChildren\n}\n\ntype ErrorBoundarySharedProps = PropsWithChildren<{\n  onError?: (error: Error, info: ErrorInfo) => void\n  onReset?: (\n    details:\n      | { reason: 'imperative-api'; args: any[] }\n      | { reason: 'keys'; prev: any[] | undefined; next: any[] | undefined },\n  ) => void\n  resetKeys?: any[]\n}>\n\nexport type ErrorBoundaryPropsWithComponent = ErrorBoundarySharedProps & {\n  fallback?: never\n  FallbackComponent: ComponentType<FallbackProps>\n  fallbackRender?: never\n}\n\nexport type ErrorBoundaryPropsWithRender = ErrorBoundarySharedProps & {\n  fallback?: never\n  FallbackComponent?: never\n  fallbackRender: (props: FallbackProps) => ComponentChild\n}\n\nexport type ErrorBoundaryPropsWithFallback = ErrorBoundarySharedProps & {\n  fallback: ComponentChild\n  FallbackComponent?: never\n  fallbackRender?: never\n}\n\nexport type ErrorBoundaryProps =\n  | ErrorBoundaryPropsWithFallback\n  | ErrorBoundaryPropsWithComponent\n  | ErrorBoundaryPropsWithRender\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/HydrationBoundary.test.tsx",
    "content": "import * as coreModule from '@tanstack/query-core'\nimport type { hydrate } from '@tanstack/query-core'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { render } from '@testing-library/preact'\nimport { Suspense, startTransition } from 'preact/compat'\nimport { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\n\nimport {\n  HydrationBoundary,\n  QueryClient,\n  QueryClientProvider,\n  dehydrate,\n  useQuery,\n} from '..'\n\ndescribe('Preact hydration', () => {\n  let stringifiedState: string\n\n  beforeEach(async () => {\n    vi.useFakeTimers()\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: ['string'],\n      queryFn: () => sleep(10).then(() => ['stringCached']),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n    const dehydrated = dehydrate(queryClient)\n    stringifiedState = JSON.stringify(dehydrated)\n    queryClient.clear()\n  })\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('should hydrate queries to the cache on context', async () => {\n    const dehydratedState = JSON.parse(stringifiedState)\n    const queryClient = new QueryClient()\n\n    function Page() {\n      const { data } = useQuery({\n        queryKey: ['string'],\n        queryFn: () => sleep(20).then(() => ['string']),\n      })\n      return (\n        <div>\n          <h1>{data}</h1>\n        </div>\n      )\n    }\n\n    const rendered = render(\n      <QueryClientProvider client={queryClient}>\n        <HydrationBoundary state={dehydratedState}>\n          <Page />\n        </HydrationBoundary>\n      </QueryClientProvider>,\n    )\n\n    expect(rendered.getByText('stringCached')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(21)\n    expect(rendered.getByText('string')).toBeInTheDocument()\n    queryClient.clear()\n  })\n\n  test('should hydrate queries to the cache on custom context', async () => {\n    const queryClientInner = new QueryClient()\n    const queryClientOuter = new QueryClient()\n\n    const dehydratedState = JSON.parse(stringifiedState)\n\n    function Page() {\n      const { data } = useQuery({\n        queryKey: ['string'],\n        queryFn: () => sleep(20).then(() => ['string']),\n      })\n      return (\n        <div>\n          <h1>{data}</h1>\n        </div>\n      )\n    }\n\n    const rendered = render(\n      <QueryClientProvider client={queryClientOuter}>\n        <QueryClientProvider client={queryClientInner}>\n          <HydrationBoundary state={dehydratedState}>\n            <Page />\n          </HydrationBoundary>\n        </QueryClientProvider>\n      </QueryClientProvider>,\n    )\n\n    expect(rendered.getByText('stringCached')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(21)\n    expect(rendered.getByText('string')).toBeInTheDocument()\n\n    queryClientInner.clear()\n    queryClientOuter.clear()\n  })\n\n  describe('PreactQueryCacheProvider with hydration support', () => {\n    test('should hydrate new queries if queries change', async () => {\n      const dehydratedState = JSON.parse(stringifiedState)\n      const queryClient = new QueryClient()\n\n      function Page({ queryKey }: { queryKey: [string] }) {\n        const { data } = useQuery({\n          queryKey,\n          queryFn: () => sleep(20).then(() => queryKey),\n        })\n        return (\n          <div>\n            <h1>{data}</h1>\n          </div>\n        )\n      }\n\n      const rendered = render(\n        <QueryClientProvider client={queryClient}>\n          <HydrationBoundary state={dehydratedState}>\n            <Page queryKey={['string']} />\n          </HydrationBoundary>\n        </QueryClientProvider>,\n      )\n\n      expect(rendered.getByText('stringCached')).toBeInTheDocument()\n      await vi.advanceTimersByTimeAsync(21)\n      expect(rendered.getByText('string')).toBeInTheDocument()\n\n      const intermediateClient = new QueryClient()\n\n      intermediateClient.prefetchQuery({\n        queryKey: ['string'],\n        queryFn: () => sleep(20).then(() => ['should change']),\n      })\n      intermediateClient.prefetchQuery({\n        queryKey: ['added'],\n        queryFn: () => sleep(20).then(() => ['added']),\n      })\n      await vi.advanceTimersByTimeAsync(20)\n      const dehydrated = dehydrate(intermediateClient)\n      intermediateClient.clear()\n\n      rendered.rerender(\n        <QueryClientProvider client={queryClient}>\n          <HydrationBoundary state={dehydrated}>\n            <Page queryKey={['string']} />\n            <Page queryKey={['added']} />\n          </HydrationBoundary>\n        </QueryClientProvider>,\n      )\n\n      // Existing observer should not have updated at this point,\n      // as that would indicate a side effect in the render phase\n      expect(rendered.getByText('string')).toBeInTheDocument()\n      // New query data should be available immediately\n      expect(rendered.getByText('added')).toBeInTheDocument()\n\n      await vi.advanceTimersByTimeAsync(0)\n      // After effects phase has had time to run, the observer should have updated\n      expect(rendered.queryByText('string')).not.toBeInTheDocument()\n      expect(rendered.getByText('should change')).toBeInTheDocument()\n\n      queryClient.clear()\n    })\n\n    // When we hydrate in transitions that are later aborted, it could be\n    // confusing to both developers and users if we suddenly updated existing\n    // state on the screen (why did this update when it was not stale, nothing\n    // remounted, I didn't change tabs etc?).\n    // Any queries that does not exist in the cache yet can still be hydrated\n    // since they don't have any observers on the current page that would update.\n    test('should hydrate new but not existing queries if transition is aborted', async () => {\n      const initialDehydratedState = JSON.parse(stringifiedState)\n      const queryClient = new QueryClient()\n\n      function Page({ queryKey }: { queryKey: [string] }) {\n        const { data } = useQuery({\n          queryKey,\n          queryFn: () => sleep(20).then(() => queryKey),\n        })\n        return (\n          <div>\n            <h1>{data}</h1>\n          </div>\n        )\n      }\n\n      const rendered = render(\n        <QueryClientProvider client={queryClient}>\n          <HydrationBoundary state={initialDehydratedState}>\n            <Page queryKey={['string']} />\n          </HydrationBoundary>\n        </QueryClientProvider>,\n      )\n\n      expect(rendered.getByText('stringCached')).toBeInTheDocument()\n      await vi.advanceTimersByTimeAsync(21)\n      expect(rendered.getByText('string')).toBeInTheDocument()\n\n      const intermediateClient = new QueryClient()\n      intermediateClient.prefetchQuery({\n        queryKey: ['string'],\n        queryFn: () => sleep(20).then(() => ['should not change']),\n      })\n      intermediateClient.prefetchQuery({\n        queryKey: ['added'],\n        queryFn: () => sleep(20).then(() => ['added']),\n      })\n      await vi.advanceTimersByTimeAsync(20)\n\n      const newDehydratedState = dehydrate(intermediateClient)\n      intermediateClient.clear()\n\n      function Thrower(): never {\n        throw new Promise(() => {\n          // Never resolve\n        })\n      }\n\n      startTransition(() => {\n        rendered.rerender(\n          <Suspense fallback=\"loading\">\n            <QueryClientProvider client={queryClient}>\n              <HydrationBoundary state={newDehydratedState}>\n                <Page queryKey={['string']} />\n                <Page queryKey={['added']} />\n                <Thrower />\n              </HydrationBoundary>\n            </QueryClientProvider>\n          </Suspense>,\n        )\n\n        expect(rendered.getByText('loading')).toBeInTheDocument()\n      })\n\n      startTransition(() => {\n        rendered.rerender(\n          <QueryClientProvider client={queryClient}>\n            <HydrationBoundary state={initialDehydratedState}>\n              <Page queryKey={['string']} />\n              <Page queryKey={['added']} />\n            </HydrationBoundary>\n          </QueryClientProvider>,\n        )\n\n        // This query existed before the transition so it should stay the same\n        expect(rendered.getByText('string')).toBeInTheDocument()\n        expect(\n          rendered.queryByText('should not change'),\n        ).not.toBeInTheDocument()\n        // New query data should be available immediately because it was\n        // hydrated in the previous transition, even though the new dehydrated\n        // state did not contain it\n        expect(rendered.getByText('added')).toBeInTheDocument()\n      })\n\n      await vi.advanceTimersByTimeAsync(20)\n      // It should stay the same even after effects have had a chance to run\n      expect(rendered.getByText('string')).toBeInTheDocument()\n      expect(rendered.queryByText('should not change')).not.toBeInTheDocument()\n\n      queryClient.clear()\n    })\n\n    test('should hydrate queries to new cache if cache changes', async () => {\n      const dehydratedState = JSON.parse(stringifiedState)\n      const queryClient = new QueryClient()\n\n      function Page() {\n        const { data } = useQuery({\n          queryKey: ['string'],\n          queryFn: () => sleep(20).then(() => ['string']),\n        })\n        return (\n          <div>\n            <h1>{data}</h1>\n          </div>\n        )\n      }\n\n      const rendered = render(\n        <QueryClientProvider client={queryClient}>\n          <HydrationBoundary state={dehydratedState}>\n            <Page />\n          </HydrationBoundary>\n        </QueryClientProvider>,\n      )\n\n      expect(rendered.getByText('stringCached')).toBeInTheDocument()\n      await vi.advanceTimersByTimeAsync(21)\n      expect(rendered.getByText('string')).toBeInTheDocument()\n      const newClientQueryClient = new QueryClient()\n\n      rendered.rerender(\n        <QueryClientProvider client={newClientQueryClient}>\n          <HydrationBoundary state={dehydratedState}>\n            <Page />\n          </HydrationBoundary>\n        </QueryClientProvider>,\n      )\n\n      await vi.advanceTimersByTimeAsync(20)\n      expect(rendered.getByText('string')).toBeInTheDocument()\n\n      queryClient.clear()\n      newClientQueryClient.clear()\n    })\n  })\n\n  test('should not hydrate queries if state is null', async () => {\n    const queryClient = new QueryClient()\n\n    const hydrateSpy = vi.spyOn(coreModule, 'hydrate')\n\n    function Page() {\n      return null\n    }\n\n    render(\n      <QueryClientProvider client={queryClient}>\n        <HydrationBoundary state={null}>\n          <Page />\n        </HydrationBoundary>\n      </QueryClientProvider>,\n    )\n\n    await Promise.all(\n      Array.from({ length: 1000 }).map(async (_, index) => {\n        await vi.advanceTimersByTimeAsync(index)\n        expect(hydrateSpy).toHaveBeenCalledTimes(0)\n      }),\n    )\n\n    hydrateSpy.mockRestore()\n    queryClient.clear()\n  })\n\n  test('should not hydrate queries if state is undefined', async () => {\n    const queryClient = new QueryClient()\n\n    const hydrateSpy = vi.spyOn(coreModule, 'hydrate')\n\n    function Page() {\n      return null\n    }\n\n    render(\n      <QueryClientProvider client={queryClient}>\n        <HydrationBoundary state={undefined}>\n          <Page />\n        </HydrationBoundary>\n      </QueryClientProvider>,\n    )\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(hydrateSpy).toHaveBeenCalledTimes(0)\n\n    hydrateSpy.mockRestore()\n    queryClient.clear()\n  })\n\n  test('should not hydrate queries if state is not an object', async () => {\n    const queryClient = new QueryClient()\n\n    const hydrateSpy = vi.spyOn(coreModule, 'hydrate')\n\n    function Page() {\n      return null\n    }\n\n    render(\n      <QueryClientProvider client={queryClient}>\n        <HydrationBoundary state={'invalid-state' as any}>\n          <Page />\n        </HydrationBoundary>\n      </QueryClientProvider>,\n    )\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(hydrateSpy).toHaveBeenCalledTimes(0)\n\n    hydrateSpy.mockRestore()\n    queryClient.clear()\n  })\n\n  test('should handle state without queries property gracefully', async () => {\n    const queryClient = new QueryClient()\n\n    const hydrateSpy = vi.spyOn(coreModule, 'hydrate')\n\n    function Page() {\n      return null\n    }\n\n    render(\n      <QueryClientProvider client={queryClient}>\n        <HydrationBoundary state={{} as any}>\n          <Page />\n        </HydrationBoundary>\n      </QueryClientProvider>,\n    )\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(hydrateSpy).toHaveBeenCalledTimes(0)\n\n    hydrateSpy.mockRestore()\n    queryClient.clear()\n  })\n\n  // https://github.com/TanStack/query/issues/8677\n  test('should not infinite loop when hydrating promises that resolve to errors', async () => {\n    const originalHydrate = coreModule.hydrate\n    const hydrateSpy = vi.spyOn(coreModule, 'hydrate')\n    let hydrationCount = 0\n    hydrateSpy.mockImplementation((...args: Parameters<typeof hydrate>) => {\n      hydrationCount++\n      // Arbitrary number\n      if (hydrationCount > 10) {\n        // This is a rough way to detect it. Calling hydrate multiple times with\n        // the same data is usually fine, but in this case it indicates the\n        // logic in HydrationBoundary is not working as expected.\n        throw new Error('Too many hydrations detected')\n      }\n      return originalHydrate(...args)\n    })\n\n    // For the bug to trigger, there needs to already be a query in the cache,\n    // with a dataUpdatedAt earlier than the dehydratedAt of the next query\n    const clientQueryClient = new QueryClient()\n    clientQueryClient.prefetchQuery({\n      queryKey: ['promise'],\n      queryFn: () => sleep(20).then(() => 'existing'),\n    })\n    await vi.advanceTimersByTimeAsync(20)\n\n    const prefetchQueryClient = new QueryClient({\n      defaultOptions: {\n        dehydrate: {\n          shouldDehydrateQuery: () => true,\n        },\n      },\n    })\n    prefetchQueryClient.prefetchQuery({\n      queryKey: ['promise'],\n      queryFn: () =>\n        sleep(10).then(() => Promise.reject(new Error('Query failed'))),\n    })\n\n    const dehydratedState = dehydrate(prefetchQueryClient)\n\n    // Mimic what React/our synchronous thenable does for already rejected promises\n    // @ts-expect-error\n    dehydratedState.queries[0].promise.status = 'failure'\n\n    function Page() {\n      const { data } = useQuery({\n        queryKey: ['promise'],\n        queryFn: () => sleep(20).then(() => ['new']),\n      })\n      return (\n        <div>\n          <h1>{data}</h1>\n        </div>\n      )\n    }\n\n    const rendered = render(\n      <QueryClientProvider client={clientQueryClient}>\n        <HydrationBoundary state={dehydratedState}>\n          <Page />\n        </HydrationBoundary>\n      </QueryClientProvider>,\n    )\n\n    expect(rendered.getByText('existing')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(21)\n    expect(rendered.getByText('new')).toBeInTheDocument()\n\n    hydrateSpy.mockRestore()\n    prefetchQueryClient.clear()\n    clientQueryClient.clear()\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/QueryClientProvider.test.tsx",
    "content": "import { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { render } from '@testing-library/preact'\nimport { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\n\nimport {\n  QueryCache,\n  QueryClient,\n  QueryClientProvider,\n  useQuery,\n  useQueryClient,\n} from '..'\n\ndescribe('QueryClientProvider', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('sets a specific cache for all queries to use', async () => {\n    const key = queryKey()\n\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({ queryCache })\n\n    function Page() {\n      const { data } = useQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'test'),\n      })\n\n      return (\n        <div>\n          <h1>{data}</h1>\n        </div>\n      )\n    }\n\n    const rendered = render(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('test')).toBeInTheDocument()\n\n    expect(queryCache.find({ queryKey: key })).toBeDefined()\n  })\n\n  test('allows multiple caches to be partitioned', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    const queryCache1 = new QueryCache()\n    const queryCache2 = new QueryCache()\n\n    const queryClient1 = new QueryClient({ queryCache: queryCache1 })\n    const queryClient2 = new QueryClient({ queryCache: queryCache2 })\n\n    function Page1() {\n      const { data } = useQuery({\n        queryKey: key1,\n        queryFn: () => sleep(10).then(() => 'test1'),\n      })\n\n      return (\n        <div>\n          <h1>{data}</h1>\n        </div>\n      )\n    }\n    function Page2() {\n      const { data } = useQuery({\n        queryKey: key2,\n        queryFn: () => sleep(10).then(() => 'test2'),\n      })\n\n      return (\n        <div>\n          <h1>{data}</h1>\n        </div>\n      )\n    }\n\n    const rendered = render(\n      <>\n        <QueryClientProvider client={queryClient1}>\n          <Page1 />\n        </QueryClientProvider>\n        <QueryClientProvider client={queryClient2}>\n          <Page2 />\n        </QueryClientProvider>\n      </>,\n    )\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('test1')).toBeInTheDocument()\n    expect(rendered.getByText('test2')).toBeInTheDocument()\n\n    expect(queryCache1.find({ queryKey: key1 })).toBeDefined()\n    expect(queryCache1.find({ queryKey: key2 })).not.toBeDefined()\n    expect(queryCache2.find({ queryKey: key1 })).not.toBeDefined()\n    expect(queryCache2.find({ queryKey: key2 })).toBeDefined()\n  })\n\n  test(\"uses defaultOptions for queries when they don't provide their own config\", async () => {\n    const key = queryKey()\n\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({\n      queryCache,\n      defaultOptions: {\n        queries: {\n          gcTime: Infinity,\n        },\n      },\n    })\n\n    function Page() {\n      const { data } = useQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'test'),\n      })\n\n      return (\n        <div>\n          <h1>{data}</h1>\n        </div>\n      )\n    }\n\n    const rendered = render(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('test')).toBeInTheDocument()\n\n    expect(queryCache.find({ queryKey: key })).toBeDefined()\n    expect(queryCache.find({ queryKey: key })?.options.gcTime).toBe(Infinity)\n  })\n\n  describe('useQueryClient', () => {\n    test('should throw an error if no query client has been set', () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n\n      function Page() {\n        useQueryClient()\n        return null\n      }\n\n      expect(() => render(<Page />)).toThrow(\n        'No QueryClient set, use QueryClientProvider to set one',\n      )\n\n      consoleMock.mockRestore()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/QueryResetErrorBoundary.test.tsx",
    "content": "import { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { fireEvent } from '@testing-library/preact'\nimport { Suspense } from 'preact/compat'\nimport { useEffect, useState } from 'preact/hooks'\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\n\nimport {\n  QueryCache,\n  QueryClient,\n  QueryErrorResetBoundary,\n  useQueries,\n  useQuery,\n  useSuspenseQueries,\n  useSuspenseQuery,\n} from '..'\nimport { ErrorBoundary } from './ErrorBoundary'\nimport { renderWithClient } from './utils'\n\ndescribe('QueryErrorResetBoundary', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  const queryCache = new QueryCache()\n  const queryClient = new QueryClient({ queryCache })\n\n  describe('useQuery', () => {\n    it('should retry fetch if the reset error boundary has been reset', async () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n      const key = queryKey()\n\n      let succeed = false\n\n      function Page() {\n        const { data } = useQuery({\n          queryKey: key,\n          queryFn: () =>\n            sleep(10).then(() => {\n              if (!succeed) throw new Error('Error')\n              return 'data'\n            }),\n          retry: false,\n          throwOnError: true,\n        })\n\n        return <div>{data}</div>\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          {({ reset }) => (\n            <ErrorBoundary\n              onReset={reset}\n              fallbackRender={({ resetErrorBoundary }) => (\n                <div>\n                  <div>error boundary</div>\n                  <button\n                    onClick={() => {\n                      resetErrorBoundary()\n                    }}\n                  >\n                    retry\n                  </button>\n                </div>\n              )}\n            >\n              <Page />\n            </ErrorBoundary>\n          )}\n        </QueryErrorResetBoundary>,\n      )\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      succeed = true\n\n      fireEvent.click(rendered.getByText('retry'))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('data')).toBeInTheDocument()\n\n      consoleMock.mockRestore()\n    })\n\n    it('should not throw error if query is disabled', async () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n      const key = queryKey()\n\n      let succeed = false\n\n      function Page() {\n        const { data, status } = useQuery({\n          queryKey: key,\n          queryFn: () =>\n            sleep(10).then(() => {\n              if (!succeed) throw new Error('Error')\n              return 'data'\n            }),\n          retry: false,\n          enabled: !succeed,\n          throwOnError: true,\n        })\n\n        return (\n          <div>\n            <div>status: {status}</div>\n            <div>{data}</div>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          {({ reset }) => (\n            <ErrorBoundary\n              onReset={reset}\n              fallbackRender={({ resetErrorBoundary }) => (\n                <div>\n                  <div>error boundary</div>\n                  <button\n                    onClick={() => {\n                      resetErrorBoundary()\n                    }}\n                  >\n                    retry\n                  </button>\n                </div>\n              )}\n            >\n              <Page />\n            </ErrorBoundary>\n          )}\n        </QueryErrorResetBoundary>,\n      )\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      succeed = true\n\n      fireEvent.click(rendered.getByText('retry'))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('status: error')).toBeInTheDocument()\n\n      consoleMock.mockRestore()\n    })\n\n    it('should not throw error if query is disabled, and refetch if query becomes enabled again', async () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n\n      const key = queryKey()\n\n      let succeed = false\n\n      function Page() {\n        const [enabled, setEnabled] = useState(false)\n        const { data } = useQuery({\n          queryKey: key,\n          queryFn: () =>\n            sleep(10).then(() => {\n              if (!succeed) throw new Error('Error')\n              return 'data'\n            }),\n          retry: false,\n          enabled,\n          throwOnError: true,\n        })\n\n        useEffect(() => {\n          setEnabled(true)\n        }, [])\n\n        return <div>{data}</div>\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          {({ reset }) => (\n            <ErrorBoundary\n              onReset={reset}\n              fallbackRender={({ resetErrorBoundary }) => (\n                <div>\n                  <div>error boundary</div>\n                  <button\n                    onClick={() => {\n                      resetErrorBoundary()\n                    }}\n                  >\n                    retry\n                  </button>\n                </div>\n              )}\n            >\n              <Page />\n            </ErrorBoundary>\n          )}\n        </QueryErrorResetBoundary>,\n      )\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      succeed = true\n\n      fireEvent.click(rendered.getByText('retry'))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('data')).toBeInTheDocument()\n\n      consoleMock.mockRestore()\n    })\n\n    it('should throw error if query is disabled and manually refetch', async () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n\n      const key = queryKey()\n\n      function Page() {\n        const { data, refetch, status, fetchStatus } = useQuery<string>({\n          queryKey: key,\n          queryFn: () =>\n            sleep(10).then(() => Promise.reject(new Error('Error'))),\n          retry: false,\n          enabled: false,\n          throwOnError: true,\n        })\n\n        return (\n          <div>\n            <button onClick={() => refetch()}>refetch</button>\n            <div>\n              status: {status}, fetchStatus: {fetchStatus}\n            </div>\n            <div>{data}</div>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          {({ reset }) => (\n            <ErrorBoundary\n              onReset={reset}\n              fallbackRender={({ resetErrorBoundary }) => (\n                <div>\n                  <div>error boundary</div>\n                  <button\n                    onClick={() => {\n                      resetErrorBoundary()\n                    }}\n                  >\n                    retry\n                  </button>\n                </div>\n              )}\n            >\n              <Page />\n            </ErrorBoundary>\n          )}\n        </QueryErrorResetBoundary>,\n      )\n\n      expect(\n        rendered.getByText('status: pending, fetchStatus: idle'),\n      ).toBeInTheDocument()\n      await vi.advanceTimersByTimeAsync(11)\n      expect(\n        rendered.getByText('status: pending, fetchStatus: idle'),\n      ).toBeInTheDocument()\n\n      fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n\n      consoleMock.mockRestore()\n    })\n\n    it('should not retry fetch if the reset error boundary has not been reset', async () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n\n      const key = queryKey()\n\n      let succeed = false\n\n      function Page() {\n        const { data } = useQuery({\n          queryKey: key,\n          queryFn: () =>\n            sleep(10).then(() => {\n              if (!succeed) throw new Error('Error')\n              return 'data'\n            }),\n          retry: false,\n          throwOnError: true,\n        })\n\n        return <div>{data}</div>\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          {() => (\n            <ErrorBoundary\n              fallbackRender={({ resetErrorBoundary }) => (\n                <div>\n                  <div>error boundary</div>\n                  <button\n                    onClick={() => {\n                      resetErrorBoundary()\n                    }}\n                  >\n                    retry\n                  </button>\n                </div>\n              )}\n            >\n              <Page />\n            </ErrorBoundary>\n          )}\n        </QueryErrorResetBoundary>,\n      )\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      succeed = true\n\n      fireEvent.click(rendered.getByText('retry'))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n\n      consoleMock.mockRestore()\n    })\n\n    it('should retry fetch if the reset error boundary has been reset and the query contains data from a previous fetch', async () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n\n      const key = queryKey()\n\n      let succeed = false\n\n      function Page() {\n        const { data } = useQuery({\n          queryKey: key,\n          queryFn: () =>\n            sleep(10).then(() => {\n              if (!succeed) throw new Error('Error')\n              return 'data'\n            }),\n          retry: false,\n          throwOnError: true,\n          initialData: 'initial',\n        })\n\n        return <div>{data}</div>\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          {({ reset }) => (\n            <ErrorBoundary\n              onReset={reset}\n              fallbackRender={({ resetErrorBoundary }) => (\n                <div>\n                  <div>error boundary</div>\n                  <button\n                    onClick={() => {\n                      resetErrorBoundary()\n                    }}\n                  >\n                    retry\n                  </button>\n                </div>\n              )}\n            >\n              <Page />\n            </ErrorBoundary>\n          )}\n        </QueryErrorResetBoundary>,\n      )\n\n      expect(rendered.getByText('initial')).toBeInTheDocument()\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      succeed = true\n\n      fireEvent.click(rendered.getByText('retry'))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('data')).toBeInTheDocument()\n\n      consoleMock.mockRestore()\n    })\n\n    it('should not retry fetch if the reset error boundary has not been reset after a previous reset', async () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n\n      const key = queryKey()\n\n      let succeed = false\n      let shouldReset = false\n\n      function Page() {\n        const { data } = useQuery({\n          queryKey: key,\n          queryFn: () =>\n            sleep(10).then(() => {\n              if (!succeed) throw new Error('Error')\n              return 'data'\n            }),\n          retry: false,\n          throwOnError: true,\n        })\n\n        return <div>{data}</div>\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          {({ reset }) => (\n            <ErrorBoundary\n              onReset={() => {\n                if (shouldReset) {\n                  reset()\n                }\n              }}\n              fallbackRender={({ resetErrorBoundary }) => (\n                <div>\n                  <div>error boundary</div>\n                  <button\n                    onClick={() => {\n                      resetErrorBoundary()\n                    }}\n                  >\n                    retry\n                  </button>\n                </div>\n              )}\n            >\n              <Page />\n            </ErrorBoundary>\n          )}\n        </QueryErrorResetBoundary>,\n      )\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      succeed = false\n      shouldReset = true\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      succeed = true\n      shouldReset = false\n\n      fireEvent.click(rendered.getByText('retry'))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n\n      succeed = true\n      shouldReset = true\n\n      fireEvent.click(rendered.getByText('retry'))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('data')).toBeInTheDocument()\n\n      consoleMock.mockRestore()\n    })\n\n    it('should throw again on error after the reset error boundary has been reset', async () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n\n      const key = queryKey()\n      let fetchCount = 0\n\n      function Page() {\n        const { data } = useQuery<string>({\n          queryKey: key,\n          queryFn: () =>\n            sleep(10).then(() => {\n              fetchCount++\n              throw new Error('Error')\n            }),\n          retry: false,\n          throwOnError: true,\n        })\n\n        return <div>{data}</div>\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          {({ reset }) => (\n            <ErrorBoundary\n              onReset={reset}\n              fallbackRender={({ resetErrorBoundary }) => (\n                <div>\n                  <div>error boundary</div>\n                  <button\n                    onClick={() => {\n                      resetErrorBoundary()\n                    }}\n                  >\n                    retry\n                  </button>\n                </div>\n              )}\n            >\n              <Page />\n            </ErrorBoundary>\n          )}\n        </QueryErrorResetBoundary>,\n      )\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      fireEvent.click(rendered.getByText('retry'))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      fireEvent.click(rendered.getByText('retry'))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n\n      expect(fetchCount).toBe(3)\n\n      consoleMock.mockRestore()\n    })\n\n    it('should never render the component while the query is in error state', async () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n\n      const key = queryKey()\n      let fetchCount = 0\n      let renders = 0\n\n      function Page() {\n        const { data } = useSuspenseQuery({\n          queryKey: key,\n          queryFn: () =>\n            sleep(10).then(() => {\n              fetchCount++\n              if (fetchCount > 2) return 'data'\n              throw new Error('Error')\n            }),\n          retry: false,\n        })\n\n        renders++\n\n        return <div>{data}</div>\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          {({ reset }) => (\n            <ErrorBoundary\n              onReset={reset}\n              fallbackRender={({ resetErrorBoundary }) => (\n                <div>\n                  <div>error boundary</div>\n                  <button\n                    onClick={() => {\n                      resetErrorBoundary()\n                    }}\n                  >\n                    retry\n                  </button>\n                </div>\n              )}\n            >\n              <Suspense fallback={<div>loading</div>}>\n                <Page />\n              </Suspense>\n            </ErrorBoundary>\n          )}\n        </QueryErrorResetBoundary>,\n      )\n\n      expect(rendered.getByText('loading')).toBeInTheDocument()\n      await vi.advanceTimersByTimeAsync(10)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      fireEvent.click(rendered.getByText('retry'))\n      expect(rendered.getByText('loading')).toBeInTheDocument()\n      await vi.advanceTimersByTimeAsync(10)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      fireEvent.click(rendered.getByText('retry'))\n      expect(rendered.getByText('loading')).toBeInTheDocument()\n      await vi.advanceTimersByTimeAsync(10)\n      expect(rendered.getByText('data')).toBeInTheDocument()\n\n      expect(fetchCount).toBe(3)\n      expect(renders).toBe(1)\n\n      consoleMock.mockRestore()\n    })\n\n    it('should render children', () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n\n      function Page() {\n        return (\n          <div>\n            <span>page</span>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          <Page />\n        </QueryErrorResetBoundary>,\n      )\n\n      expect(rendered.queryByText('page')).not.toBeNull()\n\n      consoleMock.mockRestore()\n    })\n\n    it('should show error boundary when using tracked queries even though we do not track the error field', async () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n\n      const key = queryKey()\n\n      let succeed = false\n\n      function Page() {\n        const { data } = useQuery({\n          queryKey: key,\n          queryFn: () =>\n            sleep(10).then(() => {\n              if (!succeed) throw new Error('Error')\n              return 'data'\n            }),\n          retry: false,\n          throwOnError: true,\n        })\n\n        return <div>{data}</div>\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          {({ reset }) => (\n            <ErrorBoundary\n              onReset={reset}\n              fallbackRender={({ resetErrorBoundary }) => (\n                <div>\n                  <div>error boundary</div>\n                  <button\n                    onClick={() => {\n                      resetErrorBoundary()\n                    }}\n                  >\n                    retry\n                  </button>\n                </div>\n              )}\n            >\n              <Page />\n            </ErrorBoundary>\n          )}\n        </QueryErrorResetBoundary>,\n      )\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      succeed = true\n\n      fireEvent.click(rendered.getByText('retry'))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('data')).toBeInTheDocument()\n\n      consoleMock.mockRestore()\n    })\n  })\n\n  describe('useQueries', () => {\n    it('should retry fetch if the reset error boundary has been reset', async () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n      const key = queryKey()\n\n      let succeed = false\n\n      function Page() {\n        const [{ data }] = useQueries({\n          queries: [\n            {\n              queryKey: key,\n              queryFn: () =>\n                sleep(10).then(() => {\n                  if (!succeed) throw new Error('Error')\n                  return 'data'\n                }),\n              retry: false,\n              throwOnError: true,\n              retryOnMount: true,\n            },\n          ],\n        })\n\n        return <div>{data}</div>\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          {({ reset }) => (\n            <ErrorBoundary\n              onReset={reset}\n              fallbackRender={({ resetErrorBoundary }) => (\n                <div>\n                  <div>error boundary</div>\n                  <button\n                    onClick={() => {\n                      resetErrorBoundary()\n                    }}\n                  >\n                    retry\n                  </button>\n                </div>\n              )}\n            >\n              <Page />\n            </ErrorBoundary>\n          )}\n        </QueryErrorResetBoundary>,\n      )\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      succeed = true\n\n      fireEvent.click(rendered.getByText('retry'))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('data')).toBeInTheDocument()\n\n      consoleMock.mockRestore()\n    })\n\n    it('with suspense should retry fetch if the reset error boundary has been reset', async () => {\n      const key = queryKey()\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n\n      let succeed = false\n\n      function Page() {\n        const [{ data }] = useSuspenseQueries({\n          queries: [\n            {\n              queryKey: key,\n              queryFn: () =>\n                sleep(10).then(() => {\n                  if (!succeed) throw new Error('Error')\n                  return 'data'\n                }),\n              retry: false,\n              retryOnMount: true,\n            },\n          ],\n        })\n\n        return <div>{data}</div>\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          {({ reset }) => (\n            <ErrorBoundary\n              onReset={reset}\n              fallbackRender={({ resetErrorBoundary }) => (\n                <div>\n                  <div>error boundary</div>\n                  <button\n                    onClick={() => {\n                      resetErrorBoundary()\n                    }}\n                  >\n                    retry\n                  </button>\n                </div>\n              )}\n            >\n              <Suspense fallback=\"loading\">\n                <Page />\n              </Suspense>\n            </ErrorBoundary>\n          )}\n        </QueryErrorResetBoundary>,\n      )\n\n      expect(rendered.getByText('loading')).toBeInTheDocument()\n      await vi.advanceTimersByTimeAsync(10)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      succeed = true\n\n      fireEvent.click(rendered.getByText('retry'))\n      expect(rendered.getByText('loading')).toBeInTheDocument()\n      await vi.advanceTimersByTimeAsync(10)\n      expect(rendered.getByText('data')).toBeInTheDocument()\n\n      consoleMock.mockRestore()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/fine-grained-persister.test.tsx",
    "content": "import {\n  PERSISTER_KEY_PREFIX,\n  experimental_createQueryPersister,\n} from '@tanstack/query-persist-client-core'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { useState } from 'preact/hooks'\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\n\nimport { QueryCache, QueryClient, hashKey, useQuery } from '..'\nimport { renderWithClient } from './utils'\n\ndescribe('fine grained persister', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  const queryCache = new QueryCache()\n  const queryClient = new QueryClient({ queryCache })\n\n  it('should restore query state from persister and not refetch', async () => {\n    const key = queryKey()\n    const hash = hashKey(key)\n    const spy = vi.fn(() => Promise.resolve('Works from queryFn'))\n\n    const mapStorage = new Map()\n    const storage = {\n      getItem: (itemKey: string) => Promise.resolve(mapStorage.get(itemKey)),\n      setItem: (itemKey: string, value: unknown) => {\n        mapStorage.set(itemKey, value)\n        return Promise.resolve()\n      },\n      removeItem: (itemKey: string) => {\n        mapStorage.delete(itemKey)\n        return Promise.resolve()\n      },\n    }\n\n    await storage.setItem(\n      `${PERSISTER_KEY_PREFIX}-${hash}`,\n      JSON.stringify({\n        buster: '',\n        queryHash: hash,\n        queryKey: key,\n        state: {\n          dataUpdatedAt: Date.now(),\n          data: 'Works from persister',\n        },\n      }),\n    )\n\n    function Test() {\n      const [_, setRef] = useState<HTMLDivElement | null>()\n\n      const { data } = useQuery({\n        queryKey: key,\n        queryFn: spy,\n        persister: experimental_createQueryPersister({\n          storage,\n        }).persisterFn,\n        staleTime: 5000,\n      })\n\n      return <div ref={(value) => setRef(value)}>{data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Test />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Works from persister')).toBeInTheDocument()\n    expect(spy).not.toHaveBeenCalled()\n  })\n\n  it('should restore query state from persister and refetch', async () => {\n    const key = queryKey()\n    const hash = hashKey(key)\n    const spy = vi.fn(async () => {\n      await sleep(5)\n\n      return 'Works from queryFn'\n    })\n\n    const mapStorage = new Map()\n    const storage = {\n      getItem: (itemKey: string) => Promise.resolve(mapStorage.get(itemKey)),\n      setItem: (itemKey: string, value: unknown) => {\n        mapStorage.set(itemKey, value)\n        return Promise.resolve()\n      },\n      removeItem: (itemKey: string) => {\n        mapStorage.delete(itemKey)\n        return Promise.resolve()\n      },\n    }\n\n    await storage.setItem(\n      `${PERSISTER_KEY_PREFIX}-${hash}`,\n      JSON.stringify({\n        buster: '',\n        queryHash: hash,\n        queryKey: key,\n        state: {\n          dataUpdatedAt: Date.now(),\n          data: 'Works from persister',\n        },\n      }),\n    )\n\n    function Test() {\n      const [_, setRef] = useState<HTMLDivElement | null>()\n\n      const { data } = useQuery({\n        queryKey: key,\n        queryFn: spy,\n        persister: experimental_createQueryPersister({\n          storage,\n        }).persisterFn,\n      })\n\n      return <div ref={(value) => setRef(value)}>{data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Test />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Works from persister')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(6)\n    expect(rendered.getByText('Works from queryFn')).toBeInTheDocument()\n    expect(spy).toHaveBeenCalledTimes(1)\n  })\n\n  it('should store query state to persister after fetch', async () => {\n    const key = queryKey()\n    const hash = hashKey(key)\n    const spy = vi.fn(() => Promise.resolve('Works from queryFn'))\n\n    const mapStorage = new Map()\n    const storage = {\n      getItem: (itemKey: string) => Promise.resolve(mapStorage.get(itemKey)),\n      setItem: (itemKey: string, value: unknown) => {\n        mapStorage.set(itemKey, value)\n        return Promise.resolve()\n      },\n      removeItem: (itemKey: string) => {\n        mapStorage.delete(itemKey)\n        return Promise.resolve()\n      },\n    }\n\n    function Test() {\n      const [_, setRef] = useState<HTMLDivElement | null>()\n\n      const { data } = useQuery({\n        queryKey: key,\n        queryFn: spy,\n        persister: experimental_createQueryPersister({\n          storage,\n        }).persisterFn,\n      })\n\n      return <div ref={(value) => setRef(value)}>{data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Test />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Works from queryFn')).toBeInTheDocument()\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    const storedItem = await storage.getItem(`${PERSISTER_KEY_PREFIX}-${hash}`)\n    expect(JSON.parse(storedItem)).toMatchObject({\n      state: {\n        data: 'Works from queryFn',\n      },\n    })\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/infiniteQueryOptions.test-d.tsx",
    "content": "import { QueryClient, dataTagSymbol, skipToken } from '@tanstack/query-core'\nimport type {\n  DataTag,\n  InfiniteData,\n  InitialDataFunction,\n} from '@tanstack/query-core'\nimport { assertType, describe, expectTypeOf, it, test } from 'vitest'\n\nimport { infiniteQueryOptions } from '../infiniteQueryOptions'\nimport { useInfiniteQuery } from '../useInfiniteQuery'\nimport { useQuery } from '../useQuery'\nimport { useSuspenseInfiniteQuery } from '../useSuspenseInfiniteQuery'\n\ndescribe('infiniteQueryOptions', () => {\n  it('should not allow excess properties', () => {\n    assertType(\n      infiniteQueryOptions({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve('data'),\n        getNextPageParam: () => 1,\n        initialPageParam: 1,\n        // @ts-expect-error this is a good error, because stallTime does not exist!\n        stallTime: 1000,\n      }),\n    )\n  })\n  it('should infer types for callbacks', () => {\n    infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('data'),\n      staleTime: 1000,\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n      select: (data) => {\n        expectTypeOf(data).toEqualTypeOf<InfiniteData<string, number>>()\n      },\n    })\n  })\n  it('should work when passed to useInfiniteQuery', () => {\n    const options = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    const { data } = useInfiniteQuery(options)\n\n    // known issue: type of pageParams is unknown when returned from useInfiniteQuery\n    expectTypeOf(data).toEqualTypeOf<\n      InfiniteData<string, unknown> | undefined\n    >()\n  })\n  it('should work when passed to useSuspenseInfiniteQuery', () => {\n    const options = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    const { data } = useSuspenseInfiniteQuery(options)\n\n    expectTypeOf(data).toEqualTypeOf<InfiniteData<string, unknown>>()\n  })\n  it('should work when passed to fetchInfiniteQuery', async () => {\n    const options = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    const data = await new QueryClient().fetchInfiniteQuery(options)\n\n    expectTypeOf(data).toEqualTypeOf<InfiniteData<string, number>>()\n  })\n  it('should tag the queryKey with the result type of the QueryFn', () => {\n    const { queryKey } = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<InfiniteData<string>>()\n  })\n  it('should tag the queryKey even if no promise is returned', () => {\n    const { queryKey } = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => 'string',\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<InfiniteData<string>>()\n  })\n  it('should tag the queryKey with the result type of the QueryFn if select is used', () => {\n    const { queryKey } = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      select: (data) => data.pages,\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<InfiniteData<string>>()\n  })\n  it('should return the proper type when passed to getQueryData', () => {\n    const { queryKey } = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryData(queryKey)\n\n    expectTypeOf(data).toEqualTypeOf<\n      InfiniteData<string, unknown> | undefined\n    >()\n  })\n  it('should properly type when passed to setQueryData', () => {\n    const { queryKey } = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.setQueryData(queryKey, (prev) => {\n      expectTypeOf(prev).toEqualTypeOf<\n        InfiniteData<string, unknown> | undefined\n      >()\n      return prev\n    })\n\n    expectTypeOf(data).toEqualTypeOf<\n      InfiniteData<string, unknown> | undefined\n    >()\n  })\n  it('should throw a type error when using queryFn with skipToken in a suspense query', () => {\n    const options = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn:\n        Math.random() > 0.5 ? skipToken : () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n    // @ts-expect-error TS2345\n    const { data } = useSuspenseInfiniteQuery(options)\n    expectTypeOf(data).toEqualTypeOf<InfiniteData<string, unknown>>()\n  })\n\n  test('should not be allowed to be passed to non-infinite query functions', () => {\n    const queryClient = new QueryClient()\n    const options = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n    assertType(\n      // @ts-expect-error cannot pass infinite options to non-infinite query functions\n      useQuery(options),\n    )\n    assertType(\n      // @ts-expect-error cannot pass infinite options to non-infinite query functions\n      queryClient.ensureQueryData(options),\n    )\n    assertType(\n      // @ts-expect-error cannot pass infinite options to non-infinite query functions\n      queryClient.fetchQuery(options),\n    )\n    assertType(\n      // @ts-expect-error cannot pass infinite options to non-infinite query functions\n      queryClient.prefetchQuery(options),\n    )\n  })\n\n  test('allow optional initialData function', () => {\n    const initialData: { example: boolean } | undefined = { example: true }\n    const queryOptions = infiniteQueryOptions({\n      queryKey: ['example'],\n      queryFn: () => initialData,\n      initialData: initialData\n        ? () => ({ pages: [initialData], pageParams: [] })\n        : undefined,\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n    expectTypeOf(queryOptions.initialData).toMatchTypeOf<\n      | InitialDataFunction<InfiniteData<{ example: boolean }, number>>\n      | InfiniteData<{ example: boolean }, number>\n      | undefined\n    >()\n  })\n\n  test('allow optional initialData object', () => {\n    const initialData: { example: boolean } | undefined = { example: true }\n    const queryOptions = infiniteQueryOptions({\n      queryKey: ['example'],\n      queryFn: () => initialData,\n      initialData: initialData\n        ? { pages: [initialData], pageParams: [] }\n        : undefined,\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n    expectTypeOf(queryOptions.initialData).toMatchTypeOf<\n      | InitialDataFunction<InfiniteData<{ example: boolean }, number>>\n      | InfiniteData<{ example: boolean }, number>\n      | undefined\n    >()\n  })\n\n  it('should return a custom query key type', () => {\n    type MyQueryKey = [Array<string>, { type: 'foo' }]\n\n    const options = infiniteQueryOptions({\n      queryKey: [['key'], { type: 'foo' }] as MyQueryKey,\n      queryFn: () => Promise.resolve(1),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    expectTypeOf(options.queryKey).toEqualTypeOf<\n      DataTag<MyQueryKey, InfiniteData<number>, Error>\n    >()\n  })\n\n  it('should return a custom query key type with datatag', () => {\n    type MyQueryKey = DataTag<\n      [Array<string>, { type: 'foo' }],\n      number,\n      Error & { myMessage: string }\n    >\n\n    const options = infiniteQueryOptions({\n      queryKey: [['key'], { type: 'foo' }] as MyQueryKey,\n      queryFn: () => Promise.resolve(1),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    expectTypeOf(options.queryKey).toEqualTypeOf<\n      DataTag<MyQueryKey, InfiniteData<number>, Error & { myMessage: string }>\n    >()\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/infiniteQueryOptions.test.tsx",
    "content": "import { describe, expect, it } from 'vitest'\n\nimport { infiniteQueryOptions } from '../infiniteQueryOptions'\nimport type { UseInfiniteQueryOptions } from '../types'\n\ndescribe('infiniteQueryOptions', () => {\n  it('should return the object received as a parameter without any modification.', () => {\n    const object: UseInfiniteQueryOptions = {\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n      getNextPageParam: () => null,\n      initialPageParam: null,\n    }\n\n    expect(infiniteQueryOptions(object)).toBe(object)\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/mutationOptions.test-d.tsx",
    "content": "import { QueryClient } from '@tanstack/query-core'\nimport type {\n  DefaultError,\n  MutationFunctionContext,\n  MutationState,\n  WithRequired,\n} from '@tanstack/query-core'\nimport { assertType, describe, expectTypeOf, it } from 'vitest'\n\nimport { useIsMutating, useMutation, useMutationState } from '..'\nimport { mutationOptions } from '../mutationOptions'\nimport type { UseMutationOptions, UseMutationResult } from '../types'\n\ndescribe('mutationOptions', () => {\n  it('should not allow excess properties', () => {\n    // @ts-expect-error this is a good error, because onMutates does not exist!\n    mutationOptions({\n      mutationFn: () => Promise.resolve(5),\n      mutationKey: ['key'],\n      onMutates: 1000,\n      onSuccess: (data) => {\n        expectTypeOf(data).toEqualTypeOf<number>()\n      },\n    })\n  })\n\n  it('should infer types for callbacks', () => {\n    mutationOptions({\n      mutationFn: () => Promise.resolve(5),\n      mutationKey: ['key'],\n      onSuccess: (data) => {\n        expectTypeOf(data).toEqualTypeOf<number>()\n      },\n    })\n  })\n\n  it('should infer types for onError callback', () => {\n    mutationOptions({\n      mutationFn: () => {\n        throw new Error('fail')\n      },\n      mutationKey: ['key'],\n      onError: (error) => {\n        expectTypeOf(error).toEqualTypeOf<DefaultError>()\n      },\n    })\n  })\n\n  it('should infer types for variables', () => {\n    mutationOptions<number, DefaultError, { id: string }>({\n      mutationFn: (vars) => {\n        expectTypeOf(vars).toEqualTypeOf<{ id: string }>()\n        return Promise.resolve(5)\n      },\n      mutationKey: ['with-vars'],\n    })\n  })\n\n  it('should infer result type correctly', () => {\n    mutationOptions<number, DefaultError, void, { name: string }>({\n      mutationFn: () => Promise.resolve(5),\n      mutationKey: ['key'],\n      onMutate: () => {\n        return { name: 'onMutateResult' }\n      },\n      onSuccess: (_data, _variables, onMutateResult) => {\n        expectTypeOf(onMutateResult).toEqualTypeOf<{ name: string }>()\n      },\n    })\n  })\n\n  it('should infer context type correctly', () => {\n    mutationOptions<number>({\n      mutationFn: (_variables, context) => {\n        expectTypeOf(context).toEqualTypeOf<MutationFunctionContext>()\n        return Promise.resolve(5)\n      },\n      mutationKey: ['key'],\n      onMutate: (_variables, context) => {\n        expectTypeOf(context).toEqualTypeOf<MutationFunctionContext>()\n      },\n      onSuccess: (_data, _variables, _onMutateResult, context) => {\n        expectTypeOf(context).toEqualTypeOf<MutationFunctionContext>()\n      },\n      onError: (_error, _variables, _onMutateResult, context) => {\n        expectTypeOf(context).toEqualTypeOf<MutationFunctionContext>()\n      },\n      onSettled: (_data, _error, _variables, _onMutateResult, context) => {\n        expectTypeOf(context).toEqualTypeOf<MutationFunctionContext>()\n      },\n    })\n  })\n\n  it('should error if mutationFn return type mismatches TData', () => {\n    assertType(\n      mutationOptions<number>({\n        // @ts-expect-error this is a good error, because return type is string, not number\n        mutationFn: async () => Promise.resolve('wrong return'),\n      }),\n    )\n  })\n\n  it('should allow mutationKey to be omitted', () => {\n    return mutationOptions({\n      mutationFn: () => Promise.resolve(123),\n      onSuccess: (data) => {\n        expectTypeOf(data).toEqualTypeOf<number>()\n      },\n    })\n  })\n\n  it('should infer all types when not explicitly provided', () => {\n    expectTypeOf(\n      mutationOptions({\n        mutationFn: (id: string) => Promise.resolve(id.length),\n        mutationKey: ['key'],\n        onSuccess: (data) => {\n          expectTypeOf(data).toEqualTypeOf<number>()\n        },\n      }),\n    ).toEqualTypeOf<\n      WithRequired<\n        UseMutationOptions<number, DefaultError, string>,\n        'mutationKey'\n      >\n    >()\n    expectTypeOf(\n      mutationOptions({\n        mutationFn: (id: string) => Promise.resolve(id.length),\n        onSuccess: (data) => {\n          expectTypeOf(data).toEqualTypeOf<number>()\n        },\n      }),\n    ).toEqualTypeOf<\n      Omit<UseMutationOptions<number, DefaultError, string>, 'mutationKey'>\n    >()\n  })\n\n  it('should infer types when used with useMutation', () => {\n    const mutation = useMutation(\n      mutationOptions({\n        mutationKey: ['key'],\n        mutationFn: () => Promise.resolve('data'),\n        onSuccess: (data) => {\n          expectTypeOf(data).toEqualTypeOf<string>()\n        },\n      }),\n    )\n    expectTypeOf(mutation).toEqualTypeOf<\n      UseMutationResult<string, DefaultError, void, unknown>\n    >()\n\n    useMutation(\n      // should allow when used with useMutation without mutationKey\n      mutationOptions({\n        mutationFn: () => Promise.resolve('data'),\n        onSuccess: (data) => {\n          expectTypeOf(data).toEqualTypeOf<string>()\n        },\n      }),\n    )\n  })\n\n  it('should infer types when used with useIsMutating', () => {\n    const isMutating = useIsMutating(\n      mutationOptions({\n        mutationKey: ['key'],\n        mutationFn: () => Promise.resolve(5),\n      }),\n    )\n    expectTypeOf(isMutating).toEqualTypeOf<number>()\n\n    useIsMutating(\n      // @ts-expect-error filters should have mutationKey\n      mutationOptions({\n        mutationFn: () => Promise.resolve(5),\n      }),\n    )\n  })\n\n  it('should infer types when used with queryClient.isMutating', () => {\n    const queryClient = new QueryClient()\n\n    const isMutating = queryClient.isMutating(\n      mutationOptions({\n        mutationKey: ['key'],\n        mutationFn: () => Promise.resolve(5),\n      }),\n    )\n    expectTypeOf(isMutating).toEqualTypeOf<number>()\n\n    queryClient.isMutating(\n      // @ts-expect-error filters should have mutationKey\n      mutationOptions({\n        mutationFn: () => Promise.resolve(5),\n      }),\n    )\n  })\n\n  it('should infer types when used with useMutationState', () => {\n    const mutationState = useMutationState({\n      filters: mutationOptions({\n        mutationKey: ['key'],\n        mutationFn: () => Promise.resolve(5),\n      }),\n    })\n    expectTypeOf(mutationState).toEqualTypeOf<\n      Array<MutationState<unknown, Error, unknown, unknown>>\n    >()\n\n    useMutationState({\n      // @ts-expect-error filters should have mutationKey\n      filters: mutationOptions({\n        mutationFn: () => Promise.resolve(5),\n      }),\n    })\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/mutationOptions.test.tsx",
    "content": "import { QueryClient } from '@tanstack/query-core'\nimport type { MutationState } from '@tanstack/query-core'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { fireEvent } from '@testing-library/preact'\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\n\nimport { useIsMutating, useMutation, useMutationState } from '..'\nimport { mutationOptions } from '../mutationOptions'\nimport { renderWithClient } from './utils'\nimport type { UseMutationOptions } from '../types'\n\ndescribe('mutationOptions', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should return the object received as a parameter without any modification (with mutationKey in mutationOptions)', () => {\n    const object: UseMutationOptions = {\n      mutationKey: ['key'],\n      mutationFn: () => sleep(10).then(() => 5),\n    } as const\n\n    expect(mutationOptions(object)).toBe(object)\n  })\n\n  it('should return the object received as a parameter without any modification (without mutationKey in mutationOptions)', () => {\n    const object: UseMutationOptions = {\n      mutationFn: () => sleep(10).then(() => 5),\n    } as const\n\n    expect(mutationOptions(object)).toBe(object)\n  })\n\n  it('should return the number of fetching mutations when used with useIsMutating (with mutationKey in mutationOptions)', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n    const mutationOpts = mutationOptions({\n      mutationKey: ['key'],\n      mutationFn: () => sleep(50).then(() => 'data'),\n    })\n\n    function IsMutating() {\n      const isMutating = useIsMutating()\n\n      isMutatingArray.push(isMutating)\n\n      return null\n    }\n\n    function Mutation() {\n      const { mutate } = useMutation(mutationOpts)\n\n      return (\n        <div>\n          <button onClick={() => mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    function Page() {\n      return (\n        <div>\n          <IsMutating />\n          <Mutation />\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    expect(isMutatingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isMutatingArray[1]).toEqual(1)\n    await vi.advanceTimersByTimeAsync(51)\n    expect(isMutatingArray[2]).toEqual(0)\n    expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0)\n  })\n\n  it('should return the number of fetching mutations when used with useIsMutating (without mutationKey in mutationOptions)', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n    const mutationOpts = mutationOptions({\n      mutationFn: () => sleep(50).then(() => 'data'),\n    })\n\n    function IsMutating() {\n      const isMutating = useIsMutating()\n\n      isMutatingArray.push(isMutating)\n\n      return null\n    }\n\n    function Mutation() {\n      const { mutate } = useMutation(mutationOpts)\n\n      return (\n        <div>\n          <button onClick={() => mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    function Page() {\n      return (\n        <div>\n          <IsMutating />\n          <Mutation />\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    expect(isMutatingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isMutatingArray[1]).toEqual(1)\n    await vi.advanceTimersByTimeAsync(51)\n    expect(isMutatingArray[2]).toEqual(0)\n    expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0)\n  })\n\n  it('should return the number of fetching mutations when used with useIsMutating', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['key'],\n      mutationFn: () => sleep(50).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(50).then(() => 'data2'),\n    })\n\n    function IsMutating() {\n      const isMutating = useIsMutating()\n\n      isMutatingArray.push(isMutating)\n\n      return null\n    }\n\n    function Mutation() {\n      const { mutate: mutate1 } = useMutation(mutationOpts1)\n      const { mutate: mutate2 } = useMutation(mutationOpts2)\n\n      return (\n        <div>\n          <button onClick={() => mutate1()}>mutate1</button>\n          <button onClick={() => mutate2()}>mutate2</button>\n        </div>\n      )\n    }\n\n    function Page() {\n      return (\n        <div>\n          <IsMutating />\n          <Mutation />\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n    expect(isMutatingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isMutatingArray[1]).toEqual(2)\n    await vi.advanceTimersByTimeAsync(51)\n    expect(isMutatingArray[2]).toEqual(0)\n    expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0)\n  })\n\n  it('should return the number of fetching mutations when used with useIsMutating (filter mutationOpts1.mutationKey)', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['key'],\n      mutationFn: () => sleep(50).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(50).then(() => 'data2'),\n    })\n\n    function IsMutating() {\n      const isMutating = useIsMutating({\n        mutationKey: mutationOpts1.mutationKey,\n      })\n\n      isMutatingArray.push(isMutating)\n\n      return null\n    }\n\n    function Mutation() {\n      const { mutate: mutate1 } = useMutation(mutationOpts1)\n      const { mutate: mutate2 } = useMutation(mutationOpts2)\n\n      return (\n        <div>\n          <button onClick={() => mutate1()}>mutate1</button>\n          <button onClick={() => mutate2()}>mutate2</button>\n        </div>\n      )\n    }\n\n    function Page() {\n      return (\n        <div>\n          <IsMutating />\n          <Mutation />\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n    expect(isMutatingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isMutatingArray[1]).toEqual(1)\n    await vi.advanceTimersByTimeAsync(51)\n    expect(isMutatingArray[2]).toEqual(0)\n    expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0)\n  })\n\n  it('should return the number of fetching mutations when used with queryClient.isMutating (with mutationKey in mutationOptions)', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n    const mutationOpts = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(500).then(() => 'data'),\n    })\n\n    function Mutation() {\n      const isMutating = queryClient.isMutating(mutationOpts)\n      const { mutate } = useMutation(mutationOpts)\n\n      isMutatingArray.push(isMutating)\n\n      return (\n        <div>\n          <button onClick={() => mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Mutation />)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    expect(isMutatingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isMutatingArray[1]).toEqual(1)\n    await vi.advanceTimersByTimeAsync(501)\n    expect(isMutatingArray[2]).toEqual(0)\n    expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0)\n  })\n\n  it('should return the number of fetching mutations when used with queryClient.isMutating (without mutationKey in mutationOptions)', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n    const mutationOpts = mutationOptions({\n      mutationFn: () => sleep(500).then(() => 'data'),\n    })\n\n    function Mutation() {\n      const isMutating = queryClient.isMutating()\n      const { mutate } = useMutation(mutationOpts)\n\n      isMutatingArray.push(isMutating)\n\n      return (\n        <div>\n          <button onClick={() => mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Mutation />)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    expect(isMutatingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isMutatingArray[1]).toEqual(1)\n    await vi.advanceTimersByTimeAsync(501)\n    expect(isMutatingArray[2]).toEqual(0)\n    expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0)\n  })\n\n  it('should return the number of fetching mutations when used with queryClient.isMutating', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(500).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(500).then(() => 'data2'),\n    })\n\n    function Mutation() {\n      const isMutating = queryClient.isMutating()\n      const { mutate: mutate1 } = useMutation(mutationOpts1)\n      const { mutate: mutate2 } = useMutation(mutationOpts2)\n\n      isMutatingArray.push(isMutating)\n\n      return (\n        <div>\n          <button onClick={() => mutate1()}>mutate1</button>\n          <button onClick={() => mutate2()}>mutate2</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Mutation />)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n    expect(isMutatingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isMutatingArray[1]).toEqual(2)\n    await vi.advanceTimersByTimeAsync(501)\n    expect(isMutatingArray[2]).toEqual(0)\n    expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0)\n  })\n\n  it('should return the number of fetching mutations when used with queryClient.isMutating (filter mutationOpt1.mutationKey)', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(500).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(500).then(() => 'data2'),\n    })\n\n    function Mutation() {\n      const isMutating = queryClient.isMutating({\n        mutationKey: mutationOpts1.mutationKey,\n      })\n      const { mutate: mutate1 } = useMutation(mutationOpts1)\n      const { mutate: mutate2 } = useMutation(mutationOpts2)\n\n      isMutatingArray.push(isMutating)\n\n      return (\n        <div>\n          <button onClick={() => mutate1()}>mutate1</button>\n          <button onClick={() => mutate2()}>mutate2</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Mutation />)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n    expect(isMutatingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isMutatingArray[1]).toEqual(1)\n    await vi.advanceTimersByTimeAsync(501)\n    expect(isMutatingArray[2]).toEqual(0)\n    expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0)\n  })\n\n  it('should return the number of fetching mutations when used with useMutationState (with mutationKey in mutationOptions)', async () => {\n    const mutationStateArray: Array<\n      MutationState<unknown, Error, unknown, unknown>\n    > = []\n    const queryClient = new QueryClient()\n    const mutationOpts = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(10).then(() => 'data'),\n    })\n\n    function Mutation() {\n      const { mutate } = useMutation(mutationOpts)\n      const data = useMutationState({\n        filters: { mutationKey: mutationOpts.mutationKey, status: 'success' },\n      })\n\n      mutationStateArray.push(...data)\n\n      return (\n        <div>\n          <button onClick={() => mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Mutation />)\n\n    expect(mutationStateArray.length).toEqual(0)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(mutationStateArray.length).toEqual(1)\n    expect(mutationStateArray[0]?.data).toEqual('data')\n  })\n\n  it('should return the number of fetching mutations when used with useMutationState (without mutationKey in mutationOptions)', async () => {\n    const mutationStateArray: Array<\n      MutationState<unknown, Error, unknown, unknown>\n    > = []\n    const queryClient = new QueryClient()\n    const mutationOpts = mutationOptions({\n      mutationFn: () => sleep(10).then(() => 'data'),\n    })\n\n    function Mutation() {\n      const { mutate } = useMutation(mutationOpts)\n      const data = useMutationState({\n        filters: { status: 'success' },\n      })\n\n      mutationStateArray.push(...data)\n\n      return (\n        <div>\n          <button onClick={() => mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Mutation />)\n\n    expect(mutationStateArray.length).toEqual(0)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(mutationStateArray.length).toEqual(1)\n    expect(mutationStateArray[0]?.data).toEqual('data')\n  })\n\n  it('should return the number of fetching mutations when used with useMutationState', async () => {\n    const mutationStateArray: Array<\n      MutationState<unknown, Error, unknown, unknown>\n    > = []\n    const queryClient = new QueryClient()\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(10).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(10).then(() => 'data2'),\n    })\n\n    function Mutation() {\n      const { mutate: mutate1 } = useMutation(mutationOpts1)\n      const { mutate: mutate2 } = useMutation(mutationOpts2)\n      const data = useMutationState({\n        filters: { status: 'success' },\n      })\n\n      mutationStateArray.push(...data)\n\n      return (\n        <div>\n          <button onClick={() => mutate1()}>mutate1</button>\n          <button onClick={() => mutate2()}>mutate2</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Mutation />)\n\n    expect(mutationStateArray.length).toEqual(0)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(mutationStateArray.length).toEqual(2)\n    expect(mutationStateArray[0]?.data).toEqual('data1')\n    expect(mutationStateArray[1]?.data).toEqual('data2')\n  })\n\n  it('should return the number of fetching mutations when used with useMutationState (filter mutationOpt1.mutationKey)', async () => {\n    const mutationStateArray: Array<\n      MutationState<unknown, Error, unknown, unknown>\n    > = []\n    const queryClient = new QueryClient()\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(10).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(10).then(() => 'data2'),\n    })\n\n    function Mutation() {\n      const { mutate: mutate1 } = useMutation(mutationOpts1)\n      const { mutate: mutate2 } = useMutation(mutationOpts2)\n      const data = useMutationState({\n        filters: { mutationKey: mutationOpts1.mutationKey, status: 'success' },\n      })\n\n      mutationStateArray.push(...data)\n\n      return (\n        <div>\n          <button onClick={() => mutate1()}>mutate1</button>\n          <button onClick={() => mutate2()}>mutate2</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Mutation />)\n\n    expect(mutationStateArray.length).toEqual(0)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(mutationStateArray.length).toEqual(1)\n    expect(mutationStateArray[0]?.data).toEqual('data1')\n    expect(mutationStateArray[1]).toBeFalsy()\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/queryOptions.test-d.tsx",
    "content": "import {\n  QueriesObserver,\n  QueryClient,\n  dataTagSymbol,\n  skipToken,\n} from '@tanstack/query-core'\nimport type {\n  DataTag,\n  InitialDataFunction,\n  QueryObserverResult,\n} from '@tanstack/query-core'\nimport { assertType, describe, expectTypeOf, it } from 'vitest'\n\nimport { queryOptions } from '../queryOptions'\nimport type { AnyUseQueryOptions } from '../types'\nimport { useQueries } from '../useQueries'\nimport { useQuery } from '../useQuery'\nimport { useSuspenseQuery } from '../useSuspenseQuery'\n\ndescribe('queryOptions', () => {\n  it('should not allow excess properties', () => {\n    assertType(\n      queryOptions({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        // @ts-expect-error this is a good error, because stallTime does not exist!\n        stallTime: 1000,\n      }),\n    )\n  })\n  it('should infer types for callbacks', () => {\n    queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n      staleTime: 1000,\n      select: (data) => {\n        expectTypeOf(data).toEqualTypeOf<number>()\n      },\n    })\n  })\n  it('should work when passed to useQuery', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const { data } = useQuery(options)\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n  it('should work when passed to useSuspenseQuery', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const { data } = useSuspenseQuery(options)\n    expectTypeOf(data).toEqualTypeOf<number>()\n  })\n\n  it('should work when passed to fetchQuery', async () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const data = await new QueryClient().fetchQuery(options)\n    expectTypeOf(data).toEqualTypeOf<number>()\n  })\n  it('should work when passed to useQueries', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const [{ data }] = useQueries({\n      queries: [options],\n    })\n\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n  it('should tag the queryKey with the result type of the QueryFn', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<number>()\n  })\n  it('should tag the queryKey even if no promise is returned', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => 5,\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<number>()\n  })\n  it('should tag the queryKey with unknown if there is no queryFn', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<unknown>()\n  })\n  it('should tag the queryKey with the result type of the QueryFn if select is used', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n      select: (data) => data.toString(),\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<number>()\n  })\n  it('should return the proper type when passed to getQueryData', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryData(queryKey)\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n  it('should return the proper type when passed to getQueryState', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n    const state = queryClient.getQueryState(queryKey)\n    expectTypeOf(state?.data).toEqualTypeOf<number | undefined>()\n  })\n  it('should properly type updaterFn when passed to setQueryData', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.setQueryData(queryKey, (prev) => {\n      expectTypeOf(prev).toEqualTypeOf<number | undefined>()\n      return prev\n    })\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n  it('should properly type value when passed to setQueryData', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n\n    // @ts-expect-error value should be a number\n    queryClient.setQueryData(queryKey, '5')\n    // @ts-expect-error value should be a number\n    queryClient.setQueryData(queryKey, () => '5')\n\n    const data = queryClient.setQueryData(queryKey, 5)\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n\n  it('should infer even if there is a conditional skipToken', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryData(options.queryKey)\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n\n  it('should infer to unknown if we disable a query with just a skipToken', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: skipToken,\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryData(options.queryKey)\n    expectTypeOf(data).toEqualTypeOf<unknown>()\n  })\n\n  it('should throw a type error when using queryFn with skipToken in a suspense query', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),\n    })\n    // @ts-expect-error TS2345\n    const { data } = useSuspenseQuery(options)\n    expectTypeOf(data).toEqualTypeOf<number>()\n  })\n\n  it('should return the proper type when passed to QueriesObserver', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n    const queriesObserver = new QueriesObserver(queryClient, [options])\n    expectTypeOf(queriesObserver).toEqualTypeOf<\n      QueriesObserver<Array<QueryObserverResult>>\n    >()\n  })\n\n  it('should allow undefined response in initialData', () => {\n    assertType((id: string | null) =>\n      queryOptions({\n        queryKey: ['todo', id],\n        queryFn: () =>\n          Promise.resolve({\n            id: '1',\n            title: 'Do Laundry',\n          }),\n        initialData: () =>\n          !id\n            ? undefined\n            : {\n                id,\n                title: 'Initial Data',\n              },\n      }),\n    )\n  })\n\n  it('should allow optional initialData object', () => {\n    const testFn = (id?: string) => {\n      const options = queryOptions({\n        queryKey: ['test'],\n        queryFn: () => Promise.resolve('something string'),\n        initialData: id ? 'initial string' : undefined,\n      })\n      expectTypeOf(options.initialData).toMatchTypeOf<\n        InitialDataFunction<string> | string | undefined\n      >()\n    }\n    testFn('id')\n    testFn()\n  })\n\n  it('should be passable to UseQueryOptions', () => {\n    function somethingWithQueryOptions<TQueryOpts extends AnyUseQueryOptions>(\n      options: TQueryOpts,\n    ) {\n      return options.queryKey\n    }\n\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(1),\n    })\n\n    assertType(somethingWithQueryOptions(options))\n  })\n\n  it('should return a custom query key type', () => {\n    type MyQueryKey = [Array<string>, { type: 'foo' }]\n\n    const options = queryOptions({\n      queryKey: [['key'], { type: 'foo' }] as MyQueryKey,\n      queryFn: () => Promise.resolve(1),\n    })\n\n    expectTypeOf(options.queryKey).toEqualTypeOf<\n      DataTag<MyQueryKey, number, Error>\n    >()\n  })\n\n  it('should return a custom query key type with datatag', () => {\n    type MyQueryKey = DataTag<\n      [Array<string>, { type: 'foo' }],\n      number,\n      Error & { myMessage: string }\n    >\n\n    const options = queryOptions({\n      queryKey: [['key'], { type: 'foo' }] as MyQueryKey,\n      queryFn: () => Promise.resolve(1),\n    })\n\n    expectTypeOf(options.queryKey).toEqualTypeOf<\n      DataTag<MyQueryKey, number, Error & { myMessage: string }>\n    >()\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/queryOptions.test.tsx",
    "content": "import { describe, expect, it } from 'vitest'\n\nimport { queryOptions } from '../queryOptions'\nimport type { UseQueryOptions } from '../types'\n\ndescribe('queryOptions', () => {\n  it('should return the object received as a parameter without any modification.', () => {\n    const object: UseQueryOptions = {\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    } as const\n\n    expect(queryOptions(object)).toBe(object)\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/ssr-hydration.test.tsx",
    "content": "import { act } from '@testing-library/preact'\nimport { hydrate as preactHydrate, render } from 'preact'\nimport type { VNode } from 'preact'\nimport { renderToString } from 'preact-render-to-string'\nimport { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'\n\nimport {\n  QueryCache,\n  QueryClient,\n  QueryClientProvider,\n  dehydrate,\n  hydrate,\n  useQuery,\n} from '..'\nimport { setIsServer } from './utils'\n\nconst PreactHydrate = (element: VNode, container: Element) => {\n  act(() => {\n    preactHydrate(element, container)\n  })\n  // To unmount in Preact, you render null into the same container\n  return () => {\n    act(() => {\n      render(null, container)\n    })\n  }\n}\n\nasync function fetchData<TData>(value: TData, ms?: number): Promise<TData> {\n  await vi.advanceTimersByTimeAsync(ms || 1)\n  return value\n}\n\nfunction PrintStateComponent({ componentName, result }: any): any {\n  return `${componentName} - status:${result.status} fetching:${result.isFetching} data:${result.data}`\n}\n\ndescribe('Server side rendering with de/rehydration', () => {\n  beforeAll(() => {\n    vi.useFakeTimers()\n  })\n\n  afterAll(() => {\n    vi.useRealTimers()\n  })\n\n  it('should not mismatch on success', async () => {\n    const consoleMock = vi.spyOn(console, 'error')\n    consoleMock.mockImplementation(() => undefined)\n\n    const fetchDataSuccess = vi.fn<typeof fetchData>(fetchData)\n\n    // -- Shared part --\n    function SuccessComponent() {\n      const result = useQuery({\n        queryKey: ['success'],\n        queryFn: () => fetchDataSuccess('success!'),\n      })\n      return (\n        <PrintStateComponent componentName=\"SuccessComponent\" result={result} />\n      )\n    }\n\n    // -- Server part --\n    setIsServer(true)\n\n    const prefetchCache = new QueryCache()\n    const prefetchClient = new QueryClient({\n      queryCache: prefetchCache,\n    })\n    await prefetchClient.prefetchQuery({\n      queryKey: ['success'],\n      queryFn: () => fetchDataSuccess('success'),\n    })\n    const dehydratedStateServer = dehydrate(prefetchClient)\n    const renderCache = new QueryCache()\n    const renderClient = new QueryClient({\n      queryCache: renderCache,\n    })\n    hydrate(renderClient, dehydratedStateServer)\n    const markup = renderToString(\n      <QueryClientProvider client={renderClient}>\n        <SuccessComponent />\n      </QueryClientProvider>,\n    )\n    const stringifiedState = JSON.stringify(dehydratedStateServer)\n    renderClient.clear()\n    setIsServer(false)\n\n    const expectedMarkup =\n      'SuccessComponent - status:success fetching:true data:success'\n\n    expect(markup).toBe(expectedMarkup)\n    expect(fetchDataSuccess).toHaveBeenCalledTimes(1)\n\n    // -- Client part --\n    const el = document.createElement('div')\n    el.innerHTML = markup\n\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({ queryCache })\n    hydrate(queryClient, JSON.parse(stringifiedState))\n\n    const unmount = PreactHydrate(\n      <QueryClientProvider client={queryClient}>\n        <SuccessComponent />\n      </QueryClientProvider>,\n      el,\n    )\n\n    // Check that we have no React hydration mismatches\n    expect(consoleMock).toHaveBeenCalledTimes(0)\n\n    expect(fetchDataSuccess).toHaveBeenCalledTimes(2)\n    expect(el.innerHTML).toBe(expectedMarkup)\n\n    unmount()\n    queryClient.clear()\n    consoleMock.mockRestore()\n  })\n\n  it('should not mismatch on error', async () => {\n    const consoleMock = vi.spyOn(console, 'error')\n    consoleMock.mockImplementation(() => undefined)\n\n    const fetchDataError = vi.fn(() => {\n      throw new Error('fetchDataError')\n    })\n\n    // -- Shared part --\n    function ErrorComponent() {\n      const result = useQuery({\n        queryKey: ['error'],\n        queryFn: () => fetchDataError(),\n        retry: false,\n      })\n      return (\n        <PrintStateComponent componentName=\"ErrorComponent\" result={result} />\n      )\n    }\n\n    // -- Server part --\n    setIsServer(true)\n    const prefetchCache = new QueryCache()\n    const prefetchClient = new QueryClient({\n      queryCache: prefetchCache,\n    })\n    await prefetchClient.prefetchQuery({\n      queryKey: ['error'],\n      queryFn: () => fetchDataError(),\n    })\n    const dehydratedStateServer = dehydrate(prefetchClient)\n    const renderCache = new QueryCache()\n    const renderClient = new QueryClient({\n      queryCache: renderCache,\n    })\n    hydrate(renderClient, dehydratedStateServer)\n    const markup = renderToString(\n      <QueryClientProvider client={renderClient}>\n        <ErrorComponent />\n      </QueryClientProvider>,\n    )\n    const stringifiedState = JSON.stringify(dehydratedStateServer)\n    renderClient.clear()\n    setIsServer(false)\n\n    const expectedMarkup =\n      'ErrorComponent - status:pending fetching:true data:undefined'\n\n    expect(markup).toBe(expectedMarkup)\n\n    // -- Client part --\n    const el = document.createElement('div')\n    el.innerHTML = markup\n\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({ queryCache })\n    hydrate(queryClient, JSON.parse(stringifiedState))\n\n    const unmount = PreactHydrate(\n      <QueryClientProvider client={queryClient}>\n        <ErrorComponent />\n      </QueryClientProvider>,\n      el,\n    )\n\n    expect(consoleMock).toHaveBeenCalledTimes(0)\n    expect(fetchDataError).toHaveBeenCalledTimes(2)\n    expect(el.innerHTML).toBe(expectedMarkup)\n    await vi.advanceTimersByTimeAsync(50)\n    expect(fetchDataError).toHaveBeenCalledTimes(2)\n    expect(el.innerHTML).toBe(\n      'ErrorComponent - status:error fetching:false data:undefined',\n    )\n\n    unmount()\n    queryClient.clear()\n    consoleMock.mockRestore()\n  })\n\n  it('should not mismatch on queries that were not prefetched', async () => {\n    const consoleMock = vi.spyOn(console, 'error')\n    consoleMock.mockImplementation(() => undefined)\n\n    const fetchDataSuccess = vi.fn<typeof fetchData>(fetchData)\n\n    // -- Shared part --\n    function SuccessComponent() {\n      const result = useQuery({\n        queryKey: ['success'],\n        queryFn: () => fetchDataSuccess('success!'),\n      })\n      return (\n        <PrintStateComponent componentName=\"SuccessComponent\" result={result} />\n      )\n    }\n\n    // -- Server part --\n    setIsServer(true)\n\n    const prefetchClient = new QueryClient()\n    const dehydratedStateServer = dehydrate(prefetchClient)\n    const renderClient = new QueryClient()\n    hydrate(renderClient, dehydratedStateServer)\n    const markup = renderToString(\n      <QueryClientProvider client={renderClient}>\n        <SuccessComponent />\n      </QueryClientProvider>,\n    )\n    const stringifiedState = JSON.stringify(dehydratedStateServer)\n    renderClient.clear()\n    setIsServer(false)\n\n    const expectedMarkup =\n      'SuccessComponent - status:pending fetching:true data:undefined'\n\n    expect(markup).toBe(expectedMarkup)\n\n    // -- Client part --\n    const el = document.createElement('div')\n    el.innerHTML = markup\n\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({ queryCache })\n    hydrate(queryClient, JSON.parse(stringifiedState))\n\n    const unmount = PreactHydrate(\n      <QueryClientProvider client={queryClient}>\n        <SuccessComponent />\n      </QueryClientProvider>,\n      el,\n    )\n\n    // Check that we have no React hydration mismatches\n    expect(consoleMock).toHaveBeenCalledTimes(0)\n    expect(fetchDataSuccess).toHaveBeenCalledTimes(1)\n    expect(el.innerHTML).toBe(expectedMarkup)\n    await vi.advanceTimersByTimeAsync(50)\n    expect(fetchDataSuccess).toHaveBeenCalledTimes(1)\n    expect(el.innerHTML).toBe(\n      'SuccessComponent - status:success fetching:false data:success!',\n    )\n\n    unmount()\n    queryClient.clear()\n    consoleMock.mockRestore()\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/ssr.test.tsx",
    "content": "import { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { renderToString } from 'preact-render-to-string'\nimport { useState } from 'preact/hooks'\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\n\nimport {\n  QueryCache,\n  QueryClient,\n  QueryClientProvider,\n  useInfiniteQuery,\n  useMutationState,\n  useQuery,\n} from '..'\nimport { setIsServer } from './utils'\n\ndescribe('Server Side Rendering', () => {\n  setIsServer(true)\n\n  let queryCache: QueryCache\n  let queryClient: QueryClient\n\n  beforeEach(() => {\n    vi.useFakeTimers()\n    queryCache = new QueryCache()\n    queryClient = new QueryClient({ queryCache })\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should not trigger fetch', () => {\n    const key = queryKey()\n    const queryFn = vi.fn(() => sleep(10).then(() => 'data'))\n\n    function Page() {\n      const query = useQuery({ queryKey: key, queryFn })\n\n      const content = `status ${query.status}`\n\n      return (\n        <div>\n          <div>{content}</div>\n        </div>\n      )\n    }\n\n    const markup = renderToString(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    expect(markup).toContain('status pending')\n    expect(queryFn).toHaveBeenCalledTimes(0)\n\n    queryCache.clear()\n  })\n\n  it('should add prefetched data to cache', async () => {\n    const key = queryKey()\n\n    const promise = queryClient.fetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'data'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const data = await promise\n\n    expect(data).toBe('data')\n    expect(queryCache.find({ queryKey: key })?.state.data).toBe('data')\n\n    queryCache.clear()\n  })\n\n  it('should return existing data from the cache', async () => {\n    const key = queryKey()\n    const queryFn = vi.fn(() => sleep(10).then(() => 'data'))\n\n    function Page() {\n      const query = useQuery({ queryKey: key, queryFn })\n\n      const content = `status ${query.status}`\n\n      return (\n        <div>\n          <div>{content}</div>\n        </div>\n      )\n    }\n\n    queryClient.prefetchQuery({ queryKey: key, queryFn })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const markup = renderToString(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    expect(markup).toContain('status success')\n    expect(queryFn).toHaveBeenCalledTimes(1)\n\n    queryCache.clear()\n  })\n\n  it('should add initialData to the cache', () => {\n    const key = queryKey()\n\n    function Page() {\n      const [page, setPage] = useState(1)\n      const { data } = useQuery({\n        queryKey: [key, page],\n        queryFn: () => sleep(10).then(() => page),\n        initialData: 1,\n      })\n\n      return (\n        <div>\n          <h1 data-testid=\"title\">{data}</h1>\n          <button onClick={() => setPage(page + 1)}>next</button>\n        </div>\n      )\n    }\n\n    renderToString(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    const keys = queryCache.getAll().map((query) => query.queryKey)\n\n    expect(keys).toEqual([[key, 1]])\n\n    queryCache.clear()\n  })\n\n  it('useMutationState should return empty array', () => {\n    function Page() {\n      const mutationState = useMutationState()\n\n      return <div>{`mutationState: ${mutationState.length}`}</div>\n    }\n\n    const markup = renderToString(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    expect(markup).toContain('mutationState: 0')\n\n    queryCache.clear()\n  })\n\n  it('useInfiniteQuery should return the correct state', async () => {\n    const key = queryKey()\n    const queryFn = vi.fn(() => sleep(10).then(() => 'page 1'))\n\n    function Page() {\n      const query = useInfiniteQuery({\n        queryKey: key,\n        queryFn,\n        getNextPageParam: () => undefined,\n        initialPageParam: 0,\n      })\n      return (\n        <ul>\n          {query.data?.pages.map((page) => (\n            <li key={page}>{page}</li>\n          ))}\n        </ul>\n      )\n    }\n\n    queryClient.prefetchInfiniteQuery({\n      queryKey: key,\n      queryFn,\n      initialPageParam: 0,\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const markup = renderToString(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    expect(markup).toContain('page 1')\n    expect(queryFn).toHaveBeenCalledTimes(1)\n\n    queryCache.clear()\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/suspense.test.tsx",
    "content": "import { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { render } from '@testing-library/preact'\nimport type { ComponentChildren } from 'preact'\nimport { Suspense } from 'preact/compat'\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\n\nimport { QueryClient, QueryClientProvider, useSuspenseQuery } from '..'\nimport type { StaleTime } from '@tanstack/query-core'\nimport type { QueryKey } from '..'\n\nfunction renderWithSuspense(client: QueryClient, ui: ComponentChildren) {\n  return render(\n    <QueryClientProvider client={client}>\n      <Suspense fallback=\"loading\">{ui}</Suspense>\n    </QueryClientProvider>,\n  )\n}\n\nfunction createTestQuery(options: {\n  fetchCount: { count: number }\n  queryKey: QueryKey\n  staleTime?: StaleTime | (() => StaleTime)\n}) {\n  return function TestComponent() {\n    const { data } = useSuspenseQuery({\n      queryKey: options.queryKey,\n      queryFn: () =>\n        sleep(10).then(() => {\n          options.fetchCount.count++\n          return 'data'\n        }),\n      staleTime: options.staleTime,\n    })\n    return <div>data: {data}</div>\n  }\n}\n\ndescribe('Suspense Timer Tests', () => {\n  let queryClient: QueryClient\n  let fetchCount: { count: number }\n\n  beforeEach(() => {\n    vi.useFakeTimers()\n    queryClient = new QueryClient({\n      defaultOptions: {\n        queries: {\n          retry: false,\n        },\n      },\n    })\n    fetchCount = { count: 0 }\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should enforce minimum staleTime of 1000ms when using suspense with number', async () => {\n    const TestComponent = createTestQuery({\n      fetchCount,\n      queryKey: ['test'],\n      staleTime: 10,\n    })\n\n    const rendered = renderWithSuspense(queryClient, <TestComponent />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: data')).toBeInTheDocument()\n\n    rendered.rerender(\n      <QueryClientProvider client={queryClient}>\n        <Suspense fallback=\"loading\">\n          <TestComponent />\n        </Suspense>\n      </QueryClientProvider>,\n    )\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(fetchCount.count).toBe(1)\n  })\n\n  it('should enforce minimum staleTime of 1000ms when using suspense with function', async () => {\n    const TestComponent = createTestQuery({\n      fetchCount,\n      queryKey: ['test-func'],\n      staleTime: () => 10,\n    })\n\n    const rendered = renderWithSuspense(queryClient, <TestComponent />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: data')).toBeInTheDocument()\n\n    rendered.rerender(\n      <QueryClientProvider client={queryClient}>\n        <Suspense fallback=\"loading\">\n          <TestComponent />\n        </Suspense>\n      </QueryClientProvider>,\n    )\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(fetchCount.count).toBe(1)\n  })\n\n  it('should respect staleTime when value is greater than 1000ms', async () => {\n    const TestComponent = createTestQuery({\n      fetchCount,\n      queryKey: queryKey(),\n      staleTime: 2000,\n    })\n\n    const rendered = renderWithSuspense(queryClient, <TestComponent />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: data')).toBeInTheDocument()\n\n    rendered.rerender(\n      <QueryClientProvider client={queryClient}>\n        <Suspense fallback=\"loading\">\n          <TestComponent />\n        </Suspense>\n      </QueryClientProvider>,\n    )\n\n    await vi.advanceTimersByTimeAsync(1500)\n\n    expect(fetchCount.count).toBe(1)\n  })\n\n  it('should enforce minimum staleTime when undefined is provided', async () => {\n    const TestComponent = createTestQuery({\n      fetchCount,\n      queryKey: queryKey(),\n      staleTime: undefined,\n    })\n\n    const rendered = renderWithSuspense(queryClient, <TestComponent />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: data')).toBeInTheDocument()\n\n    rendered.rerender(\n      <QueryClientProvider client={queryClient}>\n        <Suspense fallback=\"loading\">\n          <TestComponent />\n        </Suspense>\n      </QueryClientProvider>,\n    )\n\n    await vi.advanceTimersByTimeAsync(500)\n\n    expect(fetchCount.count).toBe(1)\n  })\n\n  it('should preserve staleTime when value is static', async () => {\n    const TestComponent = createTestQuery({\n      fetchCount,\n      queryKey: queryKey(),\n      staleTime: 'static',\n    })\n\n    const rendered = renderWithSuspense(queryClient, <TestComponent />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: data')).toBeInTheDocument()\n\n    rendered.rerender(\n      <QueryClientProvider client={queryClient}>\n        <Suspense fallback=\"loading\">\n          <TestComponent />\n        </Suspense>\n      </QueryClientProvider>,\n    )\n\n    await vi.advanceTimersByTimeAsync(2000)\n\n    expect(fetchCount.count).toBe(1)\n  })\n\n  it('should preserve staleTime when function returns static', async () => {\n    const TestComponent = createTestQuery({\n      fetchCount,\n      queryKey: queryKey(),\n      staleTime: () => 'static',\n    })\n\n    const rendered = renderWithSuspense(queryClient, <TestComponent />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: data')).toBeInTheDocument()\n\n    rendered.rerender(\n      <QueryClientProvider client={queryClient}>\n        <Suspense fallback=\"loading\">\n          <TestComponent />\n        </Suspense>\n      </QueryClientProvider>,\n    )\n\n    await vi.advanceTimersByTimeAsync(2000)\n\n    expect(fetchCount.count).toBe(1)\n  })\n\n  it('should respect staleTime when function returns value greater than 1000ms', async () => {\n    const TestComponent = createTestQuery({\n      fetchCount,\n      queryKey: queryKey(),\n      staleTime: () => 3000,\n    })\n\n    const rendered = renderWithSuspense(queryClient, <TestComponent />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: data')).toBeInTheDocument()\n\n    rendered.rerender(\n      <QueryClientProvider client={queryClient}>\n        <Suspense fallback=\"loading\">\n          <TestComponent />\n        </Suspense>\n      </QueryClientProvider>,\n    )\n\n    await vi.advanceTimersByTimeAsync(2000)\n\n    expect(fetchCount.count).toBe(1)\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/useInfiniteQuery.test-d.tsx",
    "content": "import { QueryClient } from '@tanstack/query-core'\nimport type { InfiniteData } from '@tanstack/query-core'\nimport { describe, expectTypeOf, it } from 'vitest'\n\nimport { useInfiniteQuery } from '../useInfiniteQuery'\n\ndescribe('pageParam', () => {\n  it('initialPageParam should define type of param passed to queryFunctionContext', () => {\n    useInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: ({ pageParam }) => {\n        expectTypeOf(pageParam).toEqualTypeOf<number>()\n      },\n      initialPageParam: 1,\n      getNextPageParam: () => undefined,\n    })\n  })\n\n  it('direction should be passed to queryFn of useInfiniteQuery', () => {\n    useInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: ({ direction }) => {\n        expectTypeOf(direction).toEqualTypeOf<'forward' | 'backward'>()\n      },\n      initialPageParam: 1,\n      getNextPageParam: () => undefined,\n    })\n  })\n\n  it('initialPageParam should define type of param passed to queryFunctionContext for fetchInfiniteQuery', () => {\n    const queryClient = new QueryClient()\n    queryClient.fetchInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: ({ pageParam }) => {\n        expectTypeOf(pageParam).toEqualTypeOf<number>()\n      },\n      initialPageParam: 1,\n    })\n  })\n\n  it('initialPageParam should define type of param passed to queryFunctionContext for prefetchInfiniteQuery', () => {\n    const queryClient = new QueryClient()\n    queryClient.prefetchInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: ({ pageParam }) => {\n        expectTypeOf(pageParam).toEqualTypeOf<number>()\n      },\n      initialPageParam: 1,\n    })\n  })\n})\ndescribe('select', () => {\n  it('should still return paginated data if no select result', () => {\n    const infiniteQuery = useInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: ({ pageParam }) => {\n        return pageParam * 5\n      },\n      initialPageParam: 1,\n      getNextPageParam: () => undefined,\n    })\n\n    // TODO: Order of generics prevents pageParams to be typed correctly. Using `unknown` for now\n    expectTypeOf(infiniteQuery.data).toEqualTypeOf<\n      InfiniteData<number, unknown> | undefined\n    >()\n  })\n\n  it('should be able to transform data to arbitrary result', () => {\n    const infiniteQuery = useInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: ({ pageParam }) => {\n        return pageParam * 5\n      },\n      initialPageParam: 1,\n      getNextPageParam: () => undefined,\n      select: (data) => {\n        expectTypeOf(data).toEqualTypeOf<InfiniteData<number, number>>()\n        return 'selected' as const\n      },\n    })\n\n    expectTypeOf(infiniteQuery.data).toEqualTypeOf<'selected' | undefined>()\n  })\n})\ndescribe('getNextPageParam / getPreviousPageParam', () => {\n  it('should get typed params', () => {\n    const infiniteQuery = useInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: ({ pageParam }) => {\n        return String(pageParam)\n      },\n      initialPageParam: 1,\n      getNextPageParam: (lastPage, allPages, lastPageParam, allPageParams) => {\n        expectTypeOf(lastPage).toEqualTypeOf<string>()\n        expectTypeOf(allPages).toEqualTypeOf<Array<string>>()\n        expectTypeOf(lastPageParam).toEqualTypeOf<number>()\n        expectTypeOf(allPageParams).toEqualTypeOf<Array<number>>()\n        return undefined\n      },\n      getPreviousPageParam: (\n        firstPage,\n        allPages,\n        firstPageParam,\n        allPageParams,\n      ) => {\n        expectTypeOf(firstPage).toEqualTypeOf<string>()\n        expectTypeOf(allPages).toEqualTypeOf<Array<string>>()\n        expectTypeOf(firstPageParam).toEqualTypeOf<number>()\n        expectTypeOf(allPageParams).toEqualTypeOf<Array<number>>()\n        return undefined\n      },\n    })\n\n    // TODO: Order of generics prevents pageParams to be typed correctly. Using `unknown` for now\n    expectTypeOf(infiniteQuery.data).toEqualTypeOf<\n      InfiniteData<string, unknown> | undefined\n    >()\n  })\n})\n\ndescribe('error booleans', () => {\n  it('should not be permanently `false`', () => {\n    const {\n      isFetchNextPageError,\n      isFetchPreviousPageError,\n      isLoadingError,\n      isRefetchError,\n    } = useInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: ({ pageParam }) => {\n        return pageParam * 5\n      },\n      initialPageParam: 1,\n      getNextPageParam: () => undefined,\n    })\n\n    expectTypeOf(isFetchNextPageError).toEqualTypeOf<boolean>()\n    expectTypeOf(isFetchPreviousPageError).toEqualTypeOf<boolean>()\n    expectTypeOf(isLoadingError).toEqualTypeOf<boolean>()\n    expectTypeOf(isRefetchError).toEqualTypeOf<boolean>()\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/useInfiniteQuery.test.tsx",
    "content": "import { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { fireEvent, render } from '@testing-library/preact'\nimport { useCallback, useEffect, useRef, useState } from 'preact/hooks'\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport type { Mock } from 'vitest'\n\nimport {\n  QueryCache,\n  QueryClient,\n  // QueryClientProvider,\n  keepPreviousData,\n  useInfiniteQuery,\n} from '..'\nimport type {\n  InfiniteData,\n  QueryFunctionContext,\n  UseInfiniteQueryResult,\n} from '..'\nimport { renderWithClient, setActTimeout } from './utils'\n\n// import { Suspense } from 'preact/compat'\n\ninterface Result {\n  items: Array<number>\n  nextId?: number\n  prevId?: number\n  ts: number\n}\n\nconst pageSize = 10\n\nconst fetchItems = async (\n  page: number,\n  ts: number,\n  noNext?: boolean,\n  noPrev?: boolean,\n): Promise<Result> => {\n  await sleep(10)\n  return {\n    items: [...new Array(10)].fill(null).map((_, d) => page * pageSize + d),\n    nextId: noNext ? undefined : page + 1,\n    prevId: noPrev ? undefined : page - 1,\n    ts,\n  }\n}\n\ndescribe('useInfiniteQuery', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  const queryCache = new QueryCache()\n  const queryClient = new QueryClient({\n    queryCache,\n    defaultOptions: {\n      queries: {\n        experimental_prefetchInRender: true,\n      },\n    },\n  })\n\n  it('should return the correct states for a successful query', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        getNextPageParam: (lastPage) => lastPage + 1,\n        initialPageParam: 0,\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toEqual({\n      data: undefined,\n      dataUpdatedAt: 0,\n      error: null,\n      errorUpdatedAt: 0,\n      failureCount: 0,\n      failureReason: null,\n      errorUpdateCount: 0,\n      fetchNextPage: expect.any(Function),\n      fetchPreviousPage: expect.any(Function),\n      hasNextPage: false,\n      hasPreviousPage: false,\n      isError: false,\n      isFetched: false,\n      isFetchedAfterMount: false,\n      isFetching: true,\n      isPaused: false,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isLoading: true,\n      isPending: true,\n      isInitialLoading: true,\n      isLoadingError: false,\n      isPlaceholderData: false,\n      isRefetchError: false,\n      isRefetching: false,\n      isStale: true,\n      isSuccess: false,\n      isEnabled: true,\n      refetch: expect.any(Function),\n      status: 'pending',\n      fetchStatus: 'fetching',\n      promise: expect.any(Promise),\n    })\n    expect(states[1]).toEqual({\n      data: { pages: [0], pageParams: [0] },\n      dataUpdatedAt: expect.any(Number),\n      error: null,\n      errorUpdatedAt: 0,\n      failureCount: 0,\n      failureReason: null,\n      errorUpdateCount: 0,\n      fetchNextPage: expect.any(Function),\n      fetchPreviousPage: expect.any(Function),\n      hasNextPage: true,\n      hasPreviousPage: false,\n      isError: false,\n      isFetched: true,\n      isFetchedAfterMount: true,\n      isFetching: false,\n      isPaused: false,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isLoading: false,\n      isPending: false,\n      isInitialLoading: false,\n      isLoadingError: false,\n      isPlaceholderData: false,\n      isRefetchError: false,\n      isRefetching: false,\n      isStale: true,\n      isSuccess: true,\n      isEnabled: true,\n      refetch: expect.any(Function),\n      status: 'success',\n      fetchStatus: 'idle',\n      promise: expect.any(Promise),\n    })\n  })\n\n  it('should not throw when fetchNextPage returns an error', async () => {\n    const key = queryKey()\n    let noThrow = false\n\n    function Page() {\n      const start = 1\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) =>\n          sleep(10).then(() => {\n            if (pageParam === 2) throw new Error('error')\n            return pageParam\n          }),\n        retry: 1,\n        retryDelay: 10,\n        getNextPageParam: (lastPage) => lastPage + 1,\n        initialPageParam: start,\n      })\n\n      const { fetchNextPage } = state\n\n      useEffect(() => {\n        setActTimeout(() => {\n          fetchNextPage()\n            .then(() => {\n              noThrow = true\n            })\n            .catch(() => undefined)\n        }, 20)\n      }, [fetchNextPage])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(50)\n    expect(noThrow).toBe(true)\n  })\n\n  it('should keep the previous data when placeholderData is set', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<string>>> = []\n\n    function Page() {\n      const [order, setOrder] = useState('desc')\n\n      const state = useInfiniteQuery({\n        queryKey: [key, order],\n        queryFn: ({ pageParam }) =>\n          sleep(10).then(() => `${pageParam}-${order}`),\n        getNextPageParam: () => 1,\n        initialPageParam: 0,\n        placeholderData: keepPreviousData,\n        notifyOnChangeProps: 'all',\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <button onClick={() => state.fetchNextPage()}>fetchNextPage</button>\n          <button onClick={() => setOrder('asc')}>order</button>\n          <div>data: {state.data?.pages.join(',') ?? 'null'}</div>\n          <div>isFetching: {String(state.isFetching)}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 0-desc')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 0-desc,1-desc')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /order/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 0-asc')).toBeInTheDocument()\n    expect(rendered.getByText('isFetching: false')).toBeInTheDocument()\n\n    expect(states.length).toBe(6)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: false,\n      isPlaceholderData: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: ['0-desc'] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    expect(states[2]).toMatchObject({\n      data: { pages: ['0-desc'] },\n      isFetching: true,\n      isFetchingNextPage: true,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    expect(states[3]).toMatchObject({\n      data: { pages: ['0-desc', '1-desc'] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Set state\n    expect(states[4]).toMatchObject({\n      data: { pages: ['0-desc', '1-desc'] },\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    expect(states[5]).toMatchObject({\n      data: { pages: ['0-asc'] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n  })\n\n  it('should be able to select a part of the data', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<string>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => ({ count: 1 })),\n        select: (data) => ({\n          pages: data.pages.map((x) => `count: ${x.count}`),\n          pageParams: data.pageParams,\n        }),\n        getNextPageParam: () => undefined,\n        initialPageParam: 0,\n      })\n      states.push(state)\n\n      return <div>{state.data?.pages.join(',')}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('count: 1')).toBeInTheDocument()\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isSuccess: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: ['count: 1'] },\n      isSuccess: true,\n    })\n  })\n\n  it('should be able to select a new result and not cause infinite renders', async () => {\n    const key = queryKey()\n    const states: Array<\n      UseInfiniteQueryResult<InfiniteData<{ count: number; id: number }>>\n    > = []\n    let selectCalled = 0\n\n    function Page() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => ({ count: 1 })),\n        select: useCallback((data: InfiniteData<{ count: number }>) => {\n          selectCalled++\n          return {\n            pages: data.pages.map((x) => ({ ...x, id: Math.random() })),\n            pageParams: data.pageParams,\n          }\n        }, []),\n        getNextPageParam: () => undefined,\n        initialPageParam: 0,\n      })\n      states.push(state)\n\n      return (\n        <div>\n          {state.data?.pages.map((page) => (\n            <div key={page.id}>count: {page.count}</div>\n          ))}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('count: 1')).toBeInTheDocument()\n\n    expect(states.length).toBe(2)\n    expect(selectCalled).toBe(1)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isSuccess: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: [{ count: 1 }] },\n      isSuccess: true,\n    })\n  })\n\n  it('should be able to reverse the data', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        select: (data) => ({\n          pages: [...data.pages].reverse(),\n          pageParams: [...data.pageParams].reverse(),\n        }),\n        notifyOnChangeProps: 'all',\n        getNextPageParam: () => 1,\n        initialPageParam: 0,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <button onClick={() => state.fetchNextPage()}>fetchNextPage</button>\n          <div>data: {state.data?.pages.join(',') ?? 'null'}</div>\n          <div>isFetching: {state.isFetching}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 1,0')).toBeInTheDocument()\n\n    expect(states.length).toBe(4)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isSuccess: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: [0] },\n      isSuccess: true,\n    })\n    expect(states[2]).toMatchObject({\n      data: { pages: [0] },\n      isSuccess: true,\n    })\n    expect(states[3]).toMatchObject({\n      data: { pages: [1, 0] },\n      isSuccess: true,\n    })\n  })\n\n  it('should be able to fetch a previous page', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const start = 10\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        initialPageParam: start,\n        getNextPageParam: (lastPage) => lastPage + 1,\n        getPreviousPageParam: (firstPage) => firstPage - 1,\n        notifyOnChangeProps: 'all',\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <div>data: {state.data?.pages.join(',') ?? null}</div>\n          <button onClick={() => state.fetchPreviousPage()}>\n            fetch previous page\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 10')).toBeInTheDocument()\n\n    fireEvent.click(\n      rendered.getByRole('button', { name: /fetch previous page/i }),\n    )\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 9,10')).toBeInTheDocument()\n\n    expect(states.length).toBe(4)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      hasNextPage: false,\n      hasPreviousPage: false,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isFetchingPreviousPage: false,\n      isSuccess: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: [10] },\n      hasNextPage: true,\n      hasPreviousPage: true,\n      isFetching: false,\n      isFetchingNextPage: false,\n      isFetchingPreviousPage: false,\n      isSuccess: true,\n    })\n    expect(states[2]).toMatchObject({\n      data: { pages: [10] },\n      hasNextPage: true,\n      hasPreviousPage: true,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isFetchingPreviousPage: true,\n      isSuccess: true,\n    })\n    expect(states[3]).toMatchObject({\n      data: { pages: [9, 10] },\n      hasNextPage: true,\n      hasPreviousPage: true,\n      isFetching: false,\n      isFetchingNextPage: false,\n      isFetchingPreviousPage: false,\n      isSuccess: true,\n    })\n  })\n\n  it('should be able to refetch when providing page params automatically', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        initialPageParam: 10,\n        getPreviousPageParam: (firstPage) => firstPage - 1,\n        getNextPageParam: (lastPage) => lastPage + 1,\n        notifyOnChangeProps: 'all',\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <button onClick={() => state.fetchNextPage()}>fetchNextPage</button>\n          <button onClick={() => state.fetchPreviousPage()}>\n            fetchPreviousPage\n          </button>\n          <button onClick={() => state.refetch()}>refetch</button>\n          <div>data: {state.data?.pages.join(',') ?? 'null'}</div>\n          <div>isFetching: {String(state.isFetching)}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 10')).toBeInTheDocument()\n    fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 10,11')).toBeInTheDocument()\n    fireEvent.click(\n      rendered.getByRole('button', { name: /fetchPreviousPage/i }),\n    )\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 9,10,11')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n    expect(rendered.getByText('isFetching: false')).toBeInTheDocument()\n\n    await vi.advanceTimersByTimeAsync(31)\n    expect(states.length).toBe(8)\n    // Initial fetch\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isRefetching: false,\n    })\n    // Initial fetch done\n    expect(states[1]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isRefetching: false,\n    })\n    // Fetch next page\n    expect(states[2]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: true,\n      isFetchingNextPage: true,\n      isRefetching: false,\n    })\n    // Fetch next page done\n    expect(states[3]).toMatchObject({\n      data: { pages: [10, 11] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isRefetching: false,\n    })\n    // Fetch previous page\n    expect(states[4]).toMatchObject({\n      data: { pages: [10, 11] },\n      isFetching: true,\n      isFetchingNextPage: false,\n      isFetchingPreviousPage: true,\n      isRefetching: false,\n    })\n    // Fetch previous page done\n    expect(states[5]).toMatchObject({\n      data: { pages: [9, 10, 11] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isFetchingPreviousPage: false,\n      isRefetching: false,\n    })\n    // Refetch\n    expect(states[6]).toMatchObject({\n      data: { pages: [9, 10, 11] },\n      isFetching: true,\n      isFetchingNextPage: false,\n      isFetchingPreviousPage: false,\n      isRefetching: true,\n    })\n    // Refetch done\n    expect(states[7]).toMatchObject({\n      data: { pages: [9, 10, 11] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isFetchingPreviousPage: false,\n      isRefetching: false,\n    })\n  })\n\n  it('should return the correct states when refetch fails', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n    let isRefetch = false\n\n    function Page() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) =>\n          sleep(10).then(() => {\n            if (isRefetch) throw new Error()\n            return pageParam\n          }),\n        initialPageParam: 10,\n        getPreviousPageParam: (firstPage) => firstPage - 1,\n        getNextPageParam: (lastPage) => lastPage + 1,\n        notifyOnChangeProps: 'all',\n        retry: false,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <button\n            onClick={() => {\n              isRefetch = true\n              state.refetch()\n            }}\n          >\n            refetch\n          </button>\n          <div>data: {state.data?.pages.join(',') ?? 'null'}</div>\n          <div>isFetching: {String(state.isFetching)}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 10')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n    expect(rendered.getByText('isFetching: false')).toBeInTheDocument()\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(states.length).toBe(4)\n    // Initial fetch\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n    // Initial fetch done\n    expect(states[1]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: false,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n    // Refetch\n    expect(states[2]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: true,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: true,\n    })\n    // Refetch failed\n    expect(states[3]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: false,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: true,\n      isRefetching: false,\n    })\n  })\n\n  it('should return the correct states when fetchNextPage fails', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) =>\n          sleep(10).then(() => {\n            if (pageParam !== 10) throw new Error()\n            return pageParam\n          }),\n        initialPageParam: 10,\n        getPreviousPageParam: (firstPage) => firstPage - 1,\n        getNextPageParam: (lastPage) => lastPage + 1,\n        notifyOnChangeProps: 'all',\n        retry: false,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <button onClick={() => state.fetchNextPage()}>fetchNextPage</button>\n          <div>data: {state.data?.pages.join(',') ?? 'null'}</div>\n          <div>isFetching: {String(state.isFetching)}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 10')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i }))\n    expect(rendered.getByText('isFetching: false')).toBeInTheDocument()\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(states.length).toBe(4)\n    // Initial fetch\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n    // Initial fetch done\n    expect(states[1]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: false,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n    // Fetch next page\n    expect(states[2]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: true,\n      isFetchNextPageError: false,\n      isFetchingNextPage: true,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n    // Fetch next page failed\n    expect(states[3]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: false,\n      isFetchNextPageError: true,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n  })\n\n  it('should return the correct states when fetchPreviousPage fails', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) =>\n          sleep(10).then(() => {\n            if (pageParam !== 10) throw new Error()\n            return pageParam\n          }),\n        initialPageParam: 10,\n        getPreviousPageParam: (firstPage) => firstPage - 1,\n        getNextPageParam: (lastPage) => lastPage + 1,\n        notifyOnChangeProps: 'all',\n        retry: false,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <button onClick={() => state.fetchPreviousPage()}>\n            fetchPreviousPage\n          </button>\n          <div>data: {state.data?.pages.join(',') ?? 'null'}</div>\n          <div>isFetching: {String(state.isFetching)}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 10')).toBeInTheDocument()\n\n    fireEvent.click(\n      rendered.getByRole('button', { name: /fetchPreviousPage/i }),\n    )\n    expect(rendered.getByText('isFetching: false')).toBeInTheDocument()\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(states.length).toBe(4)\n    // Initial fetch\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n    // Initial fetch done\n    expect(states[1]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: false,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n    // Fetch previous page\n    expect(states[2]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: true,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: true,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n    // Fetch previous page failed\n    expect(states[3]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: false,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: true,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n  })\n\n  it('should silently cancel any ongoing fetch when fetching more', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const start = 10\n      const { data, fetchNextPage, refetch, status, fetchStatus } =\n        useInfiniteQuery({\n          queryKey: key,\n          queryFn: ({ pageParam }) => sleep(50).then(() => pageParam),\n          initialPageParam: start,\n          getNextPageParam: (lastPage) => lastPage + 1,\n        })\n\n      return (\n        <div>\n          <button onClick={() => fetchNextPage()}>fetchNextPage</button>\n          <button onClick={() => refetch()}>refetch</button>\n          <div>data: {JSON.stringify(data)}</div>\n          <div>\n            status: {status}, {fetchStatus}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(51)\n    expect(rendered.getByText('status: success, idle')).toBeInTheDocument()\n    expect(\n      rendered.getByText('data: {\"pages\":[10],\"pageParams\":[10]}'),\n    ).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('status: success, fetching')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i }))\n    await vi.advanceTimersByTimeAsync(51)\n    expect(rendered.getByText('status: success, idle')).toBeInTheDocument()\n    expect(\n      rendered.getByText('data: {\"pages\":[10,11],\"pageParams\":[10,11]}'),\n    ).toBeInTheDocument()\n  })\n\n  it('should silently cancel an ongoing fetchNextPage request when another fetchNextPage is invoked', async () => {\n    const key = queryKey()\n    const start = 10\n    const onAborts: Array<Mock<(...args: Array<any>) => any>> = []\n    const abortListeners: Array<Mock<(...args: Array<any>) => any>> = []\n    const fetchPage = vi.fn<\n      (context: QueryFunctionContext<typeof key, number>) => Promise<number>\n    >(async ({ pageParam, signal }) => {\n      const onAbort = vi.fn()\n      const abortListener = vi.fn()\n      onAborts.push(onAbort)\n      abortListeners.push(abortListener)\n      signal.onabort = onAbort\n      signal.addEventListener('abort', abortListener)\n      await sleep(50)\n      return pageParam\n    })\n\n    function Page() {\n      const { fetchNextPage } = useInfiniteQuery({\n        queryKey: key,\n        queryFn: fetchPage,\n        initialPageParam: start,\n        getNextPageParam: (lastPage) => lastPage + 1,\n      })\n\n      useEffect(() => {\n        setActTimeout(() => {\n          fetchNextPage()\n        }, 100)\n        setActTimeout(() => {\n          fetchNextPage()\n        }, 110)\n      }, [fetchNextPage])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(160)\n\n    const expectedCallCount = 3\n    expect(fetchPage).toBeCalledTimes(expectedCallCount)\n    expect(onAborts).toHaveLength(expectedCallCount)\n    expect(abortListeners).toHaveLength(expectedCallCount)\n\n    let callIndex = 0\n    const firstCtx = fetchPage.mock.calls[callIndex]![0]\n    expect(firstCtx.pageParam).toEqual(start)\n    expect(firstCtx.queryKey).toEqual(key)\n    expect(firstCtx.signal).toBeInstanceOf(AbortSignal)\n    expect(firstCtx.signal.aborted).toBe(false)\n    expect(onAborts[callIndex]).not.toHaveBeenCalled()\n    expect(abortListeners[callIndex]).not.toHaveBeenCalled()\n\n    callIndex = 1\n    const secondCtx = fetchPage.mock.calls[callIndex]![0]\n    expect(secondCtx.pageParam).toBe(11)\n    expect(secondCtx.queryKey).toEqual(key)\n    expect(secondCtx.signal).toBeInstanceOf(AbortSignal)\n    expect(secondCtx.signal.aborted).toBe(true)\n    expect(onAborts[callIndex]).toHaveBeenCalledTimes(1)\n    expect(abortListeners[callIndex]).toHaveBeenCalledTimes(1)\n\n    callIndex = 2\n    const thirdCtx = fetchPage.mock.calls[callIndex]![0]\n    expect(thirdCtx.pageParam).toBe(11)\n    expect(thirdCtx.queryKey).toEqual(key)\n    expect(thirdCtx.signal).toBeInstanceOf(AbortSignal)\n    expect(thirdCtx.signal.aborted).toBe(false)\n    expect(onAborts[callIndex]).not.toHaveBeenCalled()\n    expect(abortListeners[callIndex]).not.toHaveBeenCalled()\n  })\n\n  it('should not cancel an ongoing fetchNextPage request when another fetchNextPage is invoked if `cancelRefetch: false` is used', async () => {\n    const key = queryKey()\n    const start = 10\n    const onAborts: Array<Mock<(...args: Array<any>) => any>> = []\n    const abortListeners: Array<Mock<(...args: Array<any>) => any>> = []\n    const fetchPage = vi.fn<\n      (context: QueryFunctionContext<typeof key, number>) => Promise<number>\n    >(async ({ pageParam, signal }) => {\n      const onAbort = vi.fn()\n      const abortListener = vi.fn()\n      onAborts.push(onAbort)\n      abortListeners.push(abortListener)\n      signal.onabort = onAbort\n      signal.addEventListener('abort', abortListener)\n      await sleep(50)\n      return pageParam\n    })\n\n    function Page() {\n      const { fetchNextPage } = useInfiniteQuery({\n        queryKey: key,\n        queryFn: fetchPage,\n        initialPageParam: start,\n        getNextPageParam: (lastPage) => lastPage + 1,\n      })\n\n      useEffect(() => {\n        setActTimeout(() => {\n          fetchNextPage()\n        }, 100)\n        setActTimeout(() => {\n          fetchNextPage({ cancelRefetch: false })\n        }, 110)\n      }, [fetchNextPage])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(160)\n\n    const expectedCallCount = 2\n    expect(fetchPage).toBeCalledTimes(expectedCallCount)\n    expect(onAborts).toHaveLength(expectedCallCount)\n    expect(abortListeners).toHaveLength(expectedCallCount)\n\n    let callIndex = 0\n    const firstCtx = fetchPage.mock.calls[callIndex]![0]\n    expect(firstCtx.pageParam).toEqual(start)\n    expect(firstCtx.queryKey).toEqual(key)\n    expect(firstCtx.signal).toBeInstanceOf(AbortSignal)\n    expect(firstCtx.signal.aborted).toBe(false)\n    expect(onAborts[callIndex]).not.toHaveBeenCalled()\n    expect(abortListeners[callIndex]).not.toHaveBeenCalled()\n\n    callIndex = 1\n    const secondCtx = fetchPage.mock.calls[callIndex]![0]\n    expect(secondCtx.pageParam).toBe(11)\n    expect(secondCtx.queryKey).toEqual(key)\n    expect(secondCtx.signal).toBeInstanceOf(AbortSignal)\n    expect(secondCtx.signal.aborted).toBe(false)\n    expect(onAborts[callIndex]).not.toHaveBeenCalled()\n    expect(abortListeners[callIndex]).not.toHaveBeenCalled()\n  })\n\n  it('should keep fetching first page when not loaded yet and triggering fetch more', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const start = 10\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(50).then(() => pageParam),\n        initialPageParam: start,\n        getNextPageParam: (lastPage) => lastPage + 1,\n        notifyOnChangeProps: 'all',\n      })\n\n      states.push(state)\n\n      const { fetchNextPage } = state\n\n      useEffect(() => {\n        setActTimeout(() => {\n          fetchNextPage()\n        }, 10)\n      }, [fetchNextPage])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(60)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      hasNextPage: false,\n      data: undefined,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: false,\n    })\n    expect(states[1]).toMatchObject({\n      hasNextPage: true,\n      data: { pages: [10] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n  })\n\n  it('should stop fetching additional pages when the component is unmounted and AbortSignal is consumed', async () => {\n    const key = queryKey()\n    let fetches = 0\n\n    const initialData = { pages: [1, 2, 3, 4], pageParams: [0, 1, 2, 3] }\n\n    function List() {\n      useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) =>\n          sleep(50).then(() => {\n            fetches++\n            return pageParam * 10\n          }),\n        initialData,\n        initialPageParam: 0,\n        getNextPageParam: (_, allPages) => {\n          return allPages.length === 4 ? undefined : allPages.length\n        },\n      })\n\n      return null\n    }\n\n    function Page() {\n      const [show, setShow] = useState(true)\n\n      useEffect(() => {\n        setActTimeout(() => {\n          setShow(false)\n        }, 75)\n      }, [])\n\n      return show ? <List /> : null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(125)\n\n    expect(fetches).toBe(2)\n    expect(queryClient.getQueryState(key)).toMatchObject({\n      data: initialData,\n      status: 'success',\n      error: null,\n    })\n  })\n\n  it('should be able to set new pages with the query client', async () => {\n    const key = queryKey()\n\n    let multiplier = 1\n\n    function Page() {\n      const [firstPage, setFirstPage] = useState(0)\n\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) =>\n          sleep(10).then(() => multiplier * pageParam),\n        getNextPageParam: (lastPage) => lastPage + 1,\n        initialPageParam: firstPage,\n      })\n\n      return (\n        <div>\n          <button\n            onClick={() => {\n              queryClient.setQueryData(key, {\n                pages: [7, 8],\n                pageParams: [7, 8],\n              })\n              setFirstPage(7)\n            }}\n          >\n            setPages\n          </button>\n          <button onClick={() => state.refetch()}>refetch</button>\n          <div>data: {JSON.stringify(state.data)}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(\n      rendered.getByText('data: {\"pages\":[0],\"pageParams\":[0]}'),\n    ).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /setPages/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(\n      rendered.getByText('data: {\"pages\":[7,8],\"pageParams\":[7,8]}'),\n    ).toBeInTheDocument()\n\n    multiplier = 2\n\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n    await vi.advanceTimersByTimeAsync(21)\n    expect(\n      rendered.getByText('data: {\"pages\":[14,30],\"pageParams\":[7,15]}'),\n    ).toBeInTheDocument()\n  })\n\n  it('should set hasNextPage to false if getNextPageParam returns undefined', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        getNextPageParam: () => undefined,\n        initialPageParam: 1,\n      })\n\n      states.push(state)\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      hasNextPage: false,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: [1] },\n      hasNextPage: false,\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n  })\n\n  it('should compute hasNextPage correctly using initialData', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        initialData: { pages: [10], pageParams: [10] },\n        getNextPageParam: (lastPage) => (lastPage === 10 ? 11 : undefined),\n        initialPageParam: 10,\n      })\n\n      states.push(state)\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: { pages: [10] },\n      hasNextPage: true,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: [10] },\n      hasNextPage: true,\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n  })\n\n  it('should compute hasNextPage correctly for falsy getFetchMore return value using initialData', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        initialPageParam: 10,\n        initialData: { pages: [10], pageParams: [10] },\n        getNextPageParam: () => undefined,\n      })\n\n      states.push(state)\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: { pages: [10] },\n      hasNextPage: false,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: [10] },\n      hasNextPage: false,\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n  })\n\n  it('should not use selected data when computing hasNextPage', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<string>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        getNextPageParam: (lastPage) => (lastPage === 1 ? 2 : undefined),\n        select: (data) => ({\n          pages: data.pages.map((x) => x.toString()),\n          pageParams: data.pageParams,\n        }),\n        initialPageParam: 1,\n      })\n\n      states.push(state)\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      hasNextPage: false,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: ['1'] },\n      hasNextPage: true,\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n  })\n\n  it('should build fresh cursors on refetch', async () => {\n    const key = queryKey()\n\n    const genItems = (size: number) =>\n      [...new Array(size)].fill(null).map((_, d) => d)\n    const items = genItems(15)\n    const limit = 3\n\n    const fetchItemsWithLimit = (cursor = 0, ts: number) =>\n      sleep(10).then(() => ({\n        nextId: cursor + limit,\n        items: items.slice(cursor, cursor + limit),\n        ts,\n      }))\n\n    function Page() {\n      const fetchCountRef = useRef(0)\n      const {\n        status,\n        data,\n        error,\n        isFetchingNextPage,\n        fetchNextPage,\n        hasNextPage,\n        refetch,\n      } = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) =>\n          fetchItemsWithLimit(pageParam, fetchCountRef.current++),\n        initialPageParam: 0,\n        getNextPageParam: (lastPage) => lastPage.nextId,\n      })\n\n      return (\n        <div>\n          <h1>Pagination</h1>\n          {status === 'pending' ? (\n            'Loading...'\n          ) : status === 'error' ? (\n            <span>Error: {error.message}</span>\n          ) : (\n            <>\n              <div>Data:</div>\n              {data.pages.map((page, i) => (\n                <div key={i}>\n                  <div>\n                    Page {i}: {page.ts}\n                  </div>\n                  <div key={i}>\n                    {page.items.map((item) => (\n                      <p key={item}>Item: {item}</p>\n                    ))}\n                  </div>\n                </div>\n              ))}\n              <div>\n                <button\n                  onClick={() => fetchNextPage()}\n                  disabled={!hasNextPage || isFetchingNextPage}\n                >\n                  {isFetchingNextPage\n                    ? 'Loading more...'\n                    : hasNextPage\n                      ? 'Load More'\n                      : 'Nothing more to load'}\n                </button>\n                <button onClick={() => refetch()}>Refetch</button>\n                <button\n                  onClick={() => {\n                    // Imagine that this mutation happens somewhere else\n                    // makes an actual network request\n                    // and calls invalidateQueries in an onSuccess\n                    items.splice(4, 1)\n                    queryClient.invalidateQueries({ queryKey: key })\n                  }}\n                >\n                  Remove item\n                </button>\n              </div>\n              <div>{!isFetchingNextPage ? 'Background Updating...' : null}</div>\n            </>\n          )}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('Loading...')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Item: 2')).toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('Load More'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Loading more...')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Item: 5')).toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 0')).toBeInTheDocument()\n    expect(rendered.getByText('Page 1: 1')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('Load More'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Loading more...')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Item: 8')).toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 0')).toBeInTheDocument()\n    expect(rendered.getByText('Page 1: 1')).toBeInTheDocument()\n    expect(rendered.getByText('Page 2: 2')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('Refetch'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Background Updating...')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(31)\n    expect(rendered.getByText('Item: 8')).toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 3')).toBeInTheDocument()\n    expect(rendered.getByText('Page 1: 4')).toBeInTheDocument()\n    expect(rendered.getByText('Page 2: 5')).toBeInTheDocument()\n    // ensure that Item: 4 is rendered before removing it\n    expect(rendered.queryAllByText('Item: 4')).toHaveLength(1)\n\n    // remove Item: 4\n    fireEvent.click(rendered.getByText('Remove item'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Background Updating...')).toBeInTheDocument()\n    // ensure that an additional item is rendered (it means that cursors were properly rebuilt)\n    await vi.advanceTimersByTimeAsync(31)\n    expect(rendered.getByText('Item: 9')).toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 6')).toBeInTheDocument()\n    expect(rendered.getByText('Page 1: 7')).toBeInTheDocument()\n    expect(rendered.getByText('Page 2: 8')).toBeInTheDocument()\n    // ensure that Item: 4 is no longer rendered\n    expect(rendered.queryAllByText('Item: 4')).toHaveLength(0)\n  })\n\n  it('should compute hasNextPage correctly for falsy getFetchMore return value on refetching', async () => {\n    const key = queryKey()\n    const MAX = 2\n\n    function Page() {\n      const fetchCountRef = useRef(0)\n      const [isRemovedLastPage, setIsRemovedLastPage] = useState<boolean>(false)\n      const {\n        status,\n        data,\n        error,\n        isFetching,\n        isFetchingNextPage,\n        fetchNextPage,\n        hasNextPage,\n        refetch,\n      } = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) =>\n          fetchItems(\n            pageParam,\n            fetchCountRef.current++,\n            pageParam === MAX || (pageParam === MAX - 1 && isRemovedLastPage),\n          ),\n        getNextPageParam: (lastPage) => lastPage.nextId,\n        initialPageParam: 0,\n      })\n\n      return (\n        <div>\n          <h1>Pagination</h1>\n          {status === 'pending' ? (\n            'Loading...'\n          ) : status === 'error' ? (\n            <span>Error: {error.message}</span>\n          ) : (\n            <>\n              <div>Data:</div>\n              {data.pages.map((page, i) => (\n                <div key={i}>\n                  <div>\n                    Page {i}: {page.ts}\n                  </div>\n                  <div key={i}>\n                    {page.items.map((item) => (\n                      <p key={item}>Item: {item}</p>\n                    ))}\n                  </div>\n                </div>\n              ))}\n              <div>\n                <button\n                  onClick={() => fetchNextPage()}\n                  disabled={!hasNextPage || isFetchingNextPage}\n                >\n                  {isFetchingNextPage\n                    ? 'Loading more...'\n                    : hasNextPage\n                      ? 'Load More'\n                      : 'Nothing more to load'}\n                </button>\n                <button onClick={() => refetch()}>Refetch</button>\n                <button onClick={() => setIsRemovedLastPage(true)}>\n                  Remove Last Page\n                </button>\n              </div>\n              <div>\n                {isFetching && !isFetchingNextPage\n                  ? 'Background Updating...'\n                  : null}\n              </div>\n            </>\n          )}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('Loading...')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Item: 9')).toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('Load More'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Loading more...')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Item: 19')).toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 0')).toBeInTheDocument()\n    expect(rendered.getByText('Page 1: 1')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('Load More'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Loading more...')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Item: 29')).toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 0')).toBeInTheDocument()\n    expect(rendered.getByText('Page 1: 1')).toBeInTheDocument()\n    expect(rendered.getByText('Page 2: 2')).toBeInTheDocument()\n    expect(rendered.getByText('Nothing more to load')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('Remove Last Page'))\n    fireEvent.click(rendered.getByText('Refetch'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Background Updating...')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(21)\n    expect(rendered.queryByText('Item: 29')).not.toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 3')).toBeInTheDocument()\n    expect(rendered.getByText('Page 1: 4')).toBeInTheDocument()\n    expect(rendered.queryByText('Page 2: 5')).not.toBeInTheDocument()\n    expect(rendered.getByText('Nothing more to load')).toBeInTheDocument()\n  })\n\n  it('should cancel the query function when there are no more subscriptions', () => {\n    const key = queryKey()\n    let cancelFn: Mock = vi.fn()\n\n    const queryFn = ({ signal }: { signal?: AbortSignal }) => {\n      const promise = new Promise<string>((resolve, reject) => {\n        cancelFn = vi.fn(() => reject('Cancelled'))\n        signal?.addEventListener('abort', cancelFn)\n        sleep(1000).then(() => resolve('OK'))\n      })\n\n      return promise\n    }\n\n    function Inner() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn,\n        getNextPageParam: () => undefined,\n        initialPageParam: 0,\n      })\n      return (\n        <div>\n          <h1>Status: {state.status}</h1>\n        </div>\n      )\n    }\n\n    function Page() {\n      const [isVisible, setIsVisible] = useState(true)\n\n      return (\n        <>\n          <button onClick={() => setIsVisible(false)}>hide</button>\n          {isVisible && <Inner />}\n          <div>{isVisible ? 'visible' : 'hidden'}</div>\n        </>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('visible')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: 'hide' }))\n    expect(rendered.getByText('hidden')).toBeInTheDocument()\n\n    expect(cancelFn).toHaveBeenCalled()\n  })\n\n  it('should use provided custom queryClient', async () => {\n    const key = queryKey()\n    const queryFn = () => sleep(10).then(() => 'custom client')\n\n    function Page() {\n      const { data } = useInfiniteQuery(\n        {\n          queryKey: key,\n          queryFn,\n          getNextPageParam: () => undefined,\n          initialPageParam: 0,\n        },\n        queryClient,\n      )\n\n      return <div>data: {data?.pages[0]}</div>\n    }\n\n    const rendered = render(<Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: custom client')).toBeInTheDocument()\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/useIsFetching.test.tsx",
    "content": "import { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { fireEvent, render } from '@testing-library/preact'\nimport { useEffect, useState } from 'preact/hooks'\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\n\nimport { QueryCache, QueryClient, useIsFetching, useQuery } from '..'\nimport { renderWithClient, setActTimeout } from './utils'\n\ndescribe('useIsFetching', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/105\n  it('should update as queries start and stop fetching', async () => {\n    const queryClient = new QueryClient()\n    const key = queryKey()\n\n    function IsFetching() {\n      const isFetching = useIsFetching()\n\n      return <div>isFetching: {isFetching}</div>\n    }\n\n    function Query() {\n      const [ready, setReady] = useState(false)\n\n      useQuery({\n        queryKey: key,\n        queryFn: () => sleep(50).then(() => 'test'),\n        enabled: ready,\n      })\n\n      return <button onClick={() => setReady(true)}>setReady</button>\n    }\n\n    function Page() {\n      return (\n        <div>\n          <IsFetching />\n          <Query />\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('isFetching: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /setReady/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('isFetching: 1')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(51)\n    expect(rendered.getByText('isFetching: 0')).toBeInTheDocument()\n  })\n\n  it('should not update state while rendering', async () => {\n    const queryClient = new QueryClient()\n\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    const isFetchingArray: Array<number> = []\n\n    function IsFetching() {\n      const isFetching = useIsFetching()\n\n      isFetchingArray.push(isFetching)\n\n      return null\n    }\n\n    function FirstQuery() {\n      useQuery({\n        queryKey: key1,\n        queryFn: () => sleep(100).then(() => 'data1'),\n      })\n\n      return null\n    }\n\n    function SecondQuery() {\n      useQuery({\n        queryKey: key2,\n        queryFn: () => sleep(100).then(() => 'data2'),\n      })\n\n      return null\n    }\n\n    function Page() {\n      const [renderSecond, setRenderSecond] = useState(false)\n\n      useEffect(() => {\n        setActTimeout(() => {\n          setRenderSecond(true)\n        }, 50)\n      }, [])\n\n      return (\n        <>\n          <IsFetching />\n          <FirstQuery />\n          {renderSecond && <SecondQuery />}\n        </>\n      )\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    expect(isFetchingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isFetchingArray[1]).toEqual(1)\n    await vi.advanceTimersByTimeAsync(50)\n    expect(isFetchingArray[2]).toEqual(1)\n    await vi.advanceTimersByTimeAsync(1)\n    expect(isFetchingArray[3]).toEqual(2)\n    await vi.advanceTimersByTimeAsync(50)\n    expect(isFetchingArray[4]).toEqual(1)\n    await vi.advanceTimersByTimeAsync(50)\n    expect(isFetchingArray[5]).toEqual(0)\n\n    expect(isFetchingArray).toEqual([0, 1, 1, 2, 1, 0])\n  })\n\n  it('should be able to filter', async () => {\n    const queryClient = new QueryClient()\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    const isFetchingArray: Array<number> = []\n\n    function One() {\n      useQuery({\n        queryKey: key1,\n        queryFn: () => sleep(10).then(() => 'test1'),\n      })\n\n      return null\n    }\n\n    function Two() {\n      useQuery({\n        queryKey: key2,\n        queryFn: () => sleep(20).then(() => 'test2'),\n      })\n\n      return null\n    }\n\n    function Page() {\n      const [started, setStarted] = useState(false)\n      const isFetching = useIsFetching({ queryKey: key1 })\n\n      isFetchingArray.push(isFetching)\n\n      return (\n        <div>\n          <button onClick={() => setStarted(true)}>setStarted</button>\n          <div>isFetching: {isFetching}</div>\n          {started ? (\n            <>\n              <One />\n              <Two />\n            </>\n          ) : null}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('isFetching: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /setStarted/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('isFetching: 1')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('isFetching: 0')).toBeInTheDocument()\n\n    // at no point should we have isFetching: 2\n    expect(isFetchingArray).toEqual(expect.not.arrayContaining([2]))\n  })\n\n  it('should show the correct fetching state when mounted after a query', async () => {\n    const queryClient = new QueryClient()\n    const key = queryKey()\n\n    function Page() {\n      useQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'test'),\n      })\n\n      const isFetching = useIsFetching()\n\n      return (\n        <div>\n          <div>isFetching: {isFetching}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('isFetching: 1')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('isFetching: 0')).toBeInTheDocument()\n  })\n\n  it('should use provided custom queryClient', async () => {\n    const onSuccess = vi.fn()\n\n    const queryCache = new QueryCache({ onSuccess })\n    const queryClient = new QueryClient({ queryCache })\n    const key = queryKey()\n\n    function Page() {\n      useQuery(\n        {\n          queryKey: key,\n          queryFn: () => sleep(10).then(() => 'test'),\n        },\n        queryClient,\n      )\n\n      const isFetching = useIsFetching({}, queryClient)\n\n      return (\n        <div>\n          <div>isFetching: {isFetching}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(<Page />)\n\n    expect(rendered.getByText('isFetching: 1')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('isFetching: 0')).toBeInTheDocument()\n    expect(onSuccess).toHaveBeenCalledOnce()\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/useMutation.test.tsx",
    "content": "import { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { fireEvent, render } from '@testing-library/preact'\nimport { useEffect, useState } from 'preact/hooks'\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\n\nimport { MutationCache, QueryCache, QueryClient, useMutation } from '..'\nimport type { UseMutationResult } from '../types'\nimport { ErrorBoundary } from './ErrorBoundary'\nimport {\n  mockOnlineManagerIsOnline,\n  renderWithClient,\n  setActTimeout,\n} from './utils'\n\ndescribe('useMutation', () => {\n  let queryCache: QueryCache\n  let mutationCache: MutationCache\n  let queryClient: QueryClient\n\n  beforeEach(() => {\n    queryCache = new QueryCache()\n    mutationCache = new MutationCache()\n    queryClient = new QueryClient({\n      queryCache,\n      mutationCache,\n    })\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should be able to reset `data`', async () => {\n    function Page() {\n      const {\n        mutate,\n        data = 'empty',\n        reset,\n      } = useMutation({ mutationFn: () => Promise.resolve('mutation') })\n\n      return (\n        <div>\n          <h1>{data}</h1>\n          <button onClick={() => reset()}>reset</button>\n          <button onClick={() => mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    const { getByRole } = renderWithClient(queryClient, <Page />)\n\n    expect(getByRole('heading').textContent).toBe('empty')\n\n    fireEvent.click(getByRole('button', { name: /mutate/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(getByRole('heading').textContent).toBe('mutation')\n\n    fireEvent.click(getByRole('button', { name: /reset/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(getByRole('heading').textContent).toBe('empty')\n  })\n\n  it('should be able to reset `error`', async () => {\n    function Page() {\n      const { mutate, error, reset } = useMutation<string, Error>({\n        mutationFn: () => {\n          const err = new Error('Expected mock error. All is well!')\n          err.stack = ''\n          return Promise.reject(err)\n        },\n      })\n\n      return (\n        <div>\n          {error && <h1>{error.message}</h1>}\n          <button onClick={() => reset()}>reset</button>\n          <button onClick={() => mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    const { getByRole, queryByRole } = renderWithClient(queryClient, <Page />)\n\n    expect(queryByRole('heading')).toBeNull()\n\n    fireEvent.click(getByRole('button', { name: /mutate/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(getByRole('heading').textContent).toBe(\n      'Expected mock error. All is well!',\n    )\n\n    fireEvent.click(getByRole('button', { name: /reset/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(queryByRole('heading')).toBeNull()\n  })\n\n  it('should be able to call `onSuccess` and `onSettled` after each successful mutate', async () => {\n    let count = 0\n    const onSuccessMock = vi.fn()\n    const onSettledMock = vi.fn()\n\n    function Page() {\n      const { mutate } = useMutation({\n        mutationFn: (vars: { count: number }) => Promise.resolve(vars.count),\n\n        onSuccess: (data) => {\n          onSuccessMock(data)\n        },\n        onSettled: (data) => {\n          onSettledMock(data)\n        },\n      })\n\n      return (\n        <div>\n          <h1>{count}</h1>\n          <button onClick={() => mutate({ count: ++count })}>mutate</button>\n        </div>\n      )\n    }\n\n    const { getByRole } = renderWithClient(queryClient, <Page />)\n\n    expect(getByRole('heading').textContent).toBe('0')\n\n    fireEvent.click(getByRole('button', { name: /mutate/i }))\n    fireEvent.click(getByRole('button', { name: /mutate/i }))\n    fireEvent.click(getByRole('button', { name: /mutate/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(getByRole('heading').textContent).toBe('3')\n    expect(onSuccessMock).toHaveBeenCalledTimes(3)\n\n    expect(onSuccessMock).toHaveBeenCalledWith(1)\n    expect(onSuccessMock).toHaveBeenCalledWith(2)\n    expect(onSuccessMock).toHaveBeenCalledWith(3)\n\n    expect(onSettledMock).toHaveBeenCalledTimes(3)\n\n    expect(onSettledMock).toHaveBeenCalledWith(1)\n    expect(onSettledMock).toHaveBeenCalledWith(2)\n    expect(onSettledMock).toHaveBeenCalledWith(3)\n  })\n\n  it('should set correct values for `failureReason` and `failureCount` on multiple mutate calls', async () => {\n    let count = 0\n    type Value = { count: number }\n\n    const mutateFn = vi.fn<(value: Value) => Promise<Value>>()\n\n    mutateFn.mockImplementationOnce(() => {\n      return Promise.reject(new Error('Error test Jonas'))\n    })\n\n    mutateFn.mockImplementation(async (value) => {\n      await sleep(10)\n      return Promise.resolve(value)\n    })\n\n    function Page() {\n      const { mutate, failureCount, failureReason, data, status } = useMutation(\n        { mutationFn: mutateFn },\n      )\n\n      return (\n        <div>\n          <h1>Data {data?.count}</h1>\n          <h2>Status {status}</h2>\n          <h2>Failed {failureCount} times</h2>\n          <h2>Failed because {failureReason?.message ?? 'null'}</h2>\n          <button onClick={() => mutate({ count: ++count })}>mutate</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('Data')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Status error')).toBeInTheDocument()\n    expect(rendered.getByText('Failed 1 times')).toBeInTheDocument()\n    expect(\n      rendered.getByText('Failed because Error test Jonas'),\n    ).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Status pending')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Status success')).toBeInTheDocument()\n    expect(rendered.getByText('Data 2')).toBeInTheDocument()\n    expect(rendered.getByText('Failed 0 times')).toBeInTheDocument()\n    expect(rendered.getByText('Failed because null')).toBeInTheDocument()\n  })\n\n  it('should be able to call `onError` and `onSettled` after each failed mutate', async () => {\n    const onErrorMock = vi.fn()\n    const onSettledMock = vi.fn()\n    let count = 0\n\n    function Page() {\n      const { mutate } = useMutation({\n        mutationFn: (vars: { count: number }) => {\n          const error = new Error(\n            `Expected mock error. All is well! ${vars.count}`,\n          )\n          error.stack = ''\n          return Promise.reject(error)\n        },\n        onError: (error: Error) => {\n          onErrorMock(error.message)\n        },\n        onSettled: (_data, error) => {\n          onSettledMock(error?.message)\n        },\n      })\n\n      return (\n        <div>\n          <h1>{count}</h1>\n          <button onClick={() => mutate({ count: ++count })}>mutate</button>\n        </div>\n      )\n    }\n\n    const { getByRole } = renderWithClient(queryClient, <Page />)\n\n    expect(getByRole('heading').textContent).toBe('0')\n\n    fireEvent.click(getByRole('button', { name: /mutate/i }))\n    fireEvent.click(getByRole('button', { name: /mutate/i }))\n    fireEvent.click(getByRole('button', { name: /mutate/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(getByRole('heading').textContent).toBe('3')\n    expect(onErrorMock).toHaveBeenCalledTimes(3)\n    expect(onErrorMock).toHaveBeenCalledWith(\n      'Expected mock error. All is well! 1',\n    )\n    expect(onErrorMock).toHaveBeenCalledWith(\n      'Expected mock error. All is well! 2',\n    )\n    expect(onErrorMock).toHaveBeenCalledWith(\n      'Expected mock error. All is well! 3',\n    )\n\n    expect(onSettledMock).toHaveBeenCalledTimes(3)\n    expect(onSettledMock).toHaveBeenCalledWith(\n      'Expected mock error. All is well! 1',\n    )\n    expect(onSettledMock).toHaveBeenCalledWith(\n      'Expected mock error. All is well! 2',\n    )\n    expect(onSettledMock).toHaveBeenCalledWith(\n      'Expected mock error. All is well! 3',\n    )\n  })\n\n  it('should be able to override the useMutation success callbacks', async () => {\n    const callbacks: Array<string> = []\n\n    function Page() {\n      const { mutateAsync } = useMutation({\n        mutationFn: (text: string) => Promise.resolve(text),\n        onSuccess: () => {\n          callbacks.push('useMutation.onSuccess')\n          return Promise.resolve()\n        },\n        onSettled: () => {\n          callbacks.push('useMutation.onSettled')\n          return Promise.resolve()\n        },\n      })\n\n      useEffect(() => {\n        setActTimeout(async () => {\n          try {\n            const result = await mutateAsync('todo', {\n              onSuccess: () => {\n                callbacks.push('mutateAsync.onSuccess')\n                return Promise.resolve()\n              },\n              onSettled: () => {\n                callbacks.push('mutateAsync.onSettled')\n                return Promise.resolve()\n              },\n            })\n            callbacks.push(`mutateAsync.result:${result}`)\n          } catch {}\n        }, 10)\n      }, [mutateAsync])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(callbacks).toEqual([\n      'useMutation.onSuccess',\n      'useMutation.onSettled',\n      'mutateAsync.onSuccess',\n      'mutateAsync.onSettled',\n      'mutateAsync.result:todo',\n    ])\n  })\n\n  it('should be able to override the error callbacks when using mutateAsync', async () => {\n    const callbacks: Array<string> = []\n\n    function Page() {\n      const { mutateAsync } = useMutation({\n        mutationFn: async (_text: string) => Promise.reject(new Error('oops')),\n        onError: () => {\n          callbacks.push('useMutation.onError')\n          return Promise.resolve()\n        },\n        onSettled: () => {\n          callbacks.push('useMutation.onSettled')\n          return Promise.resolve()\n        },\n      })\n\n      useEffect(() => {\n        setActTimeout(async () => {\n          try {\n            await mutateAsync('todo', {\n              onError: () => {\n                callbacks.push('mutateAsync.onError')\n                return Promise.resolve()\n              },\n              onSettled: () => {\n                callbacks.push('mutateAsync.onSettled')\n                return Promise.resolve()\n              },\n            })\n          } catch (error) {\n            callbacks.push(`mutateAsync.error:${(error as Error).message}`)\n          }\n        }, 10)\n      }, [mutateAsync])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(callbacks).toEqual([\n      'useMutation.onError',\n      'useMutation.onSettled',\n      'mutateAsync.onError',\n      'mutateAsync.onSettled',\n      'mutateAsync.error:oops',\n    ])\n  })\n\n  it('should be able to use mutation defaults', async () => {\n    const key = queryKey()\n\n    queryClient.setMutationDefaults(key, {\n      mutationFn: async (text: string) => {\n        await sleep(10)\n        return text\n      },\n    })\n\n    const states: Array<UseMutationResult<any, any, any, any>> = []\n\n    function Page() {\n      const state = useMutation<string, unknown, string>({ mutationKey: key })\n\n      states.push(state)\n\n      const { mutate } = state\n\n      useEffect(() => {\n        setActTimeout(() => {\n          mutate('todo')\n        }, 10)\n      }, [mutate])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(21)\n\n    expect(states.length).toBe(3)\n    expect(states[0]).toMatchObject({ data: undefined, isPending: false })\n    expect(states[1]).toMatchObject({ data: undefined, isPending: true })\n    expect(states[2]).toMatchObject({ data: 'todo', isPending: false })\n  })\n\n  it('should be able to retry a failed mutation', async () => {\n    let count = 0\n\n    function Page() {\n      const { mutate } = useMutation({\n        mutationFn: (_text: string) => {\n          count++\n          return Promise.reject(new Error('oops'))\n        },\n        retry: 1,\n        retryDelay: 5,\n      })\n\n      useEffect(() => {\n        setActTimeout(() => {\n          mutate('todo')\n        }, 10)\n      }, [mutate])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(15)\n\n    expect(count).toBe(2)\n  })\n\n  it('should not retry mutations while offline', async () => {\n    const onlineMock = mockOnlineManagerIsOnline(false)\n\n    let count = 0\n\n    function Page() {\n      const mutation = useMutation({\n        mutationFn: (_text: string) => {\n          count++\n          return Promise.reject(new Error('oops'))\n        },\n        retry: 1,\n        retryDelay: 5,\n      })\n\n      return (\n        <div>\n          <button onClick={() => mutation.mutate('todo')}>mutate</button>\n          <div>\n            error:{' '}\n            {mutation.error instanceof Error ? mutation.error.message : 'null'},\n            status: {mutation.status}, isPaused: {String(mutation.isPaused)}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(\n      rendered.getByText('error: null, status: idle, isPaused: false'),\n    ).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(\n      rendered.getByText('error: null, status: pending, isPaused: true'),\n    ).toBeInTheDocument()\n\n    expect(count).toBe(0)\n\n    onlineMock.mockReturnValue(true)\n    queryClient.getMutationCache().resumePausedMutations()\n\n    await vi.advanceTimersByTimeAsync(6)\n    expect(\n      rendered.getByText('error: oops, status: error, isPaused: false'),\n    ).toBeInTheDocument()\n\n    expect(count).toBe(2)\n    onlineMock.mockRestore()\n  })\n\n  it('should call onMutate even if paused', async () => {\n    const onlineMock = mockOnlineManagerIsOnline(false)\n    const onMutate = vi.fn()\n    let count = 0\n\n    function Page() {\n      const mutation = useMutation({\n        mutationFn: async (_text: string) => {\n          count++\n          await sleep(10)\n          return count\n        },\n        onMutate,\n      })\n\n      return (\n        <div>\n          <button onClick={() => mutation.mutate('todo')}>mutate</button>\n          <div>\n            data: {mutation.data ?? 'null'}, status: {mutation.status},\n            isPaused: {String(mutation.isPaused)}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(\n      rendered.getByText('data: null, status: idle, isPaused: false'),\n    ).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(\n      rendered.getByText('data: null, status: pending, isPaused: true'),\n    ).toBeInTheDocument()\n\n    expect(onMutate).toHaveBeenCalledTimes(1)\n    expect(onMutate).toHaveBeenCalledWith('todo', {\n      client: queryClient,\n      meta: undefined,\n      mutationKey: undefined,\n    })\n\n    onlineMock.mockReturnValue(true)\n    queryClient.getMutationCache().resumePausedMutations()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(\n      rendered.getByText('data: 1, status: success, isPaused: false'),\n    ).toBeInTheDocument()\n\n    expect(onMutate).toHaveBeenCalledTimes(1)\n    expect(count).toBe(1)\n\n    onlineMock.mockRestore()\n  })\n\n  it('should optimistically go to paused state if offline', async () => {\n    const onlineMock = mockOnlineManagerIsOnline(false)\n    let count = 0\n    const states: Array<string> = []\n\n    function Page() {\n      const mutation = useMutation({\n        mutationFn: async (_text: string) => {\n          count++\n          await sleep(10)\n          return count\n        },\n      })\n\n      states.push(`${mutation.status}, ${mutation.isPaused}`)\n\n      return (\n        <div>\n          <button onClick={() => mutation.mutate('todo')}>mutate</button>\n          <div>\n            data: {mutation.data ?? 'null'}, status: {mutation.status},\n            isPaused: {String(mutation.isPaused)}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(\n      rendered.getByText('data: null, status: idle, isPaused: false'),\n    ).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(\n      rendered.getByText('data: null, status: pending, isPaused: true'),\n    ).toBeInTheDocument()\n\n    // no intermediate 'pending, false' state is expected because we don't start mutating!\n    expect(states[0]).toBe('idle, false')\n    expect(states[1]).toBe('pending, true')\n\n    onlineMock.mockReturnValue(true)\n    queryClient.getMutationCache().resumePausedMutations()\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(\n      rendered.getByText('data: 1, status: success, isPaused: false'),\n    ).toBeInTheDocument()\n\n    onlineMock.mockRestore()\n  })\n\n  it('should be able to retry a mutation when online', async () => {\n    const onlineMock = mockOnlineManagerIsOnline(false)\n    const key = queryKey()\n\n    let count = 0\n\n    function Page() {\n      const state = useMutation({\n        mutationKey: key,\n        mutationFn: async (_text: string) => {\n          await sleep(10)\n          count++\n          return count > 1\n            ? Promise.resolve(`data${count}`)\n            : Promise.reject(new Error('oops'))\n        },\n        retry: 1,\n        retryDelay: 5,\n        networkMode: 'offlineFirst',\n      })\n\n      return (\n        <div>\n          <button onClick={() => state.mutate('todo')}>mutate</button>\n          <div>status: {state.status}</div>\n          <div>isPaused: {String(state.isPaused)}</div>\n          <div>data: {state.data ?? 'null'}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('status: idle')).toBeInTheDocument()\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(16)\n    expect(rendered.getByText('isPaused: true')).toBeInTheDocument()\n\n    expect(\n      queryClient.getMutationCache().findAll({ mutationKey: key }).length,\n    ).toBe(1)\n    expect(\n      queryClient.getMutationCache().findAll({ mutationKey: key })[0]?.state,\n    ).toMatchObject({\n      status: 'pending',\n      isPaused: true,\n      failureCount: 1,\n      failureReason: new Error('oops'),\n    })\n\n    onlineMock.mockReturnValue(true)\n    queryClient.getMutationCache().resumePausedMutations()\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: data2')).toBeInTheDocument()\n\n    expect(\n      queryClient.getMutationCache().findAll({ mutationKey: key })[0]?.state,\n    ).toMatchObject({\n      status: 'success',\n      isPaused: false,\n      failureCount: 0,\n      failureReason: null,\n      data: 'data2',\n    })\n\n    onlineMock.mockRestore()\n  })\n\n  // eslint-disable-next-line vitest/expect-expect\n  it('should not change state if unmounted', () => {\n    function Mutates() {\n      const { mutate } = useMutation({ mutationFn: () => sleep(10) })\n      return <button onClick={() => mutate()}>mutate</button>\n    }\n    function Page() {\n      const [mounted, setMounted] = useState(true)\n      return (\n        <div>\n          <button onClick={() => setMounted(false)}>unmount</button>\n          {mounted && <Mutates />}\n        </div>\n      )\n    }\n\n    const { getByText } = renderWithClient(queryClient, <Page />)\n    fireEvent.click(getByText('mutate'))\n    fireEvent.click(getByText('unmount'))\n  })\n\n  it('should be able to throw an error when throwOnError is set to true', async () => {\n    const err = new Error('Expected mock error. All is well!')\n    err.stack = ''\n\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    function Page() {\n      const { mutate } = useMutation<string, Error>({\n        mutationFn: () => {\n          return Promise.reject(err)\n        },\n        throwOnError: true,\n      })\n\n      return (\n        <div>\n          <button onClick={() => mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    const { getByText, queryByText } = renderWithClient(\n      queryClient,\n      <ErrorBoundary\n        fallbackRender={() => (\n          <div>\n            <span>error</span>\n          </div>\n        )}\n      >\n        <Page />\n      </ErrorBoundary>,\n    )\n\n    fireEvent.click(getByText('mutate'))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(queryByText('error')).not.toBeNull()\n\n    expect(consoleMock.mock.calls[0]?.[1]).toBe(err)\n\n    consoleMock.mockRestore()\n  })\n\n  it('should be able to throw an error when throwOnError is a function that returns true', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    let boundary = false\n    function Page() {\n      const { mutate, error } = useMutation<string>({\n        mutationFn: () => {\n          const err = new Error('mock error')\n          err.stack = ''\n          return Promise.reject(err)\n        },\n        throwOnError: () => {\n          return boundary\n        },\n      })\n\n      return (\n        <div>\n          <button onClick={() => mutate()}>mutate</button>\n          {error && error.message}\n        </div>\n      )\n    }\n\n    const { getByText, queryByText } = renderWithClient(\n      queryClient,\n      <ErrorBoundary\n        fallbackRender={() => (\n          <div>\n            <span>error boundary</span>\n          </div>\n        )}\n      >\n        <Page />\n      </ErrorBoundary>,\n    )\n\n    // first error goes to component\n    fireEvent.click(getByText('mutate'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(queryByText('mock error')).not.toBeNull()\n\n    // second error goes to boundary\n    boundary = true\n    fireEvent.click(getByText('mutate'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(queryByText('error boundary')).not.toBeNull()\n    consoleMock.mockRestore()\n  })\n\n  it('should pass meta to mutation', async () => {\n    const errorMock = vi.fn()\n    const successMock = vi.fn()\n\n    const queryClientMutationMeta = new QueryClient({\n      mutationCache: new MutationCache({\n        onSuccess: (_, __, ___, mutation) => {\n          successMock(mutation.meta?.metaSuccessMessage)\n        },\n        onError: (_, __, ___, mutation) => {\n          errorMock(mutation.meta?.metaErrorMessage)\n        },\n      }),\n    })\n\n    const metaSuccessMessage = 'mutation succeeded'\n    const metaErrorMessage = 'mutation failed'\n\n    function Page() {\n      const { mutate: succeed, isSuccess } = useMutation({\n        mutationFn: () => Promise.resolve(''),\n        meta: { metaSuccessMessage },\n      })\n      const { mutate: error, isError } = useMutation({\n        mutationFn: () => {\n          return Promise.reject(new Error(''))\n        },\n        meta: { metaErrorMessage },\n      })\n\n      return (\n        <div>\n          <button onClick={() => succeed()}>succeed</button>\n          <button onClick={() => error()}>error</button>\n          {isSuccess && <div>successTest</div>}\n          {isError && <div>errorTest</div>}\n        </div>\n      )\n    }\n\n    const { getByText, queryByText } = renderWithClient(\n      queryClientMutationMeta,\n      <Page />,\n    )\n\n    fireEvent.click(getByText('succeed'))\n    fireEvent.click(getByText('error'))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(queryByText('successTest')).not.toBeNull()\n    expect(queryByText('errorTest')).not.toBeNull()\n\n    expect(successMock).toHaveBeenCalledTimes(1)\n    expect(successMock).toHaveBeenCalledWith(metaSuccessMessage)\n    expect(errorMock).toHaveBeenCalledTimes(1)\n    expect(errorMock).toHaveBeenCalledWith(metaErrorMessage)\n  })\n\n  it('should call cache callbacks when unmounted', async () => {\n    const onSuccess = vi.fn()\n    const onSuccessMutate = vi.fn()\n    const onSettled = vi.fn()\n    const onSettledMutate = vi.fn()\n    const mutationKey = queryKey()\n    let count = 0\n\n    function Page() {\n      const [show, setShow] = useState(true)\n      return (\n        <div>\n          <button onClick={() => setShow(false)}>hide</button>\n          {show && <Component />}\n        </div>\n      )\n    }\n\n    function Component() {\n      const mutation = useMutation({\n        mutationFn: async (_text: string) => {\n          count++\n          await sleep(10)\n          return count\n        },\n        mutationKey,\n        gcTime: 0,\n        onSuccess,\n        onSettled,\n      })\n\n      return (\n        <div>\n          <button\n            onClick={() =>\n              mutation.mutate('todo', {\n                onSuccess: onSuccessMutate,\n                onSettled: onSettledMutate,\n              })\n            }\n          >\n            mutate\n          </button>\n          <div>\n            data: {mutation.data ?? 'null'}, status: {mutation.status},\n            isPaused: {String(mutation.isPaused)}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(\n      rendered.getByText('data: null, status: idle, isPaused: false'),\n    ).toBeInTheDocument()\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /hide/i }))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(\n      queryClient.getMutationCache().findAll({ mutationKey }),\n    ).toHaveLength(0)\n\n    expect(count).toBe(1)\n\n    expect(onSuccess).toHaveBeenCalledTimes(1)\n    expect(onSettled).toHaveBeenCalledTimes(1)\n    expect(onSuccessMutate).toHaveBeenCalledTimes(0)\n    expect(onSettledMutate).toHaveBeenCalledTimes(0)\n  })\n\n  it('should call mutate callbacks only for the last observer', async () => {\n    const onSuccess = vi.fn()\n    const onSuccessMutate = vi.fn()\n    const onSettled = vi.fn()\n    const onSettledMutate = vi.fn()\n    let count = 0\n\n    function Page() {\n      const mutation = useMutation({\n        mutationFn: async (text: string) => {\n          count++\n          const result = `result-${text}`\n          await sleep(10)\n          return result\n        },\n        onSuccess,\n        onSettled,\n      })\n\n      return (\n        <div>\n          <button\n            onClick={() =>\n              mutation.mutate('todo1', {\n                onSuccess: onSuccessMutate,\n                onSettled: onSettledMutate,\n              })\n            }\n          >\n            mutate1\n          </button>\n          <button\n            onClick={() =>\n              mutation.mutate('todo2', {\n                onSuccess: onSuccessMutate,\n                onSettled: onSettledMutate,\n              })\n            }\n          >\n            mutate2\n          </button>\n          <div>\n            data: {mutation.data ?? 'null'}, status: {mutation.status}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('data: null, status: idle')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(\n      rendered.getByText('data: result-todo2, status: success'),\n    ).toBeInTheDocument()\n\n    expect(count).toBe(2)\n\n    expect(onSuccess).toHaveBeenCalledTimes(2)\n    expect(onSuccess).toHaveBeenNthCalledWith(\n      1,\n      'result-todo1',\n      'todo1',\n      undefined,\n      {\n        client: queryClient,\n        meta: undefined,\n        mutationKey: undefined,\n      },\n    )\n    expect(onSuccess).toHaveBeenNthCalledWith(\n      2,\n      'result-todo2',\n      'todo2',\n      undefined,\n      {\n        client: queryClient,\n        meta: undefined,\n        mutationKey: undefined,\n      },\n    )\n    expect(onSettled).toHaveBeenCalledTimes(2)\n    expect(onSuccessMutate).toHaveBeenCalledTimes(1)\n    expect(onSuccessMutate).toHaveBeenCalledWith(\n      'result-todo2',\n      'todo2',\n      undefined,\n      {\n        client: queryClient,\n        meta: undefined,\n        mutationKey: undefined,\n      },\n    )\n    expect(onSettledMutate).toHaveBeenCalledTimes(1)\n    expect(onSettledMutate).toHaveBeenCalledWith(\n      'result-todo2',\n      null,\n      'todo2',\n      undefined,\n      {\n        client: queryClient,\n        meta: undefined,\n        mutationKey: undefined,\n      },\n    )\n  })\n\n  it('should go to error state if onSuccess callback errors', async () => {\n    const error = new Error('error from onSuccess')\n    const onError = vi.fn()\n\n    function Page() {\n      const mutation = useMutation({\n        mutationFn: async (_text: string) => {\n          await sleep(10)\n          return 'result'\n        },\n        onSuccess: () => Promise.reject(error),\n        onError,\n      })\n\n      return (\n        <div>\n          <button onClick={() => mutation.mutate('todo')}>mutate</button>\n          <div>status: {mutation.status}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('status: idle')).toBeInTheDocument()\n\n    rendered.getByRole('button', { name: /mutate/i }).click()\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('status: error')).toBeInTheDocument()\n\n    expect(onError).toHaveBeenCalledWith(error, 'todo', undefined, {\n      client: queryClient,\n      meta: undefined,\n      mutationKey: undefined,\n    })\n  })\n\n  it('should go to error state if onError callback errors', async ({\n    onTestFinished,\n  }) => {\n    const unhandledRejectionFn = vi.fn()\n    process.on('unhandledRejection', (error) => unhandledRejectionFn(error))\n    onTestFinished(() => {\n      process.off('unhandledRejection', unhandledRejectionFn)\n    })\n\n    const error = new Error('error from onError')\n    const mutateFnError = new Error('mutateFnError')\n\n    function Page() {\n      const mutation = useMutation({\n        mutationFn: async (_text: string) => {\n          await sleep(10)\n          throw mutateFnError\n        },\n        onError: () => Promise.reject(error),\n      })\n\n      return (\n        <div>\n          <button onClick={() => mutation.mutate('todo')}>mutate</button>\n          <div>\n            error:{' '}\n            {mutation.error instanceof Error ? mutation.error.message : 'null'},\n            status: {mutation.status}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('error: null, status: idle')).toBeInTheDocument()\n\n    rendered.getByRole('button', { name: /mutate/i }).click()\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(\n      rendered.getByText('error: mutateFnError, status: error'),\n    ).toBeInTheDocument()\n  })\n\n  it('should go to error state if onSettled callback errors', async ({\n    onTestFinished,\n  }) => {\n    const unhandledRejectionFn = vi.fn()\n    process.on('unhandledRejection', (error) => unhandledRejectionFn(error))\n    onTestFinished(() => {\n      process.off('unhandledRejection', unhandledRejectionFn)\n    })\n\n    const error = new Error('error from onSettled')\n    const mutateFnError = new Error('mutateFnError')\n    const onError = vi.fn()\n\n    function Page() {\n      const mutation = useMutation({\n        mutationFn: async (_text: string) => {\n          await sleep(10)\n          throw mutateFnError\n        },\n        onSettled: () => Promise.reject(error),\n        onError,\n      })\n\n      return (\n        <div>\n          <button onClick={() => mutation.mutate('todo')}>mutate</button>\n          <div>\n            error:{' '}\n            {mutation.error instanceof Error ? mutation.error.message : 'null'},\n            status: {mutation.status}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('error: null, status: idle')).toBeInTheDocument()\n\n    rendered.getByRole('button', { name: /mutate/i }).click()\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(\n      rendered.getByText('error: mutateFnError, status: error'),\n    ).toBeInTheDocument()\n    expect(onError).toHaveBeenCalledWith(mutateFnError, 'todo', undefined, {\n      client: queryClient,\n      meta: undefined,\n      mutationKey: undefined,\n    })\n  })\n\n  it('should use provided custom queryClient', async () => {\n    function Page() {\n      const mutation = useMutation(\n        {\n          mutationFn: async (text: string) => {\n            return Promise.resolve(text)\n          },\n        },\n        queryClient,\n      )\n\n      return (\n        <div>\n          <button onClick={() => mutation.mutate('custom client')}>\n            mutate\n          </button>\n          <div>\n            data: {mutation.data ?? 'null'}, status: {mutation.status}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = render(<Page />)\n\n    expect(rendered.getByText('data: null, status: idle')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(\n      rendered.getByText('data: custom client, status: success'),\n    ).toBeInTheDocument()\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/useMutationState.test-d.tsx",
    "content": "import type { MutationState, MutationStatus } from '@tanstack/query-core'\nimport { describe, expectTypeOf, it } from 'vitest'\n\nimport { useMutationState } from '../useMutationState'\n\ndescribe('useMutationState', () => {\n  it('should default to QueryState', () => {\n    const result = useMutationState({\n      filters: { status: 'pending' },\n    })\n\n    expectTypeOf(result).toEqualTypeOf<\n      Array<MutationState<unknown, Error, unknown, unknown>>\n    >()\n  })\n  it('should infer with select', () => {\n    const result = useMutationState({\n      filters: { status: 'pending' },\n      select: (mutation) => mutation.state.status,\n    })\n\n    expectTypeOf(result).toEqualTypeOf<Array<MutationStatus>>()\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/useMutationState.test.tsx",
    "content": "import { sleep } from '@tanstack/query-test-utils'\nimport { fireEvent, render } from '@testing-library/preact'\nimport { useEffect } from 'preact/hooks'\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\n\nimport { QueryClient, useIsMutating, useMutation, useMutationState } from '..'\nimport { renderWithClient } from './utils'\n\ndescribe('useIsMutating', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should return the number of fetching mutations', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n\n    function IsMutating() {\n      const isMutating = useIsMutating()\n\n      isMutatingArray.push(isMutating)\n\n      return null\n    }\n\n    function Mutations() {\n      const { mutate: mutate1 } = useMutation({\n        mutationKey: ['mutation1'],\n        mutationFn: () => sleep(50).then(() => 'data'),\n      })\n      const { mutate: mutate2 } = useMutation({\n        mutationKey: ['mutation2'],\n        mutationFn: () => sleep(10).then(() => 'data'),\n      })\n\n      return (\n        <div>\n          <button onClick={() => mutate1()}>mutate1</button>\n          <button onClick={() => mutate2()}>mutate2</button>\n        </div>\n      )\n    }\n\n    function Page() {\n      return (\n        <div>\n          <IsMutating />\n          <Mutations />\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    await vi.advanceTimersByTimeAsync(10)\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n\n    // we don't really care if this yields\n    // [ +0, 1, 2, +0 ]\n    // or\n    // [ +0, 1, 2, 1, +0 ]\n    // our batching strategy might yield different results\n\n    await vi.advanceTimersByTimeAsync(41)\n    expect(isMutatingArray[0]).toEqual(0)\n    expect(isMutatingArray[1]).toEqual(1)\n    expect(isMutatingArray[2]).toEqual(2)\n    expect(isMutatingArray[3]).toEqual(1)\n    expect(isMutatingArray[4]).toEqual(0)\n\n    expect(isMutatingArray).toEqual([0, 1, 2, 1, 0])\n  })\n\n  it('should filter correctly by mutationKey', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n\n    function IsMutating() {\n      const isMutating = useIsMutating({ mutationKey: ['mutation1'] })\n      isMutatingArray.push(isMutating)\n      return null\n    }\n\n    function Page() {\n      const { mutate: mutate1 } = useMutation({\n        mutationKey: ['mutation1'],\n        mutationFn: () => sleep(100).then(() => 'data'),\n      })\n      const { mutate: mutate2 } = useMutation({\n        mutationKey: ['mutation2'],\n        mutationFn: () => sleep(100).then(() => 'data'),\n      })\n\n      useEffect(() => {\n        mutate1()\n        mutate2()\n      }, [mutate1, mutate2])\n\n      return <IsMutating />\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(101)\n    expect(isMutatingArray).toEqual([0, 1, 0])\n  })\n\n  it('should filter correctly by predicate', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n\n    function IsMutating() {\n      const isMutating = useIsMutating({\n        predicate: (mutation) =>\n          mutation.options.mutationKey?.[0] === 'mutation1',\n      })\n      isMutatingArray.push(isMutating)\n      return null\n    }\n\n    function Page() {\n      const { mutate: mutate1 } = useMutation({\n        mutationKey: ['mutation1'],\n        mutationFn: () => sleep(100).then(() => 'data'),\n      })\n      const { mutate: mutate2 } = useMutation({\n        mutationKey: ['mutation2'],\n        mutationFn: () => sleep(100).then(() => 'data'),\n      })\n\n      useEffect(() => {\n        mutate1()\n        mutate2()\n      }, [mutate1, mutate2])\n\n      return <IsMutating />\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(101)\n    expect(isMutatingArray).toEqual([0, 1, 0])\n  })\n\n  it('should use provided custom queryClient', async () => {\n    const queryClient = new QueryClient()\n\n    function Page() {\n      const isMutating = useIsMutating({}, queryClient)\n      const { mutate } = useMutation(\n        {\n          mutationKey: ['mutation1'],\n          mutationFn: () => sleep(10).then(() => 'data'),\n        },\n        queryClient,\n      )\n\n      useEffect(() => {\n        mutate()\n      }, [mutate])\n\n      return (\n        <div>\n          <div>mutating: {isMutating}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(<Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('mutating: 1')).toBeInTheDocument()\n  })\n})\n\ndescribe('useMutationState', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should return variables after calling mutate', async () => {\n    const queryClient = new QueryClient()\n    const variables: Array<Array<unknown>> = []\n    const mutationKey = ['mutation']\n\n    function Variables() {\n      variables.push(\n        useMutationState({\n          filters: { mutationKey, status: 'pending' },\n          select: (mutation) => mutation.state.variables,\n        }),\n      )\n\n      return null\n    }\n\n    function Mutate() {\n      const { mutate, data } = useMutation({\n        mutationKey,\n        mutationFn: (input: number) => sleep(150).then(() => 'data' + input),\n      })\n\n      return (\n        <div>\n          data: {data ?? 'null'}\n          <button onClick={() => mutate(1)}>mutate</button>\n        </div>\n      )\n    }\n\n    function Page() {\n      return (\n        <div>\n          <Variables />\n          <Mutate />\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('data: null')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(151)\n    expect(rendered.getByText('data: data1')).toBeInTheDocument()\n\n    expect(variables).toEqual([[], [1], []])\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/usePrefetchInfiniteQuery.test-d.tsx",
    "content": "import { assertType, describe, expectTypeOf, it } from 'vitest'\n\nimport { usePrefetchInfiniteQuery } from '..'\n\ndescribe('usePrefetchInfiniteQuery', () => {\n  it('should return nothing', () => {\n    const result = usePrefetchInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n      initialPageParam: 1,\n      getNextPageParam: () => 1,\n    })\n\n    expectTypeOf(result).toEqualTypeOf<void>()\n  })\n\n  it('should require initialPageParam and getNextPageParam', () => {\n    assertType(\n      // @ts-expect-error TS2345\n      usePrefetchInfiniteQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n      }),\n    )\n  })\n\n  it('should not allow refetchInterval, enabled or throwOnError options', () => {\n    assertType(\n      usePrefetchInfiniteQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        initialPageParam: 1,\n        getNextPageParam: () => 1,\n        // @ts-expect-error TS2353\n        refetchInterval: 1000,\n      }),\n    )\n\n    assertType(\n      usePrefetchInfiniteQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        initialPageParam: 1,\n        getNextPageParam: () => 1,\n        // @ts-expect-error TS2353\n        enabled: true,\n      }),\n    )\n\n    assertType(\n      usePrefetchInfiniteQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        initialPageParam: 1,\n        getNextPageParam: () => 1,\n        // @ts-expect-error TS2353\n        throwOnError: true,\n      }),\n    )\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/usePrefetchInfiniteQuery.test.tsx",
    "content": "import { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { fireEvent } from '@testing-library/preact'\nimport type { VNode } from 'preact'\nimport { Suspense } from 'preact/compat'\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport type { Mock } from 'vitest'\n\nimport {\n  QueryCache,\n  QueryClient,\n  usePrefetchInfiniteQuery,\n  useSuspenseInfiniteQuery,\n} from '..'\nimport type { InfiniteData, UseSuspenseInfiniteQueryOptions } from '..'\nimport { renderWithClient } from './utils'\n\nconst generateInfiniteQueryOptions = (\n  data: Array<{ data: string; currentPage: number; totalPages: number }>,\n) => {\n  let currentPage = 0\n\n  return {\n    queryFn: vi\n      .fn<(...args: Array<any>) => Promise<(typeof data)[number]>>()\n      .mockImplementation(async () => {\n        const currentPageData = data[currentPage]\n        if (!currentPageData) {\n          throw new Error('No data defined for page ' + currentPage)\n        }\n\n        await sleep(10)\n        currentPage++\n\n        return currentPageData\n      }),\n    initialPageParam: 1,\n    getNextPageParam: (lastPage: (typeof data)[number]) =>\n      lastPage.currentPage === lastPage.totalPages\n        ? undefined\n        : lastPage.currentPage + 1,\n  }\n}\n\ndescribe('usePrefetchInfiniteQuery', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    queryClient.clear()\n    Fallback.mockClear()\n    vi.useRealTimers()\n  })\n\n  const queryCache = new QueryCache()\n  const queryClient = new QueryClient({ queryCache })\n\n  const Fallback = vi.fn().mockImplementation(() => <div>Loading...</div>)\n\n  function Suspended<T = unknown>(props: {\n    queryOpts: UseSuspenseInfiniteQueryOptions<\n      T,\n      Error,\n      InfiniteData<T>,\n      Array<string>,\n      any\n    >\n    renderPage: (page: T) => VNode\n  }) {\n    const state = useSuspenseInfiniteQuery(props.queryOpts)\n\n    return (\n      <div>\n        {state.data.pages.map((page, index) => (\n          <div key={index}>{props.renderPage(page)}</div>\n        ))}\n        <button onClick={() => state.fetchNextPage()}>Next Page</button>\n      </div>\n    )\n  }\n\n  it('should prefetch an infinite query if query state does not exist', async () => {\n    const data = [\n      { data: 'Do you fetch on render?', currentPage: 1, totalPages: 3 },\n      { data: 'Or do you render as you fetch?', currentPage: 2, totalPages: 3 },\n      {\n        data: 'Either way, Tanstack Query helps you!',\n        currentPage: 3,\n        totalPages: 3,\n      },\n    ]\n\n    const queryOpts = {\n      queryKey: queryKey(),\n      ...generateInfiniteQueryOptions(data),\n    }\n\n    function App() {\n      usePrefetchInfiniteQuery({ ...queryOpts, pages: data.length })\n\n      return (\n        <Suspense fallback={<Fallback />}>\n          <Suspended\n            queryOpts={queryOpts}\n            renderPage={(page) => <div>data: {page.data}</div>}\n          />\n        </Suspense>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    await vi.advanceTimersByTimeAsync(30)\n    rendered.getByText('data: Do you fetch on render?')\n    fireEvent.click(rendered.getByText('Next Page'))\n    expect(\n      rendered.getByText('data: Or do you render as you fetch?'),\n    ).toBeInTheDocument()\n    fireEvent.click(rendered.getByText('Next Page'))\n    expect(\n      rendered.getByText('data: Either way, Tanstack Query helps you!'),\n    ).toBeInTheDocument()\n    expect(Fallback).toHaveBeenCalledTimes(1)\n    expect(queryOpts.queryFn).toHaveBeenCalledTimes(3)\n  })\n\n  it('should not display fallback if the query cache is already populated', async () => {\n    const queryOpts = {\n      queryKey: queryKey(),\n      ...generateInfiniteQueryOptions([\n        { data: 'Prefetch rocks!', currentPage: 1, totalPages: 3 },\n        { data: 'No waterfalls, boy!', currentPage: 2, totalPages: 3 },\n        { data: 'Tanstack Query #ftw', currentPage: 3, totalPages: 3 },\n      ]),\n    }\n\n    queryClient.prefetchInfiniteQuery({ ...queryOpts, pages: 3 })\n    await vi.advanceTimersByTimeAsync(30)\n    ;(queryOpts.queryFn as Mock).mockClear()\n\n    function App() {\n      usePrefetchInfiniteQuery(queryOpts)\n\n      return (\n        <Suspense fallback={<Fallback />}>\n          <Suspended\n            queryOpts={queryOpts}\n            renderPage={(page) => <div>data: {page.data}</div>}\n          />\n        </Suspense>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    expect(rendered.getByText('data: Prefetch rocks!')).toBeInTheDocument()\n    fireEvent.click(rendered.getByText('Next Page'))\n    expect(rendered.getByText('data: No waterfalls, boy!')).toBeInTheDocument()\n    fireEvent.click(rendered.getByText('Next Page'))\n    expect(rendered.getByText('data: Tanstack Query #ftw')).toBeInTheDocument()\n    expect(queryOpts.queryFn).not.toHaveBeenCalled()\n    expect(Fallback).not.toHaveBeenCalled()\n  })\n\n  it('should not create an endless loop when using inside a suspense boundary', async () => {\n    const queryOpts = {\n      queryKey: queryKey(),\n      ...generateInfiniteQueryOptions([\n        { data: 'Infinite Page 1', currentPage: 1, totalPages: 3 },\n        { data: 'Infinite Page 2', currentPage: 1, totalPages: 3 },\n        { data: 'Infinite Page 3', currentPage: 1, totalPages: 3 },\n      ]),\n    }\n\n    function Prefetch({ children }: { children: VNode }) {\n      usePrefetchInfiniteQuery(queryOpts)\n      return <>{children}</>\n    }\n\n    function App() {\n      return (\n        <Suspense fallback={<></>}>\n          <Prefetch>\n            <Suspended\n              queryOpts={queryOpts}\n              renderPage={(page) => <div>data: {page.data}</div>}\n            />\n          </Prefetch>\n        </Suspense>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    await vi.advanceTimersByTimeAsync(10)\n    rendered.getByText('data: Infinite Page 1')\n    fireEvent.click(rendered.getByText('Next Page'))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: Infinite Page 2')).toBeInTheDocument()\n    fireEvent.click(rendered.getByText('Next Page'))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: Infinite Page 3')).toBeInTheDocument()\n    expect(queryOpts.queryFn).toHaveBeenCalledTimes(3)\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/usePrefetchQuery.test-d.tsx",
    "content": "import { assertType, describe, expectTypeOf, it } from 'vitest'\n\nimport { skipToken, usePrefetchQuery } from '..'\n\ndescribe('usePrefetchQuery', () => {\n  it('should return nothing', () => {\n    const result = usePrefetchQuery({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    expectTypeOf(result).toEqualTypeOf<void>()\n  })\n\n  it('should not allow refetchInterval, enabled or throwOnError options', () => {\n    assertType(\n      usePrefetchQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        // @ts-expect-error TS2345\n        refetchInterval: 1000,\n      }),\n    )\n\n    assertType(\n      usePrefetchQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        // @ts-expect-error TS2345\n        enabled: true,\n      }),\n    )\n\n    assertType(\n      usePrefetchQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        // @ts-expect-error TS2345\n        throwOnError: true,\n      }),\n    )\n  })\n\n  it('should not allow skipToken in queryFn', () => {\n    assertType(\n      usePrefetchQuery({\n        queryKey: ['key'],\n        // @ts-expect-error\n        queryFn: skipToken,\n      }),\n    )\n    assertType(\n      usePrefetchQuery({\n        queryKey: ['key'],\n        // @ts-expect-error\n        queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),\n      }),\n    )\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/usePrefetchQuery.test.tsx",
    "content": "import { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { act, fireEvent } from '@testing-library/preact'\nimport type { VNode } from 'preact'\nimport { Suspense } from 'preact/compat'\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\n\nimport {\n  QueryCache,\n  QueryClient,\n  usePrefetchQuery,\n  useQueryErrorResetBoundary,\n  useSuspenseQuery,\n} from '..'\nimport type { UseSuspenseQueryOptions } from '..'\nimport { ErrorBoundary } from './ErrorBoundary'\nimport { renderWithClient } from './utils'\n\nconst generateQueryFn = (data: string) =>\n  vi\n    .fn<(...args: Array<any>) => Promise<string>>()\n    .mockImplementation(async () => {\n      await sleep(10)\n\n      return data\n    })\n\ndescribe('usePrefetchQuery', () => {\n  const queryCache = new QueryCache()\n  const queryClient = new QueryClient({ queryCache })\n\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  function Suspended<TData = unknown>(props: {\n    queryOpts: UseSuspenseQueryOptions<TData, Error, TData, Array<string>>\n    children?: VNode\n  }) {\n    const state = useSuspenseQuery(props.queryOpts)\n\n    return (\n      <div>\n        <div>data: {String(state.data)}</div>\n        {props.children}\n      </div>\n    )\n  }\n\n  it('should prefetch query if query state does not exist', async () => {\n    const queryOpts = {\n      queryKey: queryKey(),\n      queryFn: generateQueryFn('prefetchQuery'),\n    }\n\n    const componentQueryOpts = {\n      ...queryOpts,\n      queryFn: generateQueryFn('useSuspenseQuery'),\n    }\n\n    function App() {\n      usePrefetchQuery(queryOpts)\n\n      return (\n        <Suspense fallback=\"Loading...\">\n          <Suspended queryOpts={componentQueryOpts} />\n        </Suspense>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: prefetchQuery')).toBeInTheDocument()\n    expect(queryOpts.queryFn).toHaveBeenCalledTimes(1)\n  })\n\n  it('should not prefetch query if query state exists', async () => {\n    const queryOpts = {\n      queryKey: queryKey(),\n      queryFn: generateQueryFn('The usePrefetchQuery hook is smart!'),\n    }\n\n    function App() {\n      usePrefetchQuery(queryOpts)\n\n      return (\n        <Suspense fallback=\"Loading...\">\n          <Suspended queryOpts={queryOpts} />\n        </Suspense>\n      )\n    }\n\n    queryClient.fetchQuery(queryOpts)\n    await vi.advanceTimersByTimeAsync(10)\n    queryOpts.queryFn.mockClear()\n    const rendered = renderWithClient(queryClient, <App />)\n\n    expect(rendered.queryByText('fetching: true')).not.toBeInTheDocument()\n    expect(\n      rendered.getByText('data: The usePrefetchQuery hook is smart!'),\n    ).toBeInTheDocument()\n    expect(queryOpts.queryFn).not.toHaveBeenCalled()\n  })\n\n  it('should let errors fall through and not refetch failed queries', async () => {\n    const consoleMock = vi.spyOn(console, 'error')\n    consoleMock.mockImplementation(() => undefined)\n    const queryFn = generateQueryFn('Not an error')\n\n    const queryOpts = {\n      queryKey: queryKey(),\n      queryFn,\n    }\n\n    queryFn.mockImplementationOnce(async () => {\n      await sleep(10)\n\n      throw new Error('Oops! Server error!')\n    })\n\n    function App() {\n      usePrefetchQuery(queryOpts)\n\n      return (\n        <ErrorBoundary fallbackRender={() => <div>Oops!</div>}>\n          <Suspense fallback=\"Loading...\">\n            <Suspended queryOpts={queryOpts} />\n          </Suspense>\n        </ErrorBoundary>\n      )\n    }\n\n    queryClient.prefetchQuery(queryOpts)\n    await vi.advanceTimersByTimeAsync(10)\n    queryFn.mockClear()\n    const rendered = renderWithClient(queryClient, <App />)\n\n    expect(rendered.getByText('Oops!')).toBeInTheDocument()\n    expect(rendered.queryByText('data: Not an error')).not.toBeInTheDocument()\n    expect(queryOpts.queryFn).not.toHaveBeenCalled()\n\n    consoleMock.mockRestore()\n  })\n\n  it('should not create an endless loop when using inside a suspense boundary', async () => {\n    const queryFn = generateQueryFn('prefetchedQuery')\n\n    const queryOpts = {\n      queryKey: queryKey(),\n      queryFn,\n    }\n\n    function Prefetch({ children }: { children: VNode }) {\n      usePrefetchQuery(queryOpts)\n      return <>{children}</>\n    }\n\n    function App() {\n      return (\n        <Suspense fallback={<></>}>\n          <Prefetch>\n            <Suspended queryOpts={queryOpts} />\n          </Prefetch>\n        </Suspense>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: prefetchedQuery')).toBeInTheDocument()\n    expect(queryOpts.queryFn).toHaveBeenCalledTimes(1)\n  })\n\n  it('should be able to recover from errors and try fetching again', async () => {\n    const consoleMock = vi.spyOn(console, 'error')\n    consoleMock.mockImplementation(() => undefined)\n    const queryFn = generateQueryFn('This is fine :dog: :fire:')\n\n    const queryOpts = {\n      queryKey: queryKey(),\n      queryFn,\n    }\n\n    queryFn.mockImplementationOnce(async () => {\n      await sleep(10)\n\n      throw new Error('Oops! Server error!')\n    })\n\n    function App() {\n      const { reset } = useQueryErrorResetBoundary()\n      usePrefetchQuery(queryOpts)\n\n      return (\n        <ErrorBoundary\n          onReset={reset}\n          fallbackRender={({ resetErrorBoundary }) => (\n            <div>\n              <div>Oops!</div>\n              <button onClick={resetErrorBoundary}>Try again</button>\n            </div>\n          )}\n        >\n          <Suspense fallback=\"Loading...\">\n            <Suspended queryOpts={queryOpts} />\n          </Suspense>\n        </ErrorBoundary>\n      )\n    }\n\n    queryClient.prefetchQuery(queryOpts)\n    await vi.advanceTimersByTimeAsync(10)\n    queryFn.mockClear()\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    expect(rendered.getByText('Oops!')).toBeInTheDocument()\n    fireEvent.click(rendered.getByText('Try again'))\n    await vi.advanceTimersByTimeAsync(10)\n    expect(\n      rendered.getByText('data: This is fine :dog: :fire:'),\n    ).toBeInTheDocument()\n    expect(queryOpts.queryFn).toHaveBeenCalledTimes(1)\n    consoleMock.mockRestore()\n  })\n\n  it('should not create a suspense waterfall if prefetch is fired', async () => {\n    const firstQueryOpts = {\n      queryKey: queryKey(),\n      queryFn: generateQueryFn('Prefetch is nice!'),\n    }\n\n    const secondQueryOpts = {\n      queryKey: queryKey(),\n      queryFn: generateQueryFn('Prefetch is really nice!!'),\n    }\n\n    const thirdQueryOpts = {\n      queryKey: queryKey(),\n      queryFn: generateQueryFn('Prefetch does not create waterfalls!!'),\n    }\n\n    const Fallback = vi.fn().mockImplementation(() => <div>Loading...</div>)\n\n    function App() {\n      usePrefetchQuery(firstQueryOpts)\n      usePrefetchQuery(secondQueryOpts)\n      usePrefetchQuery(thirdQueryOpts)\n\n      return (\n        <Suspense fallback={<Fallback />}>\n          <Suspended queryOpts={firstQueryOpts}>\n            <Suspended queryOpts={secondQueryOpts}>\n              <Suspended queryOpts={thirdQueryOpts} />\n            </Suspended>\n          </Suspended>\n        </Suspense>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n    expect(\n      queryClient.getQueryState(firstQueryOpts.queryKey)?.fetchStatus,\n    ).toBe('fetching')\n    expect(\n      queryClient.getQueryState(secondQueryOpts.queryKey)?.fetchStatus,\n    ).toBe('fetching')\n    expect(\n      queryClient.getQueryState(thirdQueryOpts.queryKey)?.fetchStatus,\n    ).toBe('fetching')\n    expect(rendered.getByText('Loading...')).toBeInTheDocument()\n    await act(async () => {\n      await vi.advanceTimersByTimeAsync(10)\n    })\n    expect(rendered.getByText('data: Prefetch is nice!')).toBeInTheDocument()\n    expect(\n      rendered.getByText('data: Prefetch is really nice!!'),\n    ).toBeInTheDocument()\n    expect(\n      rendered.getByText('data: Prefetch does not create waterfalls!!'),\n    ).toBeInTheDocument()\n    expect(Fallback).toHaveBeenCalledTimes(1)\n    expect(firstQueryOpts.queryFn).toHaveBeenCalledTimes(1)\n    expect(secondQueryOpts.queryFn).toHaveBeenCalledTimes(1)\n    expect(thirdQueryOpts.queryFn).toHaveBeenCalledTimes(1)\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/useQueries.test-d.tsx",
    "content": "import { describe, expectTypeOf, it } from 'vitest'\n\nimport { skipToken } from '..'\nimport type { OmitKeyof } from '..'\nimport { queryOptions } from '../queryOptions'\nimport type { UseQueryOptions, UseQueryResult } from '../types'\nimport { useQueries } from '../useQueries'\n\ndescribe('UseQueries config object overload', () => {\n  it('TData should always be defined when initialData is provided as an object', () => {\n    const query1 = {\n      queryKey: ['key1'],\n      queryFn: () => {\n        return {\n          wow: true,\n        }\n      },\n      initialData: {\n        wow: false,\n      },\n    }\n\n    const query2 = {\n      queryKey: ['key2'],\n      queryFn: () => 'Query Data',\n      initialData: 'initial data',\n    }\n\n    const query3 = {\n      queryKey: ['key2'],\n      queryFn: () => 'Query Data',\n    }\n\n    const queryResults = useQueries({ queries: [query1, query2, query3] })\n\n    const query1Data = queryResults[0].data\n    const query2Data = queryResults[1].data\n    const query3Data = queryResults[2].data\n\n    expectTypeOf(query1Data).toEqualTypeOf<{ wow: boolean }>()\n    expectTypeOf(query2Data).toEqualTypeOf<string>()\n    expectTypeOf(query3Data).toEqualTypeOf<string | undefined>()\n  })\n\n  it('TData should be defined when passed through queryOptions', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => {\n        return {\n          wow: true,\n        }\n      },\n      initialData: {\n        wow: true,\n      },\n    })\n    const queryResults = useQueries({ queries: [options] })\n\n    const data = queryResults[0].data\n\n    expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n  })\n\n  it('should be possible to define a different TData than TQueryFnData using select with queryOptions spread into useQuery', () => {\n    const query1 = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(1),\n      select: (data) => data > 1,\n    })\n\n    const query2 = {\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(1),\n      select: (data: number) => data > 1,\n    }\n\n    const queryResults = useQueries({ queries: [query1, query2] })\n    const query1Data = queryResults[0].data\n    const query2Data = queryResults[1].data\n\n    expectTypeOf(query1Data).toEqualTypeOf<boolean | undefined>()\n    expectTypeOf(query2Data).toEqualTypeOf<boolean | undefined>()\n  })\n\n  it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => {\n    const queryResults = useQueries({\n      queries: [\n        {\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n          initialData: () => undefined as { wow: boolean } | undefined,\n        },\n      ],\n    })\n\n    const data = queryResults[0].data\n\n    expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()\n  })\n\n  describe('custom hook', () => {\n    it('should allow custom hooks using UseQueryOptions', () => {\n      type Data = string\n\n      const useCustomQueries = (\n        options?: OmitKeyof<UseQueryOptions<Data>, 'queryKey' | 'queryFn'>,\n      ) => {\n        return useQueries({\n          queries: [\n            {\n              ...options,\n              queryKey: ['todos-key'],\n              queryFn: () => Promise.resolve('data'),\n            },\n          ],\n        })\n      }\n\n      const queryResults = useCustomQueries()\n      const data = queryResults[0].data\n\n      expectTypeOf(data).toEqualTypeOf<Data | undefined>()\n    })\n  })\n\n  it('TData should have correct type when conditional skipToken is passed', () => {\n    const queryResults = useQueries({\n      queries: [\n        {\n          queryKey: ['withSkipToken'],\n          queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),\n        },\n      ],\n    })\n\n    const firstResult = queryResults[0]\n\n    expectTypeOf(firstResult).toEqualTypeOf<UseQueryResult<number, Error>>()\n    expectTypeOf(firstResult.data).toEqualTypeOf<number | undefined>()\n  })\n\n  it('should return correct data for dynamic queries with mixed result types', () => {\n    const Queries1 = {\n      get: () =>\n        queryOptions({\n          queryKey: ['key1'],\n          queryFn: () => Promise.resolve(1),\n        }),\n    }\n    const Queries2 = {\n      get: () =>\n        queryOptions({\n          queryKey: ['key2'],\n          queryFn: () => Promise.resolve(true),\n        }),\n    }\n\n    const queries1List = [1, 2, 3].map(() => ({ ...Queries1.get() }))\n    const result = useQueries({\n      queries: [...queries1List, { ...Queries2.get() }],\n    })\n\n    expectTypeOf(result).toEqualTypeOf<\n      [...Array<UseQueryResult<number, Error>>, UseQueryResult<boolean, Error>]\n    >()\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/useQueries.test.tsx",
    "content": "import type { QueryFunctionContext } from '@tanstack/query-core'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { fireEvent, render } from '@testing-library/preact'\nimport { useCallback, useEffect, useState } from 'preact/hooks'\nimport {\n  afterEach,\n  beforeEach,\n  describe,\n  expect,\n  expectTypeOf,\n  it,\n  vi,\n} from 'vitest'\n\nimport {\n  IsRestoringProvider,\n  QueryCache,\n  QueryClient,\n  queryOptions,\n  skipToken,\n  useQueries,\n} from '..'\nimport type {\n  QueryFunction,\n  QueryKey,\n  QueryObserverResult,\n  UseQueryOptions,\n  UseQueryResult,\n} from '..'\nimport { ErrorBoundary } from './ErrorBoundary'\nimport { renderWithClient } from './utils'\n\ndescribe('useQueries', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  const queryCache = new QueryCache()\n  const queryClient = new QueryClient({ queryCache })\n\n  it('should return the correct states', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const results: Array<Array<UseQueryResult>> = []\n\n    function Page() {\n      const result = useQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: async () => {\n              await sleep(10)\n              return 1\n            },\n          },\n          {\n            queryKey: key2,\n            queryFn: async () => {\n              await sleep(200)\n              return 2\n            },\n          },\n        ],\n      })\n      results.push(result)\n\n      return (\n        <div>\n          <div>\n            data1: {String(result[0].data ?? 'null')}, data2:{' '}\n            {String(result[1].data ?? 'null')}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(201)\n    expect(rendered.getByText('data1: 1, data2: 2')).toBeInTheDocument()\n\n    expect(results.length).toBe(3)\n    expect(results[0]).toMatchObject([{ data: undefined }, { data: undefined }])\n    expect(results[1]).toMatchObject([{ data: 1 }, { data: undefined }])\n    expect(results[2]).toMatchObject([{ data: 1 }, { data: 2 }])\n  })\n\n  it('should track results', async () => {\n    const key1 = queryKey()\n    const results: Array<Array<UseQueryResult>> = []\n    let count = 0\n\n    function Page() {\n      const result = useQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: async () => {\n              await sleep(10)\n              count++\n              return count\n            },\n          },\n        ],\n      })\n      results.push(result)\n\n      return (\n        <div>\n          <div>data: {String(result[0].data ?? 'null')} </div>\n          <button onClick={() => result[0].refetch()}>refetch</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n\n    expect(results.length).toBe(2)\n    expect(results[0]).toMatchObject([{ data: undefined }])\n    expect(results[1]).toMatchObject([{ data: 1 }])\n\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 2')).toBeInTheDocument()\n\n    // only one render for data update, no render for isFetching transition\n    expect(results.length).toBe(3)\n\n    expect(results[2]).toMatchObject([{ data: 2 }])\n  })\n\n  it('handles type parameter - tuple of tuples', () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const key3 = queryKey()\n\n    // @ts-expect-error (Page component is not rendered)\n    function Page() {\n      const result1 = useQueries<\n        [[number], [string], [Array<string>, boolean]]\n      >({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 1,\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n          },\n          {\n            queryKey: key3,\n            queryFn: () => ['string[]'],\n          },\n        ],\n      })\n      expectTypeOf(result1[0]).toEqualTypeOf<UseQueryResult<number, unknown>>()\n      expectTypeOf(result1[1]).toEqualTypeOf<UseQueryResult<string, unknown>>()\n      expectTypeOf(result1[2]).toEqualTypeOf<\n        UseQueryResult<Array<string>, boolean>\n      >()\n      expectTypeOf(result1[0].data).toEqualTypeOf<number | undefined>()\n      expectTypeOf(result1[1].data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(result1[2].data).toEqualTypeOf<Array<string> | undefined>()\n      expectTypeOf(result1[2].error).toEqualTypeOf<boolean | null>()\n\n      // TData (3rd element) takes precedence over TQueryFnData (1st element)\n      const result2 = useQueries<\n        [[string, unknown, string], [string, unknown, number]]\n      >({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return a.toLowerCase()\n            },\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return parseInt(a)\n            },\n          },\n        ],\n      })\n      expectTypeOf(result2[0]).toEqualTypeOf<UseQueryResult<string, unknown>>()\n      expectTypeOf(result2[1]).toEqualTypeOf<UseQueryResult<number, unknown>>()\n      expectTypeOf(result2[0].data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(result2[1].data).toEqualTypeOf<number | undefined>()\n\n      // types should be enforced\n      useQueries<[[string, unknown, string], [string, boolean, number]]>({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return a.toLowerCase()\n            },\n            placeholderData: 'string',\n            // @ts-expect-error (initialData: string)\n            initialData: 123,\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return parseInt(a)\n            },\n            placeholderData: 'string',\n            // @ts-expect-error (initialData: string)\n            initialData: 123,\n          },\n        ],\n      })\n\n      // field names should be enforced\n      useQueries<[[string]]>({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n            // @ts-expect-error (invalidField)\n            someInvalidField: [],\n          },\n        ],\n      })\n    }\n  })\n\n  it('handles type parameter - tuple of objects', () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const key3 = queryKey()\n\n    // @ts-expect-error (Page component is not rendered)\n    function Page() {\n      const result1 = useQueries<\n        [\n          { queryFnData: number },\n          { queryFnData: string },\n          { queryFnData: Array<string>; error: boolean },\n        ]\n      >({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 1,\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n          },\n          {\n            queryKey: key3,\n            queryFn: () => ['string[]'],\n          },\n        ],\n      })\n      expectTypeOf(result1[0]).toEqualTypeOf<UseQueryResult<number, unknown>>()\n      expectTypeOf(result1[1]).toEqualTypeOf<UseQueryResult<string, unknown>>()\n      expectTypeOf(result1[2]).toEqualTypeOf<\n        UseQueryResult<Array<string>, boolean>\n      >()\n      expectTypeOf(result1[0].data).toEqualTypeOf<number | undefined>()\n      expectTypeOf(result1[1].data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(result1[2].data).toEqualTypeOf<Array<string> | undefined>()\n      expectTypeOf(result1[2].error).toEqualTypeOf<boolean | null>()\n\n      // TData (data prop) takes precedence over TQueryFnData (queryFnData prop)\n      const result2 = useQueries<\n        [\n          { queryFnData: string; data: string },\n          { queryFnData: string; data: number },\n        ]\n      >({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return a.toLowerCase()\n            },\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return parseInt(a)\n            },\n          },\n        ],\n      })\n      expectTypeOf(result2[0]).toEqualTypeOf<UseQueryResult<string, unknown>>()\n      expectTypeOf(result2[1]).toEqualTypeOf<UseQueryResult<number, unknown>>()\n      expectTypeOf(result2[0].data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(result2[1].data).toEqualTypeOf<number | undefined>()\n\n      // can pass only TData (data prop) although TQueryFnData will be left unknown\n      const result3 = useQueries<[{ data: string }, { data: number }]>({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<unknown>()\n              return a as string\n            },\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<unknown>()\n              return a as number\n            },\n          },\n        ],\n      })\n      expectTypeOf(result3[0]).toEqualTypeOf<UseQueryResult<string, unknown>>()\n      expectTypeOf(result3[1]).toEqualTypeOf<UseQueryResult<number, unknown>>()\n      expectTypeOf(result3[0].data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(result3[1].data).toEqualTypeOf<number | undefined>()\n\n      // types should be enforced\n      useQueries<\n        [\n          { queryFnData: string; data: string },\n          { queryFnData: string; data: number; error: boolean },\n        ]\n      >({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return a.toLowerCase()\n            },\n            placeholderData: 'string',\n            // @ts-expect-error (initialData: string)\n            initialData: 123,\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return parseInt(a)\n            },\n            placeholderData: 'string',\n            // @ts-expect-error (initialData: string)\n            initialData: 123,\n          },\n        ],\n      })\n\n      // field names should be enforced\n      useQueries<[{ queryFnData: string }]>({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n            // @ts-expect-error (invalidField)\n            someInvalidField: [],\n          },\n        ],\n      })\n    }\n  })\n\n  it('correctly returns types when passing through queryOptions', () => {\n    // @ts-expect-error (Page component is not rendered)\n    function Page() {\n      // data and results types are correct when using queryOptions\n      const result4 = useQueries({\n        queries: [\n          queryOptions({\n            queryKey: ['key1'],\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return a.toLowerCase()\n            },\n          }),\n          queryOptions({\n            queryKey: ['key2'],\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return parseInt(a)\n            },\n          }),\n        ],\n      })\n      expectTypeOf(result4[0]).toEqualTypeOf<UseQueryResult<string, Error>>()\n      expectTypeOf(result4[1]).toEqualTypeOf<UseQueryResult<number, Error>>()\n      expectTypeOf(result4[0].data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(result4[1].data).toEqualTypeOf<number | undefined>()\n    }\n  })\n\n  it('handles array literal without type parameter to infer result type', () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const key3 = queryKey()\n    const key4 = queryKey()\n    const key5 = queryKey()\n\n    type BizError = { code: number }\n    const throwOnError = (_error: BizError) => true\n\n    // @ts-expect-error (Page component is not rendered)\n    function Page() {\n      // Array.map preserves TQueryFnData\n      const result1 = useQueries({\n        queries: Array(50).map((_, i) => ({\n          queryKey: ['key', i] as const,\n          queryFn: () => i + 10,\n        })),\n      })\n      expectTypeOf(result1).toEqualTypeOf<\n        Array<UseQueryResult<number, Error>>\n      >()\n      if (result1[0]) {\n        expectTypeOf(result1[0].data).toEqualTypeOf<number | undefined>()\n      }\n\n      // Array.map preserves TError\n      const result1_err = useQueries({\n        queries: Array(50).map((_, i) => ({\n          queryKey: ['key', i] as const,\n          queryFn: () => i + 10,\n          throwOnError,\n        })),\n      })\n      expectTypeOf(result1_err).toEqualTypeOf<\n        Array<UseQueryResult<number, BizError>>\n      >()\n      if (result1_err[0]) {\n        expectTypeOf(result1_err[0].data).toEqualTypeOf<number | undefined>()\n        expectTypeOf(result1_err[0].error).toEqualTypeOf<BizError | null>()\n      }\n\n      // Array.map preserves TData\n      const result2 = useQueries({\n        queries: Array(50).map((_, i) => ({\n          queryKey: ['key', i] as const,\n          queryFn: () => i + 10,\n          select: (data: number) => data.toString(),\n        })),\n      })\n      expectTypeOf(result2).toEqualTypeOf<\n        Array<UseQueryResult<string, Error>>\n      >()\n\n      const result2_err = useQueries({\n        queries: Array(50).map((_, i) => ({\n          queryKey: ['key', i] as const,\n          queryFn: () => i + 10,\n          select: (data: number) => data.toString(),\n          throwOnError,\n        })),\n      })\n      expectTypeOf(result2_err).toEqualTypeOf<\n        Array<UseQueryResult<string, BizError>>\n      >()\n\n      const result3 = useQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 1,\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n          },\n          {\n            queryKey: key3,\n            queryFn: () => ['string[]'],\n            select: () => 123,\n          },\n          {\n            queryKey: key5,\n            queryFn: () => 'string',\n            throwOnError,\n          },\n        ],\n      })\n      expectTypeOf(result3[0]).toEqualTypeOf<UseQueryResult<number, Error>>()\n      expectTypeOf(result3[1]).toEqualTypeOf<UseQueryResult<string, Error>>()\n      expectTypeOf(result3[2]).toEqualTypeOf<UseQueryResult<number, Error>>()\n      expectTypeOf(result3[0].data).toEqualTypeOf<number | undefined>()\n      expectTypeOf(result3[1].data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(result3[3].data).toEqualTypeOf<string | undefined>()\n      // select takes precedence over queryFn\n      expectTypeOf(result3[2].data).toEqualTypeOf<number | undefined>()\n      // infer TError from throwOnError\n      expectTypeOf(result3[3].error).toEqualTypeOf<BizError | null>()\n\n      // initialData/placeholderData are enforced\n      useQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n            placeholderData: 'string',\n            // @ts-expect-error (initialData: string)\n            initialData: 123,\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 123,\n            // @ts-expect-error (placeholderData: number)\n            placeholderData: 'string',\n            initialData: 123,\n          },\n        ],\n      })\n\n      // select and throwOnError params are \"indirectly\" enforced\n      useQueries({\n        queries: [\n          // unfortunately TS will not suggest the type for you\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n          },\n          // however you can add a type to the callback\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n          },\n          // the type you do pass is enforced\n          {\n            queryKey: key3,\n            queryFn: () => 'string',\n          },\n          {\n            queryKey: key4,\n            queryFn: () => 'string',\n            select: (a: string) => parseInt(a),\n          },\n          {\n            queryKey: key5,\n            queryFn: () => 'string',\n            throwOnError,\n          },\n        ],\n      })\n\n      // callbacks are also indirectly enforced with Array.map\n      useQueries({\n        queries: Array(50).map((_, i) => ({\n          queryKey: ['key', i] as const,\n          queryFn: () => i + 10,\n          select: (data: number) => data.toString(),\n        })),\n      })\n      useQueries({\n        queries: Array(50).map((_, i) => ({\n          queryKey: ['key', i] as const,\n          queryFn: () => i + 10,\n          select: (data: number) => data.toString(),\n        })),\n      })\n\n      // results inference works when all the handlers are defined\n      const result4 = useQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n          },\n          {\n            queryKey: key4,\n            queryFn: () => 'string',\n            select: (a: string) => parseInt(a),\n          },\n          {\n            queryKey: key5,\n            queryFn: () => 'string',\n            select: (a: string) => parseInt(a),\n            throwOnError,\n          },\n        ],\n      })\n      expectTypeOf(result4[0]).toEqualTypeOf<UseQueryResult<string, Error>>()\n      expectTypeOf(result4[1]).toEqualTypeOf<UseQueryResult<string, Error>>()\n      expectTypeOf(result4[2]).toEqualTypeOf<UseQueryResult<number, Error>>()\n      expectTypeOf(result4[3]).toEqualTypeOf<UseQueryResult<number, BizError>>()\n\n      // handles when queryFn returns a Promise\n      const result5 = useQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => Promise.resolve('string'),\n          },\n        ],\n      })\n      expectTypeOf(result5[0]).toEqualTypeOf<UseQueryResult<string, Error>>()\n\n      // Array as const does not throw error\n      const result6 = useQueries({\n        queries: [\n          {\n            queryKey: ['key1'],\n            queryFn: () => 'string',\n          },\n          {\n            queryKey: ['key1'],\n            queryFn: () => 123,\n          },\n          {\n            queryKey: key5,\n            queryFn: () => 'string',\n            throwOnError,\n          },\n        ],\n      } as const)\n      expectTypeOf(result6[0]).toEqualTypeOf<UseQueryResult<string, Error>>()\n      expectTypeOf(result6[1]).toEqualTypeOf<UseQueryResult<number, Error>>()\n      expectTypeOf(result6[2]).toEqualTypeOf<UseQueryResult<string, BizError>>()\n\n      // field names should be enforced - array literal\n      useQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n            // @ts-expect-error (invalidField)\n            someInvalidField: [],\n          },\n        ],\n      })\n\n      // field names should be enforced - Array.map() result\n      useQueries({\n        // @ts-expect-error (invalidField)\n        queries: Array(10).map(() => ({\n          someInvalidField: '',\n        })),\n      })\n\n      // field names should be enforced - array literal\n      useQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n            // @ts-expect-error (invalidField)\n            someInvalidField: [],\n          },\n        ],\n      })\n\n      // supports queryFn using fetch() to return Promise<any> - Array.map() result\n      useQueries({\n        queries: Array(50).map((_, i) => ({\n          queryKey: ['key', i] as const,\n          queryFn: () =>\n            fetch('return Promise<any>').then((resp) => resp.json()),\n        })),\n      })\n\n      // supports queryFn using fetch() to return Promise<any> - array literal\n      useQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () =>\n              fetch('return Promise<any>').then((resp) => resp.json()),\n          },\n        ],\n      })\n    }\n  })\n\n  it('handles strongly typed queryFn factories and useQueries wrappers', () => {\n    // QueryKey + queryFn factory\n    type QueryKeyA = ['queryA']\n    const getQueryKeyA = (): QueryKeyA => ['queryA']\n    type GetQueryFunctionA = () => QueryFunction<number, QueryKeyA>\n    const getQueryFunctionA: GetQueryFunctionA = () => () => {\n      return Promise.resolve(1)\n    }\n    type SelectorA = (data: number) => [number, string]\n    const getSelectorA = (): SelectorA => (data) => [data, data.toString()]\n\n    type QueryKeyB = ['queryB', string]\n    const getQueryKeyB = (id: string): QueryKeyB => ['queryB', id]\n    type GetQueryFunctionB = () => QueryFunction<string, QueryKeyB>\n    const getQueryFunctionB: GetQueryFunctionB = () => () => {\n      return Promise.resolve('1')\n    }\n    type SelectorB = (data: string) => [string, number]\n    const getSelectorB = (): SelectorB => (data) => [data, +data]\n\n    // Wrapper with strongly typed array-parameter\n    function useWrappedQueries<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey extends QueryKey,\n    >(queries: Array<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>>) {\n      return useQueries({\n        queries: queries.map(\n          // no need to type the mapped query\n          (query) => {\n            const { queryFn: fn, queryKey: key } = query\n            expectTypeOf(fn).toEqualTypeOf<\n              | typeof skipToken\n              | QueryFunction<TQueryFnData, TQueryKey, never>\n              | undefined\n            >()\n            return {\n              queryKey: key,\n              queryFn:\n                fn && fn !== skipToken\n                  ? (ctx: QueryFunctionContext<TQueryKey>) => {\n                      // eslint-disable-next-line vitest/valid-expect\n                      expectTypeOf<TQueryKey>(ctx.queryKey)\n                      return fn.call({}, ctx)\n                    }\n                  : undefined,\n            }\n          },\n        ),\n      })\n    }\n\n    // @ts-expect-error (Page component is not rendered)\n    function Page() {\n      const result = useQueries({\n        queries: [\n          {\n            queryKey: getQueryKeyA(),\n            queryFn: getQueryFunctionA(),\n          },\n          {\n            queryKey: getQueryKeyB('id'),\n            queryFn: getQueryFunctionB(),\n          },\n        ],\n      })\n      expectTypeOf(result[0]).toEqualTypeOf<UseQueryResult<number, Error>>()\n      expectTypeOf(result[1]).toEqualTypeOf<UseQueryResult<string, Error>>()\n\n      const withSelector = useQueries({\n        queries: [\n          {\n            queryKey: getQueryKeyA(),\n            queryFn: getQueryFunctionA(),\n            select: getSelectorA(),\n          },\n          {\n            queryKey: getQueryKeyB('id'),\n            queryFn: getQueryFunctionB(),\n            select: getSelectorB(),\n          },\n        ],\n      })\n      expectTypeOf(withSelector[0]).toEqualTypeOf<\n        UseQueryResult<[number, string], Error>\n      >()\n      expectTypeOf(withSelector[1]).toEqualTypeOf<\n        UseQueryResult<[string, number], Error>\n      >()\n\n      const withWrappedQueries = useWrappedQueries(\n        Array(10).map(() => ({\n          queryKey: getQueryKeyA(),\n          queryFn: getQueryFunctionA(),\n          select: getSelectorA(),\n        })),\n      )\n\n      expectTypeOf(withWrappedQueries).toEqualTypeOf<\n        Array<UseQueryResult<number, Error>>\n      >()\n    }\n  })\n\n  it(\"should throw error if in one of queries' queryFn throws and throwOnError is in use\", async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const key3 = queryKey()\n    const key4 = queryKey()\n\n    function Page() {\n      useQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () =>\n              Promise.reject(\n                new Error(\n                  'this should not throw because throwOnError is not set',\n                ),\n              ),\n          },\n          {\n            queryKey: key2,\n            queryFn: () => Promise.reject(new Error('single query error')),\n            throwOnError: true,\n            retry: false,\n          },\n          {\n            queryKey: key3,\n            queryFn: () => Promise.resolve(2),\n          },\n          {\n            queryKey: key4,\n            queryFn: async () =>\n              Promise.reject(\n                new Error('this should not throw because query#2 already did'),\n              ),\n            throwOnError: true,\n            retry: false,\n          },\n        ],\n      })\n\n      return null\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <ErrorBoundary\n        fallbackRender={({ error }) => (\n          <div>\n            <div>error boundary</div>\n            <div>{error.message}</div>\n          </div>\n        )}\n      >\n        <Page />\n      </ErrorBoundary>,\n    )\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n    expect(rendered.getByText('single query error')).toBeInTheDocument()\n    consoleMock.mockRestore()\n  })\n\n  it(\"should throw error if in one of queries' queryFn throws and throwOnError function resolves to true\", async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const key3 = queryKey()\n    const key4 = queryKey()\n\n    function Page() {\n      useQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () =>\n              Promise.reject(\n                new Error(\n                  'this should not throw because throwOnError function resolves to false',\n                ),\n              ),\n            throwOnError: () => false,\n            retry: false,\n          },\n          {\n            queryKey: key2,\n            queryFn: () => Promise.resolve(2),\n          },\n          {\n            queryKey: key3,\n            queryFn: () => Promise.reject(new Error('single query error')),\n            throwOnError: () => true,\n            retry: false,\n          },\n          {\n            queryKey: key4,\n            queryFn: async () =>\n              Promise.reject(\n                new Error('this should not throw because query#3 already did'),\n              ),\n            throwOnError: true,\n            retry: false,\n          },\n        ],\n      })\n\n      return null\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <ErrorBoundary\n        fallbackRender={({ error }) => (\n          <div>\n            <div>error boundary</div>\n            <div>{error.message}</div>\n          </div>\n        )}\n      >\n        <Page />\n      </ErrorBoundary>,\n    )\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n    expect(rendered.getByText('single query error')).toBeInTheDocument()\n    consoleMock.mockRestore()\n  })\n\n  it('should use provided custom queryClient', async () => {\n    const key = queryKey()\n    const queryFn = async () => {\n      return Promise.resolve('custom client')\n    }\n\n    function Page() {\n      const queries = useQueries(\n        {\n          queries: [\n            {\n              queryKey: key,\n              queryFn,\n            },\n          ],\n        },\n        queryClient,\n      )\n\n      return <div>data: {queries[0].data}</div>\n    }\n\n    const rendered = render(<Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('data: custom client')).toBeInTheDocument()\n  })\n\n  it('should combine queries', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    function Page() {\n      const queries = useQueries(\n        {\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: () => Promise.resolve('first result'),\n            },\n            {\n              queryKey: key2,\n              queryFn: () => Promise.resolve('second result'),\n            },\n          ],\n          combine: (results) => {\n            return {\n              combined: true,\n              res: results.map((res) => res.data).join(','),\n            }\n          },\n        },\n        queryClient,\n      )\n\n      return (\n        <div>\n          <div>\n            data: {String(queries.combined)} {queries.res}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = render(<Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(\n      rendered.getByText('data: true first result,second result'),\n    ).toBeInTheDocument()\n  })\n\n  it('should not return new instances when called without queries', async () => {\n    const key = queryKey()\n    const ids: Array<number> = []\n    let resultChanged = 0\n\n    function Page() {\n      const [count, setCount] = useState(0)\n      const result = useQueries({\n        queries: ids.map((id) => {\n          return {\n            queryKey: [key, id],\n            queryFn: () => {\n              return () => {\n                return Promise.resolve({\n                  id,\n                  content: { value: Math.random() },\n                })\n              }\n            },\n          }\n        }),\n        combine: () => ({ empty: 'object' }),\n      })\n\n      useEffect(() => {\n        resultChanged++\n      }, [result])\n\n      return (\n        <div>\n          <div>count: {count}</div>\n          <div>data: {JSON.stringify(result)}</div>\n          <button onClick={() => setCount((c) => c + 1)}>inc</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('data: {\"empty\":\"object\"}')).toBeInTheDocument()\n    expect(rendered.getByText('count: 0')).toBeInTheDocument()\n\n    expect(resultChanged).toBe(1)\n\n    fireEvent.click(rendered.getByRole('button', { name: /inc/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('count: 1')).toBeInTheDocument()\n    // there should be no further effect calls because the returned object is structurally shared\n    expect(resultChanged).toBe(1)\n  })\n\n  it('should not have infinite render loops with empty queries (#6645)', () => {\n    let renderCount = 0\n\n    function Page() {\n      const result = useQueries({\n        queries: [],\n      })\n\n      useEffect(() => {\n        renderCount++\n      })\n\n      return <div>data: {JSON.stringify(result)}</div>\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    expect(renderCount).toBe(1)\n  })\n\n  it('should only call combine with query results', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    function Page() {\n      const result = useQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: async () => {\n              await sleep(5)\n              return Promise.resolve('query1')\n            },\n          },\n          {\n            queryKey: key2,\n            queryFn: async () => {\n              await sleep(20)\n              return Promise.resolve('query2')\n            },\n          },\n        ],\n        combine: ([query1, query2]) => {\n          return {\n            data: { query1: query1.data, query2: query2.data },\n          }\n        },\n      })\n\n      return <div>data: {JSON.stringify(result)}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(21)\n    expect(\n      rendered.getByText(\n        'data: {\"data\":{\"query1\":\"query1\",\"query2\":\"query2\"}}',\n      ),\n    ).toBeInTheDocument()\n  })\n\n  it('should track property access through combine function', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    let count = 0\n    const results: Array<unknown> = []\n\n    function Page() {\n      const queries = useQueries(\n        {\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: async () => {\n                await sleep(5)\n                return Promise.resolve('first result ' + count)\n              },\n            },\n            {\n              queryKey: key2,\n              queryFn: async () => {\n                await sleep(50)\n                return Promise.resolve('second result ' + count)\n              },\n            },\n          ],\n          combine: (queryResults) => {\n            return {\n              combined: true,\n              refetch: () => queryResults.forEach((res) => res.refetch()),\n              res: queryResults\n                .flatMap((res) => (res.data ? [res.data] : []))\n                .join(','),\n            }\n          },\n        },\n        queryClient,\n      )\n\n      results.push(queries)\n\n      return (\n        <div>\n          <div>\n            data: {String(queries.combined)} {queries.res}\n          </div>\n          <button onClick={() => queries.refetch()}>refetch</button>\n        </div>\n      )\n    }\n\n    const rendered = render(<Page />)\n\n    await vi.advanceTimersByTimeAsync(51)\n    expect(\n      rendered.getByText('data: true first result 0,second result 0'),\n    ).toBeInTheDocument()\n\n    expect(results.length).toBe(3)\n\n    expect(results[0]).toStrictEqual({\n      combined: true,\n      refetch: expect.any(Function),\n      res: '',\n    })\n\n    expect(results[1]).toStrictEqual({\n      combined: true,\n      refetch: expect.any(Function),\n      res: 'first result 0',\n    })\n\n    expect(results[2]).toStrictEqual({\n      combined: true,\n      refetch: expect.any(Function),\n      res: 'first result 0,second result 0',\n    })\n\n    count++\n\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n\n    await vi.advanceTimersByTimeAsync(51)\n    expect(\n      rendered.getByText('data: true first result 1,second result 1'),\n    ).toBeInTheDocument()\n\n    const length = results.length\n\n    expect([4, 5, 6]).toContain(results.length)\n\n    expect(results[results.length - 1]).toStrictEqual({\n      combined: true,\n      refetch: expect.any(Function),\n      res: 'first result 1,second result 1',\n    })\n\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n\n    await vi.advanceTimersByTimeAsync(100)\n    // no further re-render because data didn't change\n    expect(results.length).toBe(length)\n  })\n\n  it('should synchronously track properties of all observer even if a property (isLoading) is only accessed on one observer (#7000)', async () => {\n    const key = queryKey()\n    const ids = [1, 2]\n\n    function Page() {\n      const { isLoading } = useQueries({\n        queries: ids.map((id) => ({\n          queryKey: [key, id],\n          queryFn: () =>\n            sleep(10).then(() => {\n              if (id === 2) throw new Error('FAILURE')\n              return { id, title: `Post ${id}` }\n            }),\n          retry: false,\n        })),\n        combine: (results) => {\n          // this tracks data on all observers\n          void results.forEach((result) => result.data)\n          return {\n            // .some aborts early, so `isLoading` might not be accessed (and thus tracked) on all observers\n            // leading to missing re-renders\n            isLoading: results.some((result) => result.isLoading),\n          }\n        },\n      })\n\n      return (\n        <div>\n          <p>Loading Status: {isLoading ? 'Loading...' : 'Loaded'}</p>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('Loading Status: Loading...')).toBeInTheDocument()\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Loading Status: Loaded')).toBeInTheDocument()\n  })\n\n  it('should not have stale closures with combine (#6648)', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const [count, setCount] = useState(0)\n      const queries = useQueries(\n        {\n          queries: [\n            {\n              queryKey: key,\n              queryFn: () => Promise.resolve('result'),\n            },\n          ],\n          combine: (results) => {\n            return {\n              count,\n              res: results.map((res) => res.data).join(','),\n            }\n          },\n        },\n        queryClient,\n      )\n\n      return (\n        <div>\n          <div>\n            data: {String(queries.count)} {queries.res}\n          </div>\n          <button onClick={() => setCount((c) => c + 1)}>inc</button>\n        </div>\n      )\n    }\n\n    const rendered = render(<Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('data: 0 result')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /inc/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('data: 1 result')).toBeInTheDocument()\n  })\n\n  it('should optimize combine if it is a stable reference', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    const client = new QueryClient()\n\n    const spy = vi.fn()\n    let value = 0\n\n    function Page() {\n      const [state, setState] = useState(0)\n      const queries = useQueries(\n        {\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: async () => {\n                await sleep(10)\n                return 'first result:' + value\n              },\n            },\n            {\n              queryKey: key2,\n              queryFn: async () => {\n                await sleep(20)\n                return 'second result:' + value\n              },\n            },\n          ],\n          combine: useCallback((results: Array<QueryObserverResult>) => {\n            const result = {\n              combined: true,\n              res: results.map((res) => res.data).join(','),\n            }\n            spy(result)\n            return result\n          }, []),\n        },\n        client,\n      )\n\n      return (\n        <div>\n          <div>\n            data: {String(queries.combined)} {queries.res}\n          </div>\n          <button onClick={() => setState(state + 1)}>rerender</button>\n        </div>\n      )\n    }\n\n    const rendered = render(<Page />)\n\n    await vi.advanceTimersByTimeAsync(21)\n    expect(\n      rendered.getByText('data: true first result:0,second result:0'),\n    ).toBeInTheDocument()\n\n    // both pending, one pending, both resolved\n    expect(spy).toHaveBeenCalledTimes(3)\n\n    client.refetchQueries()\n\n    await vi.advanceTimersByTimeAsync(21)\n    // no increase because result hasn't changed\n    expect(spy).toHaveBeenCalledTimes(3)\n\n    fireEvent.click(rendered.getByRole('button', { name: /rerender/i }))\n\n    // one extra call due to recomputing the combined result on rerender\n    expect(spy).toHaveBeenCalledTimes(4)\n\n    value = 1\n\n    client.refetchQueries()\n\n    await vi.advanceTimersByTimeAsync(21)\n    expect(\n      rendered.getByText('data: true first result:1,second result:1'),\n    ).toBeInTheDocument()\n\n    // refetch with new values triggers: both pending -> one pending -> both resolved\n    expect(spy).toHaveBeenCalledTimes(7)\n  })\n\n  it('should re-run combine if the functional reference changes', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    const client = new QueryClient()\n\n    const spy = vi.fn()\n\n    function Page() {\n      const [state, setState] = useState(0)\n      const queries = useQueries(\n        {\n          queries: [\n            {\n              queryKey: [key1],\n              queryFn: async () => {\n                await sleep(10)\n                return 'first result'\n              },\n            },\n            {\n              queryKey: [key2],\n              queryFn: async () => {\n                await sleep(20)\n                return 'second result'\n              },\n            },\n          ],\n          combine: useCallback(\n            (results: Array<QueryObserverResult>) => {\n              const result = {\n                combined: true,\n                state,\n                res: results.map((res) => res.data).join(','),\n              }\n              spy(result)\n              return result\n            },\n            [state],\n          ),\n        },\n        client,\n      )\n\n      return (\n        <div>\n          <div>\n            data: {String(queries.state)} {queries.res}\n          </div>\n          <button onClick={() => setState(state + 1)}>rerender</button>\n        </div>\n      )\n    }\n\n    const rendered = render(<Page />)\n\n    await vi.advanceTimersByTimeAsync(21)\n    expect(\n      rendered.getByText('data: 0 first result,second result'),\n    ).toBeInTheDocument()\n\n    // both pending, one pending, both resolved\n    expect(spy).toHaveBeenCalledTimes(3)\n\n    fireEvent.click(rendered.getByRole('button', { name: /rerender/i }))\n\n    // state changed, re-run combine\n    expect(spy).toHaveBeenCalledTimes(4)\n  })\n\n  it('should not re-render if combine returns a stable reference', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    const client = new QueryClient()\n\n    const queryFns: Array<string> = []\n    let renders = 0\n\n    function Page() {\n      const data = useQueries(\n        {\n          queries: [\n            {\n              queryKey: [key1],\n              queryFn: async () => {\n                await sleep(10)\n                queryFns.push('first result')\n                return 'first result'\n              },\n            },\n            {\n              queryKey: [key2],\n              queryFn: async () => {\n                await sleep(20)\n                queryFns.push('second result')\n                return 'second result'\n              },\n            },\n          ],\n          combine: () => 'foo',\n        },\n        client,\n      )\n\n      renders++\n\n      return (\n        <div>\n          <div>data: {data}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(<Page />)\n\n    await vi.advanceTimersByTimeAsync(21)\n    expect(rendered.getByText('data: foo')).toBeInTheDocument()\n\n    expect(queryFns).toEqual(['first result', 'second result'])\n\n    expect(renders).toBe(1)\n  })\n\n  it('should re-render once combine returns a different reference', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const key3 = queryKey()\n\n    const client = new QueryClient()\n\n    let renders = 0\n\n    function Page() {\n      const data = useQueries(\n        {\n          queries: [\n            {\n              queryKey: [key1],\n              queryFn: async () => {\n                await sleep(10)\n                return 'first result'\n              },\n            },\n            {\n              queryKey: [key2],\n              queryFn: async () => {\n                await sleep(15)\n                return 'second result'\n              },\n            },\n            {\n              queryKey: [key3],\n              queryFn: async () => {\n                await sleep(20)\n                return 'third result'\n              },\n            },\n          ],\n          combine: (results) => {\n            const isPending = results.some((res) => res.isPending)\n\n            return isPending ? 'pending' : 'foo'\n          },\n        },\n        client,\n      )\n\n      renders++\n\n      return (\n        <div>\n          <div>data: {data}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(<Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('data: pending')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(21)\n    expect(rendered.getByText('data: foo')).toBeInTheDocument()\n\n    // one with pending, one with foo\n    expect(renders).toBe(2)\n  })\n\n  it('should track properties correctly with combine', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const key3 = queryKey()\n\n    const client = new QueryClient()\n\n    function Page() {\n      const data = useQueries(\n        {\n          queries: [\n            {\n              queryKey: [key1],\n              queryFn: async () => {\n                await sleep(10)\n                return 'first result'\n              },\n            },\n            {\n              queryKey: [key2],\n              queryFn: async () => {\n                await sleep(15)\n                return 'second result'\n              },\n            },\n            {\n              queryKey: [key3],\n              queryFn: async () => {\n                await sleep(20)\n                return 'third result'\n              },\n            },\n          ],\n          combine: (results) => {\n            if (results.find((r) => r.isPending)) {\n              return 'pending'\n            }\n            return results.map((r) => r.data).join(', ')\n          },\n        },\n        client,\n      )\n\n      return (\n        <div>\n          <div>data: {data}</div>\n          <button\n            onClick={() => {\n              client.setQueryData([key1], 'first result updated')\n            }}\n          >\n            update\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = render(<Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('data: pending')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(21)\n    expect(\n      rendered.getByText('data: first result, second result, third result'),\n    ).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /update/i }))\n\n    await vi.advanceTimersByTimeAsync(21)\n    expect(\n      rendered.getByText(\n        'data: first result updated, second result, third result',\n      ),\n    ).toBeInTheDocument()\n  })\n\n  it('should not re-run stable combine on unrelated re-render', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    const client = new QueryClient()\n\n    const spy = vi.fn()\n\n    function Page() {\n      const [unrelatedState, setUnrelatedState] = useState(0)\n\n      const queries = useQueries(\n        {\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: async () => {\n                await sleep(10)\n                return 'first result'\n              },\n            },\n            {\n              queryKey: key2,\n              queryFn: async () => {\n                await sleep(20)\n                return 'second result'\n              },\n            },\n          ],\n          combine: useCallback((results: Array<QueryObserverResult>) => {\n            const result = {\n              combined: true,\n              res: results.map((res) => res.data).join(','),\n            }\n            spy(result)\n            return result\n          }, []),\n        },\n        client,\n      )\n\n      return (\n        <div>\n          <div>\n            data: {String(queries.combined)} {queries.res}\n          </div>\n          <div>unrelated: {unrelatedState}</div>\n          <button onClick={() => setUnrelatedState((s) => s + 1)}>\n            increment\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = render(<Page />)\n\n    await vi.advanceTimersByTimeAsync(21)\n    expect(\n      rendered.getByText('data: true first result,second result'),\n    ).toBeInTheDocument()\n\n    // initial renders: both pending, one pending, both resolved\n    expect(spy).toHaveBeenCalledTimes(3)\n\n    fireEvent.click(rendered.getByRole('button', { name: /increment/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(rendered.getByText('unrelated: 1')).toBeInTheDocument()\n\n    // combine should NOT re-run for unrelated re-render with stable reference\n    expect(spy).toHaveBeenCalledTimes(3)\n\n    fireEvent.click(rendered.getByRole('button', { name: /increment/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(rendered.getByText('unrelated: 2')).toBeInTheDocument()\n\n    // still no extra calls to combine\n    expect(spy).toHaveBeenCalledTimes(3)\n  })\n\n  it('should not cause infinite re-renders when removing last query', async () => {\n    let renderCount = 0\n\n    function Page() {\n      const [queries, setQueries] = useState([\n        {\n          queryKey: ['query1'],\n          queryFn: () => 'data1',\n        },\n        {\n          queryKey: ['query2'],\n          queryFn: () => 'data2',\n        },\n      ])\n      renderCount++\n\n      const result = useQueries({ queries })\n\n      return (\n        <div>\n          <div data-testid=\"render-count\">renders: {renderCount}</div>\n          <div data-testid=\"query-count\">queries: {result.length}</div>\n          <button\n            onClick={() => {\n              setQueries([\n                {\n                  queryKey: ['query1'],\n                  queryFn: () => 'data1',\n                },\n              ])\n            }}\n          >\n            remove last\n          </button>\n          <button\n            onClick={() => {\n              setQueries([\n                {\n                  queryKey: ['query2'],\n                  queryFn: () => 'data2',\n                },\n              ])\n            }}\n          >\n            remove first\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    renderCount = 0\n\n    fireEvent.click(rendered.getByRole('button', { name: /remove last/i }))\n    await vi.advanceTimersByTimeAsync(100)\n\n    expect(renderCount).toBeLessThan(10)\n    expect(rendered.getByTestId('query-count').textContent).toBe('queries: 1')\n\n    renderCount = 0\n\n    fireEvent.click(rendered.getByRole('button', { name: /remove first/i }))\n    await vi.advanceTimersByTimeAsync(100)\n\n    expect(renderCount).toBeLessThan(10)\n    expect(rendered.getByTestId('query-count').textContent).toBe('queries: 1')\n  })\n\n  it('should not fetch for the duration of the restoring period when isRestoring is true', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const queryFn1 = vi.fn(() => sleep(10).then(() => 'data1'))\n    const queryFn2 = vi.fn(() => sleep(10).then(() => 'data2'))\n\n    function Page() {\n      const results = useQueries({\n        queries: [\n          { queryKey: key1, queryFn: queryFn1 },\n          { queryKey: key2, queryFn: queryFn2 },\n        ],\n      })\n\n      return (\n        <div>\n          <div data-testid=\"status1\">{results[0]?.status}</div>\n          <div data-testid=\"status2\">{results[1]?.status}</div>\n          <div data-testid=\"fetchStatus1\">{results[0]?.fetchStatus}</div>\n          <div data-testid=\"fetchStatus2\">{results[1]?.fetchStatus}</div>\n          <div data-testid=\"data1\">{results[0]?.data ?? 'undefined'}</div>\n          <div data-testid=\"data2\">{results[1]?.data ?? 'undefined'}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <IsRestoringProvider value={true}>\n        <Page />\n      </IsRestoringProvider>,\n    )\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(rendered.getByTestId('status1')).toHaveTextContent('pending')\n    expect(rendered.getByTestId('status2')).toHaveTextContent('pending')\n    expect(rendered.getByTestId('fetchStatus1')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('fetchStatus2')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('data1')).toHaveTextContent('undefined')\n    expect(rendered.getByTestId('data2')).toHaveTextContent('undefined')\n    expect(queryFn1).toHaveBeenCalledTimes(0)\n    expect(queryFn2).toHaveBeenCalledTimes(0)\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(rendered.getByTestId('status1')).toHaveTextContent('pending')\n    expect(rendered.getByTestId('status2')).toHaveTextContent('pending')\n    expect(rendered.getByTestId('fetchStatus1')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('fetchStatus2')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('data1')).toHaveTextContent('undefined')\n    expect(rendered.getByTestId('data2')).toHaveTextContent('undefined')\n    expect(queryFn1).toHaveBeenCalledTimes(0)\n    expect(queryFn2).toHaveBeenCalledTimes(0)\n  })\n\n  it('should not fetch queries with different durations for the duration of the restoring period when isRestoring is true', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const queryFn1 = vi.fn(() => sleep(10).then(() => 'data1'))\n    const queryFn2 = vi.fn(() => sleep(20).then(() => 'data2'))\n\n    function Page() {\n      const results = useQueries({\n        queries: [\n          { queryKey: key1, queryFn: queryFn1 },\n          { queryKey: key2, queryFn: queryFn2 },\n        ],\n      })\n\n      return (\n        <div>\n          <div data-testid=\"status1\">{results[0]?.status}</div>\n          <div data-testid=\"status2\">{results[1]?.status}</div>\n          <div data-testid=\"fetchStatus1\">{results[0]?.fetchStatus}</div>\n          <div data-testid=\"fetchStatus2\">{results[1]?.fetchStatus}</div>\n          <div data-testid=\"data1\">{results[0]?.data ?? 'undefined'}</div>\n          <div data-testid=\"data2\">{results[1]?.data ?? 'undefined'}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <IsRestoringProvider value={true}>\n        <Page />\n      </IsRestoringProvider>,\n    )\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(rendered.getByTestId('status1')).toHaveTextContent('pending')\n    expect(rendered.getByTestId('status2')).toHaveTextContent('pending')\n    expect(rendered.getByTestId('fetchStatus1')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('fetchStatus2')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('data1')).toHaveTextContent('undefined')\n    expect(rendered.getByTestId('data2')).toHaveTextContent('undefined')\n    expect(queryFn1).toHaveBeenCalledTimes(0)\n    expect(queryFn2).toHaveBeenCalledTimes(0)\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(rendered.getByTestId('status1')).toHaveTextContent('pending')\n    expect(rendered.getByTestId('status2')).toHaveTextContent('pending')\n    expect(rendered.getByTestId('fetchStatus1')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('fetchStatus2')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('data1')).toHaveTextContent('undefined')\n    expect(rendered.getByTestId('data2')).toHaveTextContent('undefined')\n    expect(queryFn1).toHaveBeenCalledTimes(0)\n    expect(queryFn2).toHaveBeenCalledTimes(0)\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(rendered.getByTestId('status1')).toHaveTextContent('pending')\n    expect(rendered.getByTestId('status2')).toHaveTextContent('pending')\n    expect(rendered.getByTestId('fetchStatus1')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('fetchStatus2')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('data1')).toHaveTextContent('undefined')\n    expect(rendered.getByTestId('data2')).toHaveTextContent('undefined')\n    expect(queryFn1).toHaveBeenCalledTimes(0)\n    expect(queryFn2).toHaveBeenCalledTimes(0)\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/useQuery.test-d.tsx",
    "content": "import { queryKey } from '@tanstack/query-test-utils'\nimport { describe, expectTypeOf, it } from 'vitest'\n\nimport type { OmitKeyof, QueryFunction, UseQueryOptions } from '..'\nimport { queryOptions } from '../queryOptions'\nimport { useQuery } from '../useQuery'\n\ndescribe('useQuery', () => {\n  const key = queryKey()\n\n  // unspecified query function should default to unknown\n  const noQueryFn = useQuery({ queryKey: key })\n  expectTypeOf(noQueryFn.data).toEqualTypeOf<unknown>()\n  expectTypeOf(noQueryFn.error).toEqualTypeOf<Error | null>()\n\n  // it should infer the result type from the query function\n  const fromQueryFn = useQuery({ queryKey: key, queryFn: () => 'test' })\n  expectTypeOf(fromQueryFn.data).toEqualTypeOf<string | undefined>()\n  expectTypeOf(fromQueryFn.error).toEqualTypeOf<Error | null>()\n  expectTypeOf(fromQueryFn.promise).toEqualTypeOf<Promise<string>>()\n\n  // it should be possible to specify the result type\n  const withResult = useQuery<string>({\n    queryKey: key,\n    queryFn: () => 'test',\n  })\n  expectTypeOf(withResult.data).toEqualTypeOf<string | undefined>()\n  expectTypeOf(withResult.error).toEqualTypeOf<Error | null>()\n\n  // it should be possible to specify the error type\n  const withError = useQuery<string, Error>({\n    queryKey: key,\n    queryFn: () => 'test',\n  })\n  expectTypeOf(withError.data).toEqualTypeOf<string | undefined>()\n  expectTypeOf(withError.error).toEqualTypeOf<Error | null>()\n\n  // it should provide the result type in the configuration\n  useQuery({\n    queryKey: [key],\n    queryFn: () => Promise.resolve(true),\n  })\n\n  // it should be possible to specify a union type as result type\n  const unionTypeSync = useQuery({\n    queryKey: key,\n    queryFn: () => (Math.random() > 0.5 ? ('a' as const) : ('b' as const)),\n  })\n  expectTypeOf(unionTypeSync.data).toEqualTypeOf<'a' | 'b' | undefined>()\n  const unionTypeAsync = useQuery<'a' | 'b'>({\n    queryKey: key,\n    queryFn: () => Promise.resolve(Math.random() > 0.5 ? 'a' : 'b'),\n  })\n  expectTypeOf(unionTypeAsync.data).toEqualTypeOf<'a' | 'b' | undefined>()\n\n  // should error when the query function result does not match with the specified type\n  // @ts-expect-error\n  useQuery<number>({ queryKey: key, queryFn: () => 'test' })\n\n  // it should infer the result type from a generic query function\n  function queryFn<T = string>(): Promise<T> {\n    return Promise.resolve({} as T)\n  }\n\n  const fromGenericQueryFn = useQuery({\n    queryKey: key,\n    queryFn: () => queryFn(),\n  })\n  expectTypeOf(fromGenericQueryFn.data).toEqualTypeOf<string | undefined>()\n  expectTypeOf(fromGenericQueryFn.error).toEqualTypeOf<Error | null>()\n\n  const fromGenericOptionsQueryFn = useQuery({\n    queryKey: key,\n    queryFn: () => queryFn(),\n  })\n  expectTypeOf(fromGenericOptionsQueryFn.data).toEqualTypeOf<\n    string | undefined\n  >()\n  expectTypeOf(fromGenericOptionsQueryFn.error).toEqualTypeOf<Error | null>()\n\n  type MyData = number\n  type MyQueryKey = readonly ['my-data', number]\n\n  const getMyDataArrayKey: QueryFunction<MyData, MyQueryKey> = ({\n    queryKey: [, n],\n  }) => {\n    return Promise.resolve(n + 42)\n  }\n\n  useQuery({\n    queryKey: ['my-data', 100],\n    queryFn: getMyDataArrayKey,\n  })\n\n  const getMyDataStringKey: QueryFunction<MyData, ['1']> = (context) => {\n    expectTypeOf(context.queryKey).toEqualTypeOf<['1']>()\n    return Promise.resolve(Number(context.queryKey[0]) + 42)\n  }\n\n  useQuery({\n    queryKey: ['1'],\n    queryFn: getMyDataStringKey,\n  })\n\n  // it should handle query-functions that return Promise<any>\n  useQuery({\n    queryKey: key,\n    queryFn: () => fetch('return Promise<any>').then((resp) => resp.json()),\n  })\n\n  // handles wrapped queries with custom fetcher passed as inline queryFn\n  const useWrappedQuery = <\n    TQueryKey extends [string, Record<string, unknown>?],\n    TQueryFnData,\n    TError,\n    TData = TQueryFnData,\n  >(\n    qk: TQueryKey,\n    fetcher: (\n      obj: TQueryKey[1],\n      token: string,\n      // return type must be wrapped with TQueryFnReturn\n    ) => Promise<TQueryFnData>,\n    options?: OmitKeyof<\n      UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n      'queryKey' | 'queryFn' | 'initialData'\n    >,\n  ) =>\n    useQuery({\n      queryKey: qk,\n      queryFn: () => fetcher(qk[1], 'token'),\n      ...options,\n    })\n  const testQuery = useWrappedQuery([''], () => Promise.resolve('1'))\n  expectTypeOf(testQuery.data).toEqualTypeOf<string | undefined>()\n\n  // handles wrapped queries with custom fetcher passed directly to useQuery\n  const useWrappedFuncStyleQuery = <\n    TQueryKey extends [string, Record<string, unknown>?],\n    TQueryFnData,\n    TError,\n    TData = TQueryFnData,\n  >(\n    qk: TQueryKey,\n    fetcher: () => Promise<TQueryFnData>,\n    options?: OmitKeyof<\n      UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n      'queryKey' | 'queryFn' | 'initialData'\n    >,\n  ) => useQuery({ queryKey: qk, queryFn: fetcher, ...options })\n  const testFuncStyle = useWrappedFuncStyleQuery([''], () =>\n    Promise.resolve(true),\n  )\n  expectTypeOf(testFuncStyle.data).toEqualTypeOf<boolean | undefined>()\n\n  it('should return the correct states for a successful query', () => {\n    const state = useQuery<string, Error>({\n      queryKey: key,\n      queryFn: () => Promise.resolve('test'),\n    })\n\n    if (state.isPending) {\n      expectTypeOf(state.data).toEqualTypeOf<undefined>()\n      expectTypeOf(state.error).toEqualTypeOf<null>()\n      return <span>pending</span>\n    }\n\n    if (state.isLoadingError) {\n      expectTypeOf(state.data).toEqualTypeOf<undefined>()\n      expectTypeOf(state.error).toEqualTypeOf<Error>()\n      return <span>{state.error.message}</span>\n    }\n\n    expectTypeOf(state.data).toEqualTypeOf<string>()\n    expectTypeOf(state.error).toEqualTypeOf<Error | null>()\n    return <span>{state.data}</span>\n  })\n\n  describe('initialData', () => {\n    describe('Config object overload', () => {\n      it('TData should always be defined when initialData is provided as an object', () => {\n        const { data } = useQuery({\n          queryKey: ['key'],\n          queryFn: () => ({ wow: true }),\n          initialData: { wow: true },\n        })\n\n        expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n      })\n\n      it('TData should be defined when passed through queryOptions', () => {\n        const options = queryOptions({\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n          initialData: {\n            wow: true,\n          },\n        })\n        const { data } = useQuery(options)\n\n        expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n      })\n\n      it('should be possible to define a different TData than TQueryFnData using select with queryOptions spread into useQuery', () => {\n        const options = queryOptions({\n          queryKey: ['key'],\n          queryFn: () => Promise.resolve(1),\n        })\n\n        const query = useQuery({\n          ...options,\n          select: (data) => data > 1,\n        })\n\n        expectTypeOf(query.data).toEqualTypeOf<boolean | undefined>()\n      })\n\n      it('TData should always be defined when initialData is provided as a function which ALWAYS returns the data', () => {\n        const { data } = useQuery({\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n          initialData: () => ({\n            wow: true,\n          }),\n        })\n\n        expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n      })\n\n      it('TData should have undefined in the union when initialData is NOT provided', () => {\n        const { data } = useQuery({\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n        })\n\n        expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()\n      })\n\n      it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => {\n        const { data } = useQuery({\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n          initialData: () => undefined as { wow: boolean } | undefined,\n        })\n\n        expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()\n      })\n\n      it('TData should be narrowed after an isSuccess check when initialData is provided as a function which can return undefined', () => {\n        const { data, isSuccess } = useQuery({\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n          initialData: () => undefined as { wow: boolean } | undefined,\n        })\n\n        if (isSuccess) {\n          expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n        }\n      })\n\n      // eslint-disable-next-line vitest/expect-expect\n      it('TData should depend from only arguments, not the result', () => {\n        // @ts-expect-error\n        // eslint-disable-next-line\n        const result: UseQueryResult<{ wow: string }> = useQuery({\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n          initialData: () => undefined as { wow: boolean } | undefined,\n        })\n\n        void result\n      })\n\n      it('data should not have undefined when initialData is provided', () => {\n        const { data } = useQuery({\n          queryKey: ['query-key'],\n          initialData: 42,\n        })\n\n        expectTypeOf(data).toEqualTypeOf<number>()\n      })\n    })\n\n    describe('custom hook', () => {\n      it('should allow custom hooks using UseQueryOptions', () => {\n        type Data = string\n\n        const useCustomQuery = (\n          options?: OmitKeyof<UseQueryOptions<Data>, 'queryKey' | 'queryFn'>,\n        ) => {\n          return useQuery({\n            ...options,\n            queryKey: ['todos-key'],\n            queryFn: () => Promise.resolve('data'),\n          })\n        }\n\n        const { data } = useCustomQuery()\n\n        expectTypeOf(data).toEqualTypeOf<Data | undefined>()\n      })\n    })\n\n    describe('structuralSharing', () => {\n      it('should be able to use structuralSharing with unknown types', () => {\n        // https://github.com/TanStack/query/issues/6525#issuecomment-1938411343\n        useQuery({\n          queryKey: ['key'],\n          queryFn: () => 5,\n          structuralSharing: (oldData, newData) => {\n            expectTypeOf(oldData).toBeUnknown()\n            expectTypeOf(newData).toBeUnknown()\n            return newData\n          },\n        })\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/useQuery.test.tsx",
    "content": "import {\n  mockVisibilityState,\n  queryKey,\n  sleep,\n} from '@tanstack/query-test-utils'\nimport { act, fireEvent, render } from '@testing-library/preact'\nimport {\n  useCallback,\n  useEffect,\n  useMemo,\n  useReducer,\n  useRef,\n  useState,\n} from 'preact/hooks'\nimport { afterEach, beforeEach, describe, expect, it, test, vi } from 'vitest'\nimport type { Mock } from 'vitest'\n\nimport {\n  IsRestoringProvider,\n  QueryCache,\n  QueryClient,\n  dehydrate,\n  hydrate,\n  keepPreviousData,\n  skipToken,\n  useQuery,\n} from '..'\nimport type { DefinedUseQueryResult, QueryFunction, UseQueryResult } from '..'\nimport { ErrorBoundary } from './ErrorBoundary'\nimport {\n  Blink,\n  mockOnlineManagerIsOnline,\n  renderWithClient,\n  setActTimeout,\n} from './utils'\n\ndescribe('useQuery', () => {\n  let queryCache: QueryCache\n  let queryClient: QueryClient\n\n  beforeEach(() => {\n    queryCache = new QueryCache()\n    queryClient = new QueryClient({\n      queryCache,\n    })\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/105\n  it('should allow to set default data value', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const { data = 'default' } = useQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'test'),\n      })\n\n      return (\n        <div>\n          <h1>{data}</h1>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('default')).toBeInTheDocument()\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('test')).toBeInTheDocument()\n  })\n\n  it('should return the correct states for a successful query', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery<string, Error>({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return 'test'\n        },\n      })\n\n      states.push(state)\n\n      if (state.isPending) {\n        return <span>pending</span>\n      }\n\n      if (state.isLoadingError) {\n        return <span>{state.error.message}</span>\n      }\n\n      return <span>{state.data}</span>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('test')\n\n    expect(states.length).toEqual(2)\n\n    expect(states[0]).toEqual({\n      data: undefined,\n      dataUpdatedAt: 0,\n      error: null,\n      errorUpdatedAt: 0,\n      failureCount: 0,\n      failureReason: null,\n      errorUpdateCount: 0,\n      isError: false,\n      isFetched: false,\n      isFetchedAfterMount: false,\n      isFetching: true,\n      isPaused: false,\n      isPending: true,\n      isInitialLoading: true,\n      isLoading: true,\n      isLoadingError: false,\n      isPlaceholderData: false,\n      isRefetchError: false,\n      isRefetching: false,\n      isStale: true,\n      isSuccess: false,\n      isEnabled: true,\n      refetch: expect.any(Function),\n      status: 'pending',\n      fetchStatus: 'fetching',\n      promise: expect.any(Promise),\n    })\n\n    expect(states[1]).toEqual({\n      data: 'test',\n      dataUpdatedAt: expect.any(Number),\n      error: null,\n      errorUpdatedAt: 0,\n      failureCount: 0,\n      failureReason: null,\n      errorUpdateCount: 0,\n      isError: false,\n      isFetched: true,\n      isFetchedAfterMount: true,\n      isFetching: false,\n      isPaused: false,\n      isPending: false,\n      isInitialLoading: false,\n      isLoading: false,\n      isLoadingError: false,\n      isPlaceholderData: false,\n      isRefetchError: false,\n      isRefetching: false,\n      isStale: true,\n      isSuccess: true,\n      isEnabled: true,\n      refetch: expect.any(Function),\n      status: 'success',\n      fetchStatus: 'idle',\n      promise: expect.any(Promise),\n    })\n\n    expect(states[0]!.promise).toEqual(states[1]!.promise)\n  })\n\n  it('should return the correct states for an unsuccessful query', async () => {\n    const key = queryKey()\n\n    const states: Array<UseQueryResult> = []\n    let index = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => Promise.reject(new Error(`rejected #${++index}`)),\n\n        retry: 1,\n        retryDelay: 1,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <h1>Status: {state.status}</h1>\n          <div>Failure Count: {state.failureCount}</div>\n          <div>Failure Reason: {state.failureReason?.message}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(2)\n    rendered.getByText('Status: error')\n\n    expect(states[0]).toEqual({\n      data: undefined,\n      dataUpdatedAt: 0,\n      error: null,\n      errorUpdatedAt: 0,\n      failureCount: 0,\n      failureReason: null,\n      errorUpdateCount: 0,\n      isError: false,\n      isFetched: false,\n      isFetchedAfterMount: false,\n      isFetching: true,\n      isPaused: false,\n      isPending: true,\n      isInitialLoading: true,\n      isLoading: true,\n      isLoadingError: false,\n      isPlaceholderData: false,\n      isRefetchError: false,\n      isRefetching: false,\n      isStale: true,\n      isSuccess: false,\n      isEnabled: true,\n      refetch: expect.any(Function),\n      status: 'pending',\n      fetchStatus: 'fetching',\n      promise: expect.any(Promise),\n    })\n\n    expect(states[1]).toEqual({\n      data: undefined,\n      dataUpdatedAt: 0,\n      error: null,\n      errorUpdatedAt: 0,\n      failureCount: 1,\n      failureReason: new Error('rejected #1'),\n      errorUpdateCount: 0,\n      isError: false,\n      isFetched: false,\n      isFetchedAfterMount: false,\n      isFetching: true,\n      isPaused: false,\n      isPending: true,\n      isInitialLoading: true,\n      isLoading: true,\n      isLoadingError: false,\n      isPlaceholderData: false,\n      isRefetchError: false,\n      isRefetching: false,\n      isStale: true,\n      isSuccess: false,\n      isEnabled: true,\n      refetch: expect.any(Function),\n      status: 'pending',\n      fetchStatus: 'fetching',\n      promise: expect.any(Promise),\n    })\n\n    expect(states[2]).toEqual({\n      data: undefined,\n      dataUpdatedAt: 0,\n      error: new Error('rejected #2'),\n      errorUpdatedAt: expect.any(Number),\n      failureCount: 2,\n      failureReason: new Error('rejected #2'),\n      errorUpdateCount: 1,\n      isError: true,\n      isFetched: true,\n      isFetchedAfterMount: true,\n      isFetching: false,\n      isPaused: false,\n      isPending: false,\n      isInitialLoading: false,\n      isLoading: false,\n      isLoadingError: true,\n      isPlaceholderData: false,\n      isRefetchError: false,\n      isRefetching: false,\n      isStale: true,\n      isSuccess: false,\n      isEnabled: true,\n      refetch: expect.any(Function),\n      status: 'error',\n      fetchStatus: 'idle',\n      promise: expect.any(Promise),\n    })\n\n    expect(states[0]!.promise).toEqual(states[1]!.promise)\n    expect(states[1]!.promise).toEqual(states[2]!.promise)\n  })\n\n  it('should set isFetchedAfterMount to true after a query has been fetched', async () => {\n    const key = queryKey()\n\n    await queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => 'prefetched',\n    })\n\n    function Page() {\n      const result = useQuery({ queryKey: key, queryFn: () => 'new data' })\n\n      return (\n        <>\n          <div>data: {result.data}</div>\n          <div>isFetched: {result.isFetched ? 'true' : 'false'}</div>\n          <div>\n            isFetchedAfterMount: {result.isFetchedAfterMount ? 'true' : 'false'}\n          </div>\n        </>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('data: prefetched')).toBeInTheDocument()\n    expect(rendered.getByText('isFetched: true')).toBeInTheDocument()\n    expect(rendered.getByText('isFetchedAfterMount: false')).toBeInTheDocument()\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('data: new data')).toBeInTheDocument()\n    expect(rendered.getByText('isFetched: true')).toBeInTheDocument()\n    expect(rendered.getByText('isFetchedAfterMount: true')).toBeInTheDocument()\n  })\n\n  it('should not cancel an ongoing fetch when refetch is called with cancelRefetch=false if we have data already', async () => {\n    const key = queryKey()\n    let fetchCount = 0\n\n    function Page() {\n      const { refetch } = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          fetchCount++\n          await sleep(10)\n          return 'data'\n        },\n        enabled: false,\n        initialData: 'initialData',\n      })\n\n      useEffect(() => {\n        setActTimeout(() => {\n          refetch()\n        }, 5)\n        setActTimeout(() => {\n          refetch({ cancelRefetch: false })\n        }, 5)\n      }, [refetch])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(15)\n    // first refetch only, second refetch is ignored\n    expect(fetchCount).toBe(1)\n  })\n\n  it('should cancel an ongoing fetch when refetch is called (cancelRefetch=true) if we have data already', async () => {\n    const key = queryKey()\n    let fetchCount = 0\n\n    function Page() {\n      const { refetch } = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          fetchCount++\n          await sleep(10)\n          return 'data'\n        },\n        enabled: false,\n        initialData: 'initialData',\n      })\n\n      useEffect(() => {\n        setActTimeout(() => {\n          refetch()\n        }, 5)\n        setActTimeout(() => {\n          refetch()\n        }, 5)\n      }, [refetch])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(15)\n    // first refetch (gets cancelled) and second refetch\n    expect(fetchCount).toBe(2)\n  })\n\n  it('should not cancel an ongoing fetch when refetch is called (cancelRefetch=true) if we do not have data yet', async () => {\n    const key = queryKey()\n    let fetchCount = 0\n\n    function Page() {\n      const { refetch } = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          fetchCount++\n          await sleep(10)\n          return 'data'\n        },\n        enabled: false,\n      })\n\n      useEffect(() => {\n        setActTimeout(() => {\n          refetch()\n        }, 5)\n        setActTimeout(() => {\n          refetch()\n        }, 5)\n      }, [refetch])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(15)\n    // first refetch will not get cancelled, second one gets skipped\n    expect(fetchCount).toBe(1)\n  })\n\n  it('should be able to watch a query without providing a query function', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    queryClient.setQueryDefaults(key, { queryFn: () => 'data' })\n\n    function Page() {\n      const state = useQuery<string>({ queryKey: key })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined })\n    expect(states[1]).toMatchObject({ data: 'data' })\n  })\n\n  it('should pick up a query when re-mounting with gcTime 0', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const [toggle, setToggle] = useState(false)\n\n      return (\n        <div>\n          <button onClick={() => setToggle(true)}>toggle</button>\n          {toggle ? (\n            <Component key=\"2\" value=\"2\" />\n          ) : (\n            <Component key=\"1\" value=\"1\" />\n          )}\n        </div>\n      )\n    }\n\n    function Component({ value }: { value: string }) {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return 'data: ' + value\n        },\n\n        gcTime: 0,\n        notifyOnChangeProps: 'all',\n      })\n      states.push(state)\n      return (\n        <div>\n          <div>{state.data}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 1')\n\n    fireEvent.click(rendered.getByRole('button', { name: /toggle/i }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 2')\n\n    expect(states.length).toBe(4)\n    // First load\n    expect(states[0]).toMatchObject({\n      isPending: true,\n      isSuccess: false,\n      isFetching: true,\n    })\n    // First success\n    expect(states[1]).toMatchObject({\n      isPending: false,\n      isSuccess: true,\n      isFetching: false,\n    })\n    // Switch, goes to fetching\n    expect(states[2]).toMatchObject({\n      isPending: false,\n      isSuccess: true,\n      isFetching: true,\n    })\n    // Second success\n    expect(states[3]).toMatchObject({\n      isPending: false,\n      isSuccess: true,\n      isFetching: false,\n    })\n  })\n\n  it('should not get into an infinite loop when removing a query with gcTime 0 and rerendering', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const [, rerender] = useState({})\n\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(5)\n          return 'data'\n        },\n\n        gcTime: 0,\n        notifyOnChangeProps: ['isPending', 'isSuccess', 'data'],\n      })\n\n      states.push(state)\n\n      return (\n        <>\n          <div>{state.data}</div>\n\n          <button\n            onClick={() => {\n              queryClient.removeQueries({ queryKey: key })\n              rerender({})\n            }}\n          >\n            remove\n          </button>\n        </>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('data')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'remove' }))\n\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('data')\n\n    expect(states.length).toBe(4)\n    // First load\n    expect(states[0]).toMatchObject({\n      isPending: true,\n      isSuccess: false,\n      data: undefined,\n    })\n    // First success\n    expect(states[1]).toMatchObject({\n      isPending: false,\n      isSuccess: true,\n      data: 'data',\n    })\n    // Remove\n    expect(states[2]).toMatchObject({\n      isPending: true,\n      isSuccess: false,\n      data: undefined,\n    })\n    // Second success\n    expect(states[3]).toMatchObject({\n      isPending: false,\n      isSuccess: true,\n      data: 'data',\n    })\n  })\n\n  it('should fetch when refetchOnMount is false and nothing has been fetched yet', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => 'test',\n        refetchOnMount: false,\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined })\n    expect(states[1]).toMatchObject({ data: 'test' })\n  })\n\n  it('should not fetch when refetchOnMount is false and data has been fetched already', () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    queryClient.setQueryData(key, 'prefetched')\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => 'test',\n        refetchOnMount: false,\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    expect(states.length).toBe(1)\n    expect(states[0]).toMatchObject({ data: 'prefetched' })\n  })\n\n  it('should be able to select a part of the data with select', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => ({ name: 'test' }),\n        select: (data) => data.name,\n      })\n      states.push(state)\n\n      return <div>{state.data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('test')\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined })\n    expect(states[1]).toMatchObject({ data: 'test' })\n  })\n\n  it('should be able to select a part of the data with select in object syntax', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => ({ name: 'test' }),\n        select: (data) => data.name,\n      })\n      states.push(state)\n\n      return <div>{state.data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('test')\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined })\n    expect(states[1]).toMatchObject({ data: 'test' })\n  })\n\n  it('should throw an error when a selector throws', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n    const error = new Error('Select Error')\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => ({ name: 'test' }),\n        select: () => {\n          throw error\n        },\n      })\n      states.push(state)\n\n      return <div>{state.status}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('error')\n\n    expect(states.length).toBe(2)\n\n    expect(states[0]).toMatchObject({ status: 'pending', data: undefined })\n    expect(states[1]).toMatchObject({ status: 'error', error })\n  })\n\n  it('should not re-run a stable select when it re-renders if selector throws an error', async () => {\n    const key = queryKey()\n    const error = new Error('Select Error')\n    let runs = 0\n\n    function Page() {\n      const [, rerender] = useReducer(() => ({}), {})\n      const state = useQuery<string, Error>({\n        queryKey: key,\n        queryFn: () => (runs === 0 ? 'test' : 'test2'),\n\n        select: useCallback(() => {\n          runs++\n          throw error\n        }, []),\n      })\n      return (\n        <div>\n          <div>error: {state.error?.message}</div>\n          <button onClick={rerender}>rerender</button>\n          <button onClick={() => state.refetch()}>refetch</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('error: Select Error')\n    expect(runs).toEqual(1)\n    fireEvent.click(rendered.getByRole('button', { name: 'rerender' }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(runs).toEqual(1)\n    fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(runs).toEqual(2)\n  })\n\n  it('should track properties and only re-render when a tracked property changes', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          return 'test' + count\n        },\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <h1>{state.data ?? null}</h1>\n          <button onClick={() => state.refetch()}>refetch</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('test1')\n\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('test2')\n\n    expect(states.length).toBe(3)\n    expect(states[0]).toMatchObject({ data: undefined })\n    expect(states[1]).toMatchObject({ data: 'test1' })\n    expect(states[2]).toMatchObject({ data: 'test2' })\n  })\n\n  it('should always re-render if we are tracking props but not using any', async () => {\n    const key = queryKey()\n    let renderCount = 0\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery({ queryKey: key, queryFn: () => 'test' })\n\n      states.push(state)\n\n      useEffect(() => {\n        renderCount++\n      }, [state])\n\n      return (\n        <div>\n          <h1>hello</h1>\n        </div>\n      )\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(renderCount).toBe(2)\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined })\n    expect(states[1]).toMatchObject({ data: 'test' })\n  })\n\n  it('should be able to remove a query', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const [, rerender] = useState({})\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => ++count,\n        notifyOnChangeProps: 'all',\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <button onClick={() => queryClient.removeQueries({ queryKey: key })}>\n            remove\n          </button>\n          <button onClick={() => rerender({})}>rerender</button>\n          data: {state.data ?? 'null'}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('data: 1')\n    fireEvent.click(rendered.getByRole('button', { name: /remove/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    fireEvent.click(rendered.getByRole('button', { name: /rerender/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('data: 2')\n\n    expect(states.length).toBe(4)\n    // Initial\n    expect(states[0]).toMatchObject({ status: 'pending', data: undefined })\n    // Fetched\n    expect(states[1]).toMatchObject({ status: 'success', data: 1 })\n    // Remove + Hook state update, batched\n    expect(states[2]).toMatchObject({ status: 'pending', data: undefined })\n    // Fetched\n    expect(states[3]).toMatchObject({ status: 'success', data: 2 })\n  })\n\n  it('should create a new query when refetching a removed query', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return ++count\n        },\n        notifyOnChangeProps: 'all',\n      })\n\n      states.push(state)\n\n      const { refetch } = state\n\n      return (\n        <div>\n          <button onClick={() => queryClient.removeQueries({ queryKey: key })}>\n            remove\n          </button>\n          <button onClick={() => refetch()}>refetch</button>\n          data: {state.data ?? 'null'}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 1')\n    fireEvent.click(rendered.getByRole('button', { name: /remove/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 2')\n\n    expect(states.length).toBe(4)\n    // Initial\n    expect(states[0]).toMatchObject({ data: undefined, dataUpdatedAt: 0 })\n    // Fetched\n    expect(states[1]).toMatchObject({ data: 1 })\n    // Switch\n    expect(states[2]).toMatchObject({ data: undefined, dataUpdatedAt: 0 })\n    // Fetched\n    expect(states[3]).toMatchObject({ data: 2 })\n  })\n\n  it('should share equal data structures between query results', async () => {\n    const key = queryKey()\n\n    const result1 = [\n      { id: '1', done: false },\n      { id: '2', done: false },\n    ]\n\n    const result2 = [\n      { id: '1', done: false },\n      { id: '2', done: true },\n    ]\n\n    const states: Array<UseQueryResult<typeof result1>> = []\n\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          return count === 1 ? result1 : result2\n        },\n        notifyOnChangeProps: 'all',\n      })\n\n      states.push(state)\n\n      const { refetch } = state\n\n      return (\n        <div>\n          <button onClick={() => refetch()}>refetch</button>\n          data: {String(state.data?.[1]?.done)}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: false')\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: true')\n\n    expect(states.length).toBe(4)\n\n    const todos = states[2]?.data\n    const todo1 = todos?.[0]\n    const todo2 = todos?.[1]\n\n    const newTodos = states[3]?.data\n    const newTodo1 = newTodos?.[0]\n    const newTodo2 = newTodos?.[1]\n\n    expect(todos).toEqual(result1)\n    expect(newTodos).toEqual(result2)\n    expect(newTodos).not.toBe(todos)\n    expect(newTodo1).toBe(todo1)\n    expect(newTodo2).not.toBe(todo2)\n\n    return null\n  })\n\n  it('should use query function from hook when the existing query does not have a query function', async () => {\n    const key = queryKey()\n\n    queryClient.setQueryData(key, 'set')\n\n    function Page() {\n      const result = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return 'fetched'\n        },\n\n        initialData: 'initial',\n        staleTime: Infinity,\n      })\n\n      return (\n        <div>\n          <div>isFetching: {result.isFetching}</div>\n          <button onClick={() => queryClient.refetchQueries({ queryKey: key })}>\n            refetch\n          </button>\n          data: {result.data}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: set')).toBeInTheDocument()\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: fetched')).toBeInTheDocument()\n  })\n\n  it('should update query stale state and refetch when invalidated with invalidateQueries', async () => {\n    const key = queryKey()\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          return count\n        },\n        staleTime: Infinity,\n      })\n\n      return (\n        <div>\n          <button\n            onClick={() => queryClient.invalidateQueries({ queryKey: key })}\n          >\n            invalidate\n          </button>\n          data: {state.data}, isStale: {String(state.isStale)}, isFetching:{' '}\n          {String(state.isFetching)}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(\n      rendered.getByText('data: 1, isStale: false, isFetching: false'),\n    ).toBeInTheDocument()\n    fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(\n      rendered.getByText('data: 1, isStale: true, isFetching: true'),\n    ).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(\n      rendered.getByText('data: 2, isStale: false, isFetching: false'),\n    ).toBeInTheDocument()\n  })\n\n  it('should not update disabled query when refetching with refetchQueries', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          return count\n        },\n        enabled: false,\n      })\n\n      states.push(state)\n\n      useEffect(() => {\n        setActTimeout(() => {\n          queryClient.refetchQueries({ queryKey: key })\n        }, 20)\n      }, [])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(31)\n\n    expect(states.length).toBe(1)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: false,\n      isSuccess: false,\n      isStale: false,\n    })\n  })\n\n  it('should not refetch disabled query when invalidated with invalidateQueries', () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          return count\n        },\n        enabled: false,\n      })\n\n      states.push(state)\n\n      useEffect(() => {\n        setActTimeout(() => {\n          queryClient.invalidateQueries({ queryKey: key })\n        }, 10)\n      }, [])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    expect(states.length).toBe(1)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: false,\n      isSuccess: false,\n      isStale: false,\n    })\n  })\n\n  it('should not fetch when switching to a disabled query', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n\n    function Page() {\n      const [count, setCount] = useState(0)\n\n      const state = useQuery({\n        queryKey: [key, count],\n        queryFn: async () => {\n          await sleep(5)\n          return count\n        },\n        enabled: count === 0,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <button onClick={() => setCount(1)}>increment</button>\n          <div>data: {state.data ?? 'undefined'}</div>\n          <div>count: {count}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('data: 0')\n\n    fireEvent.click(rendered.getByRole('button', { name: /increment/i }))\n\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('count: 1')\n    rendered.getByText('data: undefined')\n\n    expect(states.length).toBe(3)\n\n    // Fetch query\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isSuccess: false,\n    })\n    // Fetched query\n    expect(states[1]).toMatchObject({\n      data: 0,\n      isFetching: false,\n      isSuccess: true,\n    })\n    // Switch to disabled query\n    expect(states[2]).toMatchObject({\n      data: undefined,\n      isFetching: false,\n      isSuccess: false,\n    })\n  })\n\n  it('should keep the previous data when placeholderData is set', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n\n    function Page() {\n      const [count, setCount] = useState(0)\n\n      const state = useQuery({\n        queryKey: [key, count],\n        queryFn: async () => {\n          await sleep(10)\n          return count\n        },\n        placeholderData: keepPreviousData,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <div>data: {state.data}</div>\n          <button onClick={() => setCount(1)}>setCount</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 0')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 1')\n\n    // Initial\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isSuccess: false,\n      isPlaceholderData: false,\n    })\n    // Fetched\n    expect(states[1]).toMatchObject({\n      data: 0,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Set state\n    expect(states[2]).toMatchObject({\n      data: 0,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // New data\n    expect(states[3]).toMatchObject({\n      data: 1,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n  })\n\n  it('should keep the previous data when placeholderData is set and select fn transform is used', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n\n    function Page() {\n      const [count, setCount] = useState(0)\n\n      const state = useQuery({\n        queryKey: [key, count],\n        queryFn: async () => {\n          await sleep(10)\n          return {\n            count,\n          }\n        },\n        select(data) {\n          return data.count\n        },\n        placeholderData: keepPreviousData,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <div>data: {state.data}</div>\n          <button onClick={() => setCount(1)}>setCount</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 0')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 1')\n\n    // Initial\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isSuccess: false,\n      isPlaceholderData: false,\n    })\n    // Fetched\n    expect(states[1]).toMatchObject({\n      data: 0,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Set state\n    expect(states[2]).toMatchObject({\n      data: 0,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // New data\n    expect(states[3]).toMatchObject({\n      data: 1,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n  })\n\n  it('should keep the previous queryKey (from prevQuery) between multiple pending queries when placeholderData is set and select fn transform is used', async () => {\n    const keys: Array<ReadonlyArray<unknown> | null> = []\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n\n    function Page() {\n      const [count, setCount] = useState(0)\n\n      const state = useQuery({\n        queryKey: [key, count],\n        queryFn: async () => {\n          await sleep(10)\n          return {\n            count,\n          }\n        },\n        select(data) {\n          return data.count\n        },\n        placeholderData: (prevData, prevQuery) => {\n          if (prevQuery) {\n            keys.push(prevQuery.queryKey)\n          }\n          return prevData\n        },\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <div>data: {state.data}</div>\n          <button onClick={() => setCount((prev) => prev + 1)}>setCount</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 0')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))\n    fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))\n    fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 3')\n\n    const allPreviousKeysAreTheFirstQueryKey = keys.every(\n      (k) => JSON.stringify(k) === JSON.stringify([key, 0]),\n    )\n\n    expect(allPreviousKeysAreTheFirstQueryKey).toBe(true)\n  })\n\n  it('should show placeholderData between multiple pending queries when select fn transform is used', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n\n    function Page() {\n      const [count, setCount] = useState(0)\n\n      const state = useQuery({\n        queryKey: [key, count],\n        queryFn: async () => {\n          await sleep(10)\n          return {\n            count,\n          }\n        },\n        select(data) {\n          return data.count\n        },\n        placeholderData: keepPreviousData,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <div>data: {state.data}</div>\n          <button onClick={() => setCount((prev) => prev + 1)}>setCount</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 0')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))\n    fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))\n    fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 3')\n    // Initial\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isSuccess: false,\n      isPlaceholderData: false,\n    })\n    // Fetched\n    expect(states[1]).toMatchObject({\n      data: 0,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Set state -> count = 1\n    expect(states[2]).toMatchObject({\n      data: 0,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // Set state -> count = 2\n    expect(states[3]).toMatchObject({\n      data: 0,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // Set state -> count = 3\n    expect(states[4]).toMatchObject({\n      data: 0,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // New data\n    expect(states[5]).toMatchObject({\n      data: 3,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n  })\n\n  it('should transition to error state when placeholderData is set', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n\n    function Page({ count }: { count: number }) {\n      const state = useQuery<number, Error>({\n        queryKey: [key, count],\n        queryFn: async () => {\n          await sleep(10)\n          if (count === 2) {\n            throw new Error('Error test')\n          }\n          return Promise.resolve(count)\n        },\n        retry: false,\n        placeholderData: keepPreviousData,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <h1>data: {state.data}</h1>\n          <h2>error: {state.error?.message}</h2>\n          <p>placeholder data: {state.isPlaceholderData}</p>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page count={0} />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 0')\n    rendered.rerender(<Page count={1} />)\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 1')\n    rendered.rerender(<Page count={2} />)\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('error: Error test')\n\n    expect(states.length).toBe(6)\n    // Initial\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      status: 'pending',\n      error: null,\n      isPlaceholderData: false,\n    })\n    // Fetched\n    expect(states[1]).toMatchObject({\n      data: 0,\n      isFetching: false,\n      status: 'success',\n      error: null,\n      isPlaceholderData: false,\n    })\n    // rerender Page 1\n    expect(states[2]).toMatchObject({\n      data: 0,\n      isFetching: true,\n      status: 'success',\n      error: null,\n      isPlaceholderData: true,\n    })\n    // New data\n    expect(states[3]).toMatchObject({\n      data: 1,\n      isFetching: false,\n      status: 'success',\n      error: null,\n      isPlaceholderData: false,\n    })\n    // rerender Page 2\n    expect(states[4]).toMatchObject({\n      data: 1,\n      isFetching: true,\n      status: 'success',\n      error: null,\n      isPlaceholderData: true,\n    })\n    // Error\n    expect(states[5]).toMatchObject({\n      data: undefined,\n      isFetching: false,\n      status: 'error',\n      isPlaceholderData: false,\n    })\n    expect(states[5]!.error).toHaveProperty('message', 'Error test')\n  })\n\n  it('should not show initial data from next query if placeholderData is set', async () => {\n    const key = queryKey()\n    const states: Array<DefinedUseQueryResult<number>> = []\n\n    function Page() {\n      const [count, setCount] = useState(0)\n\n      const state = useQuery({\n        queryKey: [key, count],\n        queryFn: async () => {\n          await sleep(10)\n          return count\n        },\n        initialData: 99,\n        placeholderData: keepPreviousData,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <h1>\n            data: {state.data}, count: {count}, isFetching:{' '}\n            {String(state.isFetching)}\n          </h1>\n          <button onClick={() => setCount(1)}>inc</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 0, count: 0, isFetching: false')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'inc' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 1, count: 1, isFetching: false')\n\n    expect(states.length).toBe(4)\n\n    // Initial\n    expect(states[0]).toMatchObject({\n      data: 99,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Fetched\n    expect(states[1]).toMatchObject({\n      data: 0,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Set state\n    expect(states[2]).toMatchObject({\n      data: 99,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // New data\n    expect(states[3]).toMatchObject({\n      data: 1,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n  })\n\n  it('should keep the previous data on disabled query when placeholderData is set', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n\n    function Page() {\n      const [count, setCount] = useState(0)\n\n      const state = useQuery({\n        queryKey: [key, count],\n        queryFn: async () => {\n          await sleep(10)\n          return count\n        },\n        enabled: false,\n        placeholderData: keepPreviousData,\n        notifyOnChangeProps: 'all',\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <button onClick={() => state.refetch()}>refetch</button>\n          <button onClick={() => setCount(1)}>setCount</button>\n          <div>data: {state.data ?? 'undefined'}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    rendered.getByText('data: undefined')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 0')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 0')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 1')\n\n    expect(states.length).toBe(6)\n\n    // Disabled query\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: false,\n      isSuccess: false,\n      isPlaceholderData: false,\n    })\n    // Fetching query\n    expect(states[1]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isSuccess: false,\n      isPlaceholderData: false,\n    })\n    // Fetched query\n    expect(states[2]).toMatchObject({\n      data: 0,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Set state\n    expect(states[3]).toMatchObject({\n      data: 0,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // Fetching new query\n    expect(states[4]).toMatchObject({\n      data: 0,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // Fetched new query\n    expect(states[5]).toMatchObject({\n      data: 1,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n  })\n\n  it('should keep the previous data on disabled query when placeholderData is set and switching query key multiple times', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n\n    queryClient.setQueryData([key, 10], 10)\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    function Page() {\n      const [count, setCount] = useState(10)\n\n      const state = useQuery({\n        queryKey: [key, count],\n        queryFn: async () => {\n          await sleep(10)\n          return count\n        },\n        enabled: false,\n        placeholderData: keepPreviousData,\n        notifyOnChangeProps: 'all',\n      })\n\n      states.push(state)\n\n      const { refetch } = state\n\n      useEffect(() => {\n        setActTimeout(() => {\n          setCount(11)\n        }, 20)\n        setActTimeout(() => {\n          setCount(12)\n        }, 30)\n        setActTimeout(() => {\n          refetch()\n        }, 40)\n      }, [refetch])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(51)\n\n    expect(states.length).toBe(5)\n\n    // Disabled query\n    expect(states[0]).toMatchObject({\n      data: 10,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Set state\n    expect(states[1]).toMatchObject({\n      data: 10,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // State update\n    expect(states[2]).toMatchObject({\n      data: 10,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // Refetch\n    expect(states[3]).toMatchObject({\n      data: 10,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // Refetch done\n    expect(states[4]).toMatchObject({\n      data: 12,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n  })\n\n  it('should use the correct query function when components use different configurations', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n\n    function FirstComponent() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return 1\n        },\n        notifyOnChangeProps: 'all',\n      })\n      const refetch = state.refetch\n\n      states.push(state)\n\n      return (\n        <div>\n          <button onClick={() => refetch()}>refetch</button>\n          data: {state.data}\n        </div>\n      )\n    }\n\n    function SecondComponent() {\n      useQuery({ queryKey: key, queryFn: () => 2, notifyOnChangeProps: 'all' })\n      return null\n    }\n\n    function Page() {\n      return (\n        <>\n          <FirstComponent />\n          <SecondComponent />\n        </>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 1')\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(states.length).toBe(4)\n\n    expect(states[0]).toMatchObject({\n      data: undefined,\n    })\n    expect(states[1]).toMatchObject({\n      data: 1,\n    })\n    expect(states[2]).toMatchObject({\n      data: 1,\n    })\n    // This state should be 1 instead of 2\n    expect(states[3]).toMatchObject({\n      data: 1,\n    })\n  })\n\n  it('should be able to set different stale times for a query', async () => {\n    const key = queryKey()\n    const states1: Array<UseQueryResult<string>> = []\n    const states2: Array<UseQueryResult<string>> = []\n\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: async () => {\n        await sleep(10)\n        return 'prefetch'\n      },\n    })\n\n    await vi.advanceTimersByTimeAsync(20)\n\n    function FirstComponent() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return 'one'\n        },\n\n        staleTime: 100,\n      })\n      states1.push(state)\n      return null\n    }\n\n    function SecondComponent() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return 'two'\n        },\n\n        staleTime: 10,\n      })\n      states2.push(state)\n      return null\n    }\n\n    function Page() {\n      return (\n        <>\n          <FirstComponent />\n          <SecondComponent />\n        </>\n      )\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(200)\n\n    expect(states1.length).toBe(4)\n    expect(states2.length).toBe(3)\n\n    expect(states1).toMatchObject([\n      // First render\n      {\n        data: 'prefetch',\n        isStale: false,\n      },\n      // Second useQuery started fetching\n      {\n        data: 'prefetch',\n        isStale: false,\n      },\n      // Second useQuery data came in\n      {\n        data: 'two',\n        isStale: false,\n      },\n      // Data became stale after 100ms\n      {\n        data: 'two',\n        isStale: true,\n      },\n    ])\n\n    expect(states2).toMatchObject([\n      // First render, data is stale and starts fetching\n      {\n        data: 'prefetch',\n        isStale: true,\n      },\n      // Second useQuery data came in\n      {\n        data: 'two',\n        isStale: false,\n      },\n      // Data became stale after 5ms\n      {\n        data: 'two',\n        isStale: true,\n      },\n    ])\n  })\n\n  it('should re-render when a query becomes stale', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => 'test',\n        staleTime: 50,\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(100)\n\n    expect(states.length).toBe(3)\n    expect(states[0]).toMatchObject({ isStale: true })\n    expect(states[1]).toMatchObject({ isStale: false })\n    expect(states[2]).toMatchObject({ isStale: true })\n  })\n\n  it('should re-render disabled observers when other observers trigger a query (#8741)', async () => {\n    const key = queryKey()\n\n    const useUserInfoQuery = ({\n      id,\n      enabled,\n    }: {\n      id: number | null\n      enabled: boolean\n    }) => {\n      return useQuery({\n        queryKey: [key, id],\n        queryFn: async () => {\n          await sleep(10)\n          return { id, name: 'John' }\n        },\n        enabled: !!id && enabled,\n      })\n    }\n\n    const Page = () => {\n      const [id, setId] = useState<number | null>(null)\n\n      const searchQuery = useUserInfoQuery({ id, enabled: false })\n\n      return (\n        <>\n          <div>User fetching status is {searchQuery.fetchStatus}</div>\n          <UserInfo id={id} />\n          <button onClick={() => setId(42)}>\n            Set ID and trigger user load\n          </button>\n        </>\n      )\n    }\n\n    function UserInfo({ id }: { id: number | null }) {\n      const searchQuery = useUserInfoQuery({ id, enabled: true })\n\n      return <div>UserInfo data is {JSON.stringify(searchQuery.data)} </div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    rendered.getByText('User fetching status is idle')\n\n    fireEvent.click(rendered.getByRole('button', { name: /set id/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(\n      rendered.getByText('User fetching status is fetching'),\n    ).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(\n      rendered.getByText('UserInfo data is {\"id\":42,\"name\":\"John\"}'),\n    ).toBeInTheDocument()\n\n    expect(\n      rendered.getByText('User fetching status is idle'),\n    ).toBeInTheDocument()\n  })\n\n  describe('notifyOnChangeProps', () => {\n    it('should not re-render when it should only re-render only data change and the selected data did not change', async () => {\n      const key = queryKey()\n      const states: Array<UseQueryResult<string>> = []\n\n      function Page() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: () => ({ name: 'test' }),\n          select: (data) => data.name,\n          notifyOnChangeProps: ['data'],\n        })\n\n        states.push(state)\n\n        return (\n          <div>\n            <div>{state.data}</div>\n            <button onClick={() => state.refetch()}>refetch</button>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      await vi.advanceTimersByTimeAsync(0)\n      rendered.getByText('test')\n\n      fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))\n\n      await vi.advanceTimersByTimeAsync(0)\n      rendered.getByText('test')\n\n      expect(states[0]).toMatchObject({ data: undefined })\n      expect(states[1]).toMatchObject({ data: 'test' })\n\n      // make sure no additional renders happen\n      await vi.advanceTimersByTimeAsync(50)\n      expect(states.length).toBe(2)\n    })\n    it('should not re-render when it should only re-render on data changes and the data did not change', async () => {\n      const key = queryKey()\n      const states: Array<UseQueryResult<string>> = []\n\n      function Page() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: async () => {\n            await sleep(5)\n            return 'test'\n          },\n\n          notifyOnChangeProps: ['data'],\n        })\n\n        states.push(state)\n\n        return (\n          <>\n            <button\n              onClick={async () => {\n                await state.refetch()\n              }}\n            >\n              refetch\n            </button>\n\n            <div>{state.data}</div>\n          </>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      await vi.advanceTimersByTimeAsync(6)\n      rendered.getByText('test')\n\n      fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))\n\n      // sleep is required to make sure no additional renders happen after click\n      await vi.advanceTimersByTimeAsync(20)\n\n      expect(states.length).toBe(2)\n      expect(states[0]).toMatchObject({\n        data: undefined,\n        status: 'pending',\n        isFetching: true,\n      })\n      expect(states[1]).toMatchObject({\n        data: 'test',\n        status: 'success',\n        isFetching: false,\n      })\n    })\n\n    // See https://github.com/TanStack/query/discussions/5588\n    describe('function', () => {\n      it('should not re-render when it should only re-render on data changes and the data did not change', async () => {\n        const key = queryKey()\n        const states: Array<UseQueryResult<string>> = []\n\n        function Page() {\n          const state = useQuery({\n            queryKey: key,\n            queryFn: async () => {\n              await sleep(5)\n              return 'test'\n            },\n            notifyOnChangeProps: () => ['data'],\n          })\n\n          states.push(state)\n\n          return (\n            <>\n              <button\n                onClick={async () => {\n                  await state.refetch()\n                }}\n              >\n                refetch\n              </button>\n\n              <div>{state.data}</div>\n            </>\n          )\n        }\n\n        const rendered = renderWithClient(queryClient, <Page />)\n\n        await vi.advanceTimersByTimeAsync(6)\n        rendered.getByText('test')\n\n        fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))\n\n        await vi.advanceTimersByTimeAsync(20)\n\n        expect(states.length).toBe(2)\n        expect(states[0]).toMatchObject({\n          data: undefined,\n          status: 'pending',\n          isFetching: true,\n        })\n        expect(states[1]).toMatchObject({\n          data: 'test',\n          status: 'success',\n          isFetching: false,\n        })\n      })\n\n      it('should not re-render when change props are not actively being tracked', async () => {\n        const key = queryKey()\n        const states: Array<UseQueryResult<string>> = []\n\n        function Page() {\n          const fetchCounterRef = useRef(0)\n          const trackChangesRef = useRef(true)\n\n          const notifyOnChangeProps = useCallback(() => {\n            return trackChangesRef.current ? 'all' : []\n          }, [])\n\n          const state = useQuery({\n            queryKey: key,\n            queryFn: async () => {\n              await sleep(5)\n              fetchCounterRef.current++\n              return `fetch counter: ${fetchCounterRef.current}`\n            },\n            notifyOnChangeProps,\n          })\n\n          states.push(state)\n\n          return (\n            <>\n              <button\n                onClick={async () => {\n                  await state.refetch()\n                }}\n              >\n                refetch\n              </button>\n              <button\n                onClick={() => {\n                  trackChangesRef.current = true\n                }}\n              >\n                enableTracking\n              </button>\n              <button\n                onClick={() => {\n                  trackChangesRef.current = false\n                }}\n              >\n                disableTracking\n              </button>\n\n              <div>{state.data}</div>\n            </>\n          )\n        }\n\n        const rendered = renderWithClient(queryClient, <Page />)\n        await vi.advanceTimersByTimeAsync(6)\n        rendered.getByText('fetch counter: 1')\n\n        expect(states.length).toBe(2)\n        expect(states[0]).toMatchObject({\n          data: undefined,\n          isFetching: true,\n          status: 'pending',\n        })\n        expect(states[1]).toMatchObject({\n          data: 'fetch counter: 1',\n          status: 'success',\n          isFetching: false,\n        })\n\n        // disable tracking and refetch to check for re-renders\n        fireEvent.click(\n          rendered.getByRole('button', { name: 'disableTracking' }),\n        )\n        fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))\n\n        await vi.advanceTimersByTimeAsync(20)\n        // still expect to only have two re-renders from the initial fetch\n        expect(states.length).toBe(2)\n\n        // enable tracking and refetch to check for re-renders\n        fireEvent.click(\n          rendered.getByRole('button', { name: 'enableTracking' }),\n        )\n        fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))\n\n        await vi.advanceTimersByTimeAsync(6)\n        rendered.getByText('fetch counter: 3')\n        await vi.advanceTimersByTimeAsync(20)\n\n        expect(states.length).toBe(4)\n        expect(states[2]).toMatchObject({\n          data: 'fetch counter: 2',\n          status: 'success',\n          isFetching: true,\n        })\n        expect(states[3]).toMatchObject({\n          data: 'fetch counter: 3',\n          status: 'success',\n          isFetching: false,\n        })\n      })\n    })\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/137\n  it('should not override initial data in dependent queries', () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    function Page() {\n      const first = useQuery({\n        queryKey: key1,\n        queryFn: () => 'data',\n        enabled: false,\n        initialData: 'init',\n      })\n\n      const second = useQuery({\n        queryKey: key2,\n        queryFn: () => 'data',\n        enabled: false,\n        initialData: 'init',\n      })\n\n      return (\n        <div>\n          <h2>First Data: {first.data}</h2>\n          <h2>Second Data: {second.data}</h2>\n          <div>First Status: {first.status}</div>\n          <div>Second Status: {second.status}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('First Data: init')).toBeInTheDocument()\n    expect(rendered.getByText('Second Data: init')).toBeInTheDocument()\n    expect(rendered.getByText('First Status: success')).toBeInTheDocument()\n    expect(rendered.getByText('Second Status: success')).toBeInTheDocument()\n  })\n\n  it('should update query options', () => {\n    const key = queryKey()\n\n    const queryFn = async () => {\n      await sleep(10)\n      return 'data1'\n    }\n\n    function Page() {\n      useQuery({ queryKey: key, queryFn, retryDelay: 10 })\n      useQuery({ queryKey: key, queryFn, retryDelay: 20 })\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    expect(queryCache.find({ queryKey: key })!.options.retryDelay).toBe(20)\n  })\n\n  it('should batch re-renders', async () => {\n    const key = queryKey()\n\n    let renders = 0\n\n    const queryFn = async () => {\n      await sleep(15)\n      return 'data'\n    }\n\n    function Page() {\n      const query1 = useQuery({ queryKey: key, queryFn })\n      const query2 = useQuery({ queryKey: key, queryFn })\n      renders++\n\n      return (\n        <div>\n          {query1.data} {query2.data}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(16)\n    rendered.getByText('data data')\n\n    // Should be 2 instead of 3\n    expect(renders).toBe(2)\n  })\n\n  it('should render latest data even if preact has discarded certain renders', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const [, setNewState] = useState('state')\n      const state = useQuery({ queryKey: key, queryFn: () => 'data' })\n      useEffect(() => {\n        setActTimeout(() => {\n          queryClient.setQueryData(key, 'new')\n          // Update with same state to make preact discard the next render\n          setNewState('state')\n        }, 10)\n      }, [])\n      return <div>{state.data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('new')).toBeInTheDocument()\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/170\n  it('should start with status pending, fetchStatus idle if enabled is false', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    function Page() {\n      const first = useQuery({\n        queryKey: key1,\n        queryFn: async () => {\n          await sleep(10)\n          return 'data'\n        },\n        enabled: false,\n      })\n      const second = useQuery({\n        queryKey: key2,\n        queryFn: async () => {\n          await sleep(10)\n          return 'data'\n        },\n      })\n\n      return (\n        <div>\n          <div>\n            First Status: {first.status}, {first.fetchStatus}\n          </div>\n          <div>\n            Second Status: {second.status}, {second.fetchStatus}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    // use \"act\" to wait for state update and prevent console warning\n\n    expect(\n      rendered.getByText('First Status: pending, idle'),\n    ).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(0)\n    expect(\n      rendered.getByText('Second Status: pending, fetching'),\n    ).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(\n      rendered.getByText('Second Status: success, idle'),\n    ).toBeInTheDocument()\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/144\n  it('should be in \"pending\" state by default', () => {\n    const key = queryKey()\n\n    function Page() {\n      const { status } = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return 'test'\n        },\n      })\n\n      return <div>status: {status}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('status: pending')).toBeInTheDocument()\n  })\n\n  it('should not refetch query on focus when `enabled` is set to `false`', async () => {\n    const key = queryKey()\n    const queryFn = vi\n      .fn<(...args: Array<unknown>) => string>()\n      .mockReturnValue('data')\n\n    function Page() {\n      const { data = 'default' } = useQuery({\n        queryKey: key,\n        queryFn,\n        enabled: false,\n      })\n\n      return (\n        <div>\n          <h1>{data}</h1>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('default')\n\n    act(() => {\n      window.dispatchEvent(new Event('visibilitychange'))\n    })\n\n    expect(queryFn).not.toHaveBeenCalled()\n  })\n\n  it('should not refetch stale query on focus when `refetchOnWindowFocus` is set to `false`', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => count++,\n        staleTime: 0,\n        refetchOnWindowFocus: false,\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    act(() => {\n      window.dispatchEvent(new Event('visibilitychange'))\n    })\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined, isFetching: true })\n    expect(states[1]).toMatchObject({ data: 0, isFetching: false })\n  })\n\n  it('should not refetch stale query on focus when `refetchOnWindowFocus` is set to a function that returns `false`', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => count++,\n        staleTime: 0,\n        refetchOnWindowFocus: () => false,\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    act(() => {\n      window.dispatchEvent(new Event('visibilitychange'))\n    })\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined, isFetching: true })\n    expect(states[1]).toMatchObject({ data: 0, isFetching: false })\n  })\n\n  it('should not refetch fresh query on focus when `refetchOnWindowFocus` is set to `true`', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => count++,\n        staleTime: Infinity,\n        refetchOnWindowFocus: true,\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    act(() => {\n      window.dispatchEvent(new Event('visibilitychange'))\n    })\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined, isFetching: true })\n    expect(states[1]).toMatchObject({ data: 0, isFetching: false })\n  })\n\n  it('should refetch fresh query on focus when `refetchOnWindowFocus` is set to `always`', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return count++\n        },\n\n        staleTime: Infinity,\n        refetchOnWindowFocus: 'always',\n      })\n      states.push(state)\n      return (\n        <div>\n          <div>\n            data: {state.data}, isFetching: {String(state.isFetching)}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 0, isFetching: false')).toBeInTheDocument()\n\n    act(() => {\n      window.dispatchEvent(new Event('visibilitychange'))\n    })\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 1, isFetching: false')).toBeInTheDocument()\n  })\n\n  it('should calculate focus behavior for `refetchOnWindowFocus` depending on function', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return count++\n        },\n\n        staleTime: 0,\n        retry: 0,\n        refetchOnWindowFocus: (query) => (query.state.data || 0) < 1,\n      })\n      states.push(state)\n      return <div>data: {String(state.data)}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 0')\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined, isFetching: true })\n    expect(states[1]).toMatchObject({ data: 0, isFetching: false })\n\n    act(() => {\n      window.dispatchEvent(new Event('visibilitychange'))\n    })\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 1')\n\n    // refetch should happen\n    expect(states.length).toBe(4)\n\n    expect(states[2]).toMatchObject({ data: 0, isFetching: true })\n    expect(states[3]).toMatchObject({ data: 1, isFetching: false })\n\n    act(() => {\n      window.dispatchEvent(new Event('visibilitychange'))\n    })\n\n    await vi.advanceTimersByTimeAsync(20)\n\n    // no more refetch now\n    expect(states.length).toBe(4)\n  })\n\n  it('should refetch fresh query when refetchOnMount is set to always', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    await queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => 'prefetched',\n    })\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => 'data',\n        refetchOnMount: 'always',\n        staleTime: Infinity,\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: 'prefetched',\n      isStale: false,\n      isFetching: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: 'data',\n      isStale: false,\n      isFetching: false,\n    })\n  })\n\n  it('should refetch stale query when refetchOnMount is set to true', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    await queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => 'prefetched',\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => 'data',\n        refetchOnMount: true,\n        staleTime: 0,\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: 'prefetched',\n      isStale: true,\n      isFetching: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: 'data',\n      isStale: true,\n      isFetching: false,\n    })\n  })\n\n  it('should set status to error if queryFn throws', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    function Page() {\n      const { status, error } = useQuery({\n        queryKey: key,\n        queryFn: () => {\n          return Promise.reject(new Error('Error test'))\n        },\n        retry: false,\n      })\n\n      return (\n        <div>\n          <h1>{status}</h1>\n          <h2>{error?.message}</h2>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('error')).toBeInTheDocument()\n    expect(rendered.getByText('Error test')).toBeInTheDocument()\n    consoleMock.mockRestore()\n  })\n\n  it('should throw error if queryFn throws and throwOnError is in use', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    function Page() {\n      const { status, error } = useQuery<unknown, string>({\n        queryKey: key,\n        queryFn: () => Promise.reject(new Error('Error test')),\n        retry: false,\n        throwOnError: true,\n      })\n\n      return (\n        <div>\n          <h1>{status}</h1>\n          <h2>{error}</h2>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <ErrorBoundary fallbackRender={() => <div>error boundary</div>}>\n        <Page />\n      </ErrorBoundary>,\n    )\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n    consoleMock.mockRestore()\n  })\n\n  it('should update with data if we observe no properties and throwOnError', async () => {\n    const key = queryKey()\n\n    let result: UseQueryResult<string> | undefined\n\n    function Page() {\n      const query = useQuery({\n        queryKey: key,\n        queryFn: () => Promise.resolve('data'),\n        throwOnError: true,\n      })\n\n      useEffect(() => {\n        result = query\n      })\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(queryClient.isFetching()).toBe(0)\n\n    expect(result?.data).toBe('data')\n  })\n\n  it('should set status to error instead of throwing when error should not be thrown', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const { status, error } = useQuery({\n        queryKey: key,\n        queryFn: () => Promise.reject(new Error('Local Error')),\n\n        retry: false,\n        throwOnError: (err) => err.message !== 'Local Error',\n      })\n\n      return (\n        <div>\n          <h1>{status}</h1>\n          <h2>{error?.message}</h2>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <ErrorBoundary fallbackRender={() => <div>error boundary</div>}>\n        <Page />\n      </ErrorBoundary>,\n    )\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('error')).toBeInTheDocument()\n    expect(rendered.getByText('Local Error')).toBeInTheDocument()\n  })\n\n  it('should throw error instead of setting status when error should be thrown', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n\n    const key = queryKey()\n\n    function Page() {\n      const { status, error } = useQuery<unknown, Error>({\n        queryKey: key,\n        queryFn: () => Promise.reject(new Error('Remote Error')),\n\n        retry: false,\n        throwOnError: (err) => err.message !== 'Local Error',\n      })\n\n      return (\n        <div>\n          <h1>{status}</h1>\n          <h2>{error?.message ?? ''}</h2>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <ErrorBoundary\n        fallbackRender={({ error }) => (\n          <div>\n            <div>error boundary</div>\n            <div>{error?.message}</div>\n          </div>\n        )}\n      >\n        <Page />\n      </ErrorBoundary>,\n    )\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n    expect(rendered.getByText('Remote Error')).toBeInTheDocument()\n    consoleMock.mockRestore()\n  })\n\n  it('should continue retries when observers unmount and remount while waiting for a retry (#3031)', async () => {\n    const key = queryKey()\n    let count = 0\n\n    function Page() {\n      const result = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          count++\n          await sleep(10)\n          return Promise.reject(new Error('some error'))\n        },\n\n        retry: 2,\n        retryDelay: 100,\n      })\n\n      return (\n        <div>\n          <div>error: {result.error?.message ?? 'null'}</div>\n          <div>failureCount: {result.failureCount}</div>\n          <div>failureReason: {result.failureReason?.message}</div>\n        </div>\n      )\n    }\n\n    function App() {\n      const [show, toggle] = useReducer((x) => !x, true)\n\n      return (\n        <div>\n          <button onClick={toggle}>{show ? 'hide' : 'show'}</button>\n          {show && <Page />}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('failureCount: 1')).toBeInTheDocument()\n    expect(rendered.getByText('failureReason: some error')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(90)\n    fireEvent.click(rendered.getByRole('button', { name: /hide/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByRole('button', { name: /show/i })).toBeInTheDocument()\n    fireEvent.click(rendered.getByRole('button', { name: /show/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    await vi.advanceTimersByTimeAsync(110)\n    await vi.advanceTimersByTimeAsync(110)\n    expect(rendered.getByText('error: some error')).toBeInTheDocument()\n\n    expect(count).toBe(4)\n  })\n\n  it('should restart when observers unmount and remount while waiting for a retry when query was cancelled in between (#3031)', async () => {\n    const key = queryKey()\n    let count = 0\n\n    function Page() {\n      const result = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          count++\n          await sleep(10)\n          return Promise.reject(new Error('some error'))\n        },\n\n        retry: 2,\n        retryDelay: 100,\n      })\n\n      return (\n        <div>\n          <div>error: {result.error?.message ?? 'null'}</div>\n          <div>failureCount: {result.failureCount}</div>\n          <div>failureReason: {result.failureReason?.message}</div>\n        </div>\n      )\n    }\n\n    function App() {\n      const [show, toggle] = useReducer((x) => !x, true)\n\n      return (\n        <div>\n          <button onClick={toggle}>{show ? 'hide' : 'show'}</button>\n          <button onClick={() => queryClient.cancelQueries({ queryKey: key })}>\n            cancel\n          </button>\n          {show && <Page />}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('failureCount: 1')).toBeInTheDocument()\n    expect(rendered.getByText('failureReason: some error')).toBeInTheDocument()\n    fireEvent.click(rendered.getByRole('button', { name: /hide/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /cancel/i }))\n    expect(rendered.getByRole('button', { name: /show/i })).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(1)\n    fireEvent.click(rendered.getByRole('button', { name: /show/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    await vi.advanceTimersByTimeAsync(110)\n    await vi.advanceTimersByTimeAsync(110)\n    expect(rendered.getByText('error: some error')).toBeInTheDocument()\n\n    // initial fetch (1), which will be cancelled, followed by new mount(2) + 2 retries = 4\n    expect(count).toBe(4)\n  })\n\n  it('should always fetch if refetchOnMount is set to always', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    await queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => 'prefetched',\n    })\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => 'data',\n        refetchOnMount: 'always',\n        staleTime: 50,\n      })\n      states.push(state)\n      return (\n        <div>\n          <div>data: {state.data ?? 'null'}</div>\n          <div>isFetching: {state.isFetching}</div>\n          <div>isStale: {state.isStale}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('data: data')\n    await vi.advanceTimersByTimeAsync(52)\n    expect(states.length).toBe(3)\n\n    expect(states[0]).toMatchObject({\n      data: 'prefetched',\n      isStale: false,\n      isFetching: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: 'data',\n      isStale: false,\n      isFetching: false,\n    })\n    expect(states[2]).toMatchObject({\n      data: 'data',\n      isStale: true,\n      isFetching: false,\n    })\n  })\n\n  it('should fetch if initial data is set', async () => {\n    const key = queryKey()\n    const states: Array<DefinedUseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => 'data',\n        initialData: 'initial',\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(states.length).toBe(2)\n\n    expect(states[0]).toMatchObject({\n      data: 'initial',\n      isStale: true,\n      isFetching: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: 'data',\n      isStale: true,\n      isFetching: false,\n    })\n  })\n\n  it('should not fetch if initial data is set with a stale time', async () => {\n    const key = queryKey()\n    const states: Array<DefinedUseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => 'data',\n        staleTime: 50,\n        initialData: 'initial',\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(52)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: 'initial',\n      isStale: false,\n      isFetching: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: 'initial',\n      isStale: true,\n      isFetching: false,\n    })\n  })\n\n  it('should fetch if initial data updated at is older than stale time', async () => {\n    const key = queryKey()\n    const states: Array<DefinedUseQueryResult<string>> = []\n\n    const oneSecondAgo = Date.now() - 1000\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => 'data',\n        staleTime: 50,\n        initialData: 'initial',\n        initialDataUpdatedAt: oneSecondAgo,\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(52)\n\n    expect(states.length).toBe(3)\n    expect(states[0]).toMatchObject({\n      data: 'initial',\n      isStale: true,\n      isFetching: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: 'data',\n      isStale: false,\n      isFetching: false,\n    })\n    expect(states[2]).toMatchObject({\n      data: 'data',\n      isStale: true,\n      isFetching: false,\n    })\n  })\n\n  it('should fetch if \"initial data updated at\" is exactly 0', async () => {\n    const key = queryKey()\n    const states: Array<DefinedUseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => 'data',\n        staleTime: 10 * 1000, // 10 seconds\n        initialData: 'initial',\n        initialDataUpdatedAt: 0,\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: 'initial',\n      isStale: true,\n      isFetching: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: 'data',\n      isStale: false,\n      isFetching: false,\n    })\n  })\n\n  it('should keep initial data when the query key changes', async () => {\n    const key = queryKey()\n    const states: Array<DefinedUseQueryResult<{ count: number }>> = []\n\n    function Page() {\n      const [count, setCount] = useState(0)\n      const state = useQuery({\n        queryKey: [key, count],\n        queryFn: () => ({ count: 10 }),\n        staleTime: Infinity,\n        initialData: () => ({ count }),\n      })\n      states.push(state)\n\n      useEffect(() => {\n        setActTimeout(() => {\n          setCount(1)\n        }, 10)\n      }, [])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(states.length).toBe(2)\n    // Initial\n    expect(states[0]).toMatchObject({ data: { count: 0 } })\n    // Set state\n    expect(states[1]).toMatchObject({ data: { count: 1 } })\n  })\n\n  it('should retry specified number of times', async () => {\n    const key = queryKey()\n\n    const queryFn = vi.fn<(...args: Array<unknown>) => unknown>()\n    queryFn.mockImplementation(() => {\n      return Promise.reject(new Error('Error test Barrett'))\n    })\n\n    function Page() {\n      const { status, failureCount, failureReason } = useQuery({\n        queryKey: key,\n        queryFn,\n        retry: 1,\n        retryDelay: 1,\n      })\n\n      return (\n        <div>\n          <h1>{status}</h1>\n          <h2>Failed {failureCount} times</h2>\n          <h2>Failed because {failureReason?.message}</h2>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    rendered.getByText('pending')\n    await vi.advanceTimersByTimeAsync(2)\n    rendered.getByText('error')\n\n    // query should fail `retry + 1` times, since first time isn't a \"retry\"\n    rendered.getByText('Failed 2 times')\n    rendered.getByText('Failed because Error test Barrett')\n\n    expect(queryFn).toHaveBeenCalledTimes(2)\n  })\n\n  it('should not retry if retry function `false`', async () => {\n    const key = queryKey()\n\n    const queryFn = vi.fn<(...args: Array<unknown>) => unknown>()\n\n    queryFn.mockImplementationOnce(() => {\n      return Promise.reject(new Error('Error test Tanner'))\n    })\n\n    queryFn.mockImplementation(() => {\n      return Promise.reject(new Error('NoRetry'))\n    })\n\n    function Page() {\n      const { status, failureCount, failureReason, error } = useQuery({\n        queryKey: key,\n        queryFn,\n        retryDelay: 1,\n        retry: (_failureCount, err) => err.message !== 'NoRetry',\n      })\n\n      return (\n        <div>\n          <h1>{status}</h1>\n          <h2>Failed {failureCount} times</h2>\n          <h2>Failed because {failureReason?.message}</h2>\n          <h2>{error?.message}</h2>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    rendered.getByText('pending')\n    await vi.advanceTimersByTimeAsync(2)\n    rendered.getByText('error')\n\n    rendered.getByText('Failed 2 times')\n    rendered.getByText('Failed because NoRetry')\n\n    rendered.getByText('NoRetry')\n\n    expect(queryFn).toHaveBeenCalledTimes(2)\n  })\n\n  it('should extract retryDelay from error', async () => {\n    const key = queryKey()\n\n    type DelayError = { delay: number }\n\n    const queryFn = vi.fn<(...args: Array<unknown>) => unknown>()\n    queryFn.mockImplementation(() => {\n      return Promise.reject({ delay: 50 })\n    })\n\n    function Page() {\n      const { status, failureCount, failureReason } = useQuery({\n        queryKey: key,\n        queryFn,\n        retry: 1,\n        retryDelay: (_, error: DelayError) => error.delay,\n      })\n\n      return (\n        <div>\n          <h1>{status}</h1>\n          <h2>Failed {failureCount} times</h2>\n          <h2>Failed because DelayError: {failureReason?.delay}ms</h2>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(queryFn).toHaveBeenCalledTimes(1)\n\n    rendered.getByText('Failed because DelayError: 50ms')\n    await vi.advanceTimersByTimeAsync(51)\n    rendered.getByText('Failed 2 times')\n\n    expect(queryFn).toHaveBeenCalledTimes(2)\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/160\n  it('should continue retry after focus regain', async () => {\n    const key = queryKey()\n\n    // make page unfocused\n    const visibilityMock = mockVisibilityState('hidden')\n\n    let count = 0\n\n    function Page() {\n      const query = useQuery<unknown, string>({\n        queryKey: key,\n        queryFn: () => {\n          count++\n          return Promise.reject<unknown>(`fetching error ${count}`)\n        },\n        retry: 3,\n        retryDelay: 1,\n      })\n\n      return (\n        <div>\n          <div>error {String(query.error)}</div>\n          <div>status {query.status}</div>\n          <div>failureCount {query.failureCount}</div>\n          <div>failureReason {query.failureReason}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    // The query should display the first error result\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('failureCount 1')).toBeInTheDocument()\n    expect(\n      rendered.getByText('failureReason fetching error 1'),\n    ).toBeInTheDocument()\n    expect(rendered.getByText('status pending')).toBeInTheDocument()\n    expect(rendered.getByText('error null')).toBeInTheDocument()\n\n    // Check if the query really paused\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('failureCount 1')).toBeInTheDocument()\n    expect(\n      rendered.getByText('failureReason fetching error 1'),\n    ).toBeInTheDocument()\n\n    act(() => {\n      // reset visibilityState to original value\n      visibilityMock.mockRestore()\n      window.dispatchEvent(new Event('visibilitychange'))\n    })\n\n    // Wait for the final result\n    await vi.advanceTimersByTimeAsync(4)\n    expect(rendered.getByText('failureCount 4')).toBeInTheDocument()\n    expect(\n      rendered.getByText('failureReason fetching error 4'),\n    ).toBeInTheDocument()\n    expect(rendered.getByText('status error')).toBeInTheDocument()\n    expect(rendered.getByText('error fetching error 4')).toBeInTheDocument()\n\n    // Check if the query really stopped\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('failureCount 4')).toBeInTheDocument()\n    expect(\n      rendered.getByText('failureReason fetching error 4'),\n    ).toBeInTheDocument()\n  })\n\n  it('should fetch on mount when a query was already created with setQueryData', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    queryClient.setQueryData(key, 'prefetched')\n\n    function Page() {\n      const state = useQuery({ queryKey: key, queryFn: () => 'data' })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(states.length).toBe(2)\n    expect(states).toMatchObject([\n      {\n        data: 'prefetched',\n        isFetching: true,\n        isStale: true,\n      },\n      {\n        data: 'data',\n        isFetching: false,\n        isStale: true,\n      },\n    ])\n  })\n\n  it('should refetch after focus regain', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    // make page unfocused\n    const visibilityMock = mockVisibilityState('hidden')\n\n    // set data in cache to check if the hook query fn is actually called\n    queryClient.setQueryData(key, 'prefetched')\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return 'data'\n        },\n      })\n      states.push(state)\n      return (\n        <div>\n          {state.data}, {state.isStale}, {state.isFetching}\n        </div>\n      )\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(states.length).toBe(2)\n\n    act(() => {\n      // reset visibilityState to original value\n      visibilityMock.mockRestore()\n      window.dispatchEvent(new Event('visibilitychange'))\n    })\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(states.length).toBe(4)\n\n    expect(states).toMatchObject([\n      {\n        data: 'prefetched',\n        isFetching: true,\n        isStale: true,\n      },\n      {\n        data: 'data',\n        isFetching: false,\n        isStale: true,\n      },\n      {\n        data: 'data',\n        isFetching: true,\n        isStale: true,\n      },\n      {\n        data: 'data',\n        isFetching: false,\n        isStale: true,\n      },\n    ])\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/195\n  it('should refetch if stale after a prefetch', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    const queryFn = vi.fn<(...args: Array<unknown>) => string>()\n    queryFn.mockImplementation(() => 'data')\n\n    const prefetchQueryFn = vi.fn<(...args: Array<unknown>) => string>()\n    prefetchQueryFn.mockImplementation(() => 'not yet...')\n\n    await queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: prefetchQueryFn,\n      staleTime: 10,\n    })\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    function Page() {\n      const state = useQuery({ queryKey: key, queryFn })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(states.length).toBe(2)\n\n    expect(prefetchQueryFn).toHaveBeenCalledTimes(1)\n    expect(queryFn).toHaveBeenCalledTimes(1)\n  })\n\n  it('should not refetch if not stale after a prefetch', async () => {\n    const key = queryKey()\n\n    const queryFn = vi.fn<(...args: Array<unknown>) => string>()\n    queryFn.mockImplementation(() => 'data')\n\n    const prefetchQueryFn =\n      vi.fn<(...args: Array<unknown>) => Promise<string>>()\n    prefetchQueryFn.mockImplementation(async () => {\n      await sleep(10)\n      return 'not yet...'\n    })\n\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: prefetchQueryFn,\n      staleTime: 1000,\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    function Page() {\n      useQuery({ queryKey: key, queryFn, staleTime: 1000 })\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(prefetchQueryFn).toHaveBeenCalledTimes(1)\n    expect(queryFn).toHaveBeenCalledTimes(0)\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/190\n  it('should reset failureCount on successful fetch', async () => {\n    const key = queryKey()\n\n    let counter = 0\n\n    function Page() {\n      const query = useQuery({\n        queryKey: key,\n        queryFn: () => {\n          if (counter < 2) {\n            counter++\n            return Promise.reject(new Error('error'))\n          } else {\n            return Promise.resolve('data')\n          }\n        },\n        retryDelay: 10,\n      })\n\n      return (\n        <div>\n          <div>failureCount {query.failureCount}</div>\n          <div>failureReason {query.failureReason?.message ?? 'null'}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('failureCount 2')).toBeInTheDocument()\n    expect(rendered.getByText('failureReason error')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('failureCount 0')).toBeInTheDocument()\n    expect(rendered.getByText('failureReason null')).toBeInTheDocument()\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/199\n  it('should use prefetched data for dependent query', async () => {\n    const key = queryKey()\n    let count = 0\n\n    function Page() {\n      const [enabled, setEnabled] = useState(false)\n      const [isPrefetched, setPrefetched] = useState(false)\n\n      const query = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          count++\n          await sleep(10)\n          return count\n        },\n\n        enabled,\n      })\n\n      useEffect(() => {\n        async function prefetch() {\n          await queryClient.prefetchQuery({\n            queryKey: key,\n            queryFn: () => Promise.resolve('prefetched data'),\n          })\n          act(() => setPrefetched(true))\n        }\n\n        prefetch()\n      }, [])\n\n      return (\n        <div>\n          {isPrefetched && <div>isPrefetched</div>}\n          <button onClick={() => setEnabled(true)}>setKey</button>\n          <div>data: {query.data}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('isPrefetched')).toBeInTheDocument()\n    fireEvent.click(rendered.getByText('setKey'))\n    expect(rendered.getByText('data: prefetched data')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n    expect(count).toBe(1)\n  })\n\n  it('should support dependent queries via the enable config option', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const [shouldFetch, setShouldFetch] = useState(false)\n\n      const query = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return 'data'\n        },\n        enabled: shouldFetch,\n      })\n\n      return (\n        <div>\n          <div>FetchStatus: {query.fetchStatus}</div>\n          <h2>Data: {query.data || 'no data'}</h2>\n          {shouldFetch ? null : (\n            <button onClick={() => setShouldFetch(true)}>fetch</button>\n          )}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('FetchStatus: idle')).toBeInTheDocument()\n    expect(rendered.getByText('Data: no data')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('fetch'))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('FetchStatus: fetching')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('FetchStatus: idle')).toBeInTheDocument()\n    expect(rendered.getByText('Data: data')).toBeInTheDocument()\n  })\n\n  it('should mark query as fetching, when using initialData', async () => {\n    const key = queryKey()\n    const results: Array<DefinedUseQueryResult<string>> = []\n\n    function Page() {\n      const result = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return 'serverData'\n        },\n        initialData: 'initialData',\n      })\n      results.push(result)\n      return <div>data: {result.data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    rendered.getByText('data: initialData')\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: serverData')\n\n    expect(results.length).toBe(2)\n    expect(results[0]).toMatchObject({ data: 'initialData', isFetching: true })\n    expect(results[1]).toMatchObject({ data: 'serverData', isFetching: false })\n  })\n\n  it('should initialize state properly, when initialData is falsy', async () => {\n    const key = queryKey()\n    const results: Array<DefinedUseQueryResult<number>> = []\n\n    function Page() {\n      const result = useQuery({\n        queryKey: key,\n        queryFn: () => 1,\n        initialData: 0,\n      })\n      results.push(result)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(results.length).toBe(2)\n    expect(results[0]).toMatchObject({ data: 0, isFetching: true })\n    expect(results[1]).toMatchObject({ data: 1, isFetching: false })\n  })\n\n  it('should show the correct data when switching keys with initialData, placeholderData & staleTime', async () => {\n    const key = queryKey()\n\n    const ALL_TODOS = [\n      { name: 'todo A', priority: 'high' },\n      { name: 'todo B', priority: 'medium' },\n    ]\n\n    const initialTodos = ALL_TODOS\n\n    function Page() {\n      const [filter, setFilter] = useState('')\n      const { data: todos } = useQuery({\n        queryKey: [...key, filter],\n        queryFn: () => {\n          return Promise.resolve(\n            ALL_TODOS.filter((todo) =>\n              filter ? todo.priority === filter : true,\n            ),\n          )\n        },\n        initialData() {\n          return filter === '' ? initialTodos : undefined\n        },\n        placeholderData: keepPreviousData,\n        staleTime: 5000,\n      })\n\n      return (\n        <div>\n          Current Todos, filter: {filter || 'all'}\n          <hr />\n          <button onClick={() => setFilter('')}>All</button>\n          <button onClick={() => setFilter('high')}>High</button>\n          <ul>\n            {(todos ?? []).map((todo) => (\n              <li key={todo.name}>\n                {todo.name} - {todo.priority}\n              </li>\n            ))}\n          </ul>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('Current Todos, filter: all')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /high/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(\n      rendered.getByText('Current Todos, filter: high'),\n    ).toBeInTheDocument()\n    fireEvent.click(rendered.getByRole('button', { name: /all/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('todo B - medium')).toBeInTheDocument()\n  })\n\n  // // See https://github.com/tannerlinsley/react-query/issues/214\n  it('data should persist when enabled is changed to false', async () => {\n    const key = queryKey()\n    const results: Array<DefinedUseQueryResult<string>> = []\n\n    function Page() {\n      const [shouldFetch, setShouldFetch] = useState(true)\n\n      const result = useQuery({\n        queryKey: key,\n        queryFn: () => 'fetched data',\n        enabled: shouldFetch,\n        initialData: shouldFetch ? 'initial' : 'initial falsy',\n      })\n\n      results.push(result)\n\n      return (\n        <div>\n          <div>{result.data}</div>\n          <div>{shouldFetch ? 'enabled' : 'disabled'}</div>\n          <button\n            onClick={() => {\n              setShouldFetch(false)\n            }}\n          >\n            enable\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('fetched data')).toBeInTheDocument()\n    expect(rendered.getByText('enabled')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /enable/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('fetched data')).toBeInTheDocument()\n    expect(rendered.getByText('disabled')).toBeInTheDocument()\n\n    expect(results.length).toBe(3)\n    expect(results[0]).toMatchObject({ data: 'initial', isStale: true })\n    expect(results[1]).toMatchObject({ data: 'fetched data', isStale: true })\n    // disabled observers are not stale\n    expect(results[2]).toMatchObject({ data: 'fetched data', isStale: false })\n  })\n\n  it('should support enabled:false in query object syntax', () => {\n    const key = queryKey()\n    const queryFn = vi.fn<(...args: Array<unknown>) => string>()\n    queryFn.mockImplementation(() => 'data')\n\n    function Page() {\n      const { fetchStatus } = useQuery({\n        queryKey: key,\n        queryFn,\n        enabled: false,\n      })\n      return <div>fetchStatus: {fetchStatus}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(queryFn).not.toHaveBeenCalled()\n    expect(queryCache.find({ queryKey: key })).not.toBeUndefined()\n    expect(rendered.getByText('fetchStatus: idle')).toBeInTheDocument()\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/360\n  test('should init to status:pending, fetchStatus:idle when enabled is false', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const query = useQuery({\n        queryKey: key,\n        queryFn: () => 'data',\n        enabled: false,\n      })\n\n      return (\n        <div>\n          <div>\n            status: {query.status}, {query.fetchStatus}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('status: pending, idle')).toBeInTheDocument()\n  })\n\n  test('should not schedule garbage collection, if gcTimeout is set to `Infinity`', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const query = useQuery({\n        queryKey: key,\n        queryFn: () => 'fetched data',\n        gcTime: Infinity,\n      })\n      return <div>{query.data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('fetched data')\n    const setTimeoutSpy = vi.spyOn(globalThis.window, 'setTimeout')\n\n    rendered.unmount()\n\n    expect(setTimeoutSpy).not.toHaveBeenCalled()\n  })\n\n  test('should schedule garbage collection, if gcTimeout is not set to infinity', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const query = useQuery({\n        queryKey: key,\n        queryFn: () => 'fetched data',\n        gcTime: 1000 * 60 * 10, // 10 Minutes\n      })\n      return <div>{query.data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('fetched data')\n\n    const setTimeoutSpy = vi.spyOn(globalThis.window, 'setTimeout')\n\n    rendered.unmount()\n\n    expect(setTimeoutSpy).toHaveBeenLastCalledWith(\n      expect.any(Function),\n      1000 * 60 * 10,\n    )\n  })\n\n  it('should not cause memo churn when data does not change', async () => {\n    const key = queryKey()\n    const queryFn = vi\n      .fn<(...args: Array<unknown>) => string>()\n      .mockReturnValue('data')\n    const memoFn = vi.fn()\n\n    function Page() {\n      const result = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return (\n            queryFn() || {\n              data: {\n                nested: true,\n              },\n            }\n          )\n        },\n      })\n\n      useMemo(() => {\n        memoFn()\n        return result.data\n      }, [result.data])\n\n      return (\n        <div>\n          <div>status {result.status}</div>\n          <div>isFetching {result.isFetching ? 'true' : 'false'}</div>\n          <button onClick={() => result.refetch()}>refetch</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('status pending')\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('status success')\n    fireEvent.click(rendered.getByText('refetch'))\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('isFetching true')\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('isFetching false')\n    expect(queryFn).toHaveBeenCalledTimes(2)\n    expect(memoFn).toHaveBeenCalledTimes(2)\n  })\n\n  it('should update data upon interval changes', async () => {\n    const key = queryKey()\n    let count = 0\n\n    function Page() {\n      const [int, setInt] = useState(200)\n      const { data } = useQuery({\n        queryKey: key,\n        queryFn: () => count++,\n        refetchInterval: int,\n      })\n\n      useEffect(() => {\n        if (data === 2) {\n          setInt(0)\n        }\n      }, [data])\n\n      return <div>count: {data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    // mount\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('count: 0')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(201)\n    expect(rendered.getByText('count: 1')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(201)\n    expect(rendered.getByText('count: 2')).toBeInTheDocument()\n  })\n\n  it('should refetch in an interval depending on function result', async () => {\n    const key = queryKey()\n    let count = 0\n    const states: Array<UseQueryResult<number>> = []\n\n    function Page() {\n      const queryInfo = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return count++\n        },\n        refetchInterval: ({ state: { data = 0 } }) => (data < 2 ? 10 : false),\n      })\n\n      states.push(queryInfo)\n\n      return (\n        <div>\n          <h1>count: {queryInfo.data}</h1>\n          <h2>status: {queryInfo.status}</h2>\n          <h2>data: {queryInfo.data}</h2>\n          <h2>refetch: {queryInfo.isRefetching}</h2>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(51)\n    rendered.getByText('count: 2')\n\n    expect(states.length).toEqual(6)\n\n    expect(states).toMatchObject([\n      {\n        status: 'pending',\n        isFetching: true,\n        data: undefined,\n      },\n      {\n        status: 'success',\n        isFetching: false,\n        data: 0,\n      },\n      {\n        status: 'success',\n        isFetching: true,\n        data: 0,\n      },\n      {\n        status: 'success',\n        isFetching: false,\n        data: 1,\n      },\n      {\n        status: 'success',\n        isFetching: true,\n        data: 1,\n      },\n      {\n        status: 'success',\n        isFetching: false,\n        data: 2,\n      },\n    ])\n  })\n\n  it('should not interval fetch with a refetchInterval of 0', async () => {\n    const key = queryKey()\n    const queryFn = vi.fn(() => 1)\n\n    function Page() {\n      const queryInfo = useQuery({\n        queryKey: key,\n        queryFn,\n        refetchInterval: 0,\n      })\n\n      return <div>count: {queryInfo.data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('count: 1')\n\n    await vi.advanceTimersByTimeAsync(10) // extra sleep to make sure we're not re-fetching\n\n    expect(queryFn).toHaveBeenCalledTimes(1)\n  })\n\n  it('should accept an empty string as query key', async () => {\n    function Page() {\n      const result = useQuery({\n        queryKey: [''],\n        queryFn: (ctx) => ctx.queryKey,\n      })\n      return <>{JSON.stringify(result.data)}</>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('')).toBeInTheDocument()\n  })\n\n  it('should accept an object as query key', async () => {\n    function Page() {\n      const result = useQuery({\n        queryKey: [{ a: 'a' }],\n        queryFn: (ctx) => ctx.queryKey,\n      })\n      return <>{JSON.stringify(result.data)}</>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('[{\"a\":\"a\"}]')).toBeInTheDocument()\n  })\n\n  it('should refetch if any query instance becomes enabled', async () => {\n    const key = queryKey()\n\n    const queryFn = vi\n      .fn<(...args: Array<unknown>) => string>()\n      .mockReturnValue('data')\n\n    function Disabled() {\n      useQuery({ queryKey: key, queryFn, enabled: false })\n      return null\n    }\n\n    function Page() {\n      const [enabled, setEnabled] = useState(false)\n      const result = useQuery({ queryKey: key, queryFn, enabled })\n      return (\n        <>\n          <Disabled />\n          <div>{result.data}</div>\n          <button onClick={() => setEnabled(true)}>enable</button>\n        </>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n    expect(queryFn).toHaveBeenCalledTimes(0)\n    fireEvent.click(rendered.getByText('enable'))\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('data')\n    expect(queryFn).toHaveBeenCalledTimes(1)\n  })\n\n  it('should use placeholder data while the query loads', async () => {\n    const key1 = queryKey()\n\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key1,\n        queryFn: () => 'data',\n        placeholderData: 'placeholder',\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <h2>Data: {state.data}</h2>\n          <div>Status: {state.status}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('Data: data')\n\n    expect(states).toMatchObject([\n      {\n        isSuccess: true,\n        isPlaceholderData: true,\n        data: 'placeholder',\n      },\n      {\n        isSuccess: true,\n        isPlaceholderData: false,\n        data: 'data',\n      },\n    ])\n  })\n\n  it('should use placeholder data even for disabled queries', async () => {\n    const key1 = queryKey()\n\n    const states: Array<{ state: UseQueryResult<string>; count: number }> = []\n\n    function Page() {\n      const [count, setCount] = useState(0)\n\n      const state = useQuery({\n        queryKey: key1,\n        queryFn: () => 'data',\n        placeholderData: 'placeholder',\n        enabled: count === 0,\n      })\n\n      states.push({ state, count })\n\n      useEffect(() => {\n        setCount(1)\n      }, [])\n\n      return (\n        <div>\n          <h2>Data: {state.data}</h2>\n          <div>Status: {state.status}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('Data: data')\n\n    expect(states).toMatchObject([\n      {\n        state: {\n          isSuccess: true,\n          isPlaceholderData: true,\n          data: 'placeholder',\n        },\n        count: 0,\n      },\n      {\n        state: {\n          isSuccess: true,\n          isPlaceholderData: true,\n          data: 'placeholder',\n        },\n        count: 1,\n      },\n      {\n        state: {\n          isSuccess: true,\n          isPlaceholderData: false,\n          data: 'data',\n        },\n        count: 1,\n      },\n    ])\n  })\n\n  it('placeholder data should run through select', async () => {\n    const key1 = queryKey()\n\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key1,\n        queryFn: () => 1,\n        placeholderData: 23,\n        select: (data) => String(data * 2),\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <h2>Data: {state.data}</h2>\n          <div>Status: {state.status}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('Data: 2')\n\n    expect(states).toMatchObject([\n      {\n        isSuccess: true,\n        isPlaceholderData: true,\n        data: '46',\n      },\n      {\n        isSuccess: true,\n        isPlaceholderData: false,\n        data: '2',\n      },\n    ])\n  })\n\n  it('placeholder data function result should run through select', async () => {\n    const key1 = queryKey()\n\n    const states: Array<UseQueryResult<string>> = []\n    let placeholderFunctionRunCount = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key1,\n        queryFn: () => 1,\n        placeholderData: () => {\n          placeholderFunctionRunCount++\n          return 23\n        },\n        select: (data) => String(data * 2),\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <h2>Data: {state.data}</h2>\n          <div>Status: {state.status}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('Data: 2')\n\n    rendered.rerender(<Page />)\n\n    expect(states).toMatchObject([\n      {\n        isSuccess: true,\n        isPlaceholderData: true,\n        data: '46',\n      },\n      {\n        isSuccess: true,\n        isPlaceholderData: false,\n        data: '2',\n      },\n      {\n        isSuccess: true,\n        isPlaceholderData: false,\n        data: '2',\n      },\n    ])\n\n    expect(placeholderFunctionRunCount).toEqual(1)\n  })\n\n  it('select should only run when dependencies change if memoized', async () => {\n    const key1 = queryKey()\n\n    let selectRun = 0\n\n    function Page() {\n      const [count, inc] = useReducer((prev) => prev + 1, 2)\n\n      const state = useQuery({\n        queryKey: key1,\n        queryFn: async () => {\n          await sleep(10)\n          return 0\n        },\n        select: useCallback(\n          (data: number) => {\n            selectRun++\n            return `selected ${data + count}`\n          },\n          [count],\n        ),\n        placeholderData: 99,\n      })\n\n      return (\n        <div>\n          <h2>Data: {state.data}</h2>\n          <button onClick={inc}>inc: {count}</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n    rendered.getByText('Data: selected 101') // 99 + 2\n    expect(selectRun).toBe(1)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('Data: selected 2') // 0 + 2\n    expect(selectRun).toBe(2)\n\n    fireEvent.click(rendered.getByRole('button', { name: /inc/i }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('Data: selected 3') // 0 + 3\n    expect(selectRun).toBe(3)\n  })\n\n  it('select should always return the correct state', async () => {\n    const key1 = queryKey()\n\n    function Page() {\n      const [count, inc] = useReducer((prev) => prev + 1, 2)\n      const [forceValue, forceUpdate] = useReducer((prev) => prev + 1, 1)\n\n      const state = useQuery({\n        queryKey: key1,\n        queryFn: async () => {\n          await sleep(10)\n          return 0\n        },\n\n        select: useCallback(\n          (data: number) => {\n            return `selected ${data + count}`\n          },\n          [count],\n        ),\n        placeholderData: 99,\n      })\n\n      return (\n        <div>\n          <h2>Data: {state.data}</h2>\n          <h2>forceValue: {forceValue}</h2>\n          <button onClick={inc}>inc: {count}</button>\n          <button onClick={forceUpdate}>forceUpdate</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('Data: selected 101')).toBeInTheDocument() // 99 + 2\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Data: selected 2')).toBeInTheDocument() // 0 + 2\n\n    fireEvent.click(rendered.getByRole('button', { name: /inc/i }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Data: selected 3')).toBeInTheDocument() // 0 + 3\n\n    fireEvent.click(rendered.getByRole('button', { name: /forceUpdate/i }))\n\n    expect(rendered.getByText('forceValue: 2')).toBeInTheDocument()\n    // data should still be 3 after an independent re-render\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Data: selected 3')).toBeInTheDocument()\n  })\n\n  it('select should structurally share data', async () => {\n    const key1 = queryKey()\n    const states: Array<Array<number>> = []\n\n    function Page() {\n      const [forceValue, forceUpdate] = useReducer((prev) => prev + 1, 1)\n\n      const state = useQuery({\n        queryKey: key1,\n        queryFn: async () => {\n          await sleep(10)\n          return [1, 2]\n        },\n\n        select: (res) => res.map((x) => x + 1),\n      })\n\n      useEffect(() => {\n        if (state.data) {\n          states.push(state.data)\n        }\n      }, [state.data])\n\n      return (\n        <div>\n          <h2>Data: {JSON.stringify(state.data)}</h2>\n          <h2>forceValue: {forceValue}</h2>\n          <button onClick={forceUpdate}>forceUpdate</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('Data: [2,3]')\n    expect(states).toHaveLength(1)\n\n    fireEvent.click(rendered.getByRole('button', { name: /forceUpdate/i }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('forceValue: 2')\n    rendered.getByText('Data: [2,3]')\n\n    // effect should not be triggered again due to structural sharing\n    expect(states).toHaveLength(1)\n  })\n\n  it('should cancel the query function when there are no more subscriptions', async () => {\n    const key = queryKey()\n    let cancelFn: Mock = vi.fn()\n\n    const queryFn = ({ signal }: { signal?: AbortSignal }) => {\n      const promise = new Promise<string>((resolve, reject) => {\n        cancelFn = vi.fn(() => reject('Cancelled'))\n        signal?.addEventListener('abort', cancelFn)\n        sleep(20).then(() => resolve('OK'))\n      })\n\n      return promise\n    }\n\n    function Page() {\n      const state = useQuery({ queryKey: key, queryFn })\n      return (\n        <div>\n          <h1>Status: {state.status}</h1>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <Blink duration={5}>\n        <Page />\n      </Blink>,\n    )\n\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('off')\n\n    expect(cancelFn).toHaveBeenCalled()\n  })\n\n  it('should cancel the query if the signal was consumed and there are no more subscriptions', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    const queryFn: QueryFunction<string, [typeof key, number]> = async (\n      ctx,\n    ) => {\n      const [, limit] = ctx.queryKey\n      const value = limit % 2 && ctx.signal ? 'abort' : `data ${limit}`\n      await sleep(25)\n      return value\n    }\n\n    function Page(props: { limit: number }) {\n      const state = useQuery({ queryKey: [key, props.limit], queryFn })\n      states[props.limit] = state\n      return (\n        <div>\n          <h1>Status: {state.status}</h1>\n          <h1>data: {state.data}</h1>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <Blink duration={5}>\n        <Page limit={0} />\n        <Page limit={1} />\n        <Page limit={2} />\n        <Page limit={3} />\n      </Blink>,\n    )\n\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('off')\n    await vi.advanceTimersByTimeAsync(20)\n\n    expect(states).toHaveLength(4)\n\n    expect(queryCache.find({ queryKey: [key, 0] })?.state).toMatchObject({\n      data: 'data 0',\n      status: 'success',\n      dataUpdateCount: 1,\n    })\n\n    expect(queryCache.find({ queryKey: [key, 1] })?.state).toMatchObject({\n      data: undefined,\n      status: 'pending',\n      fetchStatus: 'idle',\n    })\n\n    expect(queryCache.find({ queryKey: [key, 2] })?.state).toMatchObject({\n      data: 'data 2',\n      status: 'success',\n      dataUpdateCount: 1,\n    })\n\n    expect(queryCache.find({ queryKey: [key, 3] })?.state).toMatchObject({\n      data: undefined,\n      status: 'pending',\n      fetchStatus: 'idle',\n    })\n  })\n\n  it('should refetch when quickly switching to a failed query', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    const queryFn = async () => {\n      await sleep(50)\n      return 'OK'\n    }\n\n    function Page() {\n      const [id, setId] = useState(1)\n      const [hasChanged, setHasChanged] = useState(false)\n\n      const state = useQuery({ queryKey: [key, id], queryFn })\n\n      states.push(state)\n\n      useEffect(() => {\n        setId((prevId) => (prevId === 1 ? 2 : 1))\n        setHasChanged(true)\n      }, [hasChanged])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(51)\n    expect(states.length).toBe(4)\n    // Load query 1\n    expect(states[0]).toMatchObject({\n      status: 'pending',\n      error: null,\n    })\n    // Load query 2\n    expect(states[1]).toMatchObject({\n      status: 'pending',\n      error: null,\n    })\n    // Load query 1\n    expect(states[2]).toMatchObject({\n      status: 'pending',\n      error: null,\n    })\n    // Loaded query 1\n    expect(states[3]).toMatchObject({\n      status: 'success',\n      error: null,\n    })\n  })\n\n  it('should update query state and refetch when reset with resetQueries', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          return count\n        },\n        staleTime: Infinity,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <button onClick={() => queryClient.resetQueries({ queryKey: key })}>\n            reset\n          </button>\n          <div>data: {state.data ?? 'null'}</div>\n          <div>isFetching: {state.isFetching}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 1')\n    fireEvent.click(rendered.getByRole('button', { name: /reset/i }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(states.length).toBe(4)\n    rendered.getByText('data: 2')\n\n    expect(count).toBe(2)\n\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isPending: true,\n      isFetching: true,\n      isSuccess: false,\n      isStale: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: 1,\n      isPending: false,\n      isFetching: false,\n      isSuccess: true,\n      isStale: false,\n    })\n    expect(states[2]).toMatchObject({\n      data: undefined,\n      isPending: true,\n      isFetching: true,\n      isSuccess: false,\n      isStale: true,\n    })\n    expect(states[3]).toMatchObject({\n      data: 2,\n      isPending: false,\n      isFetching: false,\n      isSuccess: true,\n      isStale: false,\n    })\n  })\n\n  it('should update query state and not refetch when resetting a disabled query with resetQueries', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          return count\n        },\n        staleTime: Infinity,\n        enabled: false,\n        notifyOnChangeProps: 'all',\n      })\n\n      states.push(state)\n\n      const { refetch } = state\n\n      return (\n        <div>\n          <button onClick={() => refetch()}>refetch</button>\n          <button onClick={() => queryClient.resetQueries({ queryKey: key })}>\n            reset\n          </button>\n          <div>data: {state.data ?? 'null'}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    rendered.getByText('data: null')\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 1')\n    fireEvent.click(rendered.getByRole('button', { name: /reset/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('data: null')\n    expect(states.length).toBe(4)\n\n    expect(count).toBe(1)\n\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isPending: true,\n      isFetching: false,\n      isSuccess: false,\n      isStale: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: undefined,\n      isPending: true,\n      isFetching: true,\n      isSuccess: false,\n      isStale: false,\n    })\n    expect(states[2]).toMatchObject({\n      data: 1,\n      isPending: false,\n      isFetching: false,\n      isSuccess: true,\n      isStale: false,\n    })\n    expect(states[3]).toMatchObject({\n      data: undefined,\n      isPending: true,\n      isFetching: false,\n      isSuccess: false,\n      isStale: false,\n    })\n  })\n\n  it('should only call the query hash function once each render', async () => {\n    const key = queryKey()\n\n    let hashes = 0\n    let renders = 0\n\n    function queryKeyHashFn(x: any) {\n      hashes++\n      return JSON.stringify(x)\n    }\n\n    function Page() {\n      useEffect(() => {\n        renders++\n      })\n\n      useQuery({ queryKey: key, queryFn: () => 'test', queryKeyHashFn })\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(renders).toBe(hashes)\n  })\n\n  it('should hash query keys that contain bigints given a supported query hash function', async () => {\n    const key = [queryKey(), 1n]\n\n    function queryKeyHashFn(x: any) {\n      return JSON.stringify(x, (_, value) => {\n        if (typeof value === 'bigint') return value.toString()\n        return value\n      })\n    }\n\n    function Page() {\n      useQuery({ queryKey: key, queryFn: () => 'test', queryKeyHashFn })\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    const query = queryClient.getQueryCache().get(queryKeyHashFn(key))\n    expect(query?.state.data).toBe('test')\n  })\n\n  it('should refetch when changed enabled to true in error state', async () => {\n    const queryFn = vi.fn<(...args: Array<unknown>) => unknown>()\n    queryFn.mockImplementation(async () => {\n      await sleep(10)\n      return Promise.reject(new Error('Suspense Error Bingo'))\n    })\n\n    function Page({ enabled }: { enabled: boolean }) {\n      const { error, isPending } = useQuery({\n        queryKey: ['key'],\n        queryFn,\n        enabled,\n        retry: false,\n        retryOnMount: false,\n        refetchOnMount: false,\n        refetchOnWindowFocus: false,\n      })\n\n      if (isPending) {\n        return <div>status: pending</div>\n      }\n      if (error instanceof Error) {\n        return <div>error</div>\n      }\n      return <div>rendered</div>\n    }\n\n    function App() {\n      const [enabled, toggle] = useReducer((x) => !x, true)\n\n      return (\n        <div>\n          <Page enabled={enabled} />\n          <button aria-label=\"retry\" onClick={toggle}>\n            retry {enabled}\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    // initial state check\n    rendered.getByText('status: pending')\n\n    // // render error state component\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('error')\n    expect(queryFn).toBeCalledTimes(1)\n\n    // change to enabled to false\n    fireEvent.click(rendered.getByLabelText('retry'))\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('error')\n    expect(queryFn).toBeCalledTimes(1)\n\n    // // change to enabled to true\n    fireEvent.click(rendered.getByLabelText('retry'))\n    expect(queryFn).toBeCalledTimes(2)\n  })\n\n  it('should refetch when query key changed when previous status is error', async () => {\n    function Page({ id }: { id: number }) {\n      const { error, isPending } = useQuery({\n        queryKey: [id],\n        queryFn: async () => {\n          await sleep(10)\n          if (id % 2 === 1) {\n            return Promise.reject(new Error('Error'))\n          } else {\n            return 'data'\n          }\n        },\n        retry: false,\n        retryOnMount: false,\n        refetchOnMount: false,\n        refetchOnWindowFocus: false,\n      })\n\n      if (isPending) {\n        return <div>status: pending</div>\n      }\n      if (error instanceof Error) {\n        return <div>error</div>\n      }\n      return <div>rendered</div>\n    }\n\n    function App() {\n      const [id, changeId] = useReducer((x) => x + 1, 1)\n\n      return (\n        <div>\n          <Page id={id} />\n          <button aria-label=\"change\" onClick={changeId}>\n            change {id}\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    // initial state check\n    expect(rendered.getByText('status: pending')).toBeInTheDocument()\n\n    // render error state component\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('error')).toBeInTheDocument()\n\n    // change to unmount query\n    fireEvent.click(rendered.getByLabelText('change'))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n\n    // change to mount new query\n    fireEvent.click(rendered.getByLabelText('change'))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('error')).toBeInTheDocument()\n  })\n\n  it('should refetch when query key changed when switching between erroneous queries', async () => {\n    function Page({ id }: { id: boolean }) {\n      const { error, isFetching } = useQuery({\n        queryKey: [id],\n        queryFn: async () => {\n          await sleep(10)\n          return Promise.reject<unknown>(new Error('Error'))\n        },\n        retry: false,\n        retryOnMount: false,\n        refetchOnMount: false,\n        refetchOnWindowFocus: false,\n      })\n\n      if (isFetching) {\n        return <div>status: fetching</div>\n      }\n      if (error instanceof Error) {\n        return <div>error</div>\n      }\n      return <div>rendered</div>\n    }\n\n    function App() {\n      const [value, toggle] = useReducer((x) => !x, true)\n\n      return (\n        <div>\n          <Page id={value} />\n          <button aria-label=\"change\" onClick={toggle}>\n            change {value}\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    // initial state check\n    expect(rendered.getByText('status: fetching')).toBeInTheDocument()\n\n    // render error state component\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('error')).toBeInTheDocument()\n\n    // change to mount second query\n    fireEvent.click(rendered.getByLabelText('change'))\n    expect(rendered.getByText('status: fetching')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('error')).toBeInTheDocument()\n\n    // change to mount first query again\n    fireEvent.click(rendered.getByLabelText('change'))\n    expect(rendered.getByText('status: fetching')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('error')).toBeInTheDocument()\n  })\n\n  it('should have no error in pending state when refetching after error occurred', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    const error = new Error('oops')\n\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          if (count === 0) {\n            count++\n            throw error\n          }\n          return 5\n        },\n        retry: false,\n      })\n\n      states.push(state)\n\n      if (state.isPending) {\n        return <div>status: pending</div>\n      }\n      if (state.error instanceof Error) {\n        return (\n          <div>\n            <div>error</div>\n            <button onClick={() => state.refetch()}>refetch</button>\n          </div>\n        )\n      }\n      return <div>data: {state.data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('error')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 5')\n\n    expect(states.length).toBe(4)\n\n    expect(states[0]).toMatchObject({\n      status: 'pending',\n      data: undefined,\n      error: null,\n    })\n\n    expect(states[1]).toMatchObject({\n      status: 'error',\n      data: undefined,\n      error,\n    })\n\n    expect(states[2]).toMatchObject({\n      status: 'pending',\n      data: undefined,\n      error: null,\n    })\n\n    expect(states[3]).toMatchObject({\n      status: 'success',\n      data: 5,\n      error: null,\n    })\n  })\n\n  describe('networkMode online', () => {\n    it('online queries should not start fetching if you are offline', async () => {\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const key = queryKey()\n      const states: Array<any> = []\n\n      function Page() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: async () => {\n            await sleep(10)\n            return 'data'\n          },\n        })\n\n        useEffect(() => {\n          states.push(state.fetchStatus)\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, isPaused: {String(state.isPaused)}\n            </div>\n            <div>data: {state.data}</div>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      rendered.getByText('status: pending, isPaused: true')\n\n      onlineMock.mockReturnValue(true)\n      queryClient.getQueryCache().onOnline()\n\n      await vi.advanceTimersByTimeAsync(11)\n      rendered.getByText('status: success, isPaused: false')\n      expect(rendered.getByText('data: data')).toBeInTheDocument()\n\n      expect(states).toEqual(['paused', 'fetching', 'idle'])\n      onlineMock.mockRestore()\n    })\n\n    it('online queries should not refetch if you are offline', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery<string, string>({\n          queryKey: key,\n          queryFn: async () => {\n            count++\n            await sleep(10)\n            return 'data' + count\n          },\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus},\n              failureCount: {state.failureCount}\n            </div>\n            <div>failureReason: {state.failureReason ?? 'null'}</div>\n            <div>data: {state.data}</div>\n            <button\n              onClick={() => queryClient.invalidateQueries({ queryKey: key })}\n            >\n              invalidate\n            </button>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      await vi.advanceTimersByTimeAsync(11)\n      rendered.getByText('data: data1')\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))\n\n      await vi.advanceTimersByTimeAsync(11)\n      rendered.getByText(\n        'status: success, fetchStatus: paused, failureCount: 0',\n      )\n      rendered.getByText('failureReason: null')\n\n      onlineMock.mockReturnValue(true)\n      queryClient.getQueryCache().onOnline()\n\n      await vi.advanceTimersByTimeAsync(0)\n      rendered.getByText(\n        'status: success, fetchStatus: fetching, failureCount: 0',\n      )\n      rendered.getByText('failureReason: null')\n      await vi.advanceTimersByTimeAsync(11)\n      rendered.getByText('status: success, fetchStatus: idle, failureCount: 0')\n      rendered.getByText('failureReason: null')\n\n      expect(rendered.getByText('data: data2')).toBeInTheDocument()\n\n      onlineMock.mockRestore()\n    })\n\n    it('online queries should not refetch if you are offline and refocus', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: async () => {\n            count++\n            await sleep(10)\n            return 'data' + count\n          },\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus}\n            </div>\n            <div>data: {state.data}</div>\n            <button\n              onClick={() => queryClient.invalidateQueries({ queryKey: key })}\n            >\n              invalidate\n            </button>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      await vi.advanceTimersByTimeAsync(11)\n      rendered.getByText('data: data1')\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n      fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))\n\n      await vi.advanceTimersByTimeAsync(0)\n      rendered.getByText('status: success, fetchStatus: paused')\n\n      window.dispatchEvent(new Event('visibilitychange'))\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.queryByText('data: data2')).not.toBeInTheDocument()\n      expect(count).toBe(1)\n      onlineMock.mockRestore()\n    })\n\n    it('online queries should not refetch while already paused', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: async () => {\n            count++\n            await sleep(10)\n            return 'data' + count\n          },\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus}\n            </div>\n            <div>data: {state.data}</div>\n            <button\n              onClick={() => queryClient.invalidateQueries({ queryKey: key })}\n            >\n              invalidate\n            </button>\n          </div>\n        )\n      }\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      await vi.advanceTimersByTimeAsync(0)\n      rendered.getByText('status: pending, fetchStatus: paused')\n\n      fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))\n\n      await vi.advanceTimersByTimeAsync(11)\n      // invalidation should not trigger a refetch\n      rendered.getByText('status: pending, fetchStatus: paused')\n\n      expect(count).toBe(0)\n      onlineMock.mockRestore()\n    })\n\n    it('online queries should not refetch while already paused if data is in the cache', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: async () => {\n            count++\n            await sleep(10)\n            return 'data' + count\n          },\n          initialData: 'initial',\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus}\n            </div>\n            <div>data: {state.data}</div>\n            <button\n              onClick={() => queryClient.invalidateQueries({ queryKey: key })}\n            >\n              invalidate\n            </button>\n          </div>\n        )\n      }\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      rendered.getByText('status: success, fetchStatus: paused')\n      expect(rendered.getByText('data: initial')).toBeInTheDocument()\n\n      fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))\n\n      await vi.advanceTimersByTimeAsync(11)\n\n      // invalidation should not trigger a refetch\n      rendered.getByText('status: success, fetchStatus: paused')\n\n      expect(count).toBe(0)\n      onlineMock.mockRestore()\n    })\n\n    it('online queries should not get stuck in fetching state when pausing multiple times', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: async () => {\n            count++\n            await sleep(10)\n            return 'data' + count\n          },\n          initialData: 'initial',\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus}\n            </div>\n            <div>data: {state.data}</div>\n            <button\n              onClick={() => queryClient.invalidateQueries({ queryKey: key })}\n            >\n              invalidate\n            </button>\n          </div>\n        )\n      }\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      rendered.getByText('status: success, fetchStatus: paused')\n      expect(rendered.getByText('data: initial')).toBeInTheDocument()\n\n      // triggers one pause\n      fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))\n\n      await vi.advanceTimersByTimeAsync(11)\n      rendered.getByText('status: success, fetchStatus: paused')\n\n      // triggers a second pause\n      act(() => {\n        window.dispatchEvent(new Event('visibilitychange'))\n      })\n\n      onlineMock.mockReturnValue(true)\n      queryClient.getQueryCache().onOnline()\n\n      await vi.advanceTimersByTimeAsync(11)\n      rendered.getByText('status: success, fetchStatus: idle')\n      expect(rendered.getByText('data: data1')).toBeInTheDocument()\n\n      expect(count).toBe(1)\n\n      onlineMock.mockRestore()\n    })\n\n    it('online queries should pause retries if you are offline', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery<unknown, Error>({\n          queryKey: key,\n          queryFn: async (): Promise<unknown> => {\n            count++\n            await sleep(10)\n            throw new Error('failed' + count)\n          },\n          retry: 2,\n          retryDelay: 10,\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus},\n              failureCount: {state.failureCount}\n            </div>\n            <div>failureReason: {state.failureReason?.message ?? 'null'}</div>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      rendered.getByText(/status: pending, fetchStatus: fetching/i)\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      await vi.advanceTimersByTimeAsync(31)\n\n      rendered.getByText(\n        'status: pending, fetchStatus: paused, failureCount: 1',\n      )\n      rendered.getByText('failureReason: failed1')\n\n      expect(count).toBe(1)\n\n      onlineMock.mockReturnValue(true)\n      queryClient.getQueryCache().onOnline()\n\n      await vi.advanceTimersByTimeAsync(31)\n      rendered.getByText('status: error, fetchStatus: idle, failureCount: 3')\n      rendered.getByText('failureReason: failed3')\n\n      expect(count).toBe(3)\n\n      onlineMock.mockRestore()\n    })\n\n    it('online queries should not fetch if paused initial load and we go online after unmount', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Component() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: async ({ signal: _signal }) => {\n            count++\n            await sleep(10)\n            return `signal${count}`\n          },\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus}\n            </div>\n            <div>data: {state.data}</div>\n          </div>\n        )\n      }\n\n      function Page() {\n        const [show, setShow] = useState(true)\n\n        return (\n          <div>\n            {show && <Component />}\n            <button onClick={() => setShow(false)}>hide</button>\n          </div>\n        )\n      }\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      rendered.getByText('status: pending, fetchStatus: paused')\n\n      fireEvent.click(rendered.getByRole('button', { name: /hide/i }))\n\n      onlineMock.mockReturnValue(true)\n      queryClient.getQueryCache().onOnline()\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(queryClient.getQueryState(key)).toMatchObject({\n        fetchStatus: 'idle',\n        status: 'pending',\n      })\n\n      expect(count).toBe(0)\n\n      onlineMock.mockRestore()\n    })\n\n    it('online queries should re-fetch if paused and we go online even if already unmounted (because not cancelled)', async () => {\n      const key = queryKey()\n      let count = 0\n\n      queryClient.setQueryData(key, 'initial')\n\n      function Component() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: async () => {\n            count++\n            await sleep(10)\n            return 'data' + count\n          },\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus}\n            </div>\n            <div>data: {state.data}</div>\n          </div>\n        )\n      }\n\n      function Page() {\n        const [show, setShow] = useState(true)\n\n        return (\n          <div>\n            {show && <Component />}\n            <button onClick={() => setShow(false)}>hide</button>\n          </div>\n        )\n      }\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      rendered.getByText('status: success, fetchStatus: paused')\n\n      fireEvent.click(rendered.getByRole('button', { name: /hide/i }))\n\n      onlineMock.mockReturnValue(true)\n      queryClient.getQueryCache().onOnline()\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(queryClient.getQueryState(key)).toMatchObject({\n        fetchStatus: 'idle',\n        status: 'success',\n      })\n\n      expect(count).toBe(1)\n\n      onlineMock.mockRestore()\n    })\n\n    it('online queries should not fetch if paused and we go online when cancelled and no refetchOnReconnect', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: async () => {\n            count++\n            await sleep(10)\n            return 'data' + count\n          },\n          refetchOnReconnect: false,\n        })\n\n        return (\n          <div>\n            <button\n              onClick={() => queryClient.cancelQueries({ queryKey: key })}\n            >\n              cancel\n            </button>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus}\n            </div>\n            <div>data: {state.data}</div>\n          </div>\n        )\n      }\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      rendered.getByText('status: pending, fetchStatus: paused')\n\n      fireEvent.click(rendered.getByRole('button', { name: /cancel/i }))\n\n      await vi.advanceTimersByTimeAsync(11)\n      rendered.getByText('status: pending, fetchStatus: idle')\n\n      expect(count).toBe(0)\n\n      onlineMock.mockReturnValue(true)\n      queryClient.getQueryCache().onOnline()\n\n      await vi.advanceTimersByTimeAsync(11)\n\n      rendered.getByText('status: pending, fetchStatus: idle')\n\n      expect(count).toBe(0)\n\n      onlineMock.mockRestore()\n    })\n\n    it('online queries should fetch if paused and we go online even if already unmounted when refetch was not cancelled', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Component() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: async () => {\n            count++\n            return `data${count}`\n          },\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus}\n            </div>\n            <div>data: {state.data}</div>\n          </div>\n        )\n      }\n\n      function Page() {\n        const [show, setShow] = useState(true)\n\n        return (\n          <div>\n            {show && <Component />}\n            <button onClick={() => setShow(false)}>hide</button>\n            <button\n              onClick={() => queryClient.invalidateQueries({ queryKey: key })}\n            >\n              invalidate\n            </button>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      await vi.advanceTimersByTimeAsync(11)\n      rendered.getByText('status: success, fetchStatus: idle')\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))\n\n      await vi.advanceTimersByTimeAsync(0)\n      rendered.getByText('status: success, fetchStatus: paused')\n\n      fireEvent.click(rendered.getByRole('button', { name: /hide/i }))\n\n      onlineMock.mockReturnValue(true)\n      queryClient.getQueryCache().onOnline()\n\n      await vi.advanceTimersByTimeAsync(11)\n\n      expect(queryClient.getQueryState(key)).toMatchObject({\n        fetchStatus: 'idle',\n        status: 'success',\n      })\n\n      expect(count).toBe(2)\n\n      onlineMock.mockRestore()\n    })\n  })\n\n  describe('networkMode always', () => {\n    it('always queries should start fetching even if you are offline', async () => {\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: async () => {\n            count++\n            await sleep(10)\n            return 'data ' + count\n          },\n          networkMode: 'always',\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, isPaused: {String(state.isPaused)}\n            </div>\n            <div>data: {state.data}</div>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      await vi.advanceTimersByTimeAsync(11)\n      rendered.getByText('status: success, isPaused: false')\n      expect(rendered.getByText('data: data 1')).toBeInTheDocument()\n\n      onlineMock.mockRestore()\n    })\n\n    it('always queries should not pause retries', async () => {\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: async (): Promise<unknown> => {\n            count++\n            await sleep(10)\n            throw new Error('error ' + count)\n          },\n          networkMode: 'always',\n          retry: 1,\n          retryDelay: 5,\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, isPaused: {String(state.isPaused)}\n            </div>\n            <div>\n              error: {state.error instanceof Error && state.error.message}\n            </div>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      await vi.advanceTimersByTimeAsync(26)\n      rendered.getByText('status: error, isPaused: false')\n      expect(rendered.getByText('error: error 2')).toBeInTheDocument()\n\n      expect(count).toBe(2)\n\n      onlineMock.mockRestore()\n    })\n  })\n\n  describe('networkMode offlineFirst', () => {\n    it('offlineFirst queries should start fetching if you are offline, but pause retries', async () => {\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery<unknown, Error>({\n          queryKey: key,\n          queryFn: async (): Promise<unknown> => {\n            count++\n            await sleep(10)\n            throw new Error('failed' + count)\n          },\n          retry: 2,\n          retryDelay: 1,\n          networkMode: 'offlineFirst',\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus},\n              failureCount: {state.failureCount}\n            </div>\n            <div>failureReason: {state.failureReason?.message ?? 'null'}</div>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      await vi.advanceTimersByTimeAsync(12)\n      rendered.getByText(\n        'status: pending, fetchStatus: paused, failureCount: 1',\n      )\n      rendered.getByText('failureReason: failed1')\n\n      expect(count).toBe(1)\n\n      onlineMock.mockReturnValue(true)\n      queryClient.getQueryCache().onOnline()\n\n      await vi.advanceTimersByTimeAsync(22)\n      rendered.getByText('status: error, fetchStatus: idle, failureCount: 3')\n      rendered.getByText('failureReason: failed3')\n\n      expect(count).toBe(3)\n      onlineMock.mockRestore()\n    })\n  })\n\n  describe('subscribed', () => {\n    it('should be able to toggle subscribed', async () => {\n      const key = queryKey()\n      const queryFn = vi.fn(() => Promise.resolve('data'))\n      function Page() {\n        const [subscribed, setSubscribed] = useState(true)\n        const { data } = useQuery({\n          queryKey: key,\n          queryFn,\n          subscribed,\n        })\n        return (\n          <div>\n            <span>data: {data}</span>\n            <button onClick={() => setSubscribed(!subscribed)}>toggle</button>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n      await vi.advanceTimersByTimeAsync(0)\n      rendered.getByText('data: data')\n\n      expect(\n        queryClient.getQueryCache().find({ queryKey: key })!.observers.length,\n      ).toBe(1)\n\n      fireEvent.click(rendered.getByRole('button', { name: 'toggle' }))\n\n      expect(\n        queryClient.getQueryCache().find({ queryKey: key })!.observers.length,\n      ).toBe(0)\n\n      expect(queryFn).toHaveBeenCalledTimes(1)\n\n      fireEvent.click(rendered.getByRole('button', { name: 'toggle' }))\n\n      // background refetch when we re-subscribe\n      await vi.advanceTimersByTimeAsync(0)\n      expect(queryFn).toHaveBeenCalledTimes(2)\n      expect(\n        queryClient.getQueryCache().find({ queryKey: key })!.observers.length,\n      ).toBe(1)\n    })\n\n    it('should not be attached to the query when subscribed is false', async () => {\n      const key = queryKey()\n      const queryFn = vi.fn(() => Promise.resolve('data'))\n      function Page() {\n        const { data } = useQuery({\n          queryKey: key,\n          queryFn,\n          subscribed: false,\n        })\n        return (\n          <div>\n            <span>data: {data}</span>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      await vi.advanceTimersByTimeAsync(0)\n      rendered.getByText('data:')\n\n      expect(\n        queryClient.getQueryCache().find({ queryKey: key })!.observers.length,\n      ).toBe(0)\n\n      expect(queryFn).toHaveBeenCalledTimes(0)\n    })\n\n    it('should not re-render when data is added to the cache when subscribed is false', async () => {\n      const key = queryKey()\n      let renders = 0\n      function Page() {\n        const { data } = useQuery({\n          queryKey: key,\n          queryFn: () => Promise.resolve('data'),\n          subscribed: false,\n        })\n        renders++\n        return (\n          <div>\n            <span>{data ? 'has data' + data : 'no data'}</span>\n            <button\n              onClick={() => queryClient.setQueryData<string>(key, 'new data')}\n            >\n              set data\n            </button>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      await vi.advanceTimersByTimeAsync(0)\n      rendered.getByText('no data')\n\n      fireEvent.click(rendered.getByRole('button', { name: 'set data' }))\n\n      await vi.advanceTimersByTimeAsync(0)\n      rendered.getByText('no data')\n\n      expect(renders).toBe(1)\n    })\n  })\n\n  it('should have status=error on mount when a query has failed', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<unknown>> = []\n    const error = new Error('oops')\n\n    const queryFn = (): Promise<unknown> => {\n      return Promise.reject(error)\n    }\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn,\n        retry: false,\n        retryOnMount: false,\n      })\n\n      states.push(state)\n\n      return <></>\n    }\n\n    await queryClient.prefetchQuery({ queryKey: key, queryFn })\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(states).toHaveLength(1)\n\n    expect(states[0]).toMatchObject({\n      status: 'error',\n      error,\n    })\n  })\n\n  it('setQueryData - should respect updatedAt', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const state = useQuery({ queryKey: key, queryFn: () => 'data' })\n      return (\n        <div>\n          <div>data: {state.data}</div>\n          <div>dataUpdatedAt: {state.dataUpdatedAt}</div>\n          <button\n            onClick={() => {\n              queryClient.setQueryData(key, 'newData', {\n                updatedAt: 100,\n              })\n            }}\n          >\n            setQueryData\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('data: data')\n    fireEvent.click(rendered.getByRole('button', { name: /setQueryData/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('data: newData')\n    expect(rendered.getByText('dataUpdatedAt: 100')).toBeInTheDocument()\n  })\n\n  it('errorUpdateCount should increased on each fetch failure', async () => {\n    const key = queryKey()\n    const error = new Error('oops')\n\n    function Page() {\n      const { refetch, errorUpdateCount } = useQuery({\n        queryKey: key,\n        queryFn: (): Promise<unknown> => {\n          return Promise.reject(error)\n        },\n        retry: false,\n      })\n      return (\n        <div>\n          <button onClick={() => refetch()}>refetch</button>\n          <span>data: {errorUpdateCount}</span>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    const fetchBtn = rendered.getByRole('button', { name: 'refetch' })\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n    fireEvent.click(fetchBtn)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('data: 2')).toBeInTheDocument()\n    fireEvent.click(fetchBtn)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('data: 3')).toBeInTheDocument()\n  })\n\n  it('should use provided custom queryClient', async () => {\n    const key = queryKey()\n    const queryFn = async () => {\n      return Promise.resolve('custom client')\n    }\n\n    function Page() {\n      const { data } = useQuery(\n        {\n          queryKey: key,\n          queryFn,\n        },\n        queryClient,\n      )\n\n      return <div>data: {data}</div>\n    }\n\n    const rendered = render(<Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('data: custom client')).toBeInTheDocument()\n  })\n\n  it('should be notified of updates between create and subscribe', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const { data, status } = useQuery({\n        enabled: false,\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return 5\n        },\n      })\n\n      const mounted = useRef<boolean>(null)\n      // this simulates a synchronous update between the time the query is created\n      // and the time it is subscribed to that could be missed otherwise\n      if (mounted.current === null) {\n        mounted.current = true\n        queryClient.setQueryData(key, 1)\n      }\n\n      return (\n        <div>\n          <span>status: {status}</span>\n          <span>data: {data}</span>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('status: success')).toBeInTheDocument()\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n  })\n  it('should reuse same data object reference when queryKey changes back to some cached data', async () => {\n    const key = queryKey()\n    const spy = vi.fn()\n\n    async function fetchNumber(id: number) {\n      await sleep(5)\n      return { numbers: { current: { id } } }\n    }\n    function Test() {\n      const [id, setId] = useState(1)\n\n      const { data } = useQuery({\n        select: selector,\n        queryKey: [key, 'user', id],\n        queryFn: () => fetchNumber(id),\n      })\n\n      useEffect(() => {\n        spy(data)\n      }, [data])\n\n      return (\n        <div>\n          <button name=\"1\" onClick={() => setId(1)}>\n            1\n          </button>\n          <button name=\"2\" onClick={() => setId(2)}>\n            2\n          </button>\n          <span>Rendered Id: {data?.id}</span>\n        </div>\n      )\n    }\n\n    function selector(data: any) {\n      return data.numbers.current\n    }\n\n    const rendered = renderWithClient(queryClient, <Test />)\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    spy.mockClear()\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('Rendered Id: 1')\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    spy.mockClear()\n    fireEvent.click(rendered.getByRole('button', { name: /2/ }))\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('Rendered Id: 2')\n    expect(spy).toHaveBeenCalledTimes(2) // called with undefined because id changed\n\n    spy.mockClear()\n    fireEvent.click(rendered.getByRole('button', { name: /1/ }))\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('Rendered Id: 1')\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    spy.mockClear()\n    fireEvent.click(rendered.getByRole('button', { name: /2/ }))\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('Rendered Id: 2')\n    expect(spy).toHaveBeenCalledTimes(1)\n  })\n\n  it('should reuse same data object reference when queryKey changes and placeholderData is present', async () => {\n    const key = queryKey()\n    const spy = vi.fn()\n\n    async function fetchNumber(id: number) {\n      await sleep(5)\n      return { numbers: { current: { id } } }\n    }\n    function Test() {\n      const [id, setId] = useState(1)\n\n      const { data } = useQuery({\n        select: selector,\n        queryKey: [key, 'user', id],\n        queryFn: () => fetchNumber(id),\n        placeholderData: { numbers: { current: { id: 99 } } },\n      })\n\n      useEffect(() => {\n        spy(data)\n      }, [data])\n\n      return (\n        <div>\n          <button name=\"1\" onClick={() => setId(1)}>\n            1\n          </button>\n          <button name=\"2\" onClick={() => setId(2)}>\n            2\n          </button>\n          <span>Rendered Id: {data?.id}</span>\n        </div>\n      )\n    }\n\n    function selector(data: any) {\n      return data.numbers.current\n    }\n\n    const rendered = renderWithClient(queryClient, <Test />)\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    spy.mockClear()\n    rendered.getByText('Rendered Id: 99')\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('Rendered Id: 1')\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    spy.mockClear()\n    fireEvent.click(rendered.getByRole('button', { name: /2/ }))\n    rendered.getByText('Rendered Id: 99')\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('Rendered Id: 2')\n    expect(spy).toHaveBeenCalledTimes(2) // called with undefined because id changed\n\n    spy.mockClear()\n    fireEvent.click(rendered.getByRole('button', { name: /1/ }))\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('Rendered Id: 1')\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    spy.mockClear()\n    fireEvent.click(rendered.getByRole('button', { name: /2/ }))\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('Rendered Id: 2')\n    expect(spy).toHaveBeenCalledTimes(1)\n  })\n\n  it('should not cause an infinite render loop when using unstable callback ref', async () => {\n    const key = queryKey()\n\n    function Test() {\n      const [_, setRef] = useState<HTMLDivElement | null>()\n\n      const { data } = useQuery({\n        queryKey: [key],\n        queryFn: async () => {\n          await sleep(5)\n          return 'Works'\n        },\n      })\n\n      return <div ref={(value) => setRef(value)}>{data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Test />)\n\n    await vi.advanceTimersByTimeAsync(6)\n    expect(rendered.getByText('Works')).toBeInTheDocument()\n  })\n\n  it('should keep the previous data when placeholderData is set and cache is used', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number | undefined>> = []\n    const steps = [0, 1, 0, 2]\n\n    function Page() {\n      const [count, setCount] = useState(0)\n\n      const state = useQuery({\n        staleTime: Infinity,\n        queryKey: [key, steps[count]],\n        queryFn: async () => {\n          await sleep(10)\n          return steps[count]\n        },\n        placeholderData: keepPreviousData,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <div>data: {state.data}</div>\n          <button onClick={() => setCount((c) => c + 1)}>setCount</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 0')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 1')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 0')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 2')\n\n    // Initial\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isSuccess: false,\n      isPlaceholderData: false,\n    })\n    // Fetched\n    expect(states[1]).toMatchObject({\n      data: 0,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Set state\n    expect(states[2]).toMatchObject({\n      data: 0,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // New data\n    expect(states[3]).toMatchObject({\n      data: 1,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Set state with existing data\n    expect(states[4]).toMatchObject({\n      data: 0,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Set state where the placeholder value should come from cache request\n    expect(states[5]).toMatchObject({\n      data: 0,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // New data\n    expect(states[6]).toMatchObject({\n      data: 2,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n  })\n\n  // For Project without TS, when migrating from v4 to v5, make sure invalid calls due to bad parameters are tracked.\n  it('should throw in case of bad arguments to enhance DevX', () => {\n    // Mock console error to avoid noise when test is run\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n\n    const key = queryKey()\n    const queryFn = () => 'data'\n\n    function Page() {\n      // Invalid call on purpose\n      // @ts-expect-error\n      useQuery(key, { queryFn })\n      return <div>Does not matter</div>\n    }\n\n    expect(() => render(<Page />)).toThrow('Bad argument type')\n    consoleMock.mockRestore()\n  })\n\n  it('should respect skipToken and refetch when skipToken is taken away', async () => {\n    const key = queryKey()\n\n    function Page({ enabled }: { enabled: boolean }) {\n      const { data, status } = useQuery({\n        queryKey: [key],\n        queryFn: enabled\n          ? async () => {\n              await sleep(10)\n\n              return Promise.resolve('data')\n            }\n          : skipToken,\n        retry: false,\n        retryOnMount: false,\n        refetchOnMount: false,\n        refetchOnWindowFocus: false,\n      })\n\n      return (\n        <div>\n          <div>status: {status}</div>\n          <div>data: {String(data)}</div>\n        </div>\n      )\n    }\n\n    function App() {\n      const [enabled, toggle] = useReducer((x) => !x, false)\n\n      return (\n        <div>\n          <Page enabled={enabled} />\n          <button onClick={toggle}>enable</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    expect(rendered.getByText('status: pending')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: 'enable' }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('status: success')).toBeInTheDocument()\n    expect(rendered.getByText('data: data')).toBeInTheDocument()\n  })\n\n  it('should allow enabled: true and queryFn: skipToken', () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    function App() {\n      const query = useQuery({\n        queryKey: key,\n        queryFn: skipToken,\n        enabled: true,\n      })\n\n      return (\n        <div>\n          <div>\n            status: {query.status}, fetchStatus: {query.fetchStatus}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    rendered.getByText('status: pending, fetchStatus: idle')\n\n    // no warnings expected about skipToken / missing queryFn\n    expect(consoleMock).toHaveBeenCalledTimes(0)\n    consoleMock.mockRestore()\n  })\n\n  it('should return correct optimistic result when fetching after error', async () => {\n    const key = queryKey()\n    const error = new Error('oh no')\n\n    const results: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const query = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return Promise.reject(error)\n        },\n        retry: false,\n        notifyOnChangeProps: 'all',\n      })\n\n      results.push(query)\n\n      return (\n        <div>\n          <div>\n            status: {query.status}, {query.fetchStatus}\n          </div>\n          <div>error: {query.error?.message}</div>\n        </div>\n      )\n    }\n\n    function App() {\n      const [enabled, setEnabled] = useState(true)\n\n      return (\n        <div>\n          <button onClick={() => setEnabled(!enabled)}>toggle</button>\n          {enabled && <Page />}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('status: error, idle')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'toggle' }))\n    fireEvent.click(rendered.getByRole('button', { name: 'toggle' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('status: error, idle')\n\n    expect(results).toHaveLength(4)\n\n    // initial fetch\n    expect(results[0]).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'fetching',\n      error: null,\n      errorUpdatedAt: 0,\n      errorUpdateCount: 0,\n      isLoading: true,\n      failureCount: 0,\n      failureReason: null,\n    })\n\n    // error state\n    expect(results[1]).toMatchObject({\n      status: 'error',\n      fetchStatus: 'idle',\n      error,\n      errorUpdateCount: 1,\n      isLoading: false,\n      failureCount: 1,\n      failureReason: error,\n    })\n    expect(results[1]?.errorUpdatedAt).toBeGreaterThan(0)\n\n    // refetch, optimistic state, no errors anymore\n    expect(results[2]).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'fetching',\n      error: null,\n      errorUpdateCount: 1,\n      isLoading: true,\n      failureCount: 0,\n      failureReason: null,\n    })\n    expect(results[2]?.errorUpdatedAt).toBeGreaterThan(0)\n\n    // final state\n    expect(results[3]).toMatchObject({\n      status: 'error',\n      fetchStatus: 'idle',\n      error: error,\n      errorUpdateCount: 2,\n      isLoading: false,\n      failureCount: 1,\n      failureReason: error,\n    })\n    expect(results[3]?.errorUpdatedAt).toBeGreaterThan(0)\n  })\n\n  it('should pick up an initialPromise', async () => {\n    const key = queryKey()\n\n    const serverQueryClient = new QueryClient({\n      defaultOptions: { dehydrate: { shouldDehydrateQuery: () => true } },\n    })\n\n    void serverQueryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: async () => {\n        await sleep(10)\n        return Promise.resolve('server')\n      },\n    })\n\n    const dehydrated = dehydrate(serverQueryClient)\n\n    let count = 0\n\n    function Page() {\n      const query = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          count++\n          await sleep(10)\n          return Promise.resolve('client')\n        },\n      })\n\n      return (\n        <div>\n          <div>data: {query.data}</div>\n          <button onClick={() => query.refetch()}>refetch</button>\n        </div>\n      )\n    }\n\n    const clientQueryClient = new QueryClient()\n    hydrate(clientQueryClient, dehydrated)\n\n    const rendered = renderWithClient(clientQueryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: server')\n    expect(count).toBe(0)\n\n    fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: client')\n    expect(count).toBe(1)\n  })\n\n  it('should retry failed initialPromise on the client', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    const serverQueryClient = new QueryClient({\n      defaultOptions: {\n        dehydrate: { shouldDehydrateQuery: () => true },\n      },\n    })\n\n    void serverQueryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: async () => {\n        await sleep(10)\n        return Promise.reject(new Error('server error'))\n      },\n    })\n\n    const dehydrated = dehydrate(serverQueryClient)\n\n    let count = 0\n\n    function Page() {\n      const query = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          count++\n          await sleep(10)\n          return Promise.resolve('client')\n        },\n      })\n\n      return (\n        <div>\n          <div>failure: {query.failureReason?.message}</div>\n          <div>data: {query.data}</div>\n        </div>\n      )\n    }\n\n    const clientQueryClient = new QueryClient({\n      defaultOptions: { hydrate: { queries: { retry: 1, retryDelay: 10 } } },\n    })\n    hydrate(clientQueryClient, dehydrated)\n\n    const rendered = renderWithClient(clientQueryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('failure: redacted')\n    await vi.advanceTimersByTimeAsync(21)\n    rendered.getByText('data: client')\n    expect(count).toBe(1)\n\n    const query = clientQueryClient.getQueryCache().find({ queryKey: key })\n\n    expect(consoleMock).toHaveBeenCalledTimes(1)\n    expect(consoleMock).toHaveBeenCalledWith(\n      `A query that was dehydrated as pending ended up rejecting. [${query?.queryHash}]: Error: server error; The error will be redacted in production builds`,\n    )\n\n    consoleMock.mockRestore()\n  })\n\n  it('should console.error when there is no queryFn', () => {\n    const consoleErrorMock = vi.spyOn(console, 'error')\n    const key = queryKey()\n    function Example() {\n      useQuery({ queryKey: key })\n      return <></>\n    }\n    renderWithClient(queryClient, <Example />)\n\n    expect(consoleErrorMock).toHaveBeenCalledTimes(1)\n    expect(consoleErrorMock).toHaveBeenCalledWith(\n      `[${queryClient.getQueryCache().find({ queryKey: key })?.queryHash}]: No queryFn was passed as an option, and no default queryFn was found. The queryFn parameter is only optional when using a default queryFn. More info here: https://tanstack.com/query/latest/docs/framework/react/guides/default-query-function`,\n    )\n\n    consoleErrorMock.mockRestore()\n  })\n\n  it('should not fetch for the duration of the restoring period when isRestoring is true', async () => {\n    const key = queryKey()\n    const queryFn = vi\n      .fn()\n      .mockImplementation(() => sleep(10).then(() => 'data'))\n\n    function Page() {\n      const result = useQuery({\n        queryKey: key,\n        queryFn,\n      })\n\n      return (\n        <div>\n          <div data-testid=\"status\">{result.status}</div>\n          <div data-testid=\"fetchStatus\">{result.fetchStatus}</div>\n          <div data-testid=\"data\">{result.data ?? 'undefined'}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <IsRestoringProvider value={true}>\n        <Page />\n      </IsRestoringProvider>,\n    )\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(rendered.getByTestId('status')).toHaveTextContent('pending')\n    expect(rendered.getByTestId('fetchStatus')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('data')).toHaveTextContent('undefined')\n    expect(queryFn).toHaveBeenCalledTimes(0)\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(rendered.getByTestId('status')).toHaveTextContent('pending')\n    expect(rendered.getByTestId('fetchStatus')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('data')).toHaveTextContent('undefined')\n    expect(queryFn).toHaveBeenCalledTimes(0)\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/useSuspenseInfiniteQuery.test-d.tsx",
    "content": "import { skipToken } from '@tanstack/query-core'\nimport type { InfiniteData } from '@tanstack/query-core'\nimport { assertType, describe, expectTypeOf, it } from 'vitest'\n\nimport { useSuspenseInfiniteQuery } from '../useSuspenseInfiniteQuery'\n\ndescribe('useSuspenseInfiniteQuery', () => {\n  it('should always have data defined', () => {\n    const { data } = useSuspenseInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n      initialPageParam: 1,\n      getNextPageParam: () => 1,\n    })\n\n    expectTypeOf(data).toEqualTypeOf<InfiniteData<number, unknown>>()\n  })\n\n  it('should not allow skipToken in queryFn', () => {\n    assertType(\n      useSuspenseInfiniteQuery({\n        queryKey: ['key'],\n        // @ts-expect-error\n        queryFn: skipToken,\n      }),\n    )\n\n    assertType(\n      useSuspenseInfiniteQuery({\n        queryKey: ['key'],\n        // @ts-expect-error\n        queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),\n      }),\n    )\n  })\n\n  it('should not have pending status', () => {\n    const { status } = useSuspenseInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n      initialPageParam: 1,\n      getNextPageParam: () => 1,\n    })\n\n    expectTypeOf(status).toEqualTypeOf<'error' | 'success'>()\n  })\n\n  it('should not allow placeholderData, enabled or throwOnError props', () => {\n    assertType(\n      useSuspenseInfiniteQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        initialPageParam: 1,\n        getNextPageParam: () => 1,\n        // @ts-expect-error TS2345\n        placeholderData: 5,\n        enabled: true,\n      }),\n    )\n\n    assertType(\n      useSuspenseInfiniteQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        initialPageParam: 1,\n        getNextPageParam: () => 1,\n        // @ts-expect-error TS2345\n        enabled: true,\n      }),\n    )\n\n    assertType(\n      useSuspenseInfiniteQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        initialPageParam: 1,\n        getNextPageParam: () => 1,\n        // @ts-expect-error TS2345\n        throwOnError: true,\n      }),\n    )\n  })\n\n  it('should not return isPlaceholderData', () => {\n    const query = useSuspenseInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n      initialPageParam: 1,\n      getNextPageParam: () => 1,\n    })\n\n    expectTypeOf(query).not.toHaveProperty('isPlaceholderData')\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/useSuspenseInfiniteQuery.test.tsx",
    "content": "import { queryKey } from '@tanstack/query-test-utils'\nimport { Suspense } from 'preact/compat'\nimport { describe, expect, it, vi } from 'vitest'\n\nimport {\n  QueryCache,\n  QueryClient,\n  skipToken,\n  useSuspenseInfiniteQuery,\n} from '..'\nimport { renderWithClient } from './utils'\n\ndescribe('useSuspenseInfiniteQuery', () => {\n  const queryCache = new QueryCache()\n  const queryClient = new QueryClient({ queryCache })\n\n  it('should log an error when skipToken is passed as queryFn', () => {\n    const consoleErrorSpy = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => {})\n    const key = queryKey()\n\n    function Page() {\n      useSuspenseInfiniteQuery({\n        queryKey: key,\n        initialPageParam: 1,\n        getNextPageParam: () => 1,\n        // @ts-expect-error\n        queryFn: Math.random() >= 0 ? skipToken : () => Promise.resolve(5),\n      })\n\n      return null\n    }\n\n    function App() {\n      return (\n        <Suspense fallback=\"Loading...\">\n          <Page />\n        </Suspense>\n      )\n    }\n\n    renderWithClient(queryClient, <App />)\n\n    expect(consoleErrorSpy).toHaveBeenCalledWith(\n      'skipToken is not allowed for useSuspenseInfiniteQuery',\n    )\n    consoleErrorSpy.mockRestore()\n  })\n\n  it('should log an error when skipToken is used in development environment', () => {\n    const envCopy = process.env.NODE_ENV\n    process.env.NODE_ENV = 'development'\n\n    const consoleErrorSpy = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    function Page() {\n      useSuspenseInfiniteQuery({\n        queryKey: key,\n        queryFn: skipToken as any,\n        initialPageParam: 1,\n        getNextPageParam: () => 1,\n      })\n\n      return null\n    }\n\n    renderWithClient(\n      queryClient,\n      <Suspense fallback=\"Loading...\">\n        <Page />\n      </Suspense>,\n    )\n\n    expect(consoleErrorSpy).toHaveBeenCalledWith(\n      'skipToken is not allowed for useSuspenseInfiniteQuery',\n    )\n\n    consoleErrorSpy.mockRestore()\n    process.env.NODE_ENV = envCopy\n  })\n\n  it('should not log an error when skipToken is used in production environment', () => {\n    const envCopy = process.env.NODE_ENV\n    process.env.NODE_ENV = 'production'\n\n    const consoleErrorSpy = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    function Page() {\n      useSuspenseInfiniteQuery({\n        queryKey: key,\n        queryFn: skipToken as any,\n        initialPageParam: 1,\n        getNextPageParam: () => 1,\n      })\n\n      return null\n    }\n\n    renderWithClient(\n      queryClient,\n      <Suspense fallback=\"Loading...\">\n        <Page />\n      </Suspense>,\n    )\n\n    expect(consoleErrorSpy).not.toHaveBeenCalled()\n\n    consoleErrorSpy.mockRestore()\n    process.env.NODE_ENV = envCopy\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/useSuspenseQueries.test-d.tsx",
    "content": "import { assertType, describe, expectTypeOf, it } from 'vitest'\n\nimport { skipToken, useSuspenseQueries } from '..'\nimport type { OmitKeyof } from '..'\nimport { queryOptions } from '../queryOptions'\nimport type { UseQueryOptions, UseSuspenseQueryResult } from '../types'\n\ndescribe('UseSuspenseQueries config object overload', () => {\n  it('TData should always be defined', () => {\n    const query1 = {\n      queryKey: ['key1'],\n      queryFn: () => {\n        return {\n          wow: true,\n        }\n      },\n      initialData: {\n        wow: false,\n      },\n    }\n\n    const query2 = {\n      queryKey: ['key2'],\n      queryFn: () => 'Query Data',\n    }\n\n    const queryResults = useSuspenseQueries({ queries: [query1, query2] })\n\n    const query1Data = queryResults[0].data\n    const query2Data = queryResults[1].data\n\n    expectTypeOf(query1Data).toEqualTypeOf<{ wow: boolean }>()\n    expectTypeOf(query2Data).toEqualTypeOf<string>()\n  })\n\n  it('TData should be defined when passed through queryOptions', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => {\n        return {\n          wow: true,\n        }\n      },\n    })\n    const queryResults = useSuspenseQueries({ queries: [options] })\n\n    const data = queryResults[0].data\n\n    expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n  })\n\n  it('should be possible to define a different TData than TQueryFnData using select with queryOptions spread into useQuery', () => {\n    const query1 = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(1),\n      select: (data) => data > 1,\n    })\n\n    const query2 = {\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(1),\n      select: (data: number) => data > 1,\n    }\n\n    const queryResults = useSuspenseQueries({ queries: [query1, query2] })\n    const query1Data = queryResults[0].data\n    const query2Data = queryResults[1].data\n\n    expectTypeOf(query1Data).toEqualTypeOf<boolean>()\n    expectTypeOf(query2Data).toEqualTypeOf<boolean>()\n  })\n\n  it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => {\n    const queryResults = useSuspenseQueries({\n      queries: [\n        {\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n          initialData: () => undefined as { wow: boolean } | undefined,\n        },\n      ],\n    })\n\n    const data = queryResults[0].data\n\n    expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n  })\n\n  it('should not allow skipToken in queryFn', () => {\n    assertType(\n      useSuspenseQueries({\n        queries: [\n          {\n            queryKey: ['key'],\n            // @ts-expect-error\n            queryFn: skipToken,\n          },\n        ],\n      }),\n    )\n\n    assertType(\n      useSuspenseQueries({\n        queries: [\n          {\n            queryKey: ['key'],\n            // @ts-expect-error\n            queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),\n          },\n        ],\n      }),\n    )\n  })\n\n  it('TData should have correct type when conditional skipToken is passed', () => {\n    const queryResults = useSuspenseQueries({\n      queries: [\n        {\n          queryKey: ['withSkipToken'],\n          // @ts-expect-error\n          queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),\n        },\n      ],\n    })\n\n    const firstResult = queryResults[0]\n\n    expectTypeOf(firstResult).toEqualTypeOf<\n      UseSuspenseQueryResult<number, Error>\n    >()\n    expectTypeOf(firstResult.data).toEqualTypeOf<number>()\n  })\n\n  describe('custom hook', () => {\n    it('should allow custom hooks using UseQueryOptions', () => {\n      type Data = string\n\n      const useCustomQueries = (\n        options?: OmitKeyof<UseQueryOptions<Data>, 'queryKey' | 'queryFn'>,\n      ) => {\n        return useSuspenseQueries({\n          queries: [\n            {\n              ...options,\n              queryKey: ['todos-key'],\n              queryFn: () => Promise.resolve('data'),\n            },\n          ],\n        })\n      }\n\n      const queryResults = useCustomQueries()\n      const data = queryResults[0].data\n\n      expectTypeOf(data).toEqualTypeOf<Data>()\n    })\n  })\n\n  it('should return correct data for dynamic queries with mixed result types', () => {\n    const Queries1 = {\n      get: () =>\n        queryOptions({\n          queryKey: ['key1'],\n          queryFn: () => Promise.resolve(1),\n        }),\n    }\n    const Queries2 = {\n      get: () =>\n        queryOptions({\n          queryKey: ['key2'],\n          queryFn: () => Promise.resolve(true),\n        }),\n    }\n\n    const queries1List = [1, 2, 3].map(() => ({ ...Queries1.get() }))\n    const result = useSuspenseQueries({\n      queries: [\n        ...queries1List,\n        {\n          ...Queries2.get(),\n          select(data: boolean) {\n            return data\n          },\n        },\n      ],\n    })\n\n    expectTypeOf(result).toEqualTypeOf<\n      [\n        ...Array<UseSuspenseQueryResult<number, Error>>,\n        UseSuspenseQueryResult<boolean, Error>,\n      ]\n    >()\n  })\n\n  it('queryOptions with initialData works on useSuspenseQueries', () => {\n    const query1 = queryOptions({\n      queryKey: ['key1'],\n      queryFn: () => 'Query Data',\n      initialData: 'initial data',\n    })\n\n    const queryResults = useSuspenseQueries({ queries: [query1] })\n    const query1Data = queryResults[0].data\n\n    expectTypeOf(query1Data).toEqualTypeOf<string>()\n  })\n\n  it('queryOptions with skipToken in queryFn should not work on useSuspenseQueries', () => {\n    assertType(\n      useSuspenseQueries({\n        queries: [\n          // @ts-expect-error\n          queryOptions({\n            queryKey: ['key1'],\n            queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),\n          }),\n        ],\n      }),\n    )\n\n    assertType(\n      useSuspenseQueries({\n        queries: [\n          // @ts-expect-error\n          queryOptions({\n            queryKey: ['key1'],\n            queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),\n            initialData: 5,\n          }),\n        ],\n      }),\n    )\n  })\n\n  it('should not show type error when using rest queryOptions', () => {\n    assertType(\n      useSuspenseQueries({\n        queries: [\n          {\n            ...queryOptions({\n              queryKey: ['key1'],\n              queryFn: () => 'Query Data',\n            }),\n            select(data: string) {\n              return data\n            },\n          },\n        ],\n      }),\n    )\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/useSuspenseQueries.test.tsx",
    "content": "import { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { act, fireEvent, render } from '@testing-library/preact'\nimport type { FunctionalComponent } from 'preact'\nimport { Suspense, startTransition, useTransition } from 'preact/compat'\nimport { useEffect, useRef, useState } from 'preact/hooks'\nimport {\n  afterAll,\n  afterEach,\n  beforeAll,\n  beforeEach,\n  describe,\n  expect,\n  it,\n  vi,\n} from 'vitest'\n\nimport {\n  QueryClient,\n  skipToken,\n  useSuspenseQueries,\n  useSuspenseQuery,\n} from '..'\nimport type { UseSuspenseQueryOptions } from '..'\nimport { ErrorBoundary } from './ErrorBoundary'\nimport { renderWithClient } from './utils'\n\ntype NumberQueryOptions = UseSuspenseQueryOptions<number>\n\nconst QUERY_DURATION = 1000\n\nconst createQuery: (id: number) => NumberQueryOptions = (id) => ({\n  queryKey: [id],\n  queryFn: () => sleep(QUERY_DURATION).then(() => id),\n})\nconst resolveQueries = async () => {\n  await vi.advanceTimersByTimeAsync(QUERY_DURATION)\n}\n\nconst queryClient = new QueryClient()\n\ndescribe('useSuspenseQueries', () => {\n  const onSuspend = vi.fn()\n  const onQueriesResolution = vi.fn()\n\n  beforeAll(() => {\n    vi.useFakeTimers()\n  })\n\n  afterAll(() => {\n    vi.useRealTimers()\n  })\n\n  afterEach(() => {\n    queryClient.clear()\n    onSuspend.mockClear()\n    onQueriesResolution.mockClear()\n  })\n\n  function SuspenseFallback() {\n    useEffect(() => {\n      onSuspend()\n    }, [])\n\n    return <div>loading</div>\n  }\n\n  const withSuspenseWrapper = <T extends object>(\n    Component: FunctionalComponent<T>,\n  ) => {\n    function SuspendedComponent(props: T) {\n      return (\n        <Suspense fallback={<SuspenseFallback />}>\n          <Component {...props} />\n        </Suspense>\n      )\n    }\n\n    return SuspendedComponent\n  }\n\n  function QueriesContainer({\n    queries,\n  }: {\n    queries: Array<NumberQueryOptions>\n  }) {\n    const queriesResults = useSuspenseQueries(\n      { queries, combine: (results) => results.map((r) => r.data) },\n      queryClient,\n    )\n\n    useEffect(() => {\n      onQueriesResolution(queriesResults)\n    }, [queriesResults])\n\n    return null\n  }\n\n  const TestComponent = withSuspenseWrapper(QueriesContainer)\n\n  it('should suspend on mount', () => {\n    render(<TestComponent queries={[1, 2].map(createQuery)} />)\n\n    expect(onSuspend).toHaveBeenCalledOnce()\n  })\n\n  it('should resolve queries', async () => {\n    render(<TestComponent queries={[1, 2].map(createQuery)} />)\n\n    await act(resolveQueries)\n\n    expect(onQueriesResolution).toHaveBeenCalledTimes(1)\n    expect(onQueriesResolution).toHaveBeenLastCalledWith([1, 2])\n  })\n\n  it('should not suspend on mount if query has been already fetched', () => {\n    const query = createQuery(1)\n\n    queryClient.setQueryData(query.queryKey, query.queryFn)\n\n    render(<TestComponent queries={[query]} />)\n\n    expect(onSuspend).not.toHaveBeenCalled()\n  })\n\n  it('should not break suspense when queries change without resolving', async () => {\n    const initQueries = [1, 2].map(createQuery)\n    const nextQueries = [3, 4, 5, 6].map(createQuery)\n\n    const { rerender } = render(<TestComponent queries={initQueries} />)\n\n    rerender(<TestComponent queries={nextQueries} />)\n\n    await act(resolveQueries)\n\n    expect(onSuspend).toHaveBeenCalled()\n    // the test for onQueriesResolution is React-specific and not applicable to Preact\n  })\n\n  it('should suspend only once per queries change', async () => {\n    const initQueries = [1, 2].map(createQuery)\n    const nextQueries = [3, 4, 5, 6].map(createQuery)\n\n    const { rerender } = render(<TestComponent queries={initQueries} />)\n\n    await act(resolveQueries)\n\n    rerender(<TestComponent queries={nextQueries} />)\n\n    await act(resolveQueries)\n\n    expect(onSuspend).toHaveBeenCalledTimes(2)\n    expect(onQueriesResolution).toHaveBeenCalledTimes(2)\n    expect(onQueriesResolution).toHaveBeenLastCalledWith([3, 4, 5, 6])\n  })\n\n  it('should only call combine after resolving', async () => {\n    const spy = vi.fn()\n    const key = queryKey()\n\n    function Page() {\n      const data = useSuspenseQueries({\n        queries: [1, 2, 3].map((value) => ({\n          queryKey: [...key, { value }],\n          queryFn: () => sleep(value * 10).then(() => ({ value: value * 10 })),\n        })),\n        combine: (result) => {\n          spy(result)\n          return 'data'\n        },\n      })\n\n      return <h1>{data}</h1>\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <Suspense fallback=\"loading\">\n        <Page />\n      </Suspense>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n\n    expect(spy).not.toHaveBeenCalled()\n\n    await vi.advanceTimersByTimeAsync(30)\n    expect(rendered.getByText('data')).toBeInTheDocument()\n\n    expect(spy).toHaveBeenCalled()\n  })\n\n  it('should handle duplicate query keys without infinite loops', async () => {\n    const key = queryKey()\n    const localDuration = 10\n    let renderCount = 0\n\n    function getUserData() {\n      return {\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(localDuration)\n          return { name: 'John Doe', age: 50 }\n        },\n      }\n    }\n\n    function getName() {\n      return {\n        ...getUserData(),\n        select: (data: any) => data.name,\n      }\n    }\n\n    function getAge() {\n      return {\n        ...getUserData(),\n        select: (data: any) => data.age,\n      }\n    }\n\n    function App() {\n      renderCount++\n      const [{ data }, { data: data2 }] = useSuspenseQueries({\n        queries: [getName(), getAge()],\n      })\n\n      useEffect(() => {\n        onQueriesResolution({ data, data2 })\n      }, [data, data2])\n\n      return (\n        <div>\n          <h1>Data</h1>\n          {JSON.stringify({ data }, null, 2)}\n          {JSON.stringify({ data2 }, null, 2)}\n        </div>\n      )\n    }\n\n    renderWithClient(\n      queryClient,\n      <Suspense fallback={<SuspenseFallback />}>\n        <App />\n      </Suspense>,\n    )\n\n    await vi.advanceTimersByTimeAsync(localDuration)\n\n    expect(onSuspend).toHaveBeenCalled()\n\n    await vi.advanceTimersByTimeAsync(100)\n\n    expect(onQueriesResolution).toHaveBeenCalledTimes(1)\n    expect(onQueriesResolution).toHaveBeenLastCalledWith({\n      data: 'John Doe',\n      data2: 50,\n    })\n\n    // With the infinite loop bug, renderCount would be very high (e.g. > 100)\n    // Without bug, it should be small (initial suspend + resolution = 2-3)\n    expect(renderCount).toBeLessThan(10)\n  })\n})\n\ndescribe('useSuspenseQueries 2', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should suspend all queries in parallel', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const results: Array<string> = []\n\n    function Fallback() {\n      results.push('loading')\n      return <div>loading</div>\n    }\n\n    function Page() {\n      const result = useSuspenseQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () =>\n              sleep(10).then(() => {\n                results.push('1')\n                return '1'\n              }),\n          },\n          {\n            queryKey: key2,\n            queryFn: () =>\n              sleep(20).then(() => {\n                results.push('2')\n                return '2'\n              }),\n          },\n        ],\n      })\n\n      return (\n        <div>\n          <h1>data: {result.map((item) => item.data ?? 'null').join(',')}</h1>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <Suspense fallback={<Fallback />}>\n        <Page />\n      </Suspense>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(20)\n    expect(rendered.getByText('data: 1,2')).toBeInTheDocument()\n\n    expect(results).toEqual(['loading', '1', '2'])\n  })\n\n  it(\"shouldn't unmount before all promises fetched\", async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const results: Array<string> = []\n    const refs: Array<number> = []\n\n    function Fallback() {\n      results.push('loading')\n      return <div>loading</div>\n    }\n\n    function Page() {\n      const ref = useRef(Math.random())\n      const result = useSuspenseQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () =>\n              sleep(10).then(() => {\n                refs.push(ref.current)\n                results.push('1')\n                return '1'\n              }),\n          },\n          {\n            queryKey: key2,\n            queryFn: () =>\n              sleep(20).then(() => {\n                refs.push(ref.current)\n                results.push('2')\n                return '2'\n              }),\n          },\n        ],\n      })\n\n      return (\n        <div>\n          <h1>data: {result.map((item) => item.data ?? 'null').join(',')}</h1>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <Suspense fallback={<Fallback />}>\n        <Page />\n      </Suspense>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n\n    await vi.advanceTimersByTimeAsync(20)\n    expect(rendered.getByText('data: 1,2')).toBeInTheDocument()\n\n    expect(refs.length).toBe(2)\n    expect(refs[0]).toBe(refs[1])\n  })\n\n  // this addresses the following issue:\n  // https://github.com/TanStack/query/issues/6344\n  it('should suspend on offline when query changes, and data should not be undefined', async () => {\n    function Page({ id }: { id: number }) {\n      const { data } = useSuspenseQuery({\n        queryKey: [id],\n        queryFn: () => sleep(10).then(() => `Data ${id}`),\n      })\n\n      // defensive guard here\n      if (data === undefined) {\n        throw new Error('data cannot be undefined')\n      }\n\n      return <div>{data}</div>\n    }\n\n    function TestApp() {\n      const [id, setId] = useState(0)\n\n      return (\n        <>\n          <button onClick={() => setId((prev) => prev + 1)}>fetch</button>\n          <Suspense fallback={<div>loading</div>}>\n            <Page id={id} />\n          </Suspense>\n        </>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <TestApp />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(async () => {\n      await vi.advanceTimersByTimeAsync(10)\n    })\n    expect(rendered.getByText('Data 0')).toBeInTheDocument()\n\n    // go offline\n    document.dispatchEvent(new CustomEvent('offline'))\n\n    fireEvent.click(rendered.getByText('fetch'))\n    // Preact unmounts the new state variable at the Suspense Boundary\n    // You will not have the old data once a key changes offline\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n\n    // go back online\n    document.dispatchEvent(new CustomEvent('online'))\n\n    // Some assertions removed to account for the synchronous execution\n    await act(async () => {\n      await vi.advanceTimersByTimeAsync(10)\n    })\n    // query should resume\n    // Preact unmounts the new state variable at the Suspense Boundary\n    expect(rendered.getByText('Data 1')).toBeInTheDocument()\n  })\n\n  it('should throw error when queryKey changes and new query fails', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    function Page({ fail }: { fail: boolean }) {\n      const { data } = useSuspenseQuery({\n        queryKey: [key, fail],\n        queryFn: () =>\n          sleep(10).then(() => {\n            if (fail) throw new Error('Suspense Error Bingo')\n            return 'data'\n          }),\n        retry: 0,\n      })\n\n      return <div>rendered: {data}</div>\n    }\n\n    function TestApp() {\n      const [fail, setFail] = useState(false)\n\n      return (\n        <>\n          <button onClick={() => setFail(true)}>trigger fail</button>\n          <ErrorBoundary fallbackRender={() => <div>error boundary</div>}>\n            <Suspense fallback=\"loading\">\n              <Page fail={fail} />\n            </Suspense>\n          </ErrorBoundary>\n        </>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <TestApp />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('rendered: data')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('trigger fail'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n\n    expect(consoleMock.mock.calls[0]?.[1]).toStrictEqual(\n      new Error('Suspense Error Bingo'),\n    )\n\n    consoleMock.mockRestore()\n  })\n\n  it('should keep previous data when wrapped in a transition', async () => {\n    const key = queryKey()\n\n    function Page({ count, isPending }: { count: number; isPending: boolean }) {\n      const { data } = useSuspenseQuery({\n        queryKey: [key, count],\n        queryFn: () => sleep(10).then(() => 'data' + count),\n      })\n\n      return <div>{isPending ? 'pending' : data}</div>\n    }\n\n    function TestApp() {\n      const [count, setCount] = useState(0)\n      const [isPending, startTransition] = useTransition()\n\n      return (\n        <>\n          <button onClick={() => startTransition(() => setCount((c) => c + 1))}>\n            inc\n          </button>\n          <Suspense fallback=\"loading\">\n            <Page count={count} isPending={isPending} />\n          </Suspense>\n        </>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <TestApp />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('inc'))\n    // Expect no concurrent updates in Preact\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data1')).toBeInTheDocument()\n  })\n\n  it('should not request old data inside transitions (issue #6486)', async () => {\n    const key = queryKey()\n    let queryFnCount = 0\n\n    function App() {\n      const [count, setCount] = useState(0)\n\n      return (\n        <div>\n          <button onClick={() => startTransition(() => setCount(count + 1))}>\n            inc\n          </button>\n          <Suspense fallback=\"loading\">\n            <Page count={count} />\n          </Suspense>\n        </div>\n      )\n    }\n\n    function Page({ count }: { count: number }) {\n      const { data } = useSuspenseQuery({\n        queryKey: [key, count],\n        queryFn: () =>\n          sleep(10).then(() => {\n            queryFnCount++\n            return 'data' + count\n          }),\n      })\n\n      return (\n        <div>\n          <div>{String(data)}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n\n      <App />,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('inc'))\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data1')).toBeInTheDocument()\n\n    expect(queryFnCount).toBe(2)\n  })\n\n  it('should still suspense if queryClient has placeholderData config', async () => {\n    const key = queryKey()\n    const queryClientWithPlaceholder = new QueryClient({\n      defaultOptions: {\n        queries: {\n          placeholderData: (previousData: any) => previousData,\n        },\n      },\n    })\n\n    function Page({ count, isPending }: { count: number; isPending: boolean }) {\n      const { data } = useSuspenseQuery({\n        queryKey: [key, count],\n        queryFn: () => sleep(10).then(() => 'data' + count),\n      })\n\n      return (\n        <div>\n          <div>{isPending ? 'pending' : data}</div>\n        </div>\n      )\n    }\n\n    function TestApp() {\n      const [count, setCount] = useState(0)\n      const [isPending, startTransition] = useTransition()\n\n      return (\n        <>\n          <button onClick={() => startTransition(() => setCount((c) => c + 1))}>\n            inc\n          </button>\n          <Suspense fallback=\"loading\">\n            <Page count={count} isPending={isPending} />\n          </Suspense>\n        </>\n      )\n    }\n\n    const rendered = renderWithClient(queryClientWithPlaceholder, <TestApp />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(async () => {\n      await vi.advanceTimersByTimeAsync(10)\n    })\n    expect(rendered.getByText('data0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('inc'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(async () => {\n      await vi.advanceTimersByTimeAsync(10)\n    })\n    expect(rendered.getByText('data1')).toBeInTheDocument()\n  })\n\n  it('should show error boundary even with gcTime:0 (#7853)', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n    let count = 0\n\n    function Page() {\n      useSuspenseQuery({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => {\n            count++\n            throw new Error('Query failed')\n          }),\n        gcTime: 0,\n        retry: false,\n      })\n\n      return null\n    }\n\n    function App() {\n      return (\n        <Suspense fallback=\"loading\">\n          <ErrorBoundary\n            fallbackRender={() => {\n              return <div>There was an error!</div>\n            }}\n          >\n            <Page />\n          </ErrorBoundary>\n        </Suspense>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('There was an error!')).toBeInTheDocument()\n\n    expect(count).toBe(1)\n\n    consoleMock.mockRestore()\n  })\n\n  describe('gc (with fake timers)', () => {\n    beforeAll(() => {\n      vi.useFakeTimers()\n    })\n\n    afterAll(() => {\n      vi.useRealTimers()\n    })\n\n    it('should gc when unmounted while fetching with low gcTime (#8159)', async () => {\n      const key = queryKey()\n\n      function Page() {\n        return (\n          <Suspense fallback=\"loading\">\n            <Component />\n          </Suspense>\n        )\n      }\n\n      function Component() {\n        const { data } = useSuspenseQuery({\n          queryKey: key,\n          queryFn: () => sleep(3000).then(() => 'data'),\n          gcTime: 1000,\n        })\n\n        return <div>{data}</div>\n      }\n\n      function Page2() {\n        return <div>page2</div>\n      }\n\n      function App() {\n        const [show, setShow] = useState(true)\n\n        return (\n          <div>\n            {show ? <Page /> : <Page2 />}\n            <button onClick={() => setShow(false)}>hide</button>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <App />)\n\n      expect(rendered.getByText('loading')).toBeInTheDocument()\n\n      fireEvent.click(rendered.getByText('hide'))\n      expect(rendered.getByText('page2')).toBeInTheDocument()\n      // wait for query to be resolved\n      await vi.advanceTimersByTimeAsync(3000)\n      expect(queryClient.getQueryData(key)).toBe('data')\n      // wait for gc\n      await vi.advanceTimersByTimeAsync(1000)\n      expect(queryClient.getQueryData(key)).toBe(undefined)\n    })\n  })\n\n  it('should log an error when skipToken is passed as queryFn', () => {\n    const consoleErrorSpy = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => {})\n    const key = queryKey()\n\n    function Page() {\n      useSuspenseQueries({\n        queries: [\n          {\n            queryKey: key,\n            // @ts-expect-error\n            queryFn: Math.random() >= 0 ? skipToken : () => Promise.resolve(5),\n          },\n        ],\n      })\n\n      return null\n    }\n\n    function App() {\n      return (\n        <Suspense fallback=\"loading\">\n          <Page />\n        </Suspense>\n      )\n    }\n\n    renderWithClient(queryClient, <App />)\n\n    expect(consoleErrorSpy).toHaveBeenCalledWith(\n      'skipToken is not allowed for useSuspenseQueries',\n    )\n    consoleErrorSpy.mockRestore()\n  })\n\n  it('should log an error when skipToken is used in development environment', () => {\n    const envCopy = process.env.NODE_ENV\n    process.env.NODE_ENV = 'development'\n\n    const consoleErrorSpy = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    function Page() {\n      useSuspenseQueries({\n        queries: [\n          {\n            queryKey: key,\n            queryFn: skipToken as any,\n          },\n        ],\n      })\n\n      return null\n    }\n\n    renderWithClient(\n      queryClient,\n      <Suspense fallback=\"loading\">\n        <Page />\n      </Suspense>,\n    )\n\n    expect(consoleErrorSpy).toHaveBeenCalledWith(\n      'skipToken is not allowed for useSuspenseQueries',\n    )\n    consoleErrorSpy.mockRestore()\n    process.env.NODE_ENV = envCopy\n  })\n\n  it('should not log an error when skipToken is used in production environment', () => {\n    const envCopy = process.env.NODE_ENV\n    process.env.NODE_ENV = 'production'\n\n    const consoleErrorSpy = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    function Page() {\n      useSuspenseQueries({\n        queries: [\n          {\n            queryKey: key,\n            queryFn: skipToken as any,\n          },\n        ],\n      })\n\n      return null\n    }\n\n    renderWithClient(\n      queryClient,\n      <Suspense fallback=\"loading\">\n        <Page />\n      </Suspense>,\n    )\n\n    expect(consoleErrorSpy).not.toHaveBeenCalled()\n    consoleErrorSpy.mockRestore()\n    process.env.NODE_ENV = envCopy\n  })\n\n  it('should only suspend queries that are pending when the slower query already has data', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    queryClient.setQueryData(key1, 'cached')\n\n    function Page() {\n      const [result1, result2] = useSuspenseQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => sleep(2000).then(() => 'data1'),\n          },\n          {\n            queryKey: key2,\n            queryFn: () => sleep(1000).then(() => 'data2'),\n          },\n        ],\n      })\n\n      return (\n        <div>\n          <div>data1: {result1.data}</div>\n          <div>data2: {result2.data}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <Suspense fallback={<div>loading</div>}>\n        <Page />\n      </Suspense>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n\n    // key2 resolves: suspend lifts, key1 shows cached data, key2 shows fresh data\n    await vi.advanceTimersByTimeAsync(1000)\n\n    expect(rendered.getByText('data1: cached')).toBeInTheDocument()\n    expect(rendered.getByText('data2: data2')).toBeInTheDocument()\n\n    // key1 stale timer fires, triggering background refetch\n    await vi.advanceTimersByTimeAsync(1000)\n\n    // key1 background refetch completes: key1 updates to fresh data\n    await vi.advanceTimersByTimeAsync(2000)\n\n    expect(rendered.getByText('data1: data1')).toBeInTheDocument()\n    expect(rendered.getByText('data2: data2')).toBeInTheDocument()\n  })\n\n  it('should only suspend queries that are pending when the faster query already has data', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    queryClient.setQueryData(key2, 'cached')\n\n    function Page() {\n      const [result1, result2] = useSuspenseQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => sleep(2000).then(() => 'data1'),\n          },\n          {\n            queryKey: key2,\n            queryFn: () => sleep(1000).then(() => 'data2'),\n          },\n        ],\n      })\n\n      return (\n        <div>\n          <div>data1: {result1.data}</div>\n          <div>data2: {result2.data}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <Suspense fallback={<div>loading</div>}>\n        <Page />\n      </Suspense>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n\n    // key1 resolves: suspend lifts, key1 shows fresh data, key2 shows cached data\n    await vi.advanceTimersByTimeAsync(2000)\n\n    expect(rendered.getByText('data1: data1')).toBeInTheDocument()\n    expect(rendered.getByText('data2: cached')).toBeInTheDocument()\n\n    // key2 stale timer fires, triggering background refetch\n    await vi.advanceTimersByTimeAsync(1000)\n\n    // key2 background refetch completes: key2 updates to fresh data\n    await vi.advanceTimersByTimeAsync(1000)\n\n    expect(rendered.getByText('data1: data1')).toBeInTheDocument()\n    expect(rendered.getByText('data2: data2')).toBeInTheDocument()\n  })\n\n  it('should not suspend and not refetch when all queries have fresh cached data', () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    queryClient.setQueryData(key1, 'cached1')\n    queryClient.setQueryData(key2, 'cached2')\n\n    const queryFn1 = vi.fn(() => sleep(20).then(() => 'data1'))\n    const queryFn2 = vi.fn(() => sleep(10).then(() => 'data2'))\n\n    function Page() {\n      const [result1, result2] = useSuspenseQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: queryFn1,\n          },\n          {\n            queryKey: key2,\n            queryFn: queryFn2,\n          },\n        ],\n      })\n\n      return (\n        <div>\n          <div>data1: {result1.data}</div>\n          <div>data2: {result2.data}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <Suspense fallback={<div>loading</div>}>\n        <Page />\n      </Suspense>,\n    )\n\n    // No suspend, fresh cached data shown immediately\n    expect(rendered.getByText('data1: cached1')).toBeInTheDocument()\n    expect(rendered.getByText('data2: cached2')).toBeInTheDocument()\n\n    // No background refetch because data is still fresh (within staleTime)\n    expect(queryFn1).toHaveBeenCalledTimes(0)\n    expect(queryFn2).toHaveBeenCalledTimes(0)\n  })\n\n  it('should not suspend but refetch when all queries have stale cached data', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    queryClient.setQueryData(key1, 'cached1')\n    queryClient.setQueryData(key2, 'cached2')\n\n    // Advance past staleTime (min 1000ms in suspense) so data becomes stale before mount\n    vi.advanceTimersByTime(1000)\n\n    function Page() {\n      const [result1, result2] = useSuspenseQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => sleep(20).then(() => 'data1'),\n          },\n          {\n            queryKey: key2,\n            queryFn: () => sleep(10).then(() => 'data2'),\n          },\n        ],\n      })\n\n      return (\n        <div>\n          <div>data1: {result1.data}</div>\n          <div>data2: {result2.data}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <Suspense fallback={<div>loading</div>}>\n        <Page />\n      </Suspense>,\n    )\n\n    // No suspend, stale cached data shown immediately with background refetch started\n    expect(rendered.getByText('data1: cached1')).toBeInTheDocument()\n    expect(rendered.getByText('data2: cached2')).toBeInTheDocument()\n\n    // key2 background refetch completes\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(rendered.getByText('data1: cached1')).toBeInTheDocument()\n    expect(rendered.getByText('data2: data2')).toBeInTheDocument()\n\n    // key1 background refetch completes\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(rendered.getByText('data1: data1')).toBeInTheDocument()\n    expect(rendered.getByText('data2: data2')).toBeInTheDocument()\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/useSuspenseQuery.test-d.tsx",
    "content": "import { skipToken } from '@tanstack/query-core'\nimport { assertType, describe, expectTypeOf, it } from 'vitest'\n\nimport { useSuspenseQuery } from '../useSuspenseQuery'\n\ndescribe('useSuspenseQuery', () => {\n  it('should always have data defined', () => {\n    const { data } = useSuspenseQuery({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    expectTypeOf(data).toEqualTypeOf<number>()\n  })\n\n  it('should not have pending status', () => {\n    const { status } = useSuspenseQuery({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    expectTypeOf(status).toEqualTypeOf<'error' | 'success'>()\n  })\n\n  it('should not allow skipToken in queryFn', () => {\n    assertType(\n      useSuspenseQuery({\n        queryKey: ['key'],\n        // @ts-expect-error\n        queryFn: skipToken,\n      }),\n    )\n    assertType(\n      useSuspenseQuery({\n        queryKey: ['key'],\n        // @ts-expect-error\n        queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),\n      }),\n    )\n  })\n\n  it('should not allow placeholderData, enabled or throwOnError props', () => {\n    assertType(\n      useSuspenseQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        // @ts-expect-error TS2345\n        placeholderData: 5,\n        enabled: true,\n      }),\n    )\n    assertType(\n      useSuspenseQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        // @ts-expect-error TS2345\n        enabled: true,\n      }),\n    )\n    assertType(\n      useSuspenseQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        // @ts-expect-error TS2345\n        throwOnError: true,\n      }),\n    )\n  })\n\n  it('should not return isPlaceholderData', () => {\n    expectTypeOf(\n      useSuspenseQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n      }),\n    ).not.toHaveProperty('isPlaceholderData')\n  })\n\n  it('should type-narrow the error field', () => {\n    const query = useSuspenseQuery({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    if (query.status === 'error') {\n      expectTypeOf(query.error).toEqualTypeOf<Error>()\n    }\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/useSuspenseQuery.test.tsx",
    "content": "import { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { act, fireEvent } from '@testing-library/preact'\nimport { Suspense } from 'preact/compat'\nimport { useReducer, useState } from 'preact/hooks'\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\n\nimport {\n  QueryCache,\n  QueryClient,\n  QueryErrorResetBoundary,\n  skipToken,\n  useQueryErrorResetBoundary,\n  useSuspenseInfiniteQuery,\n  useSuspenseQuery,\n} from '..'\nimport type {\n  InfiniteData,\n  UseSuspenseInfiniteQueryResult,\n  UseSuspenseQueryResult,\n} from '..'\nimport { ErrorBoundary } from './ErrorBoundary'\nimport { renderWithClient } from './utils'\n\ndescribe('useSuspenseQuery', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  const queryCache = new QueryCache()\n  const queryClient = new QueryClient({ queryCache })\n\n  /**\n   * Preact Suspense handles the rerenders differently than React.\n   * This test only checks for 4 renders (vs. React -> 6)\n   * so, instead of state change reacting and updating (and also losing the state)\n   * we abstract out the suspense\n   */\n  it('should render correctly when state is lifted above Suspense', async () => {\n    const states: Array<UseSuspenseQueryResult<number>> = []\n\n    let count = 0\n    let renders = 0\n\n    function TestApp() {\n      // State lives here, ABOVE the Suspense boundary, so it does not get reset\n      const [stateKey, setStateKey] = useState(queryKey())\n\n      return (\n        <>\n          <button aria-label=\"toggle\" onClick={() => setStateKey(queryKey())} />\n          <Suspense fallback=\"loading\">\n            <Page stateKey={stateKey} />\n          </Suspense>\n        </>\n      )\n    }\n\n    function Page({ stateKey }: { stateKey: Array<string> }) {\n      renders++\n      const state = useSuspenseQuery({\n        queryKey: stateKey,\n        queryFn: () => sleep(10).then(() => ++count),\n      })\n\n      states.push(state)\n\n      return <div>data: {state.data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <TestApp />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByLabelText('toggle'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 2')).toBeInTheDocument()\n\n    /**\n     * In this pattern, renders will likely be 4 (2 for each successful mount)\n     * Instead of React's 6 (where strict-mode changes the number of renders)\n     */\n    expect(renders).toBe(4)\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: 1, status: 'success' })\n    expect(states[1]).toMatchObject({ data: 2, status: 'success' })\n  })\n\n  it('should return the correct states for a successful infinite query', async () => {\n    const key = queryKey()\n    const states: Array<UseSuspenseInfiniteQueryResult<InfiniteData<number>>> =\n      []\n\n    function Page({ multiplier }: { multiplier: number }) {\n      const state = useSuspenseInfiniteQuery({\n        queryKey: [`${key}_${multiplier}`],\n        queryFn: ({ pageParam }) =>\n          sleep(10).then(() => pageParam * multiplier),\n        initialPageParam: 1,\n        getNextPageParam: (lastPage) => lastPage + 1,\n      })\n\n      states.push(state)\n\n      return <div>data: {state.data?.pages.join(',')}</div>\n    }\n\n    function TestApp() {\n      const [multiplier, setMultiplier] = useState(1)\n\n      return (\n        <>\n          <button onClick={() => setMultiplier(2)}>next</button>\n          <Suspense fallback=\"loading\">\n            <Page multiplier={multiplier} />\n          </Suspense>\n        </>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <TestApp />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n\n    expect(states.length).toBe(1)\n    expect(states[0]).toMatchObject({\n      data: { pages: [1], pageParams: [1] },\n      status: 'success',\n    })\n\n    fireEvent.click(rendered.getByText('next'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 2')).toBeInTheDocument()\n\n    expect(states.length).toBe(2)\n    expect(states[1]).toMatchObject({\n      data: { pages: [2], pageParams: [1] },\n      status: 'success',\n    })\n  })\n\n  it('should not call the queryFn twice when used in Suspense mode', async () => {\n    const key = queryKey()\n\n    const queryFn = vi.fn(() => sleep(10).then(() => 'data'))\n\n    function Page() {\n      useSuspenseQuery({ queryKey: [key], queryFn })\n\n      return <>rendered</>\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <Suspense fallback=\"loading\">\n        <Page />\n      </Suspense>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n\n    expect(queryFn).toHaveBeenCalledTimes(1)\n  })\n\n  it('should remove query instance when component unmounted', async () => {\n    const key = queryKey()\n\n    function Page() {\n      useSuspenseQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'data'),\n      })\n\n      return <>rendered</>\n    }\n\n    function App() {\n      const [show, setShow] = useState(false)\n\n      return (\n        <>\n          <Suspense fallback=\"loading\">{show && <Page />}</Suspense>\n          <button\n            aria-label=\"toggle\"\n            onClick={() => setShow((prev) => !prev)}\n          />\n        </>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    expect(rendered.queryByText('loading')).not.toBeInTheDocument()\n    expect(rendered.queryByText('rendered')).not.toBeInTheDocument()\n    expect(queryCache.find({ queryKey: key })).toBeFalsy()\n\n    fireEvent.click(rendered.getByLabelText('toggle'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(async () => {\n      await vi.advanceTimersByTimeAsync(10)\n    })\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n\n    expect(queryCache.find({ queryKey: key })?.getObserversCount()).toBe(1)\n\n    fireEvent.click(rendered.getByLabelText('toggle'))\n    expect(rendered.queryByText('loading')).not.toBeInTheDocument()\n    await act(async () => {\n      await vi.advanceTimersByTimeAsync(10)\n    })\n    expect(rendered.queryByText('rendered')).not.toBeInTheDocument()\n    expect(queryCache.find({ queryKey: key })?.getObserversCount()).toBe(0)\n  })\n\n  // https://github.com/tannerlinsley/react-query/issues/468\n  it('should reset error state if new component instances are mounted', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    let succeed = false\n\n    function Page() {\n      useSuspenseQuery({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => {\n            if (!succeed) throw new Error('Suspense Error Bingo')\n            return 'data'\n          }),\n        retryDelay: 10,\n      })\n\n      return <div>rendered</div>\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <QueryErrorResetBoundary>\n        {({ reset }) => (\n          <ErrorBoundary\n            onReset={reset}\n            fallbackRender={({ resetErrorBoundary }) => (\n              <div>\n                <div>error boundary</div>\n                <button\n                  onClick={() => {\n                    succeed = true\n                    resetErrorBoundary()\n                  }}\n                >\n                  retry\n                </button>\n              </div>\n            )}\n          >\n            <Suspense fallback=\"loading\">\n              <Page />\n            </Suspense>\n          </ErrorBoundary>\n        )}\n      </QueryErrorResetBoundary>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(70)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n    expect(rendered.getByText('retry')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('retry'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n\n    expect(consoleMock.mock.calls[0]?.[1]).toStrictEqual(\n      new Error('Suspense Error Bingo'),\n    )\n\n    consoleMock.mockRestore()\n  })\n\n  it('should retry fetch if the reset error boundary has been reset', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    let succeed = false\n\n    function Page() {\n      useSuspenseQuery({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => {\n            if (!succeed) throw new Error('Suspense Error Bingo')\n            return 'data'\n          }),\n        retry: false,\n      })\n      return <div>rendered</div>\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <QueryErrorResetBoundary>\n        {({ reset }) => (\n          <ErrorBoundary\n            onReset={reset}\n            fallbackRender={({ resetErrorBoundary }) => (\n              <div>\n                <div>error boundary</div>\n                <button\n                  onClick={() => {\n                    resetErrorBoundary()\n                  }}\n                >\n                  retry\n                </button>\n              </div>\n            )}\n          >\n            <Suspense fallback=\"loading\">\n              <Page />\n            </Suspense>\n          </ErrorBoundary>\n        )}\n      </QueryErrorResetBoundary>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n    expect(rendered.getByText('retry')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('retry'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n    expect(rendered.getByText('retry')).toBeInTheDocument()\n\n    succeed = true\n\n    fireEvent.click(rendered.getByText('retry'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n\n    consoleMock.mockRestore()\n  })\n\n  it('should set staleTime when having passed a function', async () => {\n    const key = queryKey()\n    let count = 0\n\n    function Component() {\n      const result = useSuspenseQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => ++count),\n        staleTime: () => 60 * 1000,\n      })\n      return (\n        <div>\n          <span>data: {result.data}</span>\n        </div>\n      )\n    }\n\n    function Page() {\n      return (\n        <Suspense fallback=\"loading\">\n          <Component />\n        </Suspense>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(async () => {\n      await vi.advanceTimersByTimeAsync(10)\n    })\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n\n    expect(\n      typeof queryClient.getQueryCache().find({ queryKey: key })?.observers[0]\n        ?.options.staleTime,\n    ).toBe('function')\n  })\n\n  it('should suspend when switching to a new query', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    function Component(props: { queryKey: Array<string> }) {\n      const result = useSuspenseQuery({\n        queryKey: props.queryKey,\n        queryFn: () => sleep(10).then(() => props.queryKey),\n        retry: false,\n      })\n      return <div>data: {result.data}</div>\n    }\n\n    function Page() {\n      const [key, setKey] = useState(key1)\n      return (\n        <div>\n          <button\n            onClick={() => {\n              setKey(key2)\n            }}\n          >\n            switch\n          </button>\n          <Suspense fallback=\"loading\">\n            <Component queryKey={key} />\n          </Suspense>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText(`data: ${key1}`)).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('switch'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText(`data: ${key2}`)).toBeInTheDocument()\n  })\n\n  it('should retry fetch if the reset error boundary has been reset with global hook', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    let succeed = false\n\n    function Page() {\n      useSuspenseQuery({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => {\n            if (!succeed) throw new Error('Suspense Error Bingo')\n            return 'data'\n          }),\n        retry: false,\n      })\n      return <div>rendered</div>\n    }\n\n    function App() {\n      const { reset } = useQueryErrorResetBoundary()\n      return (\n        <ErrorBoundary\n          onReset={reset}\n          fallbackRender={({ resetErrorBoundary }) => (\n            <div>\n              <div>error boundary</div>\n              <button\n                onClick={() => {\n                  resetErrorBoundary()\n                }}\n              >\n                retry\n              </button>\n            </div>\n          )}\n        >\n          <Suspense fallback=\"loading\">\n            <Page />\n          </Suspense>\n        </ErrorBoundary>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n    expect(rendered.getByText('retry')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('retry'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n    expect(rendered.getByText('retry')).toBeInTheDocument()\n\n    succeed = true\n\n    fireEvent.click(rendered.getByText('retry'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n\n    consoleMock.mockRestore()\n  })\n\n  it('should throw errors to the error boundary by default', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    function Page() {\n      useSuspenseQuery({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => Promise.reject(new Error('Suspense Error a1x'))),\n        retry: false,\n      })\n      return <div>rendered</div>\n    }\n\n    function App() {\n      return (\n        <ErrorBoundary\n          fallbackRender={() => (\n            <div>\n              <div>error boundary</div>\n            </div>\n          )}\n        >\n          <Suspense fallback=\"loading\">\n            <Page />\n          </Suspense>\n        </ErrorBoundary>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n\n    consoleMock.mockRestore()\n  })\n\n  it('should throw select errors to the error boundary by default', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    function Page() {\n      useSuspenseQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => ({ a: { b: 'c' } })),\n        select: () => {\n          throw new Error('foo')\n        },\n      })\n      return <div>rendered</div>\n    }\n\n    function App() {\n      return (\n        <ErrorBoundary\n          fallbackRender={() => (\n            <div>\n              <div>error boundary</div>\n            </div>\n          )}\n        >\n          <Suspense fallback=\"loading\">\n            <Page />\n          </Suspense>\n        </ErrorBoundary>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n\n    consoleMock.mockRestore()\n  })\n\n  it('should error caught in error boundary without infinite loop', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    function Page({ succeed }: { succeed: boolean }) {\n      const [nonce] = useState(0)\n      const queryKeys = [`${key}-${succeed}`]\n      const result = useSuspenseQuery({\n        queryKey: queryKeys,\n        queryFn: () =>\n          sleep(10).then(() => {\n            if (!succeed) throw new Error('Suspense Error Bingo')\n            return nonce\n          }),\n        retry: false,\n      })\n      return (\n        <div>\n          <span>rendered</span> <span>{result.data}</span>\n        </div>\n      )\n    }\n\n    function App() {\n      const { reset } = useQueryErrorResetBoundary()\n      const [succeed, setSucceed] = useState(true)\n\n      return (\n        <div>\n          <button\n            aria-label=\"set-fail\"\n            onClick={() => {\n              setSucceed(false)\n            }}\n          />\n          <button\n            aria-label=\"fail\"\n            onClick={() => {\n              queryClient.resetQueries()\n            }}\n          />\n          <ErrorBoundary\n            onReset={reset}\n            fallbackRender={() => <div>error boundary</div>}\n          >\n            <Suspense fallback=\"loading\">\n              <Page succeed={succeed} />\n            </Suspense>\n          </ErrorBoundary>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    // render suspense fallback (loading)\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    // resolve promise -> render Page (rendered)\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n\n    // change query result to error by updating state above Suspense\n    fireEvent.click(rendered.getByLabelText('set-fail'))\n\n    // reset query -> and throw error\n    fireEvent.click(rendered.getByLabelText('fail'))\n    // render error boundary fallback (error boundary)\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n\n    expect(consoleMock.mock.calls[0]?.[1]).toStrictEqual(\n      new Error('Suspense Error Bingo'),\n    )\n\n    consoleMock.mockRestore()\n  })\n\n  it('should error caught in error boundary without infinite loop when query keys changed', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    let succeed = true\n\n    function Child({ keyVal }: { keyVal: number }) {\n      const queryKeys = [keyVal, succeed]\n\n      const result = useSuspenseQuery({\n        queryKey: queryKeys,\n        queryFn: () =>\n          sleep(10).then(() => {\n            if (!succeed) throw new Error('Suspense Error Bingo')\n            return 'data'\n          }),\n        retry: false,\n      })\n\n      if (result.error) {\n        throw result.error\n      }\n\n      return (\n        <div>\n          <span>rendered</span> <span>{result.data}</span>\n        </div>\n      )\n    }\n\n    function Page() {\n      const [key, rerender] = useReducer((x) => x + 1, 0)\n\n      return (\n        <div>\n          <button aria-label=\"fail\" onClick={rerender}>\n            fail\n          </button>\n          <Suspense fallback=\"loading\">\n            <Child keyVal={key} />\n          </Suspense>\n        </div>\n      )\n    }\n\n    function App() {\n      const { reset } = useQueryErrorResetBoundary()\n      return (\n        <ErrorBoundary\n          onReset={reset}\n          fallbackRender={() => <div>error boundary</div>}\n        >\n          <Page />\n        </ErrorBoundary>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    // render suspense fallback (loading)\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    // resolve promise -> render Page (rendered)\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n\n    // change promise result to error\n    succeed = false\n\n    // change query key (state is above Suspense)\n    fireEvent.click(rendered.getByLabelText('fail'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    // render error boundary fallback (error boundary)\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n\n    expect(consoleMock.mock.calls[0]?.[1]).toStrictEqual(\n      new Error('Suspense Error Bingo'),\n    )\n\n    consoleMock.mockRestore()\n  })\n\n  it('should render the correct amount of times in Suspense mode when gcTime is set to 0', async () => {\n    const key = queryKey()\n    let state: UseSuspenseQueryResult<number, Error | null> | null = null\n\n    let count = 0\n    let renders = 0\n\n    function Page() {\n      renders++\n\n      state = useSuspenseQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => ++count),\n        gcTime: 0,\n      })\n\n      return (\n        <div>\n          <span>rendered</span>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <Suspense fallback=\"loading\">\n        <Page />\n      </Suspense>,\n    )\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n\n    expect(state).toMatchObject({\n      data: 1,\n      status: 'success',\n    })\n    // reducing 1 for strict mode render\n    expect(renders).toBe(2)\n  })\n\n  it('should not throw background errors to the error boundary', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    let succeed = true\n    const key = queryKey()\n\n    function Page() {\n      const result = useSuspenseQuery({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => {\n            if (!succeed) throw new Error('Suspense Error Bingo')\n            return 'data'\n          }),\n        retry: false,\n      })\n\n      return (\n        <div>\n          <span>\n            rendered {result.data} {result.status}\n          </span>\n          <button onClick={() => result.refetch()}>refetch</button>\n        </div>\n      )\n    }\n\n    function App() {\n      const { reset } = useQueryErrorResetBoundary()\n      return (\n        <ErrorBoundary\n          onReset={reset}\n          fallbackRender={() => <div>error boundary</div>}\n        >\n          <Suspense fallback=\"loading\">\n            <Page />\n          </Suspense>\n        </ErrorBoundary>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    // render suspense fallback (loading)\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    // resolve promise -> render Page (rendered)\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('rendered data success')).toBeInTheDocument()\n\n    // change promise result to error\n    succeed = false\n\n    // refetch\n    fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))\n    // we are now in error state but still have data to show\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('rendered data error')).toBeInTheDocument()\n\n    consoleMock.mockRestore()\n  })\n\n  it('should still suspense if queryClient has placeholderData config', async () => {\n    const key = queryKey()\n    const queryClientWithPlaceholder = new QueryClient({\n      defaultOptions: {\n        queries: {\n          placeholderData: (previousData: any) => previousData,\n        },\n      },\n    })\n    const states: Array<UseSuspenseQueryResult<number>> = []\n\n    let count = 0\n\n    function TestApp() {\n      // State lives here, ABOVE the Suspense boundary, so it does not get reset\n      const [stateKey, setStateKey] = useState(key)\n\n      return (\n        <>\n          <button aria-label=\"toggle\" onClick={() => setStateKey(queryKey())} />\n          <Suspense fallback=\"loading\">\n            <Page stateKey={stateKey} />\n          </Suspense>\n        </>\n      )\n    }\n\n    function Page({ stateKey }: { stateKey: Array<string> }) {\n      const state = useSuspenseQuery({\n        queryKey: stateKey,\n        queryFn: async () => sleep(10).then(() => ++count),\n      })\n\n      states.push(state)\n\n      return <div>data: {String(state.data)}</div>\n    }\n\n    const rendered = renderWithClient(queryClientWithPlaceholder, <TestApp />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByLabelText('toggle'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 2')).toBeInTheDocument()\n  })\n\n  it('should log an error when skipToken is passed as queryFn', () => {\n    const consoleErrorSpy = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => {})\n    const key = queryKey()\n\n    function Page() {\n      useSuspenseQuery({\n        queryKey: key,\n        // @ts-expect-error\n        // eslint-disable-next-line\n        queryFn: Math.random() >= 0 ? skipToken : () => Promise.resolve(5),\n      })\n\n      return null\n    }\n\n    function App() {\n      return (\n        <Suspense fallback=\"loading\">\n          <Page />\n        </Suspense>\n      )\n    }\n\n    renderWithClient(queryClient, <App />)\n\n    expect(consoleErrorSpy).toHaveBeenCalledWith(\n      'skipToken is not allowed for useSuspenseQuery',\n    )\n    consoleErrorSpy.mockRestore()\n  })\n\n  it('should properly refresh data when refetchInterval is set', async () => {\n    const key = queryKey()\n    let count = 0\n\n    function Page() {\n      const state = useSuspenseQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => ++count),\n        refetchInterval: 10,\n      })\n\n      return <div>count: {state.data}</div>\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <Suspense fallback=\"loading\">\n        <Page />\n      </Suspense>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(async () => {\n      await vi.advanceTimersByTimeAsync(10)\n    })\n    expect(rendered.getByText('count: 1')).toBeInTheDocument()\n    await act(async () => {\n      await vi.advanceTimersByTimeAsync(21)\n    })\n    expect(rendered.getByText('count: 2')).toBeInTheDocument()\n    await act(async () => {\n      await vi.advanceTimersByTimeAsync(21)\n    })\n    expect(rendered.getByText('count: 3')).toBeInTheDocument()\n\n    expect(count).toBeGreaterThanOrEqual(3)\n  })\n\n  it('should log an error when skipToken is used in development environment', () => {\n    const envCopy = process.env.NODE_ENV\n    process.env.NODE_ENV = 'development'\n\n    const consoleErrorSpy = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    function Page() {\n      useSuspenseQuery({\n        queryKey: key,\n        queryFn: skipToken as any,\n      })\n\n      return null\n    }\n\n    renderWithClient(\n      queryClient,\n      <Suspense fallback=\"loading\">\n        <Page />\n      </Suspense>,\n    )\n\n    expect(consoleErrorSpy).toHaveBeenCalledWith(\n      'skipToken is not allowed for useSuspenseQuery',\n    )\n\n    consoleErrorSpy.mockRestore()\n    process.env.NODE_ENV = envCopy\n  })\n\n  it('should not log an error when skipToken is used in production environment', () => {\n    const envCopy = process.env.NODE_ENV\n    process.env.NODE_ENV = 'production'\n\n    const consoleErrorSpy = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    function Page() {\n      useSuspenseQuery({\n        queryKey: key,\n        queryFn: skipToken as any,\n      })\n\n      return null\n    }\n\n    renderWithClient(\n      queryClient,\n      <Suspense fallback=\"loading\">\n        <Page />\n      </Suspense>,\n    )\n\n    expect(consoleErrorSpy).not.toHaveBeenCalled()\n\n    consoleErrorSpy.mockRestore()\n    process.env.NODE_ENV = envCopy\n  })\n})\n"
  },
  {
    "path": "packages/preact-query/src/__tests__/utils.tsx",
    "content": "import { environmentManager, isServer } from '@tanstack/query-core'\nimport { act, render } from '@testing-library/preact'\nimport type { ComponentChildren, VNode } from 'preact'\nimport { useEffect, useState } from 'preact/hooks'\nimport { vi } from 'vitest'\nimport type { MockInstance } from 'vitest'\n\nimport { QueryClientProvider, onlineManager } from '..'\nimport type { QueryClient } from '..'\n\nexport function renderWithClient(\n  client: QueryClient,\n  ui: VNode,\n): ReturnType<typeof render> {\n  const { rerender, ...result } = render(\n    <QueryClientProvider client={client}>{ui}</QueryClientProvider>,\n  )\n  return {\n    ...result,\n    rerender: (rerenderUi: VNode) =>\n      rerender(\n        <QueryClientProvider client={client}>{rerenderUi}</QueryClientProvider>,\n      ),\n  } as any\n}\n\nexport function Blink({\n  duration,\n  children,\n}: {\n  duration: number\n  children: ComponentChildren\n}) {\n  const [shouldShow, setShouldShow] = useState<boolean>(true)\n\n  useEffect(() => {\n    setShouldShow(true)\n    const timeout = setActTimeout(() => setShouldShow(false), duration)\n    return () => {\n      clearTimeout(timeout)\n    }\n  }, [duration, children])\n\n  return shouldShow ? <>{children}</> : <>off</>\n}\n\nexport function mockOnlineManagerIsOnline(\n  value: boolean,\n): MockInstance<() => boolean> {\n  return vi.spyOn(onlineManager, 'isOnline').mockReturnValue(value)\n}\n\nexport function setActTimeout(fn: () => void, ms?: number) {\n  return setTimeout(() => {\n    act(() => {\n      fn()\n    })\n  }, ms)\n}\n\nexport function setIsServer(value: boolean) {\n  environmentManager.setIsServer(() => value)\n  return () => {\n    environmentManager.setIsServer(() => isServer)\n  }\n}\n"
  },
  {
    "path": "packages/preact-query/src/errorBoundaryUtils.ts",
    "content": "import { shouldThrowError } from '@tanstack/query-core'\nimport type {\n  DefaultedQueryObserverOptions,\n  Query,\n  QueryKey,\n  QueryObserverResult,\n  ThrowOnError,\n} from '@tanstack/query-core'\nimport { useEffect } from 'preact/hooks'\n\nimport type { QueryErrorResetBoundaryValue } from './QueryErrorResetBoundary'\n\nexport const ensurePreventErrorBoundaryRetry = <\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryData,\n  TQueryKey extends QueryKey,\n>(\n  options: DefaultedQueryObserverOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryData,\n    TQueryKey\n  >,\n  errorResetBoundary: QueryErrorResetBoundaryValue,\n) => {\n  if (\n    options.suspense ||\n    options.throwOnError ||\n    options.experimental_prefetchInRender\n  ) {\n    // Prevent retrying failed query if the error boundary has not been reset yet\n    if (!errorResetBoundary.isReset()) {\n      options.retryOnMount = false\n    }\n  }\n}\n\nexport const useClearResetErrorBoundary = (\n  errorResetBoundary: QueryErrorResetBoundaryValue,\n) => {\n  useEffect(() => {\n    errorResetBoundary.clearReset()\n  }, [errorResetBoundary])\n}\n\nexport const getHasError = <\n  TData,\n  TError,\n  TQueryFnData,\n  TQueryData,\n  TQueryKey extends QueryKey,\n>({\n  result,\n  errorResetBoundary,\n  throwOnError,\n  query,\n  suspense,\n}: {\n  result: QueryObserverResult<TData, TError>\n  errorResetBoundary: QueryErrorResetBoundaryValue\n  throwOnError: ThrowOnError<TQueryFnData, TError, TQueryData, TQueryKey>\n  query: Query<TQueryFnData, TError, TQueryData, TQueryKey> | undefined\n  suspense: boolean | undefined\n}) => {\n  return (\n    result.isError &&\n    !errorResetBoundary.isReset() &&\n    !result.isFetching &&\n    query &&\n    ((suspense && result.data === undefined) ||\n      shouldThrowError(throwOnError, [result.error, query]))\n  )\n}\n"
  },
  {
    "path": "packages/preact-query/src/index.ts",
    "content": "/* istanbul ignore file */\n\n// Re-export core\nexport * from '@tanstack/query-core'\n\n// Preact Query\nexport * from './types'\nexport { useQueries } from './useQueries'\nexport type { QueriesResults, QueriesOptions } from './useQueries'\nexport { useQuery } from './useQuery'\nexport { useSuspenseQuery } from './useSuspenseQuery'\nexport { useSuspenseInfiniteQuery } from './useSuspenseInfiniteQuery'\nexport { useSuspenseQueries } from './useSuspenseQueries'\nexport type {\n  SuspenseQueriesResults,\n  SuspenseQueriesOptions,\n} from './useSuspenseQueries'\nexport { usePrefetchQuery } from './usePrefetchQuery'\nexport { usePrefetchInfiniteQuery } from './usePrefetchInfiniteQuery'\nexport { queryOptions } from './queryOptions'\nexport type {\n  DefinedInitialDataOptions,\n  UndefinedInitialDataOptions,\n  UnusedSkipTokenOptions,\n} from './queryOptions'\nexport { infiniteQueryOptions } from './infiniteQueryOptions'\nexport type {\n  DefinedInitialDataInfiniteOptions,\n  UndefinedInitialDataInfiniteOptions,\n  UnusedSkipTokenInfiniteOptions,\n} from './infiniteQueryOptions'\nexport {\n  QueryClientContext,\n  QueryClientProvider,\n  useQueryClient,\n} from './QueryClientProvider'\nexport type { QueryClientProviderProps } from './QueryClientProvider'\nexport type { QueryErrorResetBoundaryProps } from './QueryErrorResetBoundary'\nexport { HydrationBoundary } from './HydrationBoundary'\nexport type { HydrationBoundaryProps } from './HydrationBoundary'\nexport type {\n  QueryErrorClearResetFunction,\n  QueryErrorIsResetFunction,\n  QueryErrorResetBoundaryFunction,\n  QueryErrorResetFunction,\n} from './QueryErrorResetBoundary'\nexport {\n  QueryErrorResetBoundary,\n  useQueryErrorResetBoundary,\n} from './QueryErrorResetBoundary'\nexport { useIsFetching } from './useIsFetching'\nexport { useIsMutating, useMutationState } from './useMutationState'\nexport { useMutation } from './useMutation'\nexport { mutationOptions } from './mutationOptions'\nexport { useInfiniteQuery } from './useInfiniteQuery'\nexport { useIsRestoring, IsRestoringProvider } from './IsRestoringProvider'\n"
  },
  {
    "path": "packages/preact-query/src/infiniteQueryOptions.ts",
    "content": "import type {\n  DataTag,\n  DefaultError,\n  InfiniteData,\n  InitialDataFunction,\n  NonUndefinedGuard,\n  OmitKeyof,\n  QueryKey,\n  SkipToken,\n} from '@tanstack/query-core'\n\nimport type { UseInfiniteQueryOptions } from './types'\n\nexport type UndefinedInitialDataInfiniteOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> = UseInfiniteQueryOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey,\n  TPageParam\n> & {\n  initialData?:\n    | undefined\n    | NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>\n    | InitialDataFunction<\n        NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>\n      >\n}\n\nexport type UnusedSkipTokenInfiniteOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> = OmitKeyof<\n  UseInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>,\n  'queryFn'\n> & {\n  queryFn?: Exclude<\n    UseInfiniteQueryOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey,\n      TPageParam\n    >['queryFn'],\n    SkipToken | undefined\n  >\n}\n\nexport type DefinedInitialDataInfiniteOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> = UseInfiniteQueryOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey,\n  TPageParam\n> & {\n  initialData:\n    | NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>\n    | (() => NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>)\n    | undefined\n}\n\nexport function infiniteQueryOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: DefinedInitialDataInfiniteOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n): DefinedInitialDataInfiniteOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey,\n  TPageParam\n> & {\n  queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>\n}\n\nexport function infiniteQueryOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: UnusedSkipTokenInfiniteOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n): UnusedSkipTokenInfiniteOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey,\n  TPageParam\n> & {\n  queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>\n}\n\nexport function infiniteQueryOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: UndefinedInitialDataInfiniteOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n): UndefinedInitialDataInfiniteOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey,\n  TPageParam\n> & {\n  queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>\n}\n\nexport function infiniteQueryOptions(options: unknown) {\n  return options\n}\n"
  },
  {
    "path": "packages/preact-query/src/mutationOptions.ts",
    "content": "import type { DefaultError, WithRequired } from '@tanstack/query-core'\n\nimport type { UseMutationOptions } from './types'\n\nexport function mutationOptions<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n>(\n  options: WithRequired<\n    UseMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n    'mutationKey'\n  >,\n): WithRequired<\n  UseMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n  'mutationKey'\n>\nexport function mutationOptions<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n>(\n  options: Omit<\n    UseMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n    'mutationKey'\n  >,\n): Omit<\n  UseMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n  'mutationKey'\n>\nexport function mutationOptions<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n>(\n  options: UseMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n): UseMutationOptions<TData, TError, TVariables, TOnMutateResult> {\n  return options\n}\n"
  },
  {
    "path": "packages/preact-query/src/queryOptions.ts",
    "content": "import type {\n  DataTag,\n  DefaultError,\n  InitialDataFunction,\n  NonUndefinedGuard,\n  OmitKeyof,\n  QueryFunction,\n  QueryKey,\n  SkipToken,\n} from '@tanstack/query-core'\n\nimport type { UseQueryOptions } from './types'\n\nexport type UndefinedInitialDataOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = UseQueryOptions<TQueryFnData, TError, TData, TQueryKey> & {\n  initialData?:\n    | undefined\n    | InitialDataFunction<NonUndefinedGuard<TQueryFnData>>\n    | NonUndefinedGuard<TQueryFnData>\n}\n\nexport type UnusedSkipTokenOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = OmitKeyof<\n  UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  'queryFn'\n> & {\n  queryFn?: Exclude<\n    UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>['queryFn'],\n    SkipToken | undefined\n  >\n}\n\nexport type DefinedInitialDataOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = Omit<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'queryFn'> & {\n  initialData:\n    | NonUndefinedGuard<TQueryFnData>\n    | (() => NonUndefinedGuard<TQueryFnData>)\n  queryFn?: QueryFunction<TQueryFnData, TQueryKey>\n}\n\nexport function queryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,\n): DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> & {\n  queryKey: DataTag<TQueryKey, TQueryFnData, TError>\n}\n\nexport function queryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: UnusedSkipTokenOptions<TQueryFnData, TError, TData, TQueryKey>,\n): UnusedSkipTokenOptions<TQueryFnData, TError, TData, TQueryKey> & {\n  queryKey: DataTag<TQueryKey, TQueryFnData, TError>\n}\n\nexport function queryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,\n): UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> & {\n  queryKey: DataTag<TQueryKey, TQueryFnData, TError>\n}\n\nexport function queryOptions(options: unknown) {\n  return options\n}\n"
  },
  {
    "path": "packages/preact-query/src/suspense.ts",
    "content": "import type {\n  DefaultError,\n  DefaultedQueryObserverOptions,\n  Query,\n  QueryKey,\n  QueryObserver,\n  QueryObserverResult,\n} from '@tanstack/query-core'\n\nimport type { QueryErrorResetBoundaryValue } from './QueryErrorResetBoundary'\n\nexport const defaultThrowOnError = <\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  _error: TError,\n  query: Query<TQueryFnData, TError, TData, TQueryKey>,\n) => query.state.data === undefined\n\nexport const ensureSuspenseTimers = (\n  defaultedOptions: DefaultedQueryObserverOptions<any, any, any, any, any>,\n) => {\n  if (defaultedOptions.suspense) {\n    // Handle staleTime to ensure minimum 1000ms in Suspense mode\n    // This prevents unnecessary refetching when components remount after suspending\n    const MIN_SUSPENSE_TIME_MS = 1000\n\n    const clamp = (value: number | 'static' | undefined) =>\n      value === 'static'\n        ? value\n        : Math.max(value ?? MIN_SUSPENSE_TIME_MS, MIN_SUSPENSE_TIME_MS)\n\n    const originalStaleTime = defaultedOptions.staleTime\n    defaultedOptions.staleTime =\n      typeof originalStaleTime === 'function'\n        ? (...args) => clamp(originalStaleTime(...args))\n        : clamp(originalStaleTime)\n\n    if (typeof defaultedOptions.gcTime === 'number') {\n      defaultedOptions.gcTime = Math.max(\n        defaultedOptions.gcTime,\n        MIN_SUSPENSE_TIME_MS,\n      )\n    }\n  }\n}\n\nexport const willFetch = (\n  result: QueryObserverResult<any, any>,\n  isRestoring: boolean,\n) => result.isLoading && result.isFetching && !isRestoring\n\nexport const shouldSuspend = (\n  defaultedOptions:\n    | DefaultedQueryObserverOptions<any, any, any, any, any>\n    | undefined,\n  result: QueryObserverResult<any, any>,\n) => defaultedOptions?.suspense && result.isPending\n\nexport const fetchOptimistic = <\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryData,\n  TQueryKey extends QueryKey,\n>(\n  defaultedOptions: DefaultedQueryObserverOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryData,\n    TQueryKey\n  >,\n  observer: QueryObserver<TQueryFnData, TError, TData, TQueryData, TQueryKey>,\n  errorResetBoundary: QueryErrorResetBoundaryValue,\n) =>\n  observer.fetchOptimistic(defaultedOptions).catch(() => {\n    errorResetBoundary.clearReset()\n  })\n"
  },
  {
    "path": "packages/preact-query/src/types.ts",
    "content": "/* istanbul ignore file */\nimport type {\n  DefaultError,\n  DefinedInfiniteQueryObserverResult,\n  DefinedQueryObserverResult,\n  DistributiveOmit,\n  FetchQueryOptions,\n  InfiniteQueryObserverOptions,\n  InfiniteQueryObserverResult,\n  MutateFunction,\n  MutationObserverOptions,\n  MutationObserverResult,\n  OmitKeyof,\n  Override,\n  QueryKey,\n  QueryObserverOptions,\n  QueryObserverResult,\n  SkipToken,\n} from '@tanstack/query-core'\n\nexport type AnyUseBaseQueryOptions = UseBaseQueryOptions<\n  any,\n  any,\n  any,\n  any,\n  any\n>\nexport interface UseBaseQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> extends QueryObserverOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryData,\n  TQueryKey\n> {\n  /**\n   * Set this to `false` to unsubscribe this observer from updates to the query cache.\n   * Defaults to `true`.\n   */\n  subscribed?: boolean\n}\n\nexport interface UsePrefetchQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> extends OmitKeyof<\n  FetchQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  'queryFn'\n> {\n  queryFn?: Exclude<\n    FetchQueryOptions<TQueryFnData, TError, TData, TQueryKey>['queryFn'],\n    SkipToken\n  >\n}\n\nexport type AnyUseQueryOptions = UseQueryOptions<any, any, any, any>\nexport interface UseQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> extends OmitKeyof<\n  UseBaseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>,\n  'suspense'\n> {}\n\nexport type AnyUseSuspenseQueryOptions = UseSuspenseQueryOptions<\n  any,\n  any,\n  any,\n  any\n>\nexport interface UseSuspenseQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> extends OmitKeyof<\n  UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  'queryFn' | 'enabled' | 'throwOnError' | 'placeholderData'\n> {\n  queryFn?: Exclude<\n    UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>['queryFn'],\n    SkipToken\n  >\n}\n\nexport type AnyUseInfiniteQueryOptions = UseInfiniteQueryOptions<\n  any,\n  any,\n  any,\n  any,\n  any\n>\nexport interface UseInfiniteQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> extends OmitKeyof<\n  InfiniteQueryObserverOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n  'suspense'\n> {\n  /**\n   * Set this to `false` to unsubscribe this observer from updates to the query cache.\n   * Defaults to `true`.\n   */\n  subscribed?: boolean\n}\n\nexport type AnyUseSuspenseInfiniteQueryOptions =\n  UseSuspenseInfiniteQueryOptions<any, any, any, any, any>\nexport interface UseSuspenseInfiniteQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> extends OmitKeyof<\n  UseInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>,\n  'queryFn' | 'enabled' | 'throwOnError' | 'placeholderData'\n> {\n  queryFn?: Exclude<\n    UseInfiniteQueryOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey,\n      TPageParam\n    >['queryFn'],\n    SkipToken\n  >\n}\n\nexport type UseBaseQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = QueryObserverResult<TData, TError>\n\nexport type UseQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = UseBaseQueryResult<TData, TError>\n\nexport type UseSuspenseQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = DistributiveOmit<\n  DefinedQueryObserverResult<TData, TError>,\n  'isPlaceholderData' | 'promise'\n>\n\nexport type DefinedUseQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = DefinedQueryObserverResult<TData, TError>\n\nexport type UseInfiniteQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = InfiniteQueryObserverResult<TData, TError>\n\nexport type DefinedUseInfiniteQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = DefinedInfiniteQueryObserverResult<TData, TError>\n\nexport type UseSuspenseInfiniteQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = OmitKeyof<\n  DefinedInfiniteQueryObserverResult<TData, TError>,\n  'isPlaceholderData' | 'promise'\n>\n\nexport type AnyUseMutationOptions = UseMutationOptions<any, any, any, any>\nexport interface UseMutationOptions<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> extends OmitKeyof<\n  MutationObserverOptions<TData, TError, TVariables, TOnMutateResult>,\n  '_defaulted'\n> {}\n\nexport type UseMutateFunction<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> = (\n  ...args: Parameters<\n    MutateFunction<TData, TError, TVariables, TOnMutateResult>\n  >\n) => void\n\nexport type UseMutateAsyncFunction<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> = MutateFunction<TData, TError, TVariables, TOnMutateResult>\n\nexport type UseBaseMutationResult<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = unknown,\n  TOnMutateResult = unknown,\n> = Override<\n  MutationObserverResult<TData, TError, TVariables, TOnMutateResult>,\n  { mutate: UseMutateFunction<TData, TError, TVariables, TOnMutateResult> }\n> & {\n  mutateAsync: UseMutateAsyncFunction<\n    TData,\n    TError,\n    TVariables,\n    TOnMutateResult\n  >\n}\n\nexport type UseMutationResult<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = unknown,\n  TOnMutateResult = unknown,\n> = UseBaseMutationResult<TData, TError, TVariables, TOnMutateResult>\n"
  },
  {
    "path": "packages/preact-query/src/useBaseQuery.ts",
    "content": "import { environmentManager, noop, notifyManager } from '@tanstack/query-core'\nimport type {\n  QueryClient,\n  QueryKey,\n  QueryObserver,\n  QueryObserverResult,\n} from '@tanstack/query-core'\nimport { useCallback, useEffect, useState } from 'preact/hooks'\n\nimport { useIsRestoring } from './IsRestoringProvider'\nimport { useQueryClient } from './QueryClientProvider'\nimport { useQueryErrorResetBoundary } from './QueryErrorResetBoundary'\nimport {\n  ensurePreventErrorBoundaryRetry,\n  getHasError,\n  useClearResetErrorBoundary,\n} from './errorBoundaryUtils'\nimport {\n  ensureSuspenseTimers,\n  fetchOptimistic,\n  shouldSuspend,\n  willFetch,\n} from './suspense'\nimport type { UseBaseQueryOptions } from './types'\nimport { useSyncExternalStore } from './utils'\n\nexport function useBaseQuery<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryData,\n  TQueryKey extends QueryKey,\n>(\n  options: UseBaseQueryOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryData,\n    TQueryKey\n  >,\n  Observer: typeof QueryObserver,\n  queryClient?: QueryClient,\n): QueryObserverResult<TData, TError> {\n  if (process.env.NODE_ENV !== 'production') {\n    if (typeof options !== 'object' || Array.isArray(options)) {\n      throw new Error(\n        'Bad argument type. Starting with v5, only the \"Object\" form is allowed when calling query related functions. Please use the error stack to find the culprit call. More info here: https://tanstack.com/query/latest/docs/react/guides/migrating-to-v5#supports-a-single-signature-one-object',\n      )\n    }\n  }\n\n  const isRestoring = useIsRestoring()\n  const errorResetBoundary = useQueryErrorResetBoundary()\n  const client = useQueryClient(queryClient)\n  const defaultedOptions = client.defaultQueryOptions(options)\n\n  ;(client.getDefaultOptions().queries as any)?._experimental_beforeQuery?.(\n    defaultedOptions,\n  )\n\n  if (process.env.NODE_ENV !== 'production') {\n    if (!defaultedOptions.queryFn) {\n      console.error(\n        `[${defaultedOptions.queryHash}]: No queryFn was passed as an option, and no default queryFn was found. The queryFn parameter is only optional when using a default queryFn. More info here: https://tanstack.com/query/latest/docs/framework/react/guides/default-query-function`,\n      )\n    }\n  }\n\n  // Make sure results are optimistically set in fetching state before subscribing or updating options\n  defaultedOptions._optimisticResults = isRestoring\n    ? 'isRestoring'\n    : 'optimistic'\n\n  ensureSuspenseTimers(defaultedOptions)\n  ensurePreventErrorBoundaryRetry(defaultedOptions, errorResetBoundary)\n\n  useClearResetErrorBoundary(errorResetBoundary)\n\n  // this needs to be invoked before creating the Observer because that can create a cache entry\n  const isNewCacheEntry = !client\n    .getQueryCache()\n    .get(defaultedOptions.queryHash)\n\n  const [observer] = useState(\n    () =>\n      new Observer<TQueryFnData, TError, TData, TQueryData, TQueryKey>(\n        client,\n        defaultedOptions,\n      ),\n  )\n\n  // note: this must be called before useSyncExternalStore\n  const result = observer.getOptimisticResult(defaultedOptions)\n\n  const shouldSubscribe = !isRestoring && options.subscribed !== false\n  useSyncExternalStore(\n    useCallback(\n      (onStoreChange) => {\n        const unsubscribe = shouldSubscribe\n          ? observer.subscribe(notifyManager.batchCalls(onStoreChange))\n          : noop\n\n        // Update result to make sure we did not miss any query updates\n        // between creating the observer and subscribing to it.\n        observer.updateResult()\n\n        return unsubscribe\n      },\n      [observer, shouldSubscribe],\n    ),\n    () => observer.getCurrentResult(),\n  )\n\n  useEffect(() => {\n    observer.setOptions(defaultedOptions)\n  }, [defaultedOptions, observer])\n\n  // Handle suspense\n  if (shouldSuspend(defaultedOptions, result)) {\n    throw fetchOptimistic(defaultedOptions, observer, errorResetBoundary)\n  }\n\n  // Handle error boundary\n  if (\n    getHasError({\n      result,\n      errorResetBoundary,\n      throwOnError: defaultedOptions.throwOnError,\n      query: client\n        .getQueryCache()\n        .get<\n          TQueryFnData,\n          TError,\n          TQueryData,\n          TQueryKey\n        >(defaultedOptions.queryHash),\n      suspense: defaultedOptions.suspense,\n    })\n  ) {\n    throw result.error\n  }\n\n  ;(client.getDefaultOptions().queries as any)?._experimental_afterQuery?.(\n    defaultedOptions,\n    result,\n  )\n\n  if (\n    defaultedOptions.experimental_prefetchInRender &&\n    !environmentManager.isServer() &&\n    willFetch(result, isRestoring)\n  ) {\n    const promise = isNewCacheEntry\n      ? // Fetch immediately on render in order to ensure `.promise` is resolved even if the component is unmounted\n        fetchOptimistic(defaultedOptions, observer, errorResetBoundary)\n      : // subscribe to the \"cache promise\" so that we can finalize the currentThenable once data comes in\n        client.getQueryCache().get(defaultedOptions.queryHash)?.promise\n\n    promise?.catch(noop).finally(() => {\n      // `.updateResult()` will trigger `.#currentThenable` to finalize\n      observer.updateResult()\n    })\n  }\n\n  // Handle result property usage tracking\n  return !defaultedOptions.notifyOnChangeProps\n    ? observer.trackResult(result)\n    : result\n}\n"
  },
  {
    "path": "packages/preact-query/src/useInfiniteQuery.ts",
    "content": "import { InfiniteQueryObserver } from '@tanstack/query-core'\nimport type {\n  DefaultError,\n  InfiniteData,\n  QueryClient,\n  QueryKey,\n  QueryObserver,\n} from '@tanstack/query-core'\n\nimport type {\n  DefinedInitialDataInfiniteOptions,\n  UndefinedInitialDataInfiniteOptions,\n} from './infiniteQueryOptions'\nimport type {\n  DefinedUseInfiniteQueryResult,\n  UseInfiniteQueryOptions,\n  UseInfiniteQueryResult,\n} from './types'\nimport { useBaseQuery } from './useBaseQuery'\n\nexport function useInfiniteQuery<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: DefinedInitialDataInfiniteOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n  queryClient?: QueryClient,\n): DefinedUseInfiniteQueryResult<TData, TError>\n\nexport function useInfiniteQuery<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: UndefinedInitialDataInfiniteOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n  queryClient?: QueryClient,\n): UseInfiniteQueryResult<TData, TError>\n\nexport function useInfiniteQuery<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: UseInfiniteQueryOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n  queryClient?: QueryClient,\n): UseInfiniteQueryResult<TData, TError>\n\nexport function useInfiniteQuery(\n  options: UseInfiniteQueryOptions,\n  queryClient?: QueryClient,\n) {\n  return useBaseQuery(\n    options,\n    InfiniteQueryObserver as typeof QueryObserver,\n    queryClient,\n  )\n}\n"
  },
  {
    "path": "packages/preact-query/src/useIsFetching.ts",
    "content": "import { notifyManager } from '@tanstack/query-core'\nimport type { QueryClient, QueryFilters } from '@tanstack/query-core'\nimport { useCallback } from 'preact/hooks'\n\nimport { useQueryClient } from './QueryClientProvider'\nimport { useSyncExternalStore } from './utils'\n\nexport function useIsFetching(\n  filters?: QueryFilters,\n  queryClient?: QueryClient,\n): number {\n  const client = useQueryClient(queryClient)\n  const queryCache = client.getQueryCache()\n\n  return useSyncExternalStore(\n    useCallback(\n      (onStoreChange) =>\n        queryCache.subscribe(notifyManager.batchCalls(onStoreChange)),\n      [queryCache],\n    ),\n    () => client.isFetching(filters),\n  )\n}\n"
  },
  {
    "path": "packages/preact-query/src/useMutation.ts",
    "content": "import {\n  MutationObserver,\n  noop,\n  notifyManager,\n  shouldThrowError,\n} from '@tanstack/query-core'\nimport type { DefaultError, QueryClient } from '@tanstack/query-core'\nimport { useCallback, useEffect, useState } from 'preact/hooks'\n\nimport { useQueryClient } from './QueryClientProvider'\nimport type {\n  UseMutateFunction,\n  UseMutationOptions,\n  UseMutationResult,\n} from './types'\nimport { useSyncExternalStore } from './utils'\n\n// HOOK\n\nexport function useMutation<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n>(\n  options: UseMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n  queryClient?: QueryClient,\n): UseMutationResult<TData, TError, TVariables, TOnMutateResult> {\n  const client = useQueryClient(queryClient)\n\n  const [observer] = useState(\n    () =>\n      new MutationObserver<TData, TError, TVariables, TOnMutateResult>(\n        client,\n        options,\n      ),\n  )\n\n  useEffect(() => {\n    observer.setOptions(options)\n  }, [observer, options])\n\n  const result = useSyncExternalStore(\n    useCallback(\n      (onStoreChange) =>\n        observer.subscribe(notifyManager.batchCalls(onStoreChange)),\n      [observer],\n    ),\n    () => observer.getCurrentResult(),\n  )\n\n  const mutate = useCallback<\n    UseMutateFunction<TData, TError, TVariables, TOnMutateResult>\n  >(\n    (variables, mutateOptions) => {\n      observer.mutate(variables, mutateOptions).catch(noop)\n    },\n    [observer],\n  )\n\n  if (\n    result.error &&\n    shouldThrowError(observer.options.throwOnError, [result.error])\n  ) {\n    throw result.error\n  }\n\n  return { ...result, mutate, mutateAsync: result.mutate }\n}\n"
  },
  {
    "path": "packages/preact-query/src/useMutationState.ts",
    "content": "import { notifyManager, replaceEqualDeep } from '@tanstack/query-core'\nimport type {\n  Mutation,\n  MutationCache,\n  MutationFilters,\n  MutationState,\n  QueryClient,\n} from '@tanstack/query-core'\nimport { useCallback, useEffect, useRef } from 'preact/hooks'\n\nimport { useQueryClient } from './QueryClientProvider'\nimport { useSyncExternalStore } from './utils'\n\nexport function useIsMutating(\n  filters?: MutationFilters,\n  queryClient?: QueryClient,\n): number {\n  const client = useQueryClient(queryClient)\n  return useMutationState(\n    { filters: { ...filters, status: 'pending' } },\n    client,\n  ).length\n}\n\ntype MutationStateOptions<TResult = MutationState> = {\n  filters?: MutationFilters\n  select?: (mutation: Mutation) => TResult\n}\n\nfunction getResult<TResult = MutationState>(\n  mutationCache: MutationCache,\n  options: MutationStateOptions<TResult>,\n): Array<TResult> {\n  return mutationCache\n    .findAll(options.filters)\n    .map(\n      (mutation): TResult =>\n        (options.select ? options.select(mutation) : mutation.state) as TResult,\n    )\n}\n\nexport function useMutationState<TResult = MutationState>(\n  options: MutationStateOptions<TResult> = {},\n  queryClient?: QueryClient,\n): Array<TResult> {\n  const mutationCache = useQueryClient(queryClient).getMutationCache()\n  const optionsRef = useRef(options)\n  const result = useRef<Array<TResult>>(null)\n  if (result.current === null) {\n    result.current = getResult(mutationCache, options)\n  }\n\n  useEffect(() => {\n    optionsRef.current = options\n  })\n\n  return useSyncExternalStore(\n    useCallback(\n      (onStoreChange) =>\n        mutationCache.subscribe(() => {\n          const nextResult = replaceEqualDeep(\n            result.current,\n            getResult(mutationCache, optionsRef.current),\n          )\n          if (result.current !== nextResult) {\n            result.current = nextResult\n            notifyManager.schedule(onStoreChange)\n          }\n        }),\n      [mutationCache],\n    ),\n    () => result.current,\n  )!\n}\n"
  },
  {
    "path": "packages/preact-query/src/usePrefetchInfiniteQuery.tsx",
    "content": "import type {\n  DefaultError,\n  FetchInfiniteQueryOptions,\n  QueryClient,\n  QueryKey,\n} from '@tanstack/query-core'\n\nimport { useQueryClient } from './QueryClientProvider'\n\nexport function usePrefetchInfiniteQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: FetchInfiniteQueryOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n  queryClient?: QueryClient,\n) {\n  const client = useQueryClient(queryClient)\n\n  if (!client.getQueryState(options.queryKey)) {\n    client.prefetchInfiniteQuery(options)\n  }\n}\n"
  },
  {
    "path": "packages/preact-query/src/usePrefetchQuery.tsx",
    "content": "import type { DefaultError, QueryClient, QueryKey } from '@tanstack/query-core'\n\nimport { useQueryClient } from './QueryClientProvider'\nimport type { UsePrefetchQueryOptions } from './types'\n\nexport function usePrefetchQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: UsePrefetchQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  queryClient?: QueryClient,\n) {\n  const client = useQueryClient(queryClient)\n\n  if (!client.getQueryState(options.queryKey)) {\n    client.prefetchQuery(options)\n  }\n}\n"
  },
  {
    "path": "packages/preact-query/src/useQueries.ts",
    "content": "import {\n  QueriesObserver,\n  QueryObserver,\n  noop,\n  notifyManager,\n} from '@tanstack/query-core'\nimport type {\n  DefaultError,\n  OmitKeyof,\n  QueriesObserverOptions,\n  QueriesPlaceholderDataFunction,\n  QueryClient,\n  QueryFunction,\n  QueryKey,\n  QueryObserverOptions,\n  ThrowOnError,\n} from '@tanstack/query-core'\nimport { useCallback, useEffect, useMemo, useState } from 'preact/hooks'\n\nimport { useIsRestoring } from './IsRestoringProvider'\nimport { useQueryClient } from './QueryClientProvider'\nimport { useQueryErrorResetBoundary } from './QueryErrorResetBoundary'\nimport {\n  ensurePreventErrorBoundaryRetry,\n  getHasError,\n  useClearResetErrorBoundary,\n} from './errorBoundaryUtils'\nimport {\n  ensureSuspenseTimers,\n  fetchOptimistic,\n  shouldSuspend,\n} from './suspense'\nimport type {\n  DefinedUseQueryResult,\n  UseQueryOptions,\n  UseQueryResult,\n} from './types'\nimport { useSyncExternalStore } from './utils'\n\n// This defines the `UseQueryOptions` that are accepted in `QueriesOptions` & `GetOptions`.\n// `placeholderData` function always gets undefined passed\ntype UseQueryOptionsForUseQueries<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = OmitKeyof<\n  UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  'placeholderData' | 'subscribed'\n> & {\n  placeholderData?: TQueryFnData | QueriesPlaceholderDataFunction<TQueryFnData>\n}\n\n// Avoid TS depth-limit error in case of large array literal\ntype MAXIMUM_DEPTH = 20\n\n// Widen the type of the symbol to enable type inference even if skipToken is not immutable.\ntype SkipTokenForUseQueries = symbol\n\ntype GetUseQueryOptionsForUseQueries<T> =\n  // Part 1: responsible for applying explicit type parameter to function arguments, if object { queryFnData: TQueryFnData, error: TError, data: TData }\n  T extends {\n    queryFnData: infer TQueryFnData\n    error?: infer TError\n    data: infer TData\n  }\n    ? UseQueryOptionsForUseQueries<TQueryFnData, TError, TData>\n    : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n      ? UseQueryOptionsForUseQueries<TQueryFnData, TError>\n      : T extends { data: infer TData; error?: infer TError }\n        ? UseQueryOptionsForUseQueries<unknown, TError, TData>\n        : // Part 2: responsible for applying explicit type parameter to function arguments, if tuple [TQueryFnData, TError, TData]\n          T extends [infer TQueryFnData, infer TError, infer TData]\n          ? UseQueryOptionsForUseQueries<TQueryFnData, TError, TData>\n          : T extends [infer TQueryFnData, infer TError]\n            ? UseQueryOptionsForUseQueries<TQueryFnData, TError>\n            : T extends [infer TQueryFnData]\n              ? UseQueryOptionsForUseQueries<TQueryFnData>\n              : // Part 3: responsible for inferring and enforcing type if no explicit parameter was provided\n                T extends {\n                    queryFn?:\n                      | QueryFunction<infer TQueryFnData, infer TQueryKey>\n                      | SkipTokenForUseQueries\n                    select?: (data: any) => infer TData\n                    throwOnError?: ThrowOnError<any, infer TError, any, any>\n                  }\n                ? UseQueryOptionsForUseQueries<\n                    TQueryFnData,\n                    unknown extends TError ? DefaultError : TError,\n                    unknown extends TData ? TQueryFnData : TData,\n                    TQueryKey\n                  >\n                : // Fallback\n                  UseQueryOptionsForUseQueries\n\n// A defined initialData setting should return a DefinedUseQueryResult rather than UseQueryResult\ntype GetDefinedOrUndefinedQueryResult<T, TData, TError = unknown> = T extends {\n  initialData?: infer TInitialData\n}\n  ? unknown extends TInitialData\n    ? UseQueryResult<TData, TError>\n    : TInitialData extends TData\n      ? DefinedUseQueryResult<TData, TError>\n      : TInitialData extends () => infer TInitialDataResult\n        ? unknown extends TInitialDataResult\n          ? UseQueryResult<TData, TError>\n          : TInitialDataResult extends TData\n            ? DefinedUseQueryResult<TData, TError>\n            : UseQueryResult<TData, TError>\n        : UseQueryResult<TData, TError>\n  : UseQueryResult<TData, TError>\n\ntype GetUseQueryResult<T> =\n  // Part 1: responsible for mapping explicit type parameter to function result, if object\n  T extends { queryFnData: any; error?: infer TError; data: infer TData }\n    ? GetDefinedOrUndefinedQueryResult<T, TData, TError>\n    : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n      ? GetDefinedOrUndefinedQueryResult<T, TQueryFnData, TError>\n      : T extends { data: infer TData; error?: infer TError }\n        ? GetDefinedOrUndefinedQueryResult<T, TData, TError>\n        : // Part 2: responsible for mapping explicit type parameter to function result, if tuple\n          T extends [any, infer TError, infer TData]\n          ? GetDefinedOrUndefinedQueryResult<T, TData, TError>\n          : T extends [infer TQueryFnData, infer TError]\n            ? GetDefinedOrUndefinedQueryResult<T, TQueryFnData, TError>\n            : T extends [infer TQueryFnData]\n              ? GetDefinedOrUndefinedQueryResult<T, TQueryFnData>\n              : // Part 3: responsible for mapping inferred type to results, if no explicit parameter was provided\n                T extends {\n                    queryFn?:\n                      | QueryFunction<infer TQueryFnData, any>\n                      | SkipTokenForUseQueries\n                    select?: (data: any) => infer TData\n                    throwOnError?: ThrowOnError<any, infer TError, any, any>\n                  }\n                ? GetDefinedOrUndefinedQueryResult<\n                    T,\n                    unknown extends TData ? TQueryFnData : TData,\n                    unknown extends TError ? DefaultError : TError\n                  >\n                : // Fallback\n                  UseQueryResult\n\n/**\n * QueriesOptions reducer recursively unwraps function arguments to infer/enforce type param\n */\nexport type QueriesOptions<\n  T extends Array<any>,\n  TResults extends Array<any> = [],\n  TDepth extends ReadonlyArray<number> = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n  ? Array<UseQueryOptionsForUseQueries>\n  : T extends []\n    ? []\n    : T extends [infer Head]\n      ? [...TResults, GetUseQueryOptionsForUseQueries<Head>]\n      : T extends [infer Head, ...infer Tails]\n        ? QueriesOptions<\n            [...Tails],\n            [...TResults, GetUseQueryOptionsForUseQueries<Head>],\n            [...TDepth, 1]\n          >\n        : ReadonlyArray<unknown> extends T\n          ? T\n          : // If T is *some* array but we couldn't assign unknown[] to it, then it must hold some known/homogenous type!\n            // use this to infer the param types in the case of Array.map() argument\n            T extends Array<\n                UseQueryOptionsForUseQueries<\n                  infer TQueryFnData,\n                  infer TError,\n                  infer TData,\n                  infer TQueryKey\n                >\n              >\n            ? Array<\n                UseQueryOptionsForUseQueries<\n                  TQueryFnData,\n                  TError,\n                  TData,\n                  TQueryKey\n                >\n              >\n            : // Fallback\n              Array<UseQueryOptionsForUseQueries>\n\n/**\n * QueriesResults reducer recursively maps type param to results\n */\nexport type QueriesResults<\n  T extends Array<any>,\n  TResults extends Array<any> = [],\n  TDepth extends ReadonlyArray<number> = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n  ? Array<UseQueryResult>\n  : T extends []\n    ? []\n    : T extends [infer Head]\n      ? [...TResults, GetUseQueryResult<Head>]\n      : T extends [infer Head, ...infer Tails]\n        ? QueriesResults<\n            [...Tails],\n            [...TResults, GetUseQueryResult<Head>],\n            [...TDepth, 1]\n          >\n        : { [K in keyof T]: GetUseQueryResult<T[K]> }\n\nexport function useQueries<\n  T extends Array<any>,\n  TCombinedResult = QueriesResults<T>,\n>(\n  {\n    queries,\n    ...options\n  }: {\n    queries:\n      | readonly [...QueriesOptions<T>]\n      | readonly [...{ [K in keyof T]: GetUseQueryOptionsForUseQueries<T[K]> }]\n    combine?: (result: QueriesResults<T>) => TCombinedResult\n    subscribed?: boolean\n  },\n  queryClient?: QueryClient,\n): TCombinedResult {\n  const client = useQueryClient(queryClient)\n  const isRestoring = useIsRestoring()\n  const errorResetBoundary = useQueryErrorResetBoundary()\n\n  const defaultedQueries = useMemo(\n    () =>\n      queries.map((opts) => {\n        const defaultedOptions = client.defaultQueryOptions(\n          opts as QueryObserverOptions,\n        )\n\n        // Make sure the results are already in fetching state before subscribing or updating options\n        defaultedOptions._optimisticResults = isRestoring\n          ? 'isRestoring'\n          : 'optimistic'\n\n        return defaultedOptions\n      }),\n    [queries, client, isRestoring],\n  )\n\n  defaultedQueries.forEach((query) => {\n    ensureSuspenseTimers(query)\n    ensurePreventErrorBoundaryRetry(query, errorResetBoundary)\n  })\n\n  useClearResetErrorBoundary(errorResetBoundary)\n\n  const [observer] = useState(\n    () =>\n      new QueriesObserver<TCombinedResult>(\n        client,\n        defaultedQueries,\n        options as QueriesObserverOptions<TCombinedResult>,\n      ),\n  )\n\n  // note: this must be called before useSyncExternalStore\n  const [optimisticResult, getCombinedResult, trackResult] =\n    observer.getOptimisticResult(\n      defaultedQueries,\n      (options as QueriesObserverOptions<TCombinedResult>).combine,\n    )\n\n  const shouldSubscribe = !isRestoring && options.subscribed !== false\n  useSyncExternalStore(\n    useCallback(\n      (onStoreChange) =>\n        shouldSubscribe\n          ? observer.subscribe(notifyManager.batchCalls(onStoreChange))\n          : noop,\n      [observer, shouldSubscribe],\n    ),\n    () => observer.getCurrentResult(),\n  )\n\n  useEffect(() => {\n    observer.setQueries(\n      defaultedQueries,\n      options as QueriesObserverOptions<TCombinedResult>,\n    )\n  }, [defaultedQueries, options, observer])\n\n  const shouldAtLeastOneSuspend = optimisticResult.some((result, index) =>\n    shouldSuspend(defaultedQueries[index], result),\n  )\n\n  const suspensePromises = shouldAtLeastOneSuspend\n    ? optimisticResult.flatMap((result, index) => {\n        const opts = defaultedQueries[index]\n\n        if (opts && shouldSuspend(opts, result)) {\n          const queryObserver = new QueryObserver(client, opts)\n          return fetchOptimistic(opts, queryObserver, errorResetBoundary)\n        }\n        return []\n      })\n    : []\n\n  if (suspensePromises.length > 0) {\n    throw Promise.all(suspensePromises)\n  }\n  const firstSingleResultWhichShouldThrow = optimisticResult.find(\n    (result, index) => {\n      const query = defaultedQueries[index]\n      return (\n        query &&\n        getHasError({\n          result,\n          errorResetBoundary,\n          throwOnError: query.throwOnError,\n          query: client.getQueryCache().get(query.queryHash),\n          suspense: query.suspense,\n        })\n      )\n    },\n  )\n\n  if (firstSingleResultWhichShouldThrow?.error) {\n    throw firstSingleResultWhichShouldThrow.error\n  }\n\n  return getCombinedResult(trackResult())\n}\n"
  },
  {
    "path": "packages/preact-query/src/useQuery.ts",
    "content": "import { QueryObserver } from '@tanstack/query-core'\nimport type {\n  DefaultError,\n  NoInfer,\n  QueryClient,\n  QueryKey,\n} from '@tanstack/query-core'\n\nimport type {\n  DefinedInitialDataOptions,\n  UndefinedInitialDataOptions,\n} from './queryOptions'\nimport type {\n  DefinedUseQueryResult,\n  UseQueryOptions,\n  UseQueryResult,\n} from './types'\nimport { useBaseQuery } from './useBaseQuery'\n\nexport function useQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,\n  queryClient?: QueryClient,\n): DefinedUseQueryResult<NoInfer<TData>, TError>\n\nexport function useQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,\n  queryClient?: QueryClient,\n): UseQueryResult<NoInfer<TData>, TError>\n\nexport function useQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  queryClient?: QueryClient,\n): UseQueryResult<NoInfer<TData>, TError>\n\nexport function useQuery(options: UseQueryOptions, queryClient?: QueryClient) {\n  return useBaseQuery(options, QueryObserver, queryClient)\n}\n"
  },
  {
    "path": "packages/preact-query/src/useSuspenseInfiniteQuery.ts",
    "content": "import { InfiniteQueryObserver, skipToken } from '@tanstack/query-core'\nimport type {\n  DefaultError,\n  InfiniteData,\n  InfiniteQueryObserverSuccessResult,\n  QueryClient,\n  QueryKey,\n  QueryObserver,\n} from '@tanstack/query-core'\n\nimport { defaultThrowOnError } from './suspense'\nimport type {\n  UseSuspenseInfiniteQueryOptions,\n  UseSuspenseInfiniteQueryResult,\n} from './types'\nimport { useBaseQuery } from './useBaseQuery'\n\nexport function useSuspenseInfiniteQuery<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: UseSuspenseInfiniteQueryOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n  queryClient?: QueryClient,\n): UseSuspenseInfiniteQueryResult<TData, TError> {\n  if (process.env.NODE_ENV !== 'production') {\n    if ((options.queryFn as any) === skipToken) {\n      console.error('skipToken is not allowed for useSuspenseInfiniteQuery')\n    }\n  }\n\n  return useBaseQuery(\n    {\n      ...options,\n      enabled: true,\n      suspense: true,\n      throwOnError: defaultThrowOnError,\n    },\n    InfiniteQueryObserver as typeof QueryObserver,\n    queryClient,\n  ) as InfiniteQueryObserverSuccessResult<TData, TError>\n}\n"
  },
  {
    "path": "packages/preact-query/src/useSuspenseQueries.ts",
    "content": "import { skipToken } from '@tanstack/query-core'\nimport type {\n  DefaultError,\n  QueryClient,\n  QueryFunction,\n  ThrowOnError,\n} from '@tanstack/query-core'\n\nimport { defaultThrowOnError } from './suspense'\nimport type { UseSuspenseQueryOptions, UseSuspenseQueryResult } from './types'\nimport { useQueries } from './useQueries'\n\n// Avoid TS depth-limit error in case of large array literal\ntype MAXIMUM_DEPTH = 20\n\n// Widen the type of the symbol to enable type inference even if skipToken is not immutable.\ntype SkipTokenForUseQueries = symbol\n\ntype GetUseSuspenseQueryOptions<T> =\n  // Part 1: responsible for applying explicit type parameter to function arguments, if object { queryFnData: TQueryFnData, error: TError, data: TData }\n  T extends {\n    queryFnData: infer TQueryFnData\n    error?: infer TError\n    data: infer TData\n  }\n    ? UseSuspenseQueryOptions<TQueryFnData, TError, TData>\n    : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n      ? UseSuspenseQueryOptions<TQueryFnData, TError>\n      : T extends { data: infer TData; error?: infer TError }\n        ? UseSuspenseQueryOptions<unknown, TError, TData>\n        : // Part 2: responsible for applying explicit type parameter to function arguments, if tuple [TQueryFnData, TError, TData]\n          T extends [infer TQueryFnData, infer TError, infer TData]\n          ? UseSuspenseQueryOptions<TQueryFnData, TError, TData>\n          : T extends [infer TQueryFnData, infer TError]\n            ? UseSuspenseQueryOptions<TQueryFnData, TError>\n            : T extends [infer TQueryFnData]\n              ? UseSuspenseQueryOptions<TQueryFnData>\n              : // Part 3: responsible for inferring and enforcing type if no explicit parameter was provided\n                T extends {\n                    queryFn?:\n                      | QueryFunction<infer TQueryFnData, infer TQueryKey>\n                      | SkipTokenForUseQueries\n                    select?: (data: any) => infer TData\n                    throwOnError?: ThrowOnError<any, infer TError, any, any>\n                  }\n                ? UseSuspenseQueryOptions<\n                    TQueryFnData,\n                    TError,\n                    TData,\n                    TQueryKey\n                  >\n                : T extends {\n                      queryFn?:\n                        | QueryFunction<infer TQueryFnData, infer TQueryKey>\n                        | SkipTokenForUseQueries\n                      throwOnError?: ThrowOnError<any, infer TError, any, any>\n                    }\n                  ? UseSuspenseQueryOptions<\n                      TQueryFnData,\n                      TError,\n                      TQueryFnData,\n                      TQueryKey\n                    >\n                  : // Fallback\n                    UseSuspenseQueryOptions\n\ntype GetUseSuspenseQueryResult<T> =\n  // Part 1: responsible for mapping explicit type parameter to function result, if object\n  T extends { queryFnData: any; error?: infer TError; data: infer TData }\n    ? UseSuspenseQueryResult<TData, TError>\n    : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n      ? UseSuspenseQueryResult<TQueryFnData, TError>\n      : T extends { data: infer TData; error?: infer TError }\n        ? UseSuspenseQueryResult<TData, TError>\n        : // Part 2: responsible for mapping explicit type parameter to function result, if tuple\n          T extends [any, infer TError, infer TData]\n          ? UseSuspenseQueryResult<TData, TError>\n          : T extends [infer TQueryFnData, infer TError]\n            ? UseSuspenseQueryResult<TQueryFnData, TError>\n            : T extends [infer TQueryFnData]\n              ? UseSuspenseQueryResult<TQueryFnData>\n              : // Part 3: responsible for mapping inferred type to results, if no explicit parameter was provided\n                T extends {\n                    queryFn?:\n                      | QueryFunction<infer TQueryFnData, any>\n                      | SkipTokenForUseQueries\n                    select?: (data: any) => infer TData\n                    throwOnError?: ThrowOnError<any, infer TError, any, any>\n                  }\n                ? UseSuspenseQueryResult<\n                    unknown extends TData ? TQueryFnData : TData,\n                    unknown extends TError ? DefaultError : TError\n                  >\n                : T extends {\n                      queryFn?:\n                        | QueryFunction<infer TQueryFnData, any>\n                        | SkipTokenForUseQueries\n                      throwOnError?: ThrowOnError<any, infer TError, any, any>\n                    }\n                  ? UseSuspenseQueryResult<\n                      TQueryFnData,\n                      unknown extends TError ? DefaultError : TError\n                    >\n                  : // Fallback\n                    UseSuspenseQueryResult\n\n/**\n * SuspenseQueriesOptions reducer recursively unwraps function arguments to infer/enforce type param\n */\nexport type SuspenseQueriesOptions<\n  T extends Array<any>,\n  TResults extends Array<any> = [],\n  TDepth extends ReadonlyArray<number> = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n  ? Array<UseSuspenseQueryOptions>\n  : T extends []\n    ? []\n    : T extends [infer Head]\n      ? [...TResults, GetUseSuspenseQueryOptions<Head>]\n      : T extends [infer Head, ...infer Tails]\n        ? SuspenseQueriesOptions<\n            [...Tails],\n            [...TResults, GetUseSuspenseQueryOptions<Head>],\n            [...TDepth, 1]\n          >\n        : Array<unknown> extends T\n          ? T\n          : // If T is *some* array but we couldn't assign unknown[] to it, then it must hold some known/homogenous type!\n            // use this to infer the param types in the case of Array.map() argument\n            T extends Array<\n                UseSuspenseQueryOptions<\n                  infer TQueryFnData,\n                  infer TError,\n                  infer TData,\n                  infer TQueryKey\n                >\n              >\n            ? Array<\n                UseSuspenseQueryOptions<TQueryFnData, TError, TData, TQueryKey>\n              >\n            : // Fallback\n              Array<UseSuspenseQueryOptions>\n\n/**\n * SuspenseQueriesResults reducer recursively maps type param to results\n */\nexport type SuspenseQueriesResults<\n  T extends Array<any>,\n  TResults extends Array<any> = [],\n  TDepth extends ReadonlyArray<number> = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n  ? Array<UseSuspenseQueryResult>\n  : T extends []\n    ? []\n    : T extends [infer Head]\n      ? [...TResults, GetUseSuspenseQueryResult<Head>]\n      : T extends [infer Head, ...infer Tails]\n        ? SuspenseQueriesResults<\n            [...Tails],\n            [...TResults, GetUseSuspenseQueryResult<Head>],\n            [...TDepth, 1]\n          >\n        : { [K in keyof T]: GetUseSuspenseQueryResult<T[K]> }\n\nexport function useSuspenseQueries<\n  T extends Array<any>,\n  TCombinedResult = SuspenseQueriesResults<T>,\n>(\n  options: {\n    queries:\n      | readonly [...SuspenseQueriesOptions<T>]\n      | readonly [...{ [K in keyof T]: GetUseSuspenseQueryOptions<T[K]> }]\n    combine?: (result: SuspenseQueriesResults<T>) => TCombinedResult\n  },\n  queryClient?: QueryClient,\n): TCombinedResult\n\nexport function useSuspenseQueries<\n  T extends Array<any>,\n  TCombinedResult = SuspenseQueriesResults<T>,\n>(\n  options: {\n    queries: readonly [...SuspenseQueriesOptions<T>]\n    combine?: (result: SuspenseQueriesResults<T>) => TCombinedResult\n  },\n  queryClient?: QueryClient,\n): TCombinedResult\n\nexport function useSuspenseQueries(options: any, queryClient?: QueryClient) {\n  return useQueries(\n    {\n      ...options,\n      queries: options.queries.map((query: any) => {\n        if (process.env.NODE_ENV !== 'production') {\n          if (query.queryFn === skipToken) {\n            console.error('skipToken is not allowed for useSuspenseQueries')\n          }\n        }\n\n        return {\n          ...query,\n          suspense: true,\n          throwOnError: defaultThrowOnError,\n          enabled: true,\n          placeholderData: undefined,\n        }\n      }),\n    },\n    queryClient,\n  )\n}\n"
  },
  {
    "path": "packages/preact-query/src/useSuspenseQuery.ts",
    "content": "import { QueryObserver, skipToken } from '@tanstack/query-core'\nimport type { DefaultError, QueryClient, QueryKey } from '@tanstack/query-core'\n\nimport { defaultThrowOnError } from './suspense'\nimport type { UseSuspenseQueryOptions, UseSuspenseQueryResult } from './types'\nimport { useBaseQuery } from './useBaseQuery'\n\nexport function useSuspenseQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: UseSuspenseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  queryClient?: QueryClient,\n): UseSuspenseQueryResult<TData, TError> {\n  if (process.env.NODE_ENV !== 'production') {\n    if ((options.queryFn as any) === skipToken) {\n      console.error('skipToken is not allowed for useSuspenseQuery')\n    }\n  }\n\n  return useBaseQuery(\n    {\n      ...options,\n      enabled: true,\n      suspense: true,\n      throwOnError: defaultThrowOnError,\n      placeholderData: undefined,\n    },\n    QueryObserver,\n    queryClient,\n  ) as UseSuspenseQueryResult<TData, TError>\n}\n"
  },
  {
    "path": "packages/preact-query/src/utils.ts",
    "content": "import { useEffect, useLayoutEffect, useRef, useState } from 'preact/hooks'\n\n/**\n * This is taken from https://github.com/preactjs/preact/blob/main/compat/src/hooks.js#L8-L54\n * which is taken from https://github.com/facebook/react/blob/main/packages/use-sync-external-store/src/useSyncExternalStoreShimClient.js#L84\n * on a high level this cuts out the warnings, ... and attempts a smaller implementation.\n * This way we don't have to import preact/compat with side effects\n */\ntype InternalStore = {\n  _value: any\n  _getSnapshot: () => any\n}\ntype StoreRef = {\n  _instance: InternalStore\n}\nexport function useSyncExternalStore(\n  subscribe: (onStoreChange: () => void) => () => void,\n  getSnapshot: () => any,\n) {\n  const value = getSnapshot()\n\n  const [{ _instance }, forceUpdate] = useState<StoreRef>({\n    _instance: { _value: value, _getSnapshot: getSnapshot },\n  })\n\n  useLayoutEffect(() => {\n    _instance._value = value\n    _instance._getSnapshot = getSnapshot\n\n    if (didSnapshotChange(_instance)) {\n      forceUpdate({ _instance })\n    }\n  }, [subscribe, value, getSnapshot])\n\n  useEffect(() => {\n    if (didSnapshotChange(_instance)) {\n      forceUpdate({ _instance })\n    }\n\n    return subscribe(() => {\n      if (didSnapshotChange(_instance)) {\n        forceUpdate({ _instance })\n      }\n    })\n  }, [subscribe])\n\n  return value\n}\n\nfunction didSnapshotChange(inst: {\n  _getSnapshot: () => any\n  _value: any\n}): boolean {\n  const latestGetSnapshot = inst._getSnapshot\n  const prevValue = inst._value\n  try {\n    const nextValue = latestGetSnapshot()\n    return !Object.is(prevValue, nextValue)\n    // eslint-disable-next-line no-unused-vars\n  } catch (_error) {\n    return true\n  }\n}\n\nexport function useSyncExternalStoreWithSelector<TSnapshot, TSelected>(\n  subscribe: (onStoreChange: () => void) => () => void,\n  getSnapshot: () => TSnapshot,\n  selector: (snapshot: TSnapshot) => TSelected,\n  isEqual: (a: TSelected, b: TSelected) => boolean,\n): TSelected {\n  const selectedSnapshotRef = useRef<TSelected | undefined>()\n\n  const getSelectedSnapshot = () => {\n    const snapshot = getSnapshot()\n    const selected = selector(snapshot)\n\n    if (\n      selectedSnapshotRef.current === undefined ||\n      !isEqual(selectedSnapshotRef.current, selected)\n    ) {\n      selectedSnapshotRef.current = selected\n    }\n\n    return selectedSnapshotRef.current\n  }\n\n  return useSyncExternalStore(subscribe, getSelectedSnapshot)\n}\n"
  },
  {
    "path": "packages/preact-query/test-setup.ts",
    "content": "import { notifyManager } from '@tanstack/query-core'\nimport '@testing-library/jest-dom/vitest'\nimport { act, cleanup as cleanupRTL } from '@testing-library/preact'\nimport { afterEach } from 'vitest'\n\n// https://testing-library.com/docs/preact-testing-library/api#cleanup\nafterEach(() => {\n  cleanupRTL()\n})\n\n// Wrap notifications with act to make sure React knows about React Query updates\nnotifyManager.setNotifyFunction((fn) => {\n  act(fn)\n})\n"
  },
  {
    "path": "packages/preact-query/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\",\n    \"jsx\": \"react-jsx\",\n    \"jsxImportSource\": \"preact\"\n  },\n  \"include\": [\"src\", \"test-setup.ts\", \"*.config.*\", \"package.json\"]\n}\n"
  },
  {
    "path": "packages/preact-query/tsconfig.legacy.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"jsx\": \"react-jsx\",\n    \"outDir\": \"./dist-ts/legacy\"\n  },\n  \"include\": [\"src\"],\n  \"exclude\": [\"src/__tests__\"],\n  \"references\": [{ \"path\": \"../query-persist-client-core\" }]\n}\n"
  },
  {
    "path": "packages/preact-query/tsconfig.prod.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"incremental\": false,\n    \"composite\": false,\n    \"rootDir\": \"../../\"\n  }\n}\n"
  },
  {
    "path": "packages/preact-query/tsup.config.ts",
    "content": "import { defineConfig } from 'tsup'\n\nimport { legacyConfig, modernConfig } from './root.tsup.config.js'\n\nexport default defineConfig([\n  modernConfig({ entry: ['src/*.ts', 'src/*.tsx'] }),\n  legacyConfig({ entry: ['src/*.ts', 'src/*.tsx'] }),\n])\n"
  },
  {
    "path": "packages/preact-query/vite.config.ts",
    "content": "import preact from '@preact/preset-vite'\nimport { defineConfig } from 'vitest/config'\nimport type { UserConfig as ViteUserConfig } from 'vite'\n\nimport packageJson from './package.json'\n\nexport default defineConfig({\n  plugins: [preact() as ViteUserConfig['plugins']],\n  // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660\n  resolve: {\n    conditions: ['@tanstack/custom-condition'],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        conditions: ['@tanstack/custom-condition'],\n      },\n    },\n  },\n  test: {\n    name: packageJson.name,\n    dir: './src',\n    watch: false,\n    environment: 'jsdom',\n    setupFiles: ['test-setup.ts'],\n    coverage: {\n      enabled: true,\n      provider: 'istanbul',\n      include: ['src/**/*'],\n      exclude: ['src/__tests__/**'],\n    },\n    typecheck: { enabled: true },\n    restoreMocks: true,\n    retry: process.env.CI ? 3 : 0,\n  },\n})\n"
  },
  {
    "path": "packages/preact-query-devtools/.attw.json",
    "content": "{\n  \"ignoreRules\": [\"no-resolution\"]\n}\n"
  },
  {
    "path": "packages/preact-query-devtools/CHANGELOG.md",
    "content": "# @tanstack/preact-query-devtools\n\n## 5.92.0\n\n### Minor Changes\n\n- feat: Add preact query devtools ([#10119](https://github.com/TanStack/query/pull/10119))\n\n### Patch Changes\n\n- Updated dependencies [[`8fb3a5a`](https://github.com/TanStack/query/commit/8fb3a5a6f1b367f4bf4f148fa1ac073fbc1dcfbd)]:\n  - @tanstack/preact-query@5.92.0\n"
  },
  {
    "path": "packages/preact-query-devtools/eslint.config.js",
    "content": "// @ts-check\n// @ts-ignore: no types for eslint-config-preact\nimport preact from 'eslint-config-preact'\n// eslint-config-preact uses typescript-eslint under the hood\nimport tseslint from 'typescript-eslint'\n\nimport rootConfig from './root.eslint.config.js'\n\nexport default [\n  ...rootConfig,\n  ...preact,\n  {\n    files: ['**/*.{ts,tsx}'],\n    languageOptions: {\n      parser: tseslint.parser,\n      parserOptions: {\n        project: true,\n      },\n    },\n    plugins: {\n      'typescript-eslint': tseslint.plugin,\n    },\n    rules: {\n      // Disable base rule to prevent overload false positives\n      'no-redeclare': 'off',\n      'no-duplicate-imports': 'off',\n      'no-unused-vars': 'off',\n      'import/order': 'off',\n      'sort-imports': 'off',\n      'no-import-assign': 'off',\n      // TS-aware version handles overloads correctly\n      '@typescript-eslint/no-redeclare': 'error',\n      '@typescript-eslint/array-type': 'off',\n      '@typescript-eslint/no-unnecessary-type-assertion': 'off',\n      '@typescript-eslint/no-unnecessary-condition': 'off',\n    },\n  },\n]\n"
  },
  {
    "path": "packages/preact-query-devtools/package.json",
    "content": "{\n  \"name\": \"@tanstack/preact-query-devtools\",\n  \"version\": \"5.92.0\",\n  \"description\": \"Developer tools to interact with and visualize the TanStack/preact-query cache\",\n  \"author\": \"tannerlinsley\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/preact-query-devtools\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"scripts\": {\n    \"clean\": \"premove ./build ./coverage ./dist-ts\",\n    \"compile\": \"tsc --build\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:types\": \"npm-run-all --serial test:types:*\",\n    \"test:types:ts54\": \"node ../../node_modules/typescript54/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts55\": \"node ../../node_modules/typescript55/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts56\": \"node ../../node_modules/typescript56/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts57\": \"node ../../node_modules/typescript57/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts58\": \"node ../../node_modules/typescript58/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts59\": \"node ../../node_modules/typescript59/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:tscurrent\": \"tsc --build\",\n    \"test:types:ts60\": \"node ../../node_modules/typescript60/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:build\": \"publint --strict && attw --pack\",\n    \"build\": \"tsup --tsconfig tsconfig.prod.json\",\n    \"build:dev\": \"tsup --watch\"\n  },\n  \"type\": \"module\",\n  \"types\": \"build/legacy/index.d.ts\",\n  \"main\": \"build/legacy/index.cjs\",\n  \"module\": \"build/legacy/index.js\",\n  \"exports\": {\n    \".\": {\n      \"@tanstack/custom-condition\": \"./src/index.ts\",\n      \"import\": {\n        \"types\": \"./build/modern/index.d.ts\",\n        \"default\": \"./build/modern/index.js\"\n      },\n      \"require\": {\n        \"types\": \"./build/modern/index.d.cts\",\n        \"default\": \"./build/modern/index.cjs\"\n      }\n    },\n    \"./production\": {\n      \"import\": {\n        \"types\": \"./build/modern/production.d.ts\",\n        \"default\": \"./build/modern/production.js\"\n      },\n      \"require\": {\n        \"types\": \"./build/modern/production.d.cts\",\n        \"default\": \"./build/modern/production.cjs\"\n      }\n    },\n    \"./build/modern/production.js\": {\n      \"import\": {\n        \"types\": \"./build/modern/production.d.ts\",\n        \"default\": \"./build/modern/production.js\"\n      },\n      \"require\": {\n        \"types\": \"./build/modern/production.d.cts\",\n        \"default\": \"./build/modern/production.cjs\"\n      }\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"sideEffects\": false,\n  \"files\": [\n    \"build\",\n    \"src\",\n    \"!src/__tests__\"\n  ],\n  \"dependencies\": {\n    \"@tanstack/query-devtools\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"@preact/preset-vite\": \"^2.10.2\",\n    \"@tanstack/preact-query\": \"workspace:*\",\n    \"@testing-library/preact\": \"^3.2.4\",\n    \"eslint-config-preact\": \"^2.0.0\",\n    \"npm-run-all2\": \"^5.0.0\",\n    \"preact\": \"^10.28.0\",\n    \"typescript\": \"5.9.3\",\n    \"typescript-eslint\": \"^8.54.0\"\n  },\n  \"peerDependencies\": {\n    \"@tanstack/preact-query\": \"workspace:^\",\n    \"preact\": \"^10.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/preact-query-devtools/root.eslint.config.js",
    "content": "// @ts-check\n\n// @ts-ignore Needed due to moduleResolution Node vs Bundler\nimport { tanstackConfig } from '@tanstack/eslint-config'\nimport pluginCspell from '@cspell/eslint-plugin'\nimport vitest from '@vitest/eslint-plugin'\n\nexport default [\n  ...tanstackConfig,\n  {\n    name: 'tanstack/temp',\n    plugins: {\n      cspell: pluginCspell,\n    },\n    rules: {\n      'cspell/spellchecker': [\n        'warn',\n        {\n          cspell: {\n            words: [\n              'Promisable', // Our public interface\n              'TSES', // @typescript-eslint package's interface\n              'codemod', // We support our codemod\n              'combinate', // Library name\n              'datatag', // Query options tagging\n              'extralight', // Our public interface\n              'jscodeshift',\n              'refetches', // Query refetch operations\n              'retryer', // Our public interface\n              'solidjs', // Our target framework\n              'tabular-nums', // https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-numeric\n              'tanstack', // Our package scope\n              'todos', // Too general word to be caught as error\n              'tsqd', // Our public interface (TanStack Query Devtools shorthand)\n              'tsup', // We use tsup as builder\n              'typecheck', // Field of vite.config.ts\n              'vue-demi', // dependency of @tanstack/vue-query\n              'ɵkind', // Angular specific\n              'ɵproviders', // Angular specific\n            ],\n          },\n        },\n      ],\n      '@typescript-eslint/no-empty-function': 'off',\n      '@typescript-eslint/no-unsafe-function-type': 'off',\n      'no-case-declarations': 'off',\n      'prefer-const': 'off',\n    },\n  },\n  {\n    files: ['**/*.spec.ts*', '**/*.test.ts*', '**/*.test-d.ts*'],\n    plugins: { vitest },\n    rules: {\n      ...vitest.configs.recommended.rules,\n      'vitest/no-standalone-expect': [\n        'error',\n        {\n          additionalTestBlockFunctions: ['testIf'],\n        },\n      ],\n    },\n    settings: { vitest: { typecheck: true } },\n  },\n]\n"
  },
  {
    "path": "packages/preact-query-devtools/root.tsup.config.js",
    "content": "// @ts-check\n\nimport { esbuildPluginFilePathExtensions } from 'esbuild-plugin-file-path-extensions'\n\n/**\n * @param {Object} opts - Options for building configurations.\n * @param {string[]} opts.entry - The entry array.\n * @returns {import('tsup').Options}\n */\nexport function modernConfig(opts) {\n  return {\n    entry: opts.entry,\n    format: ['cjs', 'esm'],\n    target: ['chrome91', 'firefox90', 'edge91', 'safari15', 'ios15', 'opera77'],\n    outDir: 'build/modern',\n    experimentalDts: true,\n    sourcemap: true,\n    clean: true,\n    esbuildPlugins: [esbuildPluginFilePathExtensions({ esmExtension: 'js' })],\n  }\n}\n\n/**\n * @param {Object} opts - Options for building configurations.\n * @param {string[]} opts.entry - The entry array.\n * @returns {import('tsup').Options}\n */\nexport function legacyConfig(opts) {\n  return {\n    entry: opts.entry,\n    format: ['cjs', 'esm'],\n    target: ['es2020', 'node16'],\n    outDir: 'build/legacy',\n    experimentalDts: true,\n    sourcemap: true,\n    clean: true,\n    esbuildPlugins: [esbuildPluginFilePathExtensions({ esmExtension: 'js' })],\n  }\n}\n"
  },
  {
    "path": "packages/preact-query-devtools/src/PreactQueryDevtools.tsx",
    "content": "import { useRef, useState, useEffect } from 'preact/hooks'\nimport { onlineManager, useQueryClient } from '@tanstack/preact-query'\nimport { TanstackQueryDevtools } from '@tanstack/query-devtools'\nimport type {\n  DevtoolsButtonPosition,\n  DevtoolsErrorType,\n  DevtoolsPosition,\n  Theme,\n} from '@tanstack/query-devtools'\nimport type { QueryClient } from '@tanstack/preact-query'\nimport type { VNode } from 'preact'\n\nexport interface DevtoolsOptions {\n  /**\n   * Set this true if you want the dev tools to default to being open\n   */\n  initialIsOpen?: boolean\n  /**\n   * The position of the TanStack logo to open and close the devtools panel.\n   * Defaults to 'bottom-right'.\n   */\n  buttonPosition?: DevtoolsButtonPosition\n  /**\n   * The position of the Preact Query devtools panel.\n   * Defaults to 'bottom'.\n   */\n  position?: DevtoolsPosition\n  /**\n   * Use this to provide a custom QueryClient. Otherwise, the one from the\n   * nearest QueryClientProvider will be used.\n   */\n  client?: QueryClient\n  /**\n   * Use this to provide custom error type handlers for the devtools panel.\n   */\n  errorTypes?: Array<DevtoolsErrorType>\n  /**\n   * Use this to pass a nonce to the style tag that is added to the document\n   * head. This is useful if you are using a Content Security Policy (CSP)\n   * nonce to allow inline styles.\n   */\n  styleNonce?: string\n  /**\n   * Use this to render the devtools inside a Shadow DOM.\n   */\n  shadowDOMTarget?: ShadowRoot\n  /**\n   * Use this to hide disabled queries from the devtools panel.\n   */\n  hideDisabledQueries?: boolean\n  /**\n   * Use this to set the theme of the devtools panel.\n   * Defaults to 'system'.\n   */\n  theme?: Theme\n}\n\nexport function PreactQueryDevtools(props: DevtoolsOptions): VNode | null {\n  const queryClient = useQueryClient(props.client)\n  const ref = useRef<HTMLDivElement>(null)\n  const {\n    buttonPosition,\n    position,\n    initialIsOpen,\n    errorTypes,\n    styleNonce,\n    shadowDOMTarget,\n    hideDisabledQueries,\n    theme,\n  } = props\n  const [devtools] = useState(\n    () =>\n      new TanstackQueryDevtools({\n        client: queryClient,\n        queryFlavor: 'Preact Query',\n        version: '5',\n        onlineManager,\n        buttonPosition,\n        position,\n        initialIsOpen,\n        errorTypes,\n        styleNonce,\n        shadowDOMTarget,\n        hideDisabledQueries,\n        theme,\n      }),\n  )\n\n  useEffect(() => {\n    devtools.setClient(queryClient)\n  }, [queryClient, devtools])\n\n  useEffect(() => {\n    if (buttonPosition) {\n      devtools.setButtonPosition(buttonPosition)\n    }\n  }, [buttonPosition, devtools])\n\n  useEffect(() => {\n    if (position) {\n      devtools.setPosition(position)\n    }\n  }, [position, devtools])\n\n  useEffect(() => {\n    devtools.setInitialIsOpen(initialIsOpen || false)\n  }, [initialIsOpen, devtools])\n\n  useEffect(() => {\n    devtools.setErrorTypes(errorTypes || [])\n  }, [errorTypes, devtools])\n\n  useEffect(() => {\n    devtools.setTheme(theme)\n  }, [theme, devtools])\n\n  useEffect(() => {\n    if (ref.current) {\n      devtools.mount(ref.current)\n    }\n    return () => {\n      devtools.unmount()\n    }\n  }, [devtools])\n\n  return <div dir=\"ltr\" className=\"tsqd-parent-container\" ref={ref} />\n}\n"
  },
  {
    "path": "packages/preact-query-devtools/src/PreactQueryDevtoolsPanel.tsx",
    "content": "import { useRef, useState, useEffect } from 'preact/hooks'\nimport { onlineManager, useQueryClient } from '@tanstack/preact-query'\nimport { TanstackQueryDevtoolsPanel } from '@tanstack/query-devtools'\nimport type { DevtoolsErrorType, Theme } from '@tanstack/query-devtools'\nimport type { QueryClient } from '@tanstack/preact-query'\nimport type { JSX, VNode } from 'preact'\n\nexport interface DevtoolsPanelOptions {\n  /**\n   * Use this to provide a custom QueryClient. Otherwise, the one from the\n   * nearest QueryClientProvider will be used.\n   */\n  client?: QueryClient\n  /**\n   * Custom error types to be shown in the devtools.\n   */\n  errorTypes?: Array<DevtoolsErrorType>\n  /**\n   * Use this to pass a nonce to the style tag that is added to the document\n   * head. This is useful if you are using a Content Security Policy (CSP)\n   * nonce to allow inline styles.\n   */\n  styleNonce?: string\n  /**\n   * Use this to render the devtools inside a Shadow DOM.\n   */\n  shadowDOMTarget?: ShadowRoot\n  /**\n   * Custom styles for the devtools panel container.\n   */\n  style?: JSX.CSSProperties\n  /**\n   * Callback function when the devtools panel is closed.\n   */\n  onClose?: () => unknown\n  /**\n   * Use this to hide disabled queries from the devtools panel.\n   */\n  hideDisabledQueries?: boolean\n  /**\n   * Use this to set the theme of the devtools panel.\n   * Defaults to 'system'.\n   */\n  theme?: Theme\n}\n\nexport function PreactQueryDevtoolsPanel(\n  props: DevtoolsPanelOptions,\n): VNode | null {\n  const queryClient = useQueryClient(props.client)\n  const ref = useRef<HTMLDivElement>(null)\n  const {\n    errorTypes,\n    styleNonce,\n    shadowDOMTarget,\n    hideDisabledQueries,\n    theme,\n  } = props\n  const [devtools] = useState(\n    () =>\n      new TanstackQueryDevtoolsPanel({\n        client: queryClient,\n        queryFlavor: 'Preact Query',\n        version: '5',\n        onlineManager,\n        buttonPosition: 'bottom-left',\n        position: 'bottom',\n        initialIsOpen: true,\n        errorTypes,\n        styleNonce,\n        shadowDOMTarget,\n        onClose: props.onClose,\n        hideDisabledQueries,\n        theme,\n      }),\n  )\n\n  useEffect(() => {\n    devtools.setClient(queryClient)\n  }, [queryClient, devtools])\n\n  useEffect(() => {\n    devtools.setOnClose(props.onClose ?? (() => {}))\n  }, [props.onClose, devtools])\n\n  useEffect(() => {\n    devtools.setErrorTypes(errorTypes || [])\n  }, [errorTypes, devtools])\n\n  useEffect(() => {\n    devtools.setTheme(theme)\n  }, [theme, devtools])\n\n  useEffect(() => {\n    if (ref.current) {\n      devtools.mount(ref.current)\n    }\n    return () => {\n      devtools.unmount()\n    }\n  }, [devtools])\n\n  return (\n    <div\n      style={{ height: '500px', ...props.style }}\n      className=\"tsqd-parent-container\"\n      ref={ref}\n    />\n  )\n}\n"
  },
  {
    "path": "packages/preact-query-devtools/src/index.ts",
    "content": "import * as Devtools from './PreactQueryDevtools'\nimport * as DevtoolsPanel from './PreactQueryDevtoolsPanel'\n\nexport const PreactQueryDevtools: (typeof Devtools)['PreactQueryDevtools'] =\n  process.env.NODE_ENV !== 'development'\n    ? function () {\n        return null\n      }\n    : Devtools.PreactQueryDevtools\n\nexport const PreactQueryDevtoolsPanel: (typeof DevtoolsPanel)['PreactQueryDevtoolsPanel'] =\n  process.env.NODE_ENV !== 'development'\n    ? function () {\n        return null\n      }\n    : DevtoolsPanel.PreactQueryDevtoolsPanel\n\nexport type DevtoolsPanelOptions = DevtoolsPanel.DevtoolsPanelOptions\n"
  },
  {
    "path": "packages/preact-query-devtools/src/production.ts",
    "content": "import * as Devtools from './PreactQueryDevtools'\nimport * as DevtoolsPanel from './PreactQueryDevtoolsPanel'\n\nexport const PreactQueryDevtools = Devtools.PreactQueryDevtools\nexport const PreactQueryDevtoolsPanel = DevtoolsPanel.PreactQueryDevtoolsPanel\n"
  },
  {
    "path": "packages/preact-query-devtools/test-setup.ts",
    "content": "import '@testing-library/jest-dom/vitest'\nimport { act, cleanup as cleanupRTL } from '@testing-library/preact'\nimport { notifyManager } from '@tanstack/preact-query'\nimport { afterEach } from 'vitest'\n\n// https://testing-library.com/docs/preact-testing-library/api#cleanup\nafterEach(() => {\n  cleanupRTL()\n})\n\n// Wrap notifications with act to make sure Preact knows about Query updates\nnotifyManager.setNotifyFunction((fn) => {\n  act(fn)\n})\n"
  },
  {
    "path": "packages/preact-query-devtools/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\",\n    \"jsx\": \"react-jsx\",\n    \"jsxImportSource\": \"preact\"\n  },\n  \"include\": [\"src\", \"test-setup.ts\", \"*.config.*\", \"package.json\"],\n  \"references\": [{ \"path\": \"../query-devtools\" }, { \"path\": \"../preact-query\" }]\n}\n"
  },
  {
    "path": "packages/preact-query-devtools/tsconfig.legacy.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"jsx\": \"react-jsx\",\n    \"jsxImportSource\": \"preact\",\n    \"outDir\": \"./dist-ts/legacy\"\n  },\n  \"include\": [\"src\"],\n  \"exclude\": [\"src/__tests__\"],\n  \"references\": [{ \"path\": \"../query-devtools\" }, { \"path\": \"../preact-query\" }]\n}\n"
  },
  {
    "path": "packages/preact-query-devtools/tsconfig.prod.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"incremental\": false,\n    \"composite\": false,\n    \"rootDir\": \"../../\",\n    \"customConditions\": []\n  }\n}\n"
  },
  {
    "path": "packages/preact-query-devtools/tsup.config.ts",
    "content": "import { defineConfig } from 'tsup'\nimport { legacyConfig, modernConfig } from './root.tsup.config.js'\n\nexport default defineConfig([\n  modernConfig({ entry: ['src/*.ts', 'src/*.tsx'] }),\n  legacyConfig({ entry: ['src/*.ts', 'src/*.tsx'] }),\n])\n"
  },
  {
    "path": "packages/preact-query-devtools/vite.config.ts",
    "content": "import preact from '@preact/preset-vite'\nimport { defineConfig } from 'vitest/config'\nimport type { UserConfig as ViteUserConfig } from 'vite'\nimport packageJson from './package.json'\n\nexport default defineConfig({\n  plugins: [preact() as ViteUserConfig['plugins']],\n  resolve: { conditions: ['@tanstack/custom-condition'] },\n  environments: {\n    ssr: { resolve: { conditions: ['@tanstack/custom-condition'] } },\n  },\n  test: {\n    name: packageJson.name,\n    dir: './src',\n    watch: false,\n    environment: 'jsdom',\n    setupFiles: ['test-setup.ts'],\n    coverage: {\n      enabled: true,\n      provider: 'istanbul',\n      include: ['src/**/*'],\n      exclude: ['src/__tests__/**'],\n    },\n    typecheck: { enabled: true },\n    restoreMocks: true,\n  },\n})\n"
  },
  {
    "path": "packages/preact-query-persist-client/CHANGELOG.md",
    "content": "# @tanstack/preact-query-persist-client\n\n## 5.92.3\n\n### Patch Changes\n\n- fix(streamedQuery): maintain error state on reset refetch with initialData defined ([#10287](https://github.com/TanStack/query/pull/10287))\n\n- Updated dependencies [[`248975e`](https://github.com/TanStack/query/commit/248975e896f585f6eaa505c796e73fcf7bfd1eec)]:\n  - @tanstack/query-persist-client-core@5.92.4\n  - @tanstack/preact-query@5.94.2\n\n## 5.92.2\n\n### Patch Changes\n\n- Updated dependencies [[`a89aab9`](https://github.com/TanStack/query/commit/a89aab975581c25c113a26c8af486b4cafad272a)]:\n  - @tanstack/preact-query@5.94.1\n  - @tanstack/query-persist-client-core@5.92.3\n\n## 5.92.1\n\n### Patch Changes\n\n- Updated dependencies [[`6fa901b`](https://github.com/TanStack/query/commit/6fa901b97a22a80d0fca3f6ed86237ff0cbdd13b)]:\n  - @tanstack/preact-query@5.94.0\n  - @tanstack/query-persist-client-core@5.92.2\n\n## 5.92.0\n\n### Minor Changes\n\n- feat: Add preact persist plugin ([#10120](https://github.com/TanStack/query/pull/10120))\n\n### Patch Changes\n\n- Updated dependencies [[`887541a`](https://github.com/TanStack/query/commit/887541a2fa5eec801e53cc93c2831a55325ea44a)]:\n  - @tanstack/preact-query@5.93.0\n"
  },
  {
    "path": "packages/preact-query-persist-client/eslint.config.js",
    "content": "// @ts-check\n// @ts-ignore: no types for eslint-config-preact\nimport preact from 'eslint-config-preact'\n// eslint-config-preact uses typescript-eslint under the hood\nimport tseslint from 'typescript-eslint'\n\nimport rootConfig from './root.eslint.config.js'\n\nexport default [\n  ...rootConfig,\n  ...preact,\n  {\n    files: ['**/*.{ts,tsx}'],\n    languageOptions: {\n      parser: tseslint.parser,\n      parserOptions: {\n        project: true,\n      },\n    },\n    plugins: {\n      'typescript-eslint': tseslint.plugin,\n    },\n    rules: {\n      // Disable base rule to prevent overload false positives\n      'no-redeclare': 'off',\n      'no-duplicate-imports': 'off',\n      'no-unused-vars': 'off',\n      'import/order': 'off',\n      'sort-imports': 'off',\n      'no-import-assign': 'off',\n      // TS-aware version handles overloads correctly\n      '@typescript-eslint/no-redeclare': 'error',\n      '@typescript-eslint/array-type': 'off',\n      '@typescript-eslint/no-unnecessary-type-assertion': 'off',\n      '@typescript-eslint/no-unnecessary-condition': 'off',\n    },\n  },\n]\n"
  },
  {
    "path": "packages/preact-query-persist-client/package.json",
    "content": "{\n  \"name\": \"@tanstack/preact-query-persist-client\",\n  \"version\": \"5.92.3\",\n  \"description\": \"Preact bindings to work with persisters in TanStack/preact-query\",\n  \"author\": \"tannerlinsley\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/preact-query-persist-client\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"scripts\": {\n    \"clean\": \"premove ./build ./coverage ./dist-ts\",\n    \"compile\": \"tsc --build\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:types\": \"npm-run-all --serial test:types:*\",\n    \"test:types:ts54\": \"node ../../node_modules/typescript54/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts55\": \"node ../../node_modules/typescript55/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts56\": \"node ../../node_modules/typescript56/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts57\": \"node ../../node_modules/typescript57/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts58\": \"node ../../node_modules/typescript58/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts59\": \"node ../../node_modules/typescript59/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:tscurrent\": \"tsc --build\",\n    \"test:types:ts60\": \"node ../../node_modules/typescript60/lib/tsc.js --build\",\n    \"test:lib\": \"vitest --retry=3\",\n    \"test:lib:dev\": \"pnpm run test:lib --watch\",\n    \"test:build\": \"publint --strict && attw --pack\",\n    \"build\": \"tsup --tsconfig tsconfig.prod.json\"\n  },\n  \"type\": \"module\",\n  \"types\": \"build/legacy/index.d.ts\",\n  \"main\": \"build/legacy/index.cjs\",\n  \"module\": \"build/legacy/index.js\",\n  \"exports\": {\n    \".\": {\n      \"@tanstack/custom-condition\": \"./src/index.ts\",\n      \"import\": {\n        \"types\": \"./build/modern/index.d.ts\",\n        \"default\": \"./build/modern/index.js\"\n      },\n      \"require\": {\n        \"types\": \"./build/modern/index.d.cts\",\n        \"default\": \"./build/modern/index.cjs\"\n      }\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"sideEffects\": false,\n  \"files\": [\n    \"build\",\n    \"src\",\n    \"!src/__tests__\"\n  ],\n  \"dependencies\": {\n    \"@tanstack/query-persist-client-core\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"@preact/preset-vite\": \"^2.10.2\",\n    \"@tanstack/preact-query\": \"workspace:*\",\n    \"@tanstack/query-test-utils\": \"workspace:*\",\n    \"@testing-library/preact\": \"^3.2.4\",\n    \"eslint-config-preact\": \"^2.0.0\",\n    \"npm-run-all2\": \"^5.0.0\",\n    \"preact\": \"^10.28.0\",\n    \"typescript\": \"5.9.3\",\n    \"typescript-eslint\": \"^8.54.0\"\n  },\n  \"peerDependencies\": {\n    \"@tanstack/preact-query\": \"workspace:^\",\n    \"preact\": \"^10.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/preact-query-persist-client/src/PersistQueryClientProvider.tsx",
    "content": "import { useEffect, useRef, useState } from 'preact/hooks'\nimport type { VNode } from 'preact'\n\nimport {\n  persistQueryClientRestore,\n  persistQueryClientSubscribe,\n} from '@tanstack/query-persist-client-core'\nimport {\n  IsRestoringProvider,\n  QueryClientProvider,\n} from '@tanstack/preact-query'\nimport type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'\nimport type {\n  OmitKeyof,\n  QueryClientProviderProps,\n} from '@tanstack/preact-query'\n\nexport type PersistQueryClientProviderProps = QueryClientProviderProps & {\n  persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>\n  onSuccess?: () => Promise<unknown> | unknown\n  onError?: () => Promise<unknown> | unknown\n}\n\nexport const PersistQueryClientProvider = ({\n  children,\n  persistOptions,\n  onSuccess,\n  onError,\n  ...props\n}: PersistQueryClientProviderProps): VNode => {\n  const [isRestoring, setIsRestoring] = useState(true)\n  const refs = useRef({ persistOptions, onSuccess, onError })\n  const didRestore = useRef(false)\n\n  useEffect(() => {\n    refs.current = { persistOptions, onSuccess, onError }\n  })\n\n  useEffect(() => {\n    const options = {\n      ...refs.current.persistOptions,\n      queryClient: props.client,\n    }\n    if (!didRestore.current) {\n      didRestore.current = true\n      persistQueryClientRestore(options)\n        .then(() => refs.current.onSuccess?.())\n        .catch(() => refs.current.onError?.())\n        .finally(() => {\n          setIsRestoring(false)\n        })\n    }\n    return isRestoring ? undefined : persistQueryClientSubscribe(options)\n  }, [props.client, isRestoring])\n\n  return (\n    <QueryClientProvider {...props}>\n      <IsRestoringProvider value={isRestoring}>{children}</IsRestoringProvider>\n    </QueryClientProvider>\n  )\n}\n"
  },
  {
    "path": "packages/preact-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx",
    "content": "/** @jsxRuntime automatic */\n/** @jsxImportSource preact */\nimport '@testing-library/jest-dom/vitest'\n\nimport type {\n  PersistedClient,\n  Persister,\n} from '../../../query-persist-client-core/src'\nimport { persistQueryClientSave } from '../../../query-persist-client-core/src'\nimport { notifyManager } from '../../../query-core/src'\nimport { act, cleanup, render } from '@testing-library/preact'\nimport type { UseQueryResult } from '../../../preact-query/src'\nimport { QueryClient, useQuery } from '../../../preact-query/src'\nimport { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\n\nimport { PersistQueryClientProvider } from './testPersistProvider'\n\nnotifyManager.setNotifyFunction((fn) => {\n  act(fn)\n})\n\nconst createMockPersister = (): Persister => {\n  let storedState: PersistedClient | undefined\n\n  return {\n    persistClient(persistClient: PersistedClient) {\n      storedState = persistClient\n      return Promise.resolve()\n    },\n    async restoreClient() {\n      return sleep(10).then(() => storedState)\n    },\n    removeClient() {\n      storedState = undefined\n      return Promise.resolve()\n    },\n  }\n}\n\ndescribe('PersistQueryClientProvider (preact)', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    cleanup()\n    vi.useRealTimers()\n  })\n\n  test('restores cache from persister and refetches', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createMockPersister()\n\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'fetched'),\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <h1>{state.data}</h1>\n          <h2>fetchStatus: {state.fetchStatus}</h2>\n        </div>\n      )\n    }\n\n    const rendered = render(\n      <PersistQueryClientProvider\n        client={queryClient}\n        persistOptions={{ persister }}\n      >\n        <Page />\n      </PersistQueryClientProvider>,\n    )\n\n    expect(rendered.getByText('fetchStatus: idle')).toBeInTheDocument()\n\n    await act(async () => {\n      await vi.advanceTimersByTimeAsync(10)\n    })\n    expect(rendered.getByText('hydrated')).toBeInTheDocument()\n\n    await act(async () => {\n      await vi.advanceTimersByTimeAsync(11)\n    })\n    expect(rendered.getByText('fetched')).toBeInTheDocument()\n\n    expect(states.length).toBeGreaterThanOrEqual(3)\n    expect(states[0]).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'idle',\n      data: undefined,\n    })\n\n    expect(\n      states.some(\n        (state) =>\n          state.fetchStatus === 'fetching' && state.data === 'hydrated',\n      ),\n    ).toBe(true)\n\n    expect(states.at(-1)).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: 'fetched',\n    })\n  })\n})\n"
  },
  {
    "path": "packages/preact-query-persist-client/src/__tests__/testPersistProvider.tsx",
    "content": "/** @jsxRuntime automatic */\n/** @jsxImportSource preact */\nimport {\n  persistQueryClientRestore,\n  persistQueryClientSubscribe,\n} from '../../../query-persist-client-core/src'\nimport {\n  IsRestoringProvider,\n  QueryClientProvider,\n} from '../../../preact-query/src'\nimport type { ComponentChildren } from 'preact'\nimport { useEffect, useRef, useState } from 'preact/hooks'\n\ntype Props = {\n  children?: ComponentChildren\n  client: any\n  persistOptions: any\n  onSuccess?: () => void | Promise<void>\n  onError?: () => void\n}\n\nexport function PersistQueryClientProvider({\n  children,\n  persistOptions,\n  onSuccess,\n  onError,\n  ...props\n}: Props) {\n  const [isRestoring, setIsRestoring] = useState(true)\n  const refs = useRef({ persistOptions, onSuccess, onError })\n  const didRestore = useRef(false)\n\n  useEffect(() => {\n    refs.current = { persistOptions, onSuccess, onError }\n  })\n\n  useEffect(() => {\n    const options = {\n      ...refs.current.persistOptions,\n      queryClient: props.client,\n    }\n\n    if (!didRestore.current) {\n      didRestore.current = true\n      persistQueryClientRestore(options)\n        .then(() => refs.current.onSuccess?.())\n        .catch(() => refs.current.onError?.())\n        .finally(() => {\n          setIsRestoring(false)\n        })\n    }\n\n    return isRestoring ? undefined : persistQueryClientSubscribe(options)\n  }, [props.client, isRestoring])\n\n  return (\n    <QueryClientProvider {...props}>\n      <IsRestoringProvider value={isRestoring}>{children}</IsRestoringProvider>\n    </QueryClientProvider>\n  )\n}\n"
  },
  {
    "path": "packages/preact-query-persist-client/src/__tests__/use-queries-with-persist.test.tsx",
    "content": "/** @jsxRuntime automatic */\n/** @jsxImportSource preact */\nimport '@testing-library/jest-dom/vitest'\n\nimport type { QueryObserverResult } from '../../../query-core/src'\nimport { notifyManager } from '../../../query-core/src'\nimport type {\n  PersistedClient,\n  Persister,\n} from '../../../query-persist-client-core/src'\nimport { act, cleanup, render } from '@testing-library/preact'\nimport { QueryClient, useQueries } from '../../../preact-query/src'\nimport { useCallback } from 'preact/hooks'\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { sleep } from '@tanstack/query-test-utils'\n\nimport { PersistQueryClientProvider } from './testPersistProvider'\n\nnotifyManager.setNotifyFunction((fn) => {\n  act(fn)\n})\n\ndescribe('useQueries with persist and memoized combine (preact)', () => {\n  const storage: Record<string, string> = {}\n\n  beforeEach(() => {\n    vi.useFakeTimers()\n    Object.defineProperty(window, 'localStorage', {\n      value: {\n        getItem: (key: string) => storage[key] || null,\n        setItem: (key: string, value: string) => {\n          storage[key] = value\n        },\n        removeItem: (key: string) => {\n          delete storage[key]\n        },\n        clear: () => {\n          Object.keys(storage).forEach((key) => delete storage[key])\n        },\n      },\n      writable: true,\n    })\n  })\n\n  afterEach(() => {\n    cleanup()\n    vi.useRealTimers()\n    Object.keys(storage).forEach((key) => delete storage[key])\n  })\n\n  it('updates UI when combine is memoized with persisted results', async () => {\n    const queryClient = new QueryClient({\n      defaultOptions: {\n        queries: {\n          staleTime: 30_000,\n          gcTime: 1000 * 60 * 60 * 24,\n        },\n      },\n    })\n\n    const persister: Persister = {\n      persistClient: (client: PersistedClient) => {\n        storage.REACT_QUERY_OFFLINE_CACHE = JSON.stringify(client)\n        return Promise.resolve()\n      },\n      restoreClient: async () => {\n        const stored = storage.REACT_QUERY_OFFLINE_CACHE\n        if (stored) {\n          return sleep(10).then(() => JSON.parse(stored) as PersistedClient)\n        }\n\n        return undefined\n      },\n      removeClient: () => {\n        delete storage.REACT_QUERY_OFFLINE_CACHE\n        return Promise.resolve()\n      },\n    }\n\n    const persistedData: PersistedClient = {\n      timestamp: Date.now(),\n      buster: '',\n      clientState: {\n        mutations: [],\n        queries: [1, 2, 3].map((id) => ({\n          queryHash: `[\"post\",${id}]`,\n          queryKey: ['post', id],\n          state: {\n            data: id,\n            dataUpdateCount: 1,\n            dataUpdatedAt: Date.now() - 1000,\n            error: null,\n            errorUpdateCount: 0,\n            errorUpdatedAt: 0,\n            fetchFailureCount: 0,\n            fetchFailureReason: null,\n            fetchMeta: null,\n            isInvalidated: false,\n            status: 'success' as const,\n            fetchStatus: 'idle' as const,\n          },\n        })),\n      },\n    }\n\n    storage.REACT_QUERY_OFFLINE_CACHE = JSON.stringify(persistedData)\n\n    function TestComponent() {\n      const combinedQueries = useQueries({\n        queries: [1, 2, 3].map((id) => ({\n          queryKey: ['post', id],\n          queryFn: () => sleep(100).then(() => id),\n          staleTime: 30_000,\n        })),\n        combine: useCallback(\n          (results: Array<QueryObserverResult<number, Error>>) => ({\n            data: results.map((result) => result.data),\n            isPending: results.some((result) => result.isPending),\n          }),\n          [],\n        ),\n      })\n\n      return (\n        <div>\n          <div data-testid=\"pending\">{String(combinedQueries.isPending)}</div>\n          <div data-testid=\"data\">\n            {combinedQueries.data\n              .filter((value) => value !== undefined)\n              .join(',')}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = render(\n      <PersistQueryClientProvider\n        client={queryClient}\n        persistOptions={{ persister }}\n      >\n        <TestComponent />\n      </PersistQueryClientProvider>,\n    )\n\n    await act(async () => {\n      await vi.advanceTimersByTimeAsync(10)\n    })\n    await act(async () => {\n      await vi.advanceTimersByTimeAsync(0)\n    })\n\n    expect(rendered.getByTestId('pending').textContent).toBe('false')\n    expect(rendered.getByTestId('data').textContent).toBe('1,2,3')\n  })\n})\n"
  },
  {
    "path": "packages/preact-query-persist-client/src/index.ts",
    "content": "// Re-export core\nexport * from '@tanstack/query-persist-client-core'\n\nexport * from './PersistQueryClientProvider'\n"
  },
  {
    "path": "packages/preact-query-persist-client/test-setup.ts",
    "content": "import '@testing-library/jest-dom/vitest'\nimport { act, cleanup as cleanupRTL } from '@testing-library/preact'\nimport { afterEach } from 'vitest'\nimport { notifyManager } from '@tanstack/preact-query'\n\n// https://testing-library.com/docs/preact-testing-library/api#cleanup\nafterEach(() => {\n  cleanupRTL()\n})\n\n// Wrap notifications with act to make sure Preact knows about Query updates\nnotifyManager.setNotifyFunction((fn) => {\n  act(fn)\n})\n"
  },
  {
    "path": "packages/preact-query-persist-client/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\",\n    \"jsx\": \"react-jsx\",\n    \"jsxImportSource\": \"preact\"\n  },\n  \"include\": [\"src\", \"test-setup.ts\", \"*.config.*\", \"package.json\"],\n  \"references\": [\n    { \"path\": \"../query-persist-client-core\" },\n    { \"path\": \"../preact-query\" }\n  ]\n}\n"
  },
  {
    "path": "packages/preact-query-persist-client/tsconfig.legacy.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"jsx\": \"react-jsx\",\n    \"jsxImportSource\": \"preact\",\n    \"outDir\": \"./dist-ts/legacy\"\n  },\n  \"include\": [\"src\"],\n  \"exclude\": [\"src/__tests__\"],\n  \"references\": [\n    { \"path\": \"../query-persist-client-core\" },\n    { \"path\": \"../preact-query\" }\n  ]\n}\n"
  },
  {
    "path": "packages/preact-query-persist-client/tsconfig.prod.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"incremental\": false,\n    \"composite\": false,\n    \"rootDir\": \"../../\"\n  }\n}\n"
  },
  {
    "path": "packages/preact-query-persist-client/tsup.config.ts",
    "content": "import { defineConfig } from 'tsup'\nimport { legacyConfig, modernConfig } from './root.tsup.config.js'\n\nexport default defineConfig([\n  modernConfig({ entry: ['src/*.ts', 'src/*.tsx'] }),\n  legacyConfig({ entry: ['src/*.ts', 'src/*.tsx'] }),\n])\n"
  },
  {
    "path": "packages/preact-query-persist-client/vite.config.ts",
    "content": "import preact from '@preact/preset-vite'\nimport { defineConfig } from 'vitest/config'\nimport type { UserConfig as ViteUserConfig } from 'vite'\n\nimport packageJson from './package.json'\n\nexport default defineConfig({\n  plugins: [preact() as ViteUserConfig['plugins']],\n  // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660\n  resolve: {\n    conditions: ['@tanstack/custom-condition'],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        conditions: ['@tanstack/custom-condition'],\n      },\n    },\n  },\n  test: {\n    name: packageJson.name,\n    dir: './src',\n    watch: false,\n    environment: 'jsdom',\n    setupFiles: ['test-setup.ts'],\n    coverage: {\n      enabled: true,\n      provider: 'istanbul',\n      include: ['src/**/*'],\n      exclude: ['src/__tests__/**'],\n    },\n    typecheck: { enabled: true },\n    restoreMocks: true,\n  },\n})\n"
  },
  {
    "path": "packages/query-async-storage-persister/CHANGELOG.md",
    "content": "# @tanstack/query-async-storage-persister\n\n## 5.90.27\n\n### Patch Changes\n\n- fix(streamedQuery): maintain error state on reset refetch with initialData defined ([#10287](https://github.com/TanStack/query/pull/10287))\n\n- Updated dependencies [[`248975e`](https://github.com/TanStack/query/commit/248975e896f585f6eaa505c796e73fcf7bfd1eec)]:\n  - @tanstack/query-persist-client-core@5.92.4\n  - @tanstack/query-core@5.91.2\n\n## 5.90.26\n\n### Patch Changes\n\n- Updated dependencies [[`a89aab9`](https://github.com/TanStack/query/commit/a89aab975581c25c113a26c8af486b4cafad272a)]:\n  - @tanstack/query-core@5.91.1\n  - @tanstack/query-persist-client-core@5.92.3\n\n## 5.90.25\n\n### Patch Changes\n\n- Updated dependencies [[`6fa901b`](https://github.com/TanStack/query/commit/6fa901b97a22a80d0fca3f6ed86237ff0cbdd13b)]:\n  - @tanstack/query-core@5.91.0\n  - @tanstack/query-persist-client-core@5.92.2\n\n## 5.90.24\n\n### Patch Changes\n\n- Updated dependencies [[`e505568`](https://github.com/TanStack/query/commit/e505568f4d51c8281d38e9687091094b7d32a405)]:\n  - @tanstack/query-persist-client-core@5.92.1\n\n## 5.90.23\n\n### Patch Changes\n\n- Updated dependencies [[`978fc52`](https://github.com/TanStack/query/commit/978fc52728a8b9eb33f0a82f4ddf42a95815bd7f)]:\n  - @tanstack/query-persist-client-core@5.92.0\n\n## 5.90.22\n\n### Patch Changes\n\n- Updated dependencies [[`e7258c5`](https://github.com/TanStack/query/commit/e7258c5cb30cafa456cdb4e6bc75b43bf619954d)]:\n  - @tanstack/query-core@5.90.20\n  - @tanstack/query-persist-client-core@5.91.19\n\n## 5.90.21\n\n### Patch Changes\n\n- Updated dependencies [[`53fc74e`](https://github.com/TanStack/query/commit/53fc74ebb16730bd3317f039a69c6821386bae93)]:\n  - @tanstack/query-core@5.90.19\n  - @tanstack/query-persist-client-core@5.91.18\n\n## 5.90.20\n\n### Patch Changes\n\n- Updated dependencies [[`dea1614`](https://github.com/TanStack/query/commit/dea1614aaad5c572cf43cea54b64ac09dc4d5b41)]:\n  - @tanstack/query-core@5.90.18\n  - @tanstack/query-persist-client-core@5.91.17\n\n## 5.90.19\n\n### Patch Changes\n\n- Updated dependencies [[`269351b`](https://github.com/TanStack/query/commit/269351b8ce4b4846da3d320ac5b850ee6aada0d6)]:\n  - @tanstack/query-core@5.90.17\n  - @tanstack/query-persist-client-core@5.91.16\n\n## 5.90.18\n\n### Patch Changes\n\n- Updated dependencies [[`7f47906`](https://github.com/TanStack/query/commit/7f47906eaccc3f3aa5ce24b77a83bd7a620a237b)]:\n  - @tanstack/query-core@5.90.16\n  - @tanstack/query-persist-client-core@5.91.15\n\n## 5.90.17\n\n### Patch Changes\n\n- Updated dependencies [[`fccef79`](https://github.com/TanStack/query/commit/fccef797d57d4a9566517bba87c8377f363920f2)]:\n  - @tanstack/query-core@5.90.15\n  - @tanstack/query-persist-client-core@5.91.14\n\n## 5.90.16\n\n### Patch Changes\n\n- Updated dependencies [[`d576092`](https://github.com/TanStack/query/commit/d576092e2ece4ca3936add3eb0da5234c1d82ed4)]:\n  - @tanstack/query-core@5.90.14\n  - @tanstack/query-persist-client-core@5.91.13\n\n## 5.90.15\n\n### Patch Changes\n\n- Updated dependencies [[`4a0a78a`](https://github.com/TanStack/query/commit/4a0a78afbc2432f8cb6828035965853fa98c86a0)]:\n  - @tanstack/query-core@5.90.13\n  - @tanstack/query-persist-client-core@5.91.12\n\n## 5.90.14\n\n### Patch Changes\n\n- Updated dependencies [[`72d8ac5`](https://github.com/TanStack/query/commit/72d8ac5c592004b8f9c3ee086fcb9c3cd615ca05)]:\n  - @tanstack/query-core@5.90.12\n  - @tanstack/query-persist-client-core@5.91.11\n\n## 5.90.13\n\n### Patch Changes\n\n- Updated dependencies [[`c01b150`](https://github.com/TanStack/query/commit/c01b150e3673e11d6533768529a5e6fe3ebee68c)]:\n  - @tanstack/query-core@5.90.11\n  - @tanstack/query-persist-client-core@5.91.10\n\n## 5.90.12\n\n### Patch Changes\n\n- Updated dependencies [[`8e2e174`](https://github.com/TanStack/query/commit/8e2e174e9fd2e7b94cd232041e49c9d014d74e26), [`eb559a6`](https://github.com/TanStack/query/commit/eb559a66dc0d77dd46435f624fa64fc068bef9ae)]:\n  - @tanstack/query-core@5.90.10\n  - @tanstack/query-persist-client-core@5.91.9\n\n## 5.90.11\n\n### Patch Changes\n\n- Updated dependencies [[`08b211f`](https://github.com/TanStack/query/commit/08b211f8aa475e05d2f13a36517fc556861ef962)]:\n  - @tanstack/query-core@5.90.9\n  - @tanstack/query-persist-client-core@5.91.8\n\n## 5.90.10\n\n### Patch Changes\n\n- Updated dependencies [[`c0ec9fe`](https://github.com/TanStack/query/commit/c0ec9fe0d1426fe3f233adda3ebf23989ffaa110)]:\n  - @tanstack/query-core@5.90.8\n  - @tanstack/query-persist-client-core@5.91.7\n\n## 5.90.9\n\n### Patch Changes\n\n- Updated dependencies [[`b4cd121`](https://github.com/TanStack/query/commit/b4cd121a39d07cefaa3a3411136d342cc54ce8fb)]:\n  - @tanstack/query-core@5.90.7\n  - @tanstack/query-persist-client-core@5.91.6\n\n## 5.90.8\n\n### Patch Changes\n\n- Updated dependencies [[`1638c02`](https://github.com/TanStack/query/commit/1638c028df55648995d04431179904371a189772)]:\n  - @tanstack/query-core@5.90.6\n  - @tanstack/query-persist-client-core@5.91.5\n\n## 5.90.7\n\n### Patch Changes\n\n- Updated dependencies [[`e42ddfe`](https://github.com/TanStack/query/commit/e42ddfe919f34f847ca101aeef162c69845f9a1e)]:\n  - @tanstack/query-core@5.90.5\n  - @tanstack/query-persist-client-core@5.91.4\n\n## 5.90.6\n\n### Patch Changes\n\n- Updated dependencies [[`20ef922`](https://github.com/TanStack/query/commit/20ef922a0a7c3aee00150bf69123c338b0922922)]:\n  - @tanstack/query-core@5.90.4\n  - @tanstack/query-persist-client-core@5.91.3\n\n## 5.90.5\n\n### Patch Changes\n\n- Updated dependencies [[`4e1c433`](https://github.com/TanStack/query/commit/4e1c4338a72f7384600bbda99e44bc1891695df4)]:\n  - @tanstack/query-core@5.90.3\n  - @tanstack/query-persist-client-core@5.91.2\n\n## 5.90.4\n\n### Patch Changes\n\n- Updated dependencies [[`846d53d`](https://github.com/TanStack/query/commit/846d53d98992d50606c40634efa43dea9965b787)]:\n  - @tanstack/query-persist-client-core@5.91.1\n\n## 5.90.3\n\n### Patch Changes\n\n- Updated dependencies [[`5cd86c6`](https://github.com/TanStack/query/commit/5cd86c6ef1720b87b13e1ab70ee823616f1f029a)]:\n  - @tanstack/query-persist-client-core@5.91.0\n"
  },
  {
    "path": "packages/query-async-storage-persister/eslint.config.js",
    "content": "// @ts-check\n\nimport rootConfig from './root.eslint.config.js'\n\nexport default [...rootConfig]\n"
  },
  {
    "path": "packages/query-async-storage-persister/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-async-storage-persister\",\n  \"version\": \"5.90.27\",\n  \"description\": \"A persister for asynchronous storages, to be used with TanStack/Query\",\n  \"author\": \"tannerlinsley\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/query-async-storage-persister\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"scripts\": {\n    \"clean\": \"premove ./build ./coverage ./dist-ts\",\n    \"compile\": \"tsc --build\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:types\": \"npm-run-all --serial test:types:*\",\n    \"test:types:ts54\": \"node ../../node_modules/typescript54/lib/tsc.js --build\",\n    \"test:types:ts55\": \"node ../../node_modules/typescript55/lib/tsc.js --build\",\n    \"test:types:ts56\": \"node ../../node_modules/typescript56/lib/tsc.js --build\",\n    \"test:types:ts57\": \"node ../../node_modules/typescript57/lib/tsc.js --build\",\n    \"test:types:ts58\": \"node ../../node_modules/typescript58/lib/tsc.js --build\",\n    \"test:types:ts59\": \"node ../../node_modules/typescript59/lib/tsc.js --build\",\n    \"test:types:tscurrent\": \"tsc --build\",\n    \"test:types:ts60\": \"node ../../node_modules/typescript60/lib/tsc.js --build\",\n    \"test:lib\": \"vitest\",\n    \"test:lib:dev\": \"pnpm run test:lib --watch\",\n    \"test:build\": \"publint --strict && attw --pack\",\n    \"build\": \"tsup --tsconfig tsconfig.prod.json\"\n  },\n  \"type\": \"module\",\n  \"types\": \"build/legacy/index.d.ts\",\n  \"main\": \"build/legacy/index.cjs\",\n  \"module\": \"build/legacy/index.js\",\n  \"react-native\": \"src/index.ts\",\n  \"exports\": {\n    \".\": {\n      \"@tanstack/custom-condition\": \"./src/index.ts\",\n      \"import\": {\n        \"types\": \"./build/modern/index.d.ts\",\n        \"default\": \"./build/modern/index.js\"\n      },\n      \"require\": {\n        \"types\": \"./build/modern/index.d.cts\",\n        \"default\": \"./build/modern/index.cjs\"\n      }\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"sideEffects\": false,\n  \"files\": [\n    \"build\",\n    \"src\",\n    \"!src/__tests__\"\n  ],\n  \"dependencies\": {\n    \"@tanstack/query-core\": \"workspace:*\",\n    \"@tanstack/query-persist-client-core\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"@tanstack/query-test-utils\": \"workspace:*\",\n    \"npm-run-all2\": \"^5.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/query-async-storage-persister/src/__tests__/asyncThrottle.test.ts",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { asyncThrottle } from '../asyncThrottle'\n\ndescribe('asyncThrottle', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('basic', async () => {\n    const interval = 10\n    const execTimeStamps: Array<number> = []\n    const mockFunc = vi.fn(\n      async (id: number, complete?: (value?: unknown) => void) => {\n        await sleep(1)\n        execTimeStamps.push(Date.now())\n        if (complete) {\n          complete(id)\n        }\n      },\n    )\n    const testFunc = asyncThrottle(mockFunc, { interval })\n\n    testFunc(1)\n    await vi.advanceTimersByTimeAsync(1)\n\n    testFunc(2)\n    await vi.advanceTimersByTimeAsync(1)\n\n    new Promise((resolve) => testFunc(3, resolve))\n\n    await vi.advanceTimersToNextTimerAsync()\n    await vi.advanceTimersByTimeAsync(interval)\n\n    expect(mockFunc).toBeCalledTimes(2)\n    expect(mockFunc.mock.calls[1]?.[0]).toBe(3)\n    expect(execTimeStamps.length).toBe(2)\n    expect(execTimeStamps[1]! - execTimeStamps[0]!).toBeGreaterThanOrEqual(\n      interval,\n    )\n  })\n\n  test('Bug #3331 case 1: Special timing', async () => {\n    const interval = 1000\n    const execTimeStamps: Array<number> = []\n    const mockFunc = vi.fn(\n      async (id: number, complete?: (value?: unknown) => void) => {\n        await sleep(30)\n        execTimeStamps.push(Date.now())\n        if (complete) {\n          complete(id)\n        }\n      },\n    )\n    const testFunc = asyncThrottle(mockFunc, { interval })\n\n    testFunc(1)\n    testFunc(2)\n    await vi.advanceTimersByTimeAsync(35)\n    testFunc(3)\n    await vi.advanceTimersByTimeAsync(35)\n    new Promise((resolve) => testFunc(4, resolve))\n\n    await vi.advanceTimersToNextTimerAsync()\n    await vi.advanceTimersByTimeAsync(interval)\n\n    expect(mockFunc).toBeCalledTimes(2)\n    expect(mockFunc.mock.calls[1]?.[0]).toBe(4)\n    expect(execTimeStamps.length).toBe(2)\n    expect(execTimeStamps[1]! - execTimeStamps[0]!).toBeGreaterThanOrEqual(\n      interval,\n    )\n  })\n\n  test('Bug #3331 case 2: \"func\" execution time is greater than the interval.', async () => {\n    const interval = 1000\n    const execTimeStamps: Array<number> = []\n    const mockFunc = vi.fn(\n      async (id: number, complete?: (value?: unknown) => void) => {\n        await sleep(interval + 10)\n        execTimeStamps.push(Date.now())\n        if (complete) {\n          complete(id)\n        }\n      },\n    )\n    const testFunc = asyncThrottle(mockFunc, { interval })\n\n    testFunc(1)\n    testFunc(2)\n    new Promise((resolve) => testFunc(3, resolve))\n\n    await vi.advanceTimersToNextTimerAsync()\n    await vi.advanceTimersByTimeAsync(interval + 10)\n    await vi.advanceTimersByTimeAsync(interval + 10)\n\n    expect(mockFunc).toBeCalledTimes(2)\n    expect(mockFunc.mock.calls[1]?.[0]).toBe(3)\n    expect(execTimeStamps.length).toBe(2)\n    expect(execTimeStamps[1]! - execTimeStamps[0]!).toBeGreaterThanOrEqual(\n      interval,\n    )\n  })\n\n  test('\"func\" throw error not break next invoke', async () => {\n    const interval = 10\n\n    const mockFunc = vi.fn(\n      async (id: number, complete?: (value?: unknown) => void) => {\n        if (id === 1) throw new Error('error')\n        await sleep(1)\n        if (complete) {\n          complete(id)\n        }\n      },\n    )\n    const testFunc = asyncThrottle(mockFunc, { interval })\n\n    testFunc(1)\n    await vi.advanceTimersByTimeAsync(1)\n\n    new Promise((resolve) => testFunc(2, resolve))\n    await vi.advanceTimersByTimeAsync(interval)\n\n    expect(mockFunc).toBeCalledTimes(2)\n    expect(mockFunc.mock.calls[1]?.[0]).toBe(2)\n  })\n\n  test('\"onError\" should be called when \"func\" throw error', () => {\n    const err = new Error('error')\n    const handleError = (e: unknown) => {\n      expect(e).toBe(err)\n    }\n\n    const testFunc = asyncThrottle(\n      () => {\n        throw err\n      },\n      { onError: handleError },\n    )\n    testFunc()\n  })\n\n  test('should throw error when \"func\" is not a function', () => {\n    expect(() => asyncThrottle(1 as any)).toThrowError()\n  })\n})\n"
  },
  {
    "path": "packages/query-async-storage-persister/src/asyncThrottle.ts",
    "content": "import { timeoutManager } from '@tanstack/query-core'\nimport { noop } from './utils'\n\ninterface AsyncThrottleOptions {\n  interval?: number\n  onError?: (error: unknown) => void\n}\n\nexport function asyncThrottle<TArgs extends ReadonlyArray<unknown>>(\n  func: (...args: TArgs) => Promise<void>,\n  { interval = 1000, onError = noop }: AsyncThrottleOptions = {},\n) {\n  if (typeof func !== 'function') throw new Error('argument is not function.')\n\n  let nextExecutionTime = 0\n  let lastArgs = null\n  let isExecuting = false\n  let isScheduled = false\n\n  return async (...args: TArgs) => {\n    lastArgs = args\n    if (isScheduled) return\n    isScheduled = true\n    while (isExecuting) {\n      await new Promise((done) => timeoutManager.setTimeout(done, interval))\n    }\n    while (Date.now() < nextExecutionTime) {\n      await new Promise((done) =>\n        timeoutManager.setTimeout(done, nextExecutionTime - Date.now()),\n      )\n    }\n    isScheduled = false\n    isExecuting = true\n    try {\n      await func(...lastArgs)\n    } catch (error) {\n      try {\n        onError(error)\n      } catch {}\n    }\n    nextExecutionTime = Date.now() + interval\n    isExecuting = false\n  }\n}\n"
  },
  {
    "path": "packages/query-async-storage-persister/src/index.ts",
    "content": "import { asyncThrottle } from './asyncThrottle'\nimport { noop } from './utils'\nimport type {\n  AsyncStorage,\n  MaybePromise,\n  PersistedClient,\n  Persister,\n  Promisable,\n} from '@tanstack/query-persist-client-core'\n\nexport type AsyncPersistRetryer = (props: {\n  persistedClient: PersistedClient\n  error: Error\n  errorCount: number\n}) => Promisable<PersistedClient | undefined>\n\ninterface CreateAsyncStoragePersisterOptions {\n  /** The storage client used for setting and retrieving items from cache.\n   * For SSR pass in `undefined`. Note that window.localStorage can be\n   * `null` in Android WebViews depending on how they are configured.\n   */\n  storage: AsyncStorage<string> | undefined | null\n  /** The key to use when storing the cache */\n  key?: string\n  /** To avoid spamming,\n   * pass a time in ms to throttle saving the cache to disk */\n  throttleTime?: number\n  /**\n   * How to serialize the data to storage.\n   * @default `JSON.stringify`\n   */\n  serialize?: (client: PersistedClient) => MaybePromise<string>\n  /**\n   * How to deserialize the data from storage.\n   * @default `JSON.parse`\n   */\n  deserialize?: (cachedString: string) => MaybePromise<PersistedClient>\n\n  retry?: AsyncPersistRetryer\n}\n\nexport const createAsyncStoragePersister = ({\n  storage,\n  key = `REACT_QUERY_OFFLINE_CACHE`,\n  throttleTime = 1000,\n  serialize = JSON.stringify,\n  deserialize = JSON.parse,\n  retry,\n}: CreateAsyncStoragePersisterOptions): Persister => {\n  if (storage) {\n    const trySave = async (\n      persistedClient: PersistedClient,\n    ): Promise<Error | undefined> => {\n      try {\n        const serialized = await serialize(persistedClient)\n        await storage.setItem(key, serialized)\n        return\n      } catch (error) {\n        return error as Error\n      }\n    }\n\n    return {\n      persistClient: asyncThrottle(\n        async (persistedClient) => {\n          let client: PersistedClient | undefined = persistedClient\n          let error = await trySave(client)\n          let errorCount = 0\n          while (error && client) {\n            errorCount++\n            client = await retry?.({\n              persistedClient: client,\n              error,\n              errorCount,\n            })\n\n            if (client) {\n              error = await trySave(client)\n            }\n          }\n        },\n        { interval: throttleTime },\n      ),\n      restoreClient: async () => {\n        const cacheString = await storage.getItem(key)\n\n        if (!cacheString) {\n          return\n        }\n\n        return await deserialize(cacheString)\n      },\n      removeClient: () => storage.removeItem(key),\n    }\n  }\n\n  return {\n    persistClient: noop,\n    restoreClient: () => Promise.resolve(undefined),\n    removeClient: noop,\n  }\n}\n"
  },
  {
    "path": "packages/query-async-storage-persister/src/utils.ts",
    "content": "export function noop(): void\nexport function noop(): undefined\nexport function noop() {}\n"
  },
  {
    "path": "packages/query-async-storage-persister/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\"\n  },\n  \"include\": [\"src\", \"*.config.*\", \"package.json\"],\n  \"references\": [{ \"path\": \"../query-persist-client-core\" }]\n}\n"
  },
  {
    "path": "packages/query-async-storage-persister/tsconfig.prod.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"incremental\": false,\n    \"composite\": false,\n    \"rootDir\": \"../../\"\n  }\n}\n"
  },
  {
    "path": "packages/query-async-storage-persister/tsup.config.ts",
    "content": "import { defineConfig } from 'tsup'\nimport { legacyConfig, modernConfig } from './root.tsup.config.js'\n\nexport default defineConfig([\n  modernConfig({ entry: ['src/*.ts'] }),\n  legacyConfig({ entry: ['src/*.ts'] }),\n])\n"
  },
  {
    "path": "packages/query-async-storage-persister/vite.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nimport packageJson from './package.json'\n\nexport default defineConfig({\n  // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660\n  resolve: {\n    conditions: ['@tanstack/custom-condition'],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        conditions: ['@tanstack/custom-condition'],\n      },\n    },\n  },\n  test: {\n    name: packageJson.name,\n    dir: './src',\n    watch: false,\n    coverage: {\n      enabled: true,\n      provider: 'istanbul',\n      include: ['src/**/*'],\n      exclude: ['src/__tests__/**'],\n    },\n    typecheck: { enabled: true },\n    restoreMocks: true,\n  },\n})\n"
  },
  {
    "path": "packages/query-broadcast-client-experimental/CHANGELOG.md",
    "content": "# @tanstack/query-broadcast-client-experimental\n\n## 5.90.23\n\n### Patch Changes\n\n- fix(streamedQuery): maintain error state on reset refetch with initialData defined ([#10287](https://github.com/TanStack/query/pull/10287))\n\n- Updated dependencies [[`248975e`](https://github.com/TanStack/query/commit/248975e896f585f6eaa505c796e73fcf7bfd1eec)]:\n  - @tanstack/query-core@5.91.2\n\n## 5.90.22\n\n### Patch Changes\n\n- Updated dependencies [[`a89aab9`](https://github.com/TanStack/query/commit/a89aab975581c25c113a26c8af486b4cafad272a)]:\n  - @tanstack/query-core@5.91.1\n\n## 5.90.21\n\n### Patch Changes\n\n- Updated dependencies [[`6fa901b`](https://github.com/TanStack/query/commit/6fa901b97a22a80d0fca3f6ed86237ff0cbdd13b)]:\n  - @tanstack/query-core@5.91.0\n\n## 5.90.20\n\n### Patch Changes\n\n- Updated dependencies [[`e7258c5`](https://github.com/TanStack/query/commit/e7258c5cb30cafa456cdb4e6bc75b43bf619954d)]:\n  - @tanstack/query-core@5.90.20\n\n## 5.90.19\n\n### Patch Changes\n\n- Updated dependencies [[`53fc74e`](https://github.com/TanStack/query/commit/53fc74ebb16730bd3317f039a69c6821386bae93)]:\n  - @tanstack/query-core@5.90.19\n\n## 5.90.18\n\n### Patch Changes\n\n- Updated dependencies [[`dea1614`](https://github.com/TanStack/query/commit/dea1614aaad5c572cf43cea54b64ac09dc4d5b41)]:\n  - @tanstack/query-core@5.90.18\n\n## 5.90.17\n\n### Patch Changes\n\n- Updated dependencies [[`269351b`](https://github.com/TanStack/query/commit/269351b8ce4b4846da3d320ac5b850ee6aada0d6)]:\n  - @tanstack/query-core@5.90.17\n\n## 5.90.16\n\n### Patch Changes\n\n- Updated dependencies [[`7f47906`](https://github.com/TanStack/query/commit/7f47906eaccc3f3aa5ce24b77a83bd7a620a237b)]:\n  - @tanstack/query-core@5.90.16\n\n## 5.90.15\n\n### Patch Changes\n\n- Updated dependencies [[`fccef79`](https://github.com/TanStack/query/commit/fccef797d57d4a9566517bba87c8377f363920f2)]:\n  - @tanstack/query-core@5.90.15\n\n## 5.90.14\n\n### Patch Changes\n\n- Updated dependencies [[`d576092`](https://github.com/TanStack/query/commit/d576092e2ece4ca3936add3eb0da5234c1d82ed4)]:\n  - @tanstack/query-core@5.90.14\n\n## 5.90.13\n\n### Patch Changes\n\n- Updated dependencies [[`4a0a78a`](https://github.com/TanStack/query/commit/4a0a78afbc2432f8cb6828035965853fa98c86a0)]:\n  - @tanstack/query-core@5.90.13\n\n## 5.90.12\n\n### Patch Changes\n\n- Updated dependencies [[`72d8ac5`](https://github.com/TanStack/query/commit/72d8ac5c592004b8f9c3ee086fcb9c3cd615ca05)]:\n  - @tanstack/query-core@5.90.12\n\n## 5.90.11\n\n### Patch Changes\n\n- Updated dependencies [[`c01b150`](https://github.com/TanStack/query/commit/c01b150e3673e11d6533768529a5e6fe3ebee68c)]:\n  - @tanstack/query-core@5.90.11\n\n## 5.90.10\n\n### Patch Changes\n\n- Updated dependencies [[`8e2e174`](https://github.com/TanStack/query/commit/8e2e174e9fd2e7b94cd232041e49c9d014d74e26), [`eb559a6`](https://github.com/TanStack/query/commit/eb559a66dc0d77dd46435f624fa64fc068bef9ae)]:\n  - @tanstack/query-core@5.90.10\n\n## 5.90.9\n\n### Patch Changes\n\n- Updated dependencies [[`08b211f`](https://github.com/TanStack/query/commit/08b211f8aa475e05d2f13a36517fc556861ef962)]:\n  - @tanstack/query-core@5.90.9\n\n## 5.90.8\n\n### Patch Changes\n\n- Updated dependencies [[`c0ec9fe`](https://github.com/TanStack/query/commit/c0ec9fe0d1426fe3f233adda3ebf23989ffaa110)]:\n  - @tanstack/query-core@5.90.8\n\n## 5.90.7\n\n### Patch Changes\n\n- Updated dependencies [[`b4cd121`](https://github.com/TanStack/query/commit/b4cd121a39d07cefaa3a3411136d342cc54ce8fb)]:\n  - @tanstack/query-core@5.90.7\n\n## 5.90.6\n\n### Patch Changes\n\n- Updated dependencies [[`1638c02`](https://github.com/TanStack/query/commit/1638c028df55648995d04431179904371a189772)]:\n  - @tanstack/query-core@5.90.6\n\n## 5.90.5\n\n### Patch Changes\n\n- Updated dependencies [[`e42ddfe`](https://github.com/TanStack/query/commit/e42ddfe919f34f847ca101aeef162c69845f9a1e)]:\n  - @tanstack/query-core@5.90.5\n\n## 5.90.4\n\n### Patch Changes\n\n- Updated dependencies [[`20ef922`](https://github.com/TanStack/query/commit/20ef922a0a7c3aee00150bf69123c338b0922922)]:\n  - @tanstack/query-core@5.90.4\n\n## 5.90.3\n\n### Patch Changes\n\n- Updated dependencies [[`4e1c433`](https://github.com/TanStack/query/commit/4e1c4338a72f7384600bbda99e44bc1891695df4)]:\n  - @tanstack/query-core@5.90.3\n"
  },
  {
    "path": "packages/query-broadcast-client-experimental/eslint.config.js",
    "content": "// @ts-check\n\nimport rootConfig from './root.eslint.config.js'\n\nexport default [...rootConfig]\n"
  },
  {
    "path": "packages/query-broadcast-client-experimental/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-broadcast-client-experimental\",\n  \"version\": \"5.90.23\",\n  \"description\": \"An experimental plugin to for broadcasting the state of your queryClient between browser tabs/windows\",\n  \"author\": \"tannerlinsley\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/query-broadcast-client-experimental\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"scripts\": {\n    \"clean\": \"premove ./build ./coverage ./dist-ts\",\n    \"compile\": \"tsc --build\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:types\": \"npm-run-all --serial test:types:*\",\n    \"test:types:ts54\": \"node ../../node_modules/typescript54/lib/tsc.js --build\",\n    \"test:types:ts55\": \"node ../../node_modules/typescript55/lib/tsc.js --build\",\n    \"test:types:ts56\": \"node ../../node_modules/typescript56/lib/tsc.js --build\",\n    \"test:types:ts57\": \"node ../../node_modules/typescript57/lib/tsc.js --build\",\n    \"test:types:ts58\": \"node ../../node_modules/typescript58/lib/tsc.js --build\",\n    \"test:types:ts59\": \"node ../../node_modules/typescript59/lib/tsc.js --build\",\n    \"test:types:tscurrent\": \"tsc --build\",\n    \"test:types:ts60\": \"node ../../node_modules/typescript60/lib/tsc.js --build\",\n    \"test:lib\": \"vitest\",\n    \"test:lib:dev\": \"pnpm run test:lib --watch\",\n    \"test:build\": \"publint --strict && attw --pack\",\n    \"build\": \"tsup --tsconfig tsconfig.prod.json\"\n  },\n  \"type\": \"module\",\n  \"types\": \"build/legacy/index.d.ts\",\n  \"main\": \"build/legacy/index.cjs\",\n  \"module\": \"build/legacy/index.js\",\n  \"exports\": {\n    \".\": {\n      \"@tanstack/custom-condition\": \"./src/index.ts\",\n      \"import\": {\n        \"types\": \"./build/modern/index.d.ts\",\n        \"default\": \"./build/modern/index.js\"\n      },\n      \"require\": {\n        \"types\": \"./build/modern/index.d.cts\",\n        \"default\": \"./build/modern/index.cjs\"\n      }\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"sideEffects\": false,\n  \"files\": [\n    \"build\",\n    \"src\",\n    \"!src/__tests__\"\n  ],\n  \"dependencies\": {\n    \"@tanstack/query-core\": \"workspace:*\",\n    \"broadcast-channel\": \"^7.0.0\"\n  },\n  \"devDependencies\": {\n    \"@testing-library/react\": \"^16.1.0\",\n    \"@vitejs/plugin-react\": \"^4.3.4\",\n    \"npm-run-all2\": \"^5.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/query-broadcast-client-experimental/src/__tests__/index.test.ts",
    "content": "import { QueryClient } from '@tanstack/query-core'\nimport { beforeEach, describe, expect, it } from 'vitest'\nimport { broadcastQueryClient } from '..'\nimport type { QueryCache } from '@tanstack/query-core'\n\ndescribe('broadcastQueryClient', () => {\n  let queryClient: QueryClient\n  let queryCache: QueryCache\n\n  beforeEach(() => {\n    queryClient = new QueryClient()\n    queryCache = queryClient.getQueryCache()\n  })\n\n  it('should subscribe to the query cache', () => {\n    broadcastQueryClient({\n      queryClient,\n      broadcastChannel: 'test_channel',\n    })\n    expect(queryCache.hasListeners()).toBe(true)\n  })\n\n  it('should not have any listeners after cleanup', () => {\n    const unsubscribe = broadcastQueryClient({\n      queryClient,\n      broadcastChannel: 'test_channel',\n    })\n    unsubscribe()\n    expect(queryCache.hasListeners()).toBe(false)\n  })\n})\n"
  },
  {
    "path": "packages/query-broadcast-client-experimental/src/index.ts",
    "content": "import { BroadcastChannel } from 'broadcast-channel'\nimport type { BroadcastChannelOptions } from 'broadcast-channel'\nimport type { QueryClient } from '@tanstack/query-core'\n\ninterface BroadcastQueryClientOptions {\n  queryClient: QueryClient\n  broadcastChannel?: string\n  options?: BroadcastChannelOptions\n}\n\nexport function broadcastQueryClient({\n  queryClient,\n  broadcastChannel = 'tanstack-query',\n  options,\n}: BroadcastQueryClientOptions): () => void {\n  let transaction = false\n  const tx = (cb: () => void) => {\n    transaction = true\n    cb()\n    transaction = false\n  }\n\n  const channel = new BroadcastChannel(broadcastChannel, {\n    webWorkerSupport: false,\n    ...options,\n  })\n\n  const queryCache = queryClient.getQueryCache()\n\n  const unsubscribe = queryClient.getQueryCache().subscribe((queryEvent) => {\n    if (transaction) {\n      return\n    }\n\n    const {\n      query: { queryHash, queryKey, state, observers },\n    } = queryEvent\n\n    if (queryEvent.type === 'updated' && queryEvent.action.type === 'success') {\n      channel.postMessage({\n        type: 'updated',\n        queryHash,\n        queryKey,\n        state,\n      })\n    }\n\n    if (queryEvent.type === 'removed' && observers.length > 0) {\n      channel.postMessage({\n        type: 'removed',\n        queryHash,\n        queryKey,\n      })\n    }\n\n    if (queryEvent.type === 'added') {\n      channel.postMessage({\n        type: 'added',\n        queryHash,\n        queryKey,\n      })\n    }\n  })\n\n  channel.onmessage = (action) => {\n    if (!action?.type) {\n      return\n    }\n\n    tx(() => {\n      const { type, queryHash, queryKey, state } = action\n\n      const query = queryCache.get(queryHash)\n\n      if (type === 'updated') {\n        if (query) {\n          query.setState(state)\n          return\n        }\n\n        queryCache.build(\n          queryClient,\n          {\n            queryKey,\n            queryHash,\n          },\n          state,\n        )\n      } else if (type === 'removed') {\n        if (query) {\n          queryCache.remove(query)\n        }\n      } else if (type === 'added') {\n        if (query) {\n          query.setState(state)\n          return\n        }\n        queryCache.build(\n          queryClient,\n          {\n            queryKey,\n            queryHash,\n          },\n          state,\n        )\n      }\n    })\n  }\n  return () => {\n    unsubscribe()\n    channel.close()\n  }\n}\n"
  },
  {
    "path": "packages/query-broadcast-client-experimental/test-setup.ts",
    "content": "import '@testing-library/jest-dom/vitest'\nimport { act, cleanup as cleanupRTL } from '@testing-library/react'\nimport { afterEach } from 'vitest'\nimport { notifyManager } from '@tanstack/query-core'\n\n// https://testing-library.com/docs/react-testing-library/api#cleanup\nafterEach(() => {\n  cleanupRTL()\n})\n\n// Wrap notifications with act to make sure React knows about React Query updates\nnotifyManager.setNotifyFunction((fn) => {\n  act(fn)\n})\n"
  },
  {
    "path": "packages/query-broadcast-client-experimental/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\"\n  },\n  \"include\": [\"src\", \"test-setup.ts\", \"*.config.*\", \"package.json\"],\n  \"references\": [{ \"path\": \"../query-core\" }]\n}\n"
  },
  {
    "path": "packages/query-broadcast-client-experimental/tsconfig.prod.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"incremental\": false,\n    \"composite\": false,\n    \"rootDir\": \"../../\"\n  }\n}\n"
  },
  {
    "path": "packages/query-broadcast-client-experimental/tsup.config.ts",
    "content": "import { defineConfig } from 'tsup'\nimport { legacyConfig, modernConfig } from './root.tsup.config.js'\n\nexport default defineConfig([\n  modernConfig({ entry: ['src/*.ts'] }),\n  legacyConfig({ entry: ['src/*.ts'] }),\n])\n"
  },
  {
    "path": "packages/query-broadcast-client-experimental/vite.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\nimport react from '@vitejs/plugin-react'\n\nimport packageJson from './package.json'\n\nexport default defineConfig({\n  plugins: [react()],\n  // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660\n  resolve: {\n    conditions: ['@tanstack/custom-condition'],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        conditions: ['@tanstack/custom-condition'],\n      },\n    },\n  },\n  test: {\n    name: packageJson.name,\n    dir: './src',\n    watch: false,\n    environment: 'jsdom',\n    setupFiles: ['test-setup.ts'],\n    coverage: {\n      enabled: true,\n      provider: 'istanbul',\n      include: ['src/**/*'],\n      exclude: ['src/__tests__/**'],\n    },\n    typecheck: { enabled: true },\n    restoreMocks: true,\n    retry: process.env.CI ? 3 : 0,\n  },\n})\n"
  },
  {
    "path": "packages/query-codemods/eslint.config.js",
    "content": "// @ts-check\n\nimport rootConfig from './root.eslint.config.js'\n\nexport default [\n  ...rootConfig,\n  {\n    rules: {\n      'cspell/spellchecker': 'off',\n      '@typescript-eslint/no-unnecessary-condition': 'off',\n      'import/no-duplicates': 'off',\n      'import/no-unresolved': 'off',\n      'import/order': 'off',\n      'no-shadow': 'off',\n      'sort-imports': 'off',\n    },\n  },\n]\n"
  },
  {
    "path": "packages/query-codemods/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-codemods\",\n  \"private\": true,\n  \"description\": \"Collection of codemods to make the migration easier.\",\n  \"author\": \"Balázs Máté Petró\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/query-codemods\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"scripts\": {\n    \"clean\": \"premove ./coverage ./dist-ts\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:lib\": \"vitest\",\n    \"test:lib:dev\": \"pnpm run test:lib --watch\"\n  },\n  \"type\": \"module\",\n  \"exports\": {\n    \"./package.json\": \"./package.json\"\n  },\n  \"sideEffects\": false,\n  \"files\": [\n    \"src\",\n    \"!src/jest.config.js\",\n    \"!src/**/__testfixtures__\",\n    \"!src/**/__tests__\"\n  ],\n  \"devDependencies\": {\n    \"@types/jscodeshift\": \"17.3.0\",\n    \"jscodeshift\": \"17.3.0\"\n  }\n}\n"
  },
  {
    "path": "packages/query-codemods/src/utils/index.cjs",
    "content": "module.exports = ({ root, jscodeshift }) => {\n  const findImportIdentifierOf = (importSpecifiers, identifier) => {\n    const specifier = importSpecifiers\n      .filter((node) => node.value.imported.name === identifier)\n      .paths()\n\n    if (specifier.length > 0) {\n      return specifier[0].value.local\n    }\n\n    return jscodeshift.identifier(identifier)\n  }\n\n  const findImportSpecifiers = (packageName) =>\n    root\n      .find(jscodeshift.ImportDeclaration, {\n        source: {\n          value: packageName,\n        },\n      })\n      .find(jscodeshift.ImportSpecifier, {})\n\n  const locateImports = (\n    identifiers,\n    packageName = '@tanstack/react-query',\n  ) => {\n    const findNamespaceImportIdentifier = () => {\n      const specifier = root\n        .find(jscodeshift.ImportDeclaration, {\n          source: {\n            value: packageName,\n          },\n        })\n        .find(jscodeshift.ImportNamespaceSpecifier)\n        .paths()\n\n      return specifier.length > 0 ? specifier[0].value.local : null\n    }\n\n    /**\n     * First, we search for the namespace import identifier because if we have any, we assume the consumer uses\n     * namespace imports. In this case, we won't search for named imports at all.\n     */\n    const namespaceImportIdentifier = findNamespaceImportIdentifier()\n\n    if (namespaceImportIdentifier) {\n      const identifierMap = {}\n\n      for (const identifier of identifiers) {\n        identifierMap[identifier] = jscodeshift.identifier(identifier)\n      }\n\n      return {\n        namespace: namespaceImportIdentifier,\n        ...identifierMap,\n      }\n    }\n\n    const importSpecifiers = findImportSpecifiers(packageName)\n    const identifierMap = {}\n\n    for (const identifier of identifiers) {\n      identifierMap[identifier] = findImportIdentifierOf(\n        importSpecifiers,\n        identifier,\n      )\n    }\n\n    return {\n      namespace: null,\n      ...identifierMap,\n    }\n  }\n\n  const findAllMethodCalls = () =>\n    root\n      // First, we need to find all method calls.\n      .find(jscodeshift.CallExpression, {\n        callee: {\n          type: jscodeshift.MemberExpression.name,\n          property: {\n            type: jscodeshift.Identifier.name,\n          },\n        },\n      })\n\n  const findQueryClientIdentifiers = (importIdentifiers) =>\n    root\n      .find(jscodeshift.VariableDeclarator, {})\n      .filter((node) => {\n        if (node.value.init) {\n          const initializer = node.value.init\n\n          return (\n            isClassInstantiationOf(\n              initializer,\n              getSelectorByImports(importIdentifiers, 'QueryClient'),\n            ) ||\n            isFunctionCallOf(\n              initializer,\n              getSelectorByImports(importIdentifiers, 'useQueryClient'),\n            )\n          )\n        }\n\n        return false\n      })\n      .paths()\n      .map((node) => node.value.id.name)\n\n  const isCallExpression = (node) =>\n    jscodeshift.match(node, { type: jscodeshift.CallExpression.name })\n\n  const isIdentifier = (node) =>\n    jscodeshift.match(node, { type: jscodeshift.Identifier.name })\n\n  const isMemberExpression = (node) =>\n    jscodeshift.match(node, { type: jscodeshift.MemberExpression.name })\n\n  const isNewExpression = (node) =>\n    jscodeshift.match(node, { type: jscodeshift.NewExpression.name })\n\n  const isArrayExpression = (node) =>\n    jscodeshift.match(node, { type: jscodeshift.ArrayExpression.name })\n\n  const isObjectExpression = (node) =>\n    jscodeshift.match(node, { type: jscodeshift.ObjectExpression.name })\n\n  const isObjectProperty = (node) =>\n    jscodeshift.match(node, { type: jscodeshift.ObjectProperty.name })\n\n  const isSpreadElement = (node) =>\n    jscodeshift.match(node, { type: jscodeshift.SpreadElement.name })\n\n  /**\n   * @param {import('jscodeshift').Node} node\n   * @returns {boolean}\n   */\n  const isFunctionDefinition = (node) => {\n    const isArrowFunctionExpression = jscodeshift.match(node, {\n      type: jscodeshift.ArrowFunctionExpression.name,\n    })\n    const isFunctionExpression = jscodeshift.match(node, {\n      type: jscodeshift.FunctionExpression.name,\n    })\n\n    return isArrowFunctionExpression || isFunctionExpression\n  }\n\n  const warn = (message) => {\n    if (process.env.NODE_ENV !== 'test') {\n      console.warn(message)\n    }\n  }\n\n  const isClassInstantiationOf = (node, selector) => {\n    if (!isNewExpression(node)) {\n      return false\n    }\n\n    const parts = selector.split('.')\n\n    return parts.length === 1\n      ? isIdentifier(node.callee) && node.callee.name === parts[0]\n      : isMemberExpression(node.callee) &&\n          node.callee.object.name === parts[0] &&\n          node.callee.property.name === parts[1]\n  }\n\n  const isFunctionCallOf = (node, selector) => {\n    if (!isCallExpression(node)) {\n      return false\n    }\n\n    const parts = selector.split('.')\n\n    return parts.length === 1\n      ? isIdentifier(node.callee) && node.callee.name === parts[0]\n      : isMemberExpression(node.callee) &&\n          node.callee.object.name === parts[0] &&\n          node.callee.property.name === parts[1]\n  }\n\n  const getSelectorByImports = (imports, path) =>\n    imports.namespace\n      ? `${imports.namespace.name}.${imports[path].name}`\n      : imports[path].name\n\n  return {\n    findAllMethodCalls,\n    getSelectorByImports,\n    isCallExpression,\n    isClassInstantiationOf,\n    isFunctionCallOf,\n    isIdentifier,\n    isMemberExpression,\n    isArrayExpression,\n    isObjectExpression,\n    isObjectProperty,\n    isSpreadElement,\n    isFunctionDefinition,\n    locateImports,\n    warn,\n    queryClient: {\n      findQueryClientIdentifiers,\n    },\n  }\n}\n"
  },
  {
    "path": "packages/query-codemods/src/utils/transformers/query-cache-transformer.cjs",
    "content": "module.exports = ({\n  jscodeshift,\n  utils,\n  root,\n  packageName = '@tanstack/react-query',\n}) => {\n  const isGetQueryCacheMethodCall = (\n    initializer,\n    importIdentifiers,\n    knownQueryClientIds,\n  ) => {\n    const isKnownQueryClient = (node) =>\n      utils.isIdentifier(node) && knownQueryClientIds.includes(node.name)\n\n    const isGetQueryCacheIdentifier = (node) =>\n      utils.isIdentifier(node) && node.name === 'getQueryCache'\n\n    const isValidInitializer = (node) =>\n      utils.isCallExpression(node) && utils.isMemberExpression(node.callee)\n\n    if (isValidInitializer(initializer)) {\n      const instance = initializer.callee.object\n\n      return (\n        isGetQueryCacheIdentifier(initializer.callee.property) &&\n        (isKnownQueryClient(instance) ||\n          utils.isFunctionCallOf(\n            instance,\n            utils.getSelectorByImports(importIdentifiers, 'useQueryClient'),\n          ))\n      )\n    }\n\n    return false\n  }\n\n  const findQueryCacheInstantiations = (\n    importIdentifiers,\n    knownQueryClientIds,\n  ) =>\n    root.find(jscodeshift.VariableDeclarator, {}).filter((node) => {\n      if (node.value.init) {\n        const initializer = node.value.init\n\n        return (\n          utils.isClassInstantiationOf(\n            initializer,\n            utils.getSelectorByImports(importIdentifiers, 'QueryCache'),\n          ) ||\n          isGetQueryCacheMethodCall(\n            initializer,\n            importIdentifiers,\n            knownQueryClientIds,\n          )\n        )\n      }\n\n      return false\n    })\n\n  const filterQueryCacheMethodCalls = (node) =>\n    utils.isIdentifier(node) && ['find', 'findAll'].includes(node.name)\n\n  const findQueryCacheMethodCalls = (importIdentifiers) => {\n    /**\n     * Here we collect all query client instantiations. We have to make aware of them because the query cache can be\n     * accessed by the query client as well.\n     */\n    const queryClientIdentifiers =\n      utils.queryClient.findQueryClientIdentifiers(importIdentifiers)\n    /**\n     * Here we collect all query cache instantiations. The reason is simple: the methods can be called on query cache\n     * instances, to locate the possible usages we need to be aware of the identifier names.\n     */\n    const queryCacheIdentifiers = findQueryCacheInstantiations(\n      importIdentifiers,\n      queryClientIdentifiers,\n    )\n      .paths()\n      .map((node) => node.value.id.name)\n\n    return (\n      utils\n        // First, we need to find all method calls.\n        .findAllMethodCalls()\n        // Then we narrow the collection to all `fetch` and `fetchAll` methods.\n        .filter((node) =>\n          filterQueryCacheMethodCalls(node.value.callee.property),\n        )\n        .filter((node) => {\n          const object = node.value.callee.object\n\n          // If the method is called on a `QueryCache` instance, we keep it in the collection.\n          if (utils.isIdentifier(object)) {\n            return queryCacheIdentifiers.includes(object.name)\n          }\n\n          // If the method is called on a `QueryClient` instance, we keep it in the collection.\n          if (utils.isCallExpression(object)) {\n            return isGetQueryCacheMethodCall(\n              object,\n              importIdentifiers,\n              queryClientIdentifiers,\n            )\n          }\n\n          return false\n        })\n    )\n  }\n\n  const execute = (replacer) => {\n    findQueryCacheMethodCalls(\n      utils.locateImports(\n        ['QueryCache', 'QueryClient', 'useQueryClient'],\n        packageName,\n      ),\n    ).replaceWith(replacer)\n  }\n\n  return {\n    execute,\n  }\n}\n"
  },
  {
    "path": "packages/query-codemods/src/utils/transformers/query-client-transformer.cjs",
    "content": "module.exports = ({\n  jscodeshift,\n  utils,\n  root,\n  packageName = '@tanstack/react-query',\n}) => {\n  const filterQueryClientMethodCalls = (node, methods) =>\n    utils.isIdentifier(node) && methods.includes(node.name)\n\n  const findQueryClientMethodCalls = (importIdentifiers, methods) => {\n    /**\n     * Here we collect all query client instantiations. We have to make aware of them because some method calls might\n     * be invoked on these instances.\n     */\n    const queryClientIdentifiers =\n      utils.queryClient.findQueryClientIdentifiers(importIdentifiers)\n\n    return (\n      utils\n        // First, we need to find all method calls.\n        .findAllMethodCalls()\n        // Then we narrow the collection to `QueryClient` methods.\n        .filter((node) =>\n          filterQueryClientMethodCalls(node.value.callee.property, methods),\n        )\n        .filter((node) => {\n          const object = node.value.callee.object\n\n          // If the method is called on a `QueryClient` instance, we keep it in the collection.\n          if (utils.isIdentifier(object)) {\n            return queryClientIdentifiers.includes(object.name)\n          }\n\n          // If the method is called on the return value of `useQueryClient` hook, we keep it in the collection.\n          return utils.isFunctionCallOf(\n            object,\n            utils.getSelectorByImports(importIdentifiers, 'useQueryClient'),\n          )\n        })\n    )\n  }\n\n  const execute = (methods, replacer) => {\n    findQueryClientMethodCalls(\n      utils.locateImports(['QueryClient', 'useQueryClient'], packageName),\n      methods,\n    ).replaceWith(replacer)\n  }\n\n  return {\n    execute,\n  }\n}\n"
  },
  {
    "path": "packages/query-codemods/src/utils/transformers/use-query-like-transformer.cjs",
    "content": "module.exports = ({\n  jscodeshift,\n  utils,\n  root,\n  packageName = '@tanstack/react-query',\n}) => {\n  const filterUseQueryLikeHookCalls = (node, importIdentifiers, hooks) => {\n    for (const hook of hooks) {\n      const selector = utils.getSelectorByImports(importIdentifiers, hook)\n\n      if (utils.isFunctionCallOf(node, selector)) {\n        return true\n      }\n    }\n\n    return false\n  }\n\n  const findUseQueryLikeHookCalls = (importIdentifiers, hooks) =>\n    root\n      // First, we need to find all call expressions.\n      .find(jscodeshift.CallExpression, {})\n      // Then we narrow the collection to the `useQuery` like hook calls.\n      .filter((node) =>\n        filterUseQueryLikeHookCalls(node.value, importIdentifiers, hooks),\n      )\n\n  const execute = (hooks, replacer) => {\n    findUseQueryLikeHookCalls(\n      utils.locateImports(hooks, packageName),\n      hooks,\n    ).replaceWith(replacer)\n  }\n\n  return {\n    execute,\n  }\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v4/__testfixtures__/default-import.input.tsx",
    "content": "import * as React from 'react'\nimport {\n  QueryCache,\n  QueryClient,\n  useInfiniteQuery,\n  useIsFetching,\n  useIsMutating,\n  useMutation,\n  useQueries,\n  useQuery,\n  useQueryClient,\n} from 'react-query'\n\nexport const Examples = () => {\n  useQuery('todos')\n  useInfiniteQuery('todos')\n  useMutation('todos')\n  useIsFetching('todos')\n  useIsMutating('todos')\n  useQueries([query1, query2])\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.getMutationDefaults('todos')\n  queryClient.getQueriesData('todos')\n  queryClient.getQueryData('todos')\n  queryClient.getQueryDefaults('todos')\n  queryClient.getQueryState('todos')\n  queryClient.isFetching('todos')\n  queryClient.setMutationDefaults('todos', { mutationFn: async () => null })\n  queryClient.setQueriesData('todos', () => null)\n  queryClient.setQueryData('todos', () => null)\n  queryClient.setQueryDefaults('todos', { queryFn: async () => null })\n  queryClient.cancelQueries('todos')\n  queryClient.fetchInfiniteQuery('todos')\n  queryClient.fetchQuery('todos')\n  queryClient.invalidateQueries('todos')\n  queryClient.prefetchInfiniteQuery('todos')\n  queryClient.prefetchQuery('todos')\n  queryClient.refetchQueries('todos')\n  queryClient.removeQueries('todos')\n  queryClient.resetQueries('todos')\n  // --- Direct hook call.\n  useQueryClient().getMutationDefaults('todos')\n  useQueryClient().getQueriesData('todos')\n  useQueryClient().getQueryData('todos')\n  useQueryClient().getQueryDefaults('todos')\n  useQueryClient().getQueryState('todos')\n  useQueryClient().isFetching('todos')\n  useQueryClient().setMutationDefaults('todos', {\n    mutationFn: async () => null,\n  })\n  useQueryClient().setQueriesData('todos', () => null)\n  useQueryClient().setQueryData('todos', () => null)\n  useQueryClient().setQueryDefaults('todos', { queryFn: async () => null })\n  useQueryClient().cancelQueries('todos')\n  useQueryClient().fetchInfiniteQuery('todos')\n  useQueryClient().fetchQuery('todos')\n  useQueryClient().invalidateQueries('todos')\n  useQueryClient().prefetchInfiniteQuery('todos')\n  useQueryClient().prefetchQuery('todos')\n  useQueryClient().refetchQueries('todos')\n  useQueryClient().removeQueries('todos')\n  useQueryClient().resetQueries('todos')\n  // QueryCache\n  // --- NewExpression\n  const queryCache1 = new QueryCache({\n    onError: (error) => console.log(error),\n    onSuccess: (success) => console.log(success)\n  })\n  queryCache1.find('todos')\n  queryCache1.findAll('todos')\n  // --- Instantiated hook call.\n  const queryClient1 = useQueryClient()\n  queryClient1.getQueryCache().find('todos')\n  queryClient1.getQueryCache().findAll('todos')\n  //\n  const queryClient2 = new QueryClient({})\n  queryClient2.getQueryCache().find('todos')\n  queryClient2.getQueryCache().findAll('todos')\n  //\n  const queryCache2 = queryClient1.getQueryCache()\n  queryCache2.find('todos')\n  queryCache2.findAll('todos')\n  // --- Direct hook call.\n  useQueryClient().getQueryCache().find('todos')\n  useQueryClient().getQueryCache().findAll('todos')\n  //\n  const queryCache3 = useQueryClient().getQueryCache()\n  queryCache3.find('todos')\n  queryCache3.findAll('todos')\n\n  return <div>Example Component</div>\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v4/__testfixtures__/default-import.output.tsx",
    "content": "import * as React from 'react'\nimport {\n  QueryCache,\n  QueryClient,\n  useInfiniteQuery,\n  useIsFetching,\n  useIsMutating,\n  useMutation,\n  useQueries,\n  useQuery,\n  useQueryClient,\n} from 'react-query'\n\nexport const Examples = () => {\n  useQuery(['todos'])\n  useInfiniteQuery(['todos'])\n  useMutation(['todos'])\n  useIsFetching(['todos'])\n  useIsMutating(['todos'])\n  useQueries({\n    queries: [query1, query2]\n  })\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.getMutationDefaults(['todos'])\n  queryClient.getQueriesData(['todos'])\n  queryClient.getQueryData(['todos'])\n  queryClient.getQueryDefaults(['todos'])\n  queryClient.getQueryState(['todos'])\n  queryClient.isFetching(['todos'])\n  queryClient.setMutationDefaults(['todos'], { mutationFn: async () => null })\n  queryClient.setQueriesData(['todos'], () => null)\n  queryClient.setQueryData(['todos'], () => null)\n  queryClient.setQueryDefaults(['todos'], { queryFn: async () => null })\n  queryClient.cancelQueries(['todos'])\n  queryClient.fetchInfiniteQuery(['todos'])\n  queryClient.fetchQuery(['todos'])\n  queryClient.invalidateQueries(['todos'])\n  queryClient.prefetchInfiniteQuery(['todos'])\n  queryClient.prefetchQuery(['todos'])\n  queryClient.refetchQueries(['todos'])\n  queryClient.removeQueries(['todos'])\n  queryClient.resetQueries(['todos'])\n  // --- Direct hook call.\n  useQueryClient().getMutationDefaults(['todos'])\n  useQueryClient().getQueriesData(['todos'])\n  useQueryClient().getQueryData(['todos'])\n  useQueryClient().getQueryDefaults(['todos'])\n  useQueryClient().getQueryState(['todos'])\n  useQueryClient().isFetching(['todos'])\n  useQueryClient().setMutationDefaults(['todos'], {\n    mutationFn: async () => null,\n  })\n  useQueryClient().setQueriesData(['todos'], () => null)\n  useQueryClient().setQueryData(['todos'], () => null)\n  useQueryClient().setQueryDefaults(['todos'], { queryFn: async () => null })\n  useQueryClient().cancelQueries(['todos'])\n  useQueryClient().fetchInfiniteQuery(['todos'])\n  useQueryClient().fetchQuery(['todos'])\n  useQueryClient().invalidateQueries(['todos'])\n  useQueryClient().prefetchInfiniteQuery(['todos'])\n  useQueryClient().prefetchQuery(['todos'])\n  useQueryClient().refetchQueries(['todos'])\n  useQueryClient().removeQueries(['todos'])\n  useQueryClient().resetQueries(['todos'])\n  // QueryCache\n  // --- NewExpression\n  const queryCache1 = new QueryCache({\n    onError: (error) => console.log(error),\n    onSuccess: (success) => console.log(success)\n  })\n  queryCache1.find(['todos'])\n  queryCache1.findAll(['todos'])\n  // --- Instantiated hook call.\n  const queryClient1 = useQueryClient()\n  queryClient1.getQueryCache().find(['todos'])\n  queryClient1.getQueryCache().findAll(['todos'])\n  //\n  const queryClient2 = new QueryClient({})\n  queryClient2.getQueryCache().find(['todos'])\n  queryClient2.getQueryCache().findAll(['todos'])\n  //\n  const queryCache2 = queryClient1.getQueryCache()\n  queryCache2.find(['todos'])\n  queryCache2.findAll(['todos'])\n  // --- Direct hook call.\n  useQueryClient().getQueryCache().find(['todos'])\n  useQueryClient().getQueryCache().findAll(['todos'])\n  //\n  const queryCache3 = useQueryClient().getQueryCache()\n  queryCache3.find(['todos'])\n  queryCache3.findAll(['todos'])\n\n  return <div>Example Component</div>\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v4/__testfixtures__/named-import.input.tsx",
    "content": "import * as React from 'react'\nimport {\n  QueryCache as RenamedQueryCache,\n  QueryClient as RenamedQueryClient,\n  useInfiniteQuery as useRenamedInfiniteQuery,\n  useIsFetching as useRenamedIsFetching,\n  useIsMutating as useRenamedIsMutating,\n  useMutation as useRenamedMutation,\n  useQueries as useRenamedQueries,\n  useQuery as useRenamedQuery,\n  useQueryClient as useRenamedQueryClient,\n} from 'react-query'\n\nexport const Examples = () => {\n  useRenamedQuery('todos')\n  useRenamedInfiniteQuery('todos')\n  useRenamedMutation('todos')\n  useRenamedIsFetching('todos')\n  useRenamedIsMutating('todos')\n  useRenamedQueries([query1, query2])\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useRenamedQueryClient()\n  queryClient.getMutationDefaults('todos')\n  queryClient.getQueriesData('todos')\n  queryClient.getQueryData('todos')\n  queryClient.getQueryDefaults('todos')\n  queryClient.getQueryState('todos')\n  queryClient.isFetching('todos')\n  queryClient.setMutationDefaults('todos', { mutationFn: async () => null })\n  queryClient.setQueriesData('todos', () => null)\n  queryClient.setQueryData('todos', () => null)\n  queryClient.setQueryDefaults('todos', { queryFn: async () => null })\n  queryClient.cancelQueries('todos')\n  queryClient.fetchInfiniteQuery('todos')\n  queryClient.fetchQuery('todos')\n  queryClient.invalidateQueries('todos')\n  queryClient.prefetchInfiniteQuery('todos')\n  queryClient.prefetchQuery('todos')\n  queryClient.refetchQueries('todos')\n  queryClient.removeQueries('todos')\n  queryClient.resetQueries('todos')\n  // --- Direct hook call.\n  useRenamedQueryClient().getMutationDefaults('todos')\n  useRenamedQueryClient().getQueriesData('todos')\n  useRenamedQueryClient().getQueryData('todos')\n  useRenamedQueryClient().getQueryDefaults('todos')\n  useRenamedQueryClient().getQueryState('todos')\n  useRenamedQueryClient().isFetching('todos')\n  useRenamedQueryClient().setMutationDefaults('todos', {\n    mutationFn: async () => null,\n  })\n  useRenamedQueryClient().setQueriesData('todos', () => null)\n  useRenamedQueryClient().setQueryData('todos', () => null)\n  useRenamedQueryClient().setQueryDefaults('todos', {\n    queryFn: async () => null,\n  })\n  useRenamedQueryClient().cancelQueries('todos')\n  useRenamedQueryClient().fetchInfiniteQuery('todos')\n  useRenamedQueryClient().fetchQuery('todos')\n  useRenamedQueryClient().invalidateQueries('todos')\n  useRenamedQueryClient().prefetchInfiniteQuery('todos')\n  useRenamedQueryClient().prefetchQuery('todos')\n  useRenamedQueryClient().refetchQueries('todos')\n  useRenamedQueryClient().removeQueries('todos')\n  useRenamedQueryClient().resetQueries('todos')\n  // QueryCache\n  // --- NewExpression\n  const queryCache1 = new RenamedQueryCache({\n    onError: (error) => console.log(error),\n    onSuccess: (success) => console.log(success)\n  })\n  queryCache1.find('todos')\n  queryCache1.findAll('todos')\n  // --- Instantiated hook call.\n  const queryClient1 = useRenamedQueryClient()\n  queryClient1.getQueryCache().find('todos')\n  queryClient1.getQueryCache().findAll('todos')\n  //\n  const queryClient2 = new RenamedQueryClient({})\n  queryClient2.getQueryCache().find('todos')\n  queryClient2.getQueryCache().findAll('todos')\n  //\n  const queryCache2 = queryClient1.getQueryCache()\n  queryCache2.find('todos')\n  queryCache2.findAll('todos')\n  // --- Direct hook call.\n  useRenamedQueryClient().getQueryCache().find('todos')\n  useRenamedQueryClient().getQueryCache().findAll('todos')\n  //\n  const queryCache3 = useRenamedQueryClient().getQueryCache()\n  queryCache3.find('todos')\n  queryCache3.findAll('todos')\n\n  return <div>Example Component</div>\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v4/__testfixtures__/named-import.output.tsx",
    "content": "import * as React from 'react'\nimport {\n  QueryCache as RenamedQueryCache,\n  QueryClient as RenamedQueryClient,\n  useInfiniteQuery as useRenamedInfiniteQuery,\n  useIsFetching as useRenamedIsFetching,\n  useIsMutating as useRenamedIsMutating,\n  useMutation as useRenamedMutation,\n  useQueries as useRenamedQueries,\n  useQuery as useRenamedQuery,\n  useQueryClient as useRenamedQueryClient,\n} from 'react-query'\n\nexport const Examples = () => {\n  useRenamedQuery(['todos'])\n  useRenamedInfiniteQuery(['todos'])\n  useRenamedMutation(['todos'])\n  useRenamedIsFetching(['todos'])\n  useRenamedIsMutating(['todos'])\n  useRenamedQueries({\n    queries: [query1, query2]\n  })\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useRenamedQueryClient()\n  queryClient.getMutationDefaults(['todos'])\n  queryClient.getQueriesData(['todos'])\n  queryClient.getQueryData(['todos'])\n  queryClient.getQueryDefaults(['todos'])\n  queryClient.getQueryState(['todos'])\n  queryClient.isFetching(['todos'])\n  queryClient.setMutationDefaults(['todos'], { mutationFn: async () => null })\n  queryClient.setQueriesData(['todos'], () => null)\n  queryClient.setQueryData(['todos'], () => null)\n  queryClient.setQueryDefaults(['todos'], { queryFn: async () => null })\n  queryClient.cancelQueries(['todos'])\n  queryClient.fetchInfiniteQuery(['todos'])\n  queryClient.fetchQuery(['todos'])\n  queryClient.invalidateQueries(['todos'])\n  queryClient.prefetchInfiniteQuery(['todos'])\n  queryClient.prefetchQuery(['todos'])\n  queryClient.refetchQueries(['todos'])\n  queryClient.removeQueries(['todos'])\n  queryClient.resetQueries(['todos'])\n  // --- Direct hook call.\n  useRenamedQueryClient().getMutationDefaults(['todos'])\n  useRenamedQueryClient().getQueriesData(['todos'])\n  useRenamedQueryClient().getQueryData(['todos'])\n  useRenamedQueryClient().getQueryDefaults(['todos'])\n  useRenamedQueryClient().getQueryState(['todos'])\n  useRenamedQueryClient().isFetching(['todos'])\n  useRenamedQueryClient().setMutationDefaults(['todos'], {\n    mutationFn: async () => null,\n  })\n  useRenamedQueryClient().setQueriesData(['todos'], () => null)\n  useRenamedQueryClient().setQueryData(['todos'], () => null)\n  useRenamedQueryClient().setQueryDefaults(['todos'], {\n    queryFn: async () => null,\n  })\n  useRenamedQueryClient().cancelQueries(['todos'])\n  useRenamedQueryClient().fetchInfiniteQuery(['todos'])\n  useRenamedQueryClient().fetchQuery(['todos'])\n  useRenamedQueryClient().invalidateQueries(['todos'])\n  useRenamedQueryClient().prefetchInfiniteQuery(['todos'])\n  useRenamedQueryClient().prefetchQuery(['todos'])\n  useRenamedQueryClient().refetchQueries(['todos'])\n  useRenamedQueryClient().removeQueries(['todos'])\n  useRenamedQueryClient().resetQueries(['todos'])\n  // QueryCache\n  // --- NewExpression\n  const queryCache1 = new RenamedQueryCache({\n    onError: (error) => console.log(error),\n    onSuccess: (success) => console.log(success)\n  })\n  queryCache1.find(['todos'])\n  queryCache1.findAll(['todos'])\n  // --- Instantiated hook call.\n  const queryClient1 = useRenamedQueryClient()\n  queryClient1.getQueryCache().find(['todos'])\n  queryClient1.getQueryCache().findAll(['todos'])\n  //\n  const queryClient2 = new RenamedQueryClient({})\n  queryClient2.getQueryCache().find(['todos'])\n  queryClient2.getQueryCache().findAll(['todos'])\n  //\n  const queryCache2 = queryClient1.getQueryCache()\n  queryCache2.find(['todos'])\n  queryCache2.findAll(['todos'])\n  // --- Direct hook call.\n  useRenamedQueryClient().getQueryCache().find(['todos'])\n  useRenamedQueryClient().getQueryCache().findAll(['todos'])\n  //\n  const queryCache3 = useRenamedQueryClient().getQueryCache()\n  queryCache3.find(['todos'])\n  queryCache3.findAll(['todos'])\n\n  return <div>Example Component</div>\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v4/__testfixtures__/namespaced-import.input.tsx",
    "content": "import * as React from 'react'\nimport * as RQ from 'react-query'\n\nexport const Examples = () => {\n  RQ.useQuery('todos')\n  RQ.useInfiniteQuery('todos')\n  RQ.useMutation('todos')\n  RQ.useIsFetching('todos')\n  RQ.useIsMutating('todos')\n  RQ.useQueries([query1, query2])\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = RQ.useQueryClient()\n  queryClient.getMutationDefaults('todos')\n  queryClient.getQueriesData('todos')\n  queryClient.getQueryData('todos')\n  queryClient.getQueryDefaults('todos')\n  queryClient.getQueryState('todos')\n  queryClient.isFetching('todos')\n  queryClient.setMutationDefaults('todos', { mutationFn: async () => null })\n  queryClient.setQueriesData('todos', () => null)\n  queryClient.setQueryData('todos', () => null)\n  queryClient.setQueryDefaults('todos', { queryFn: async () => null })\n  queryClient.cancelQueries('todos')\n  queryClient.fetchInfiniteQuery('todos')\n  queryClient.fetchQuery('todos')\n  queryClient.invalidateQueries('todos')\n  queryClient.prefetchInfiniteQuery('todos')\n  queryClient.prefetchQuery('todos')\n  queryClient.refetchQueries('todos')\n  queryClient.removeQueries('todos')\n  queryClient.resetQueries('todos')\n  // --- Direct hook call.\n  RQ.useQueryClient().getMutationDefaults('todos')\n  RQ.useQueryClient().getQueriesData('todos')\n  RQ.useQueryClient().getQueryData('todos')\n  RQ.useQueryClient().getQueryDefaults('todos')\n  RQ.useQueryClient().getQueryState('todos')\n  RQ.useQueryClient().isFetching('todos')\n  RQ.useQueryClient().setMutationDefaults('todos', {\n    mutationFn: async () => null,\n  })\n  RQ.useQueryClient().setQueriesData('todos', () => null)\n  RQ.useQueryClient().setQueryData('todos', () => null)\n  RQ.useQueryClient().setQueryDefaults('todos', {\n    queryFn: async () => null,\n  })\n  RQ.useQueryClient().cancelQueries('todos')\n  RQ.useQueryClient().fetchInfiniteQuery('todos')\n  RQ.useQueryClient().fetchQuery('todos')\n  RQ.useQueryClient().invalidateQueries('todos')\n  RQ.useQueryClient().prefetchInfiniteQuery('todos')\n  RQ.useQueryClient().prefetchQuery('todos')\n  RQ.useQueryClient().refetchQueries('todos')\n  RQ.useQueryClient().removeQueries('todos')\n  RQ.useQueryClient().resetQueries('todos')\n  // QueryCache\n  // --- NewExpression\n  const queryCache1 = new RQ.QueryCache({\n    onError: (error) => console.log(error),\n    onSuccess: (success) => console.log(success)\n  })\n  queryCache1.find('todos')\n  queryCache1.findAll('todos')\n  // --- Instantiated hook call.\n  const queryClient1 = RQ.useQueryClient()\n  queryClient1.getQueryCache().find('todos')\n  queryClient1.getQueryCache().findAll('todos')\n  //\n  const queryClient2 = new RQ.QueryClient({})\n  queryClient2.getQueryCache().find('todos')\n  queryClient2.getQueryCache().findAll('todos')\n  //\n  const queryCache2 = queryClient1.getQueryCache()\n  queryCache2.find('todos')\n  queryCache2.findAll('todos')\n  // --- Direct hook call.\n  RQ.useQueryClient().getQueryCache().find('todos')\n  RQ.useQueryClient().getQueryCache().findAll('todos')\n  //\n  const queryCache3 = RQ.useQueryClient().getQueryCache()\n  queryCache3.find('todos')\n  queryCache3.findAll('todos')\n\n  return <div>Example Component</div>\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v4/__testfixtures__/namespaced-import.output.tsx",
    "content": "import * as React from 'react'\nimport * as RQ from 'react-query'\n\nexport const Examples = () => {\n  RQ.useQuery(['todos'])\n  RQ.useInfiniteQuery(['todos'])\n  RQ.useMutation(['todos'])\n  RQ.useIsFetching(['todos'])\n  RQ.useIsMutating(['todos'])\n  RQ.useQueries({\n    queries: [query1, query2]\n  })\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = RQ.useQueryClient()\n  queryClient.getMutationDefaults(['todos'])\n  queryClient.getQueriesData(['todos'])\n  queryClient.getQueryData(['todos'])\n  queryClient.getQueryDefaults(['todos'])\n  queryClient.getQueryState(['todos'])\n  queryClient.isFetching(['todos'])\n  queryClient.setMutationDefaults(['todos'], { mutationFn: async () => null })\n  queryClient.setQueriesData(['todos'], () => null)\n  queryClient.setQueryData(['todos'], () => null)\n  queryClient.setQueryDefaults(['todos'], { queryFn: async () => null })\n  queryClient.cancelQueries(['todos'])\n  queryClient.fetchInfiniteQuery(['todos'])\n  queryClient.fetchQuery(['todos'])\n  queryClient.invalidateQueries(['todos'])\n  queryClient.prefetchInfiniteQuery(['todos'])\n  queryClient.prefetchQuery(['todos'])\n  queryClient.refetchQueries(['todos'])\n  queryClient.removeQueries(['todos'])\n  queryClient.resetQueries(['todos'])\n  // --- Direct hook call.\n  RQ.useQueryClient().getMutationDefaults(['todos'])\n  RQ.useQueryClient().getQueriesData(['todos'])\n  RQ.useQueryClient().getQueryData(['todos'])\n  RQ.useQueryClient().getQueryDefaults(['todos'])\n  RQ.useQueryClient().getQueryState(['todos'])\n  RQ.useQueryClient().isFetching(['todos'])\n  RQ.useQueryClient().setMutationDefaults(['todos'], {\n    mutationFn: async () => null,\n  })\n  RQ.useQueryClient().setQueriesData(['todos'], () => null)\n  RQ.useQueryClient().setQueryData(['todos'], () => null)\n  RQ.useQueryClient().setQueryDefaults(['todos'], {\n    queryFn: async () => null,\n  })\n  RQ.useQueryClient().cancelQueries(['todos'])\n  RQ.useQueryClient().fetchInfiniteQuery(['todos'])\n  RQ.useQueryClient().fetchQuery(['todos'])\n  RQ.useQueryClient().invalidateQueries(['todos'])\n  RQ.useQueryClient().prefetchInfiniteQuery(['todos'])\n  RQ.useQueryClient().prefetchQuery(['todos'])\n  RQ.useQueryClient().refetchQueries(['todos'])\n  RQ.useQueryClient().removeQueries(['todos'])\n  RQ.useQueryClient().resetQueries(['todos'])\n  // QueryCache\n  // --- NewExpression\n  const queryCache1 = new RQ.QueryCache({\n    onError: (error) => console.log(error),\n    onSuccess: (success) => console.log(success)\n  })\n  queryCache1.find(['todos'])\n  queryCache1.findAll(['todos'])\n  // --- Instantiated hook call.\n  const queryClient1 = RQ.useQueryClient()\n  queryClient1.getQueryCache().find(['todos'])\n  queryClient1.getQueryCache().findAll(['todos'])\n  //\n  const queryClient2 = new RQ.QueryClient({})\n  queryClient2.getQueryCache().find(['todos'])\n  queryClient2.getQueryCache().findAll(['todos'])\n  //\n  const queryCache2 = queryClient1.getQueryCache()\n  queryCache2.find(['todos'])\n  queryCache2.findAll(['todos'])\n  // --- Direct hook call.\n  RQ.useQueryClient().getQueryCache().find(['todos'])\n  RQ.useQueryClient().getQueryCache().findAll(['todos'])\n  //\n  const queryCache3 = RQ.useQueryClient().getQueryCache()\n  queryCache3.find(['todos'])\n  queryCache3.findAll(['todos'])\n\n  return <div>Example Component</div>\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v4/__testfixtures__/parameter-is-identifier.input.tsx",
    "content": "import * as React from 'react'\nimport { useMutation, useQuery, useQueryClient } from 'react-query'\n\nexport const ExampleWithStringLiteralKey = () => {\n  const stringLiteralKey = 'todos'\n  useQuery(stringLiteralKey)\n  useMutation(stringLiteralKey)\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries(stringLiteralKey)\n  // --- Direct hook call.\n  useQueryClient().cancelQueries(stringLiteralKey)\n\n  return <div>Example Component</div>\n}\n\nexport const ExampleWithTemplateLiteral = () => {\n  const templateLiteralKey = `todos`\n  useQuery(templateLiteralKey)\n  useMutation(templateLiteralKey)\n}\n\nexport const ExampleWithArrayExpressionKey = () => {\n  const arrayExpressionKey = ['todos']\n  useQuery(arrayExpressionKey)\n  useMutation(arrayExpressionKey)\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries(queryKey2)\n  // --- Direct hook call.\n  useQueryClient().cancelQueries(queryKey2)\n\n  return <div>Example Component</div>\n}\n\nexport const ExampleWithUnknownKey = () => {\n  useQuery(unknownQueryKey)\n  useMutation(unknownQueryKey)\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries(unknownQueryKey)\n  // --- Direct hook call.\n  useQueryClient().cancelQueries(unknownQueryKey)\n\n  return <div>Example Component</div>\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v4/__testfixtures__/parameter-is-identifier.output.tsx",
    "content": "import * as React from 'react'\nimport { useMutation, useQuery, useQueryClient } from 'react-query'\n\nexport const ExampleWithStringLiteralKey = () => {\n  const stringLiteralKey = 'todos'\n  useQuery([stringLiteralKey])\n  useMutation([stringLiteralKey])\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries([stringLiteralKey])\n  // --- Direct hook call.\n  useQueryClient().cancelQueries([stringLiteralKey])\n\n  return <div>Example Component</div>\n}\n\nexport const ExampleWithTemplateLiteral = () => {\n  const templateLiteralKey = `todos`\n  useQuery([templateLiteralKey])\n  useMutation([templateLiteralKey])\n}\n\nexport const ExampleWithArrayExpressionKey = () => {\n  const arrayExpressionKey = ['todos']\n  useQuery(arrayExpressionKey)\n  useMutation(arrayExpressionKey)\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries(queryKey2)\n  // --- Direct hook call.\n  useQueryClient().cancelQueries(queryKey2)\n\n  return <div>Example Component</div>\n}\n\nexport const ExampleWithUnknownKey = () => {\n  useQuery(unknownQueryKey)\n  useMutation(unknownQueryKey)\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries(unknownQueryKey)\n  // --- Direct hook call.\n  useQueryClient().cancelQueries(unknownQueryKey)\n\n  return <div>Example Component</div>\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v4/__testfixtures__/parameter-is-object-expression.input.tsx",
    "content": "import * as React from 'react'\nimport { useMutation, useQuery, useQueryClient } from 'react-query'\n\nconst options = {}\n\nexport const ExampleWithStringLiteral = () => {\n  useQuery({ queryKey: 'todos', exact: true }, options)\n  useMutation({ mutationKey: 'todos', exact: true }, options)\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries({ queryKey: 'todos', exact: true }, options)\n  // --- Direct hook call.\n  useQueryClient().cancelQueries({ queryKey: 'todos', exact: true }, options)\n\n  return <div>Example Component</div>\n}\n\nexport const ExampleWithStringLiteralIdentifier = () => {\n  const stringLiteralKey = 'todos'\n  useQuery({ queryKey: stringLiteralKey, exact: true }, options)\n  useMutation({ mutationKey: stringLiteralKey, exact: true }, options)\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries({ queryKey: stringLiteralKey, exact: true }, options)\n  // --- Direct hook call.\n  useQueryClient().cancelQueries({ queryKey: stringLiteralKey, exact: true }, options)\n\n  return <div>Example Component</div>\n}\n\nexport const ExampleWithTemplateLiteral = () => {\n  useQuery({ queryKey: `todos`, exact: true }, options)\n  useMutation({ mutationKey: `todos`, exact: true }, options)\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries({ queryKey: `todos`, exact: true }, options)\n  // --- Direct hook call.\n  useQueryClient().cancelQueries({ queryKey: `todos`, exact: true }, options)\n\n  return <div>Example Component</div>\n}\n\nexport const ExampleWithTemplateLiteralIdentifier = () => {\n  const templateLiteralKey = `todos`\n  useQuery({ queryKey: templateLiteralKey, exact: true }, options)\n  useMutation({ mutationKey: templateLiteralKey, exact: true }, options)\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries({ queryKey: templateLiteralKey, exact: true }, options)\n  // --- Direct hook call.\n  useQueryClient().cancelQueries({ queryKey: templateLiteralKey, exact: true }, options)\n\n  return <div>Example Component</div>\n}\n\nexport const ExampleWithArrayExpression = () => {\n  useQuery({ queryKey: ['todos'], exact: true }, options)\n  useMutation({ mutationKey: ['todos'], exact: true }, options)\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries({ queryKey: ['todos'], exact: true }, options)\n  // --- Direct hook call.\n  useQueryClient().cancelQueries({ queryKey: ['todos'], exact: true }, options)\n\n  return <div>Example Component</div>\n}\n\nexport const ExampleWithArrayExpressionIdentifier = () => {\n  const arrayExpressionKey = ['todos']\n  useQuery({ queryKey: arrayExpressionKey, exact: true }, options)\n  useMutation({ mutationKey: arrayExpressionKey, exact: true }, options)\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries({ queryKey: arrayExpressionKey, exact: true }, options)\n  // --- Direct hook call.\n  useQueryClient().cancelQueries({ queryKey: arrayExpressionKey, exact: true }, options)\n\n  return <div>Example Component</div>\n}\n\nexport const ExampleWithUnknownIdentifier1 = () => {\n  const createKey = (id) => ['todos', id]\n  const createdKey1 = createKey(1)\n  useQuery({ queryKey: createdKey1, exact: true }, options)\n  useMutation({ mutationKey: createdKey1, exact: true }, options)\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries({ queryKey: createdKey1, exact: true }, options)\n  // --- Direct hook call.\n  useQueryClient().cancelQueries({ queryKey: createdKey1, exact: true }, options)\n\n  return <div>Example Component</div>\n}\n\nexport const ExampleWithUnknownIdentifier2 = () => {\n  const createdKey2 = createKey()\n  useQuery({ queryKey: createdKey2, exact: true }, options)\n  useMutation({ mutationKey: createdKey2, exact: true }, options)\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries({ queryKey: createdKey2, exact: true }, options)\n  // --- Direct hook call.\n  useQueryClient().cancelQueries({ queryKey: createdKey2, exact: true }, options)\n\n  return <div>Example Component</div>\n}\n\nexport const ExampleWithUnknownIdentifier3 = () => {\n  useQuery({ queryKey: unknownQueryKey, exact: true }, options)\n  useMutation({ mutationKey: unknownQueryKey, exact: true }, options)\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries({ queryKey: unknownQueryKey, exact: true }, options)\n  // --- Direct hook call.\n  useQueryClient().cancelQueries({ queryKey: unknownQueryKey, exact: true }, options)\n\n  return <div>Example Component</div>\n}\n\n"
  },
  {
    "path": "packages/query-codemods/src/v4/__testfixtures__/parameter-is-object-expression.output.tsx",
    "content": "import * as React from 'react'\nimport { useMutation, useQuery, useQueryClient } from 'react-query'\n\nconst options = {}\n\nexport const ExampleWithStringLiteral = () => {\n  useQuery({\n    queryKey: ['todos'],\n    exact: true\n  }, options)\n  useMutation({\n    mutationKey: ['todos'],\n    exact: true\n  }, options)\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries({\n    queryKey: ['todos'],\n    exact: true\n  }, options)\n  // --- Direct hook call.\n  useQueryClient().cancelQueries({\n    queryKey: ['todos'],\n    exact: true\n  }, options)\n\n  return <div>Example Component</div>\n}\n\nexport const ExampleWithStringLiteralIdentifier = () => {\n  const stringLiteralKey = 'todos'\n  useQuery({\n    queryKey: [stringLiteralKey],\n    exact: true\n  }, options)\n  useMutation({\n    mutationKey: [stringLiteralKey],\n    exact: true\n  }, options)\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries({\n    queryKey: [stringLiteralKey],\n    exact: true\n  }, options)\n  // --- Direct hook call.\n  useQueryClient().cancelQueries({\n    queryKey: [stringLiteralKey],\n    exact: true\n  }, options)\n\n  return <div>Example Component</div>\n}\n\nexport const ExampleWithTemplateLiteral = () => {\n  useQuery({\n    queryKey: [`todos`],\n    exact: true\n  }, options)\n  useMutation({\n    mutationKey: [`todos`],\n    exact: true\n  }, options)\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries({\n    queryKey: [`todos`],\n    exact: true\n  }, options)\n  // --- Direct hook call.\n  useQueryClient().cancelQueries({\n    queryKey: [`todos`],\n    exact: true\n  }, options)\n\n  return <div>Example Component</div>\n}\n\nexport const ExampleWithTemplateLiteralIdentifier = () => {\n  const templateLiteralKey = `todos`\n  useQuery({\n    queryKey: [templateLiteralKey],\n    exact: true\n  }, options)\n  useMutation({\n    mutationKey: [templateLiteralKey],\n    exact: true\n  }, options)\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries({\n    queryKey: [templateLiteralKey],\n    exact: true\n  }, options)\n  // --- Direct hook call.\n  useQueryClient().cancelQueries({\n    queryKey: [templateLiteralKey],\n    exact: true\n  }, options)\n\n  return <div>Example Component</div>\n}\n\nexport const ExampleWithArrayExpression = () => {\n  useQuery({ queryKey: ['todos'], exact: true }, options)\n  useMutation({ mutationKey: ['todos'], exact: true }, options)\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries({ queryKey: ['todos'], exact: true }, options)\n  // --- Direct hook call.\n  useQueryClient().cancelQueries({ queryKey: ['todos'], exact: true }, options)\n\n  return <div>Example Component</div>\n}\n\nexport const ExampleWithArrayExpressionIdentifier = () => {\n  const arrayExpressionKey = ['todos']\n  useQuery({ queryKey: arrayExpressionKey, exact: true }, options)\n  useMutation({ mutationKey: arrayExpressionKey, exact: true }, options)\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries({ queryKey: arrayExpressionKey, exact: true }, options)\n  // --- Direct hook call.\n  useQueryClient().cancelQueries({ queryKey: arrayExpressionKey, exact: true }, options)\n\n  return <div>Example Component</div>\n}\n\nexport const ExampleWithUnknownIdentifier1 = () => {\n  const createKey = (id) => ['todos', id]\n  const createdKey1 = createKey(1)\n  useQuery({ queryKey: createdKey1, exact: true }, options)\n  useMutation({ mutationKey: createdKey1, exact: true }, options)\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries({ queryKey: createdKey1, exact: true }, options)\n  // --- Direct hook call.\n  useQueryClient().cancelQueries({ queryKey: createdKey1, exact: true }, options)\n\n  return <div>Example Component</div>\n}\n\nexport const ExampleWithUnknownIdentifier2 = () => {\n  const createdKey2 = createKey()\n  useQuery({ queryKey: createdKey2, exact: true }, options)\n  useMutation({ mutationKey: createdKey2, exact: true }, options)\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries({ queryKey: createdKey2, exact: true }, options)\n  // --- Direct hook call.\n  useQueryClient().cancelQueries({ queryKey: createdKey2, exact: true }, options)\n\n  return <div>Example Component</div>\n}\n\nexport const ExampleWithUnknownIdentifier3 = () => {\n  useQuery({ queryKey: unknownQueryKey, exact: true }, options)\n  useMutation({ mutationKey: unknownQueryKey, exact: true }, options)\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries({ queryKey: unknownQueryKey, exact: true }, options)\n  // --- Direct hook call.\n  useQueryClient().cancelQueries({ queryKey: unknownQueryKey, exact: true }, options)\n\n  return <div>Example Component</div>\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v4/__testfixtures__/replace-import-specifier.input.tsx",
    "content": "// React Query\nimport { useQuery, useQueryClient } from 'react-query'\nimport { useQuery as RenamedUseQuery, useQueryClient as RenamedUseQueryClient } from 'react-query'\nimport DefaultReactQuery from 'react-query'\nimport * as NamespacedReactQuery from 'react-query'\n// Devtools\nimport { ReactQueryDevtools } from 'react-query/devtools'\nimport { ReactQueryDevtools as RenamedReactQueryDevtools } from 'react-query/devtools'\nimport DefaultReactQueryDevtools from 'react-query/devtools'\nimport * as NamespacedReactQueryDevtools from 'react-query/devtools'\n"
  },
  {
    "path": "packages/query-codemods/src/v4/__testfixtures__/replace-import-specifier.output.tsx",
    "content": "// React Query\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useQuery as RenamedUseQuery, useQueryClient as RenamedUseQueryClient } from '@tanstack/react-query'\nimport DefaultReactQuery from '@tanstack/react-query'\nimport * as NamespacedReactQuery from '@tanstack/react-query'\n// Devtools\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\nimport { ReactQueryDevtools as RenamedReactQueryDevtools } from '@tanstack/react-query-devtools'\nimport DefaultReactQueryDevtools from '@tanstack/react-query-devtools'\nimport * as NamespacedReactQueryDevtools from '@tanstack/react-query-devtools'\n"
  },
  {
    "path": "packages/query-codemods/src/v4/__testfixtures__/type-arguments.input.tsx",
    "content": "import * as React from 'react'\nimport { useQueries, useQuery, useQueryClient } from 'react-query'\n\ntype Todos = {\n  items: ReadonlyArray<{\n    id: string\n    text: string\n  }>\n  ts: number\n}\n\nexport const Examples = () => {\n  useQuery<Todos>('todos')\n  useQueries<Array<Todos>>([query1, query2])\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.getQueriesData<Todos>('todos')\n  queryClient.getQueriesData<Todos>({ queryKey: 'todos' })\n  // --- Direct hook call.\n  useQueryClient().getQueriesData<Todos>('todos')\n  useQueryClient().getQueriesData<Todos>({ queryKey: 'todos' })\n\n  return <div>Example Component</div>\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v4/__testfixtures__/type-arguments.output.tsx",
    "content": "import * as React from 'react'\nimport { useQueries, useQuery, useQueryClient } from 'react-query'\n\ntype Todos = {\n  items: ReadonlyArray<{\n    id: string\n    text: string\n  }>\n  ts: number\n}\n\nexport const Examples = () => {\n  useQuery<Todos>(['todos'])\n  useQueries<Array<Todos>>({\n    queries: [query1, query2]\n  })\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.getQueriesData<Todos>(['todos'])\n  queryClient.getQueriesData<Todos>({\n    queryKey: ['todos']\n  })\n  // --- Direct hook call.\n  useQueryClient().getQueriesData<Todos>(['todos'])\n  useQueryClient().getQueriesData<Todos>({\n    queryKey: ['todos']\n  })\n\n  return <div>Example Component</div>\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v4/__tests__/key-transformation.test.cjs",
    "content": "const defineTest = require('jscodeshift/dist/testUtils').defineTest\n\ndefineTest(__dirname, 'key-transformation.cjs', null, 'default-import', {\n  parser: 'tsx',\n})\n\ndefineTest(__dirname, 'key-transformation.cjs', null, 'named-import', {\n  parser: 'tsx',\n})\n\ndefineTest(__dirname, 'key-transformation.cjs', null, 'namespaced-import', {\n  parser: 'tsx',\n})\n\ndefineTest(\n  __dirname,\n  'key-transformation.cjs',\n  null,\n  'parameter-is-identifier',\n  {\n    parser: 'tsx',\n  },\n)\n\ndefineTest(\n  __dirname,\n  'key-transformation.cjs',\n  null,\n  'parameter-is-object-expression',\n  {\n    parser: 'tsx',\n  },\n)\n\ndefineTest(__dirname, 'key-transformation.cjs', null, 'type-arguments', {\n  parser: 'tsx',\n})\n"
  },
  {
    "path": "packages/query-codemods/src/v4/__tests__/replace-import-specifier.test.cjs",
    "content": "const defineTest = require('jscodeshift/dist/testUtils').defineTest\n\ndefineTest(\n  __dirname,\n  'replace-import-specifier.cjs',\n  null,\n  'replace-import-specifier',\n  {\n    parser: 'tsx',\n  },\n)\n"
  },
  {
    "path": "packages/query-codemods/src/v4/key-transformation.cjs",
    "content": "const createUtilsObject = require('../utils/index.cjs')\nconst createKeyReplacer = require('./utils/replacers/key-replacer.cjs')\nconst createUseQueryLikeTransformer = require('../utils/transformers/use-query-like-transformer.cjs')\nconst createQueryClientTransformer = require('../utils/transformers/query-client-transformer.cjs')\nconst createQueryCacheTransformer = require('../utils/transformers/query-cache-transformer.cjs')\n\nconst transformQueryClientUsages = ({\n  jscodeshift,\n  utils,\n  root,\n  filePath,\n  packageName,\n}) => {\n  const transformer = createQueryClientTransformer({\n    jscodeshift,\n    utils,\n    root,\n    packageName,\n  })\n  const replacer = createKeyReplacer({ jscodeshift, root, filePath })\n\n  transformer.execute(\n    [\n      // Not object syntax-aware methods.\n      'getMutationDefaults',\n      'getQueriesData',\n      'getQueryData',\n      'getQueryDefaults',\n      'getQueryState',\n      'isFetching',\n      'setMutationDefaults',\n      'setQueriesData',\n      'setQueryData',\n      'setQueryDefaults',\n      // Object syntax-aware methods.\n      'cancelQueries',\n      'fetchInfiniteQuery',\n      'fetchQuery',\n      'invalidateQueries',\n      'prefetchInfiniteQuery',\n      'prefetchQuery',\n      'refetchQueries',\n      'removeQueries',\n      'resetQueries',\n    ],\n    replacer,\n  )\n}\n\nconst transformUseQueriesUsages = ({\n  jscodeshift,\n  utils,\n  root,\n  packageName,\n}) => {\n  const transformer = createUseQueryLikeTransformer({\n    jscodeshift,\n    utils,\n    root,\n    packageName,\n  })\n  const replacer = ({ node }) => {\n    /**\n     * When the node doesn't have the 'original' property, that means the codemod has been already applied,\n     * so we don't need to do any changes.\n     */\n    if (!node.original) {\n      return node\n    }\n\n    const newCallExpression = jscodeshift.callExpression(node.original.callee, [\n      jscodeshift.objectExpression([\n        jscodeshift.property(\n          'init',\n          jscodeshift.identifier('queries'),\n          node.original.arguments[0],\n        ),\n      ]),\n    ])\n\n    // TODO: This should be part of one function!\n    if (node.typeParameters) {\n      newCallExpression.typeArguments = node.typeParameters\n    }\n\n    return newCallExpression\n  }\n\n  transformer.execute(['useQueries'], replacer)\n}\n\nconst transformUseQueryLikeUsages = ({\n  jscodeshift,\n  utils,\n  root,\n  filePath,\n  packageName,\n}) => {\n  const transformer = createUseQueryLikeTransformer({\n    jscodeshift,\n    utils,\n    root,\n    packageName,\n  })\n\n  transformer.execute(\n    ['useQuery', 'useInfiniteQuery', 'useIsFetching', 'useIsMutating'],\n    createKeyReplacer({\n      jscodeshift,\n      root,\n      filePath,\n      keyName: 'queryKey',\n    }),\n  )\n  transformer.execute(\n    ['useMutation'],\n    createKeyReplacer({\n      jscodeshift,\n      root,\n      filePath,\n      keyName: 'mutationKey',\n    }),\n  )\n}\n\nconst transformQueryCacheUsages = ({\n  jscodeshift,\n  utils,\n  root,\n  filePath,\n  packageName,\n}) => {\n  const transformer = createQueryCacheTransformer({\n    jscodeshift,\n    utils,\n    root,\n    packageName,\n  })\n  const replacer = createKeyReplacer({ jscodeshift, root, filePath })\n\n  transformer.execute(replacer)\n}\n\nmodule.exports = (file, api) => {\n  const jscodeshift = api.jscodeshift\n  const root = jscodeshift(file.source)\n\n  // TODO: Execute the transformers only when it contains a `react-query` import!\n\n  const utils = createUtilsObject({ root, jscodeshift })\n  const filePath = file.path\n  const packageName = 'react-query'\n\n  // This function transforms usages like `useQuery` and `useMutation`.\n  transformUseQueryLikeUsages({\n    jscodeshift,\n    utils,\n    root,\n    filePath,\n    packageName,\n  })\n  // This function transforms usages of `useQueries`.\n  transformUseQueriesUsages({\n    jscodeshift,\n    utils,\n    root,\n    packageName,\n  })\n  // This function transforms usages of `QueryClient`.\n  transformQueryClientUsages({\n    jscodeshift,\n    utils,\n    root,\n    filePath,\n    packageName,\n  })\n  // This function transforms usages of `QueryCache`.\n  transformQueryCacheUsages({ jscodeshift, utils, root, filePath, packageName })\n\n  return root.toSource({ quote: 'single', lineTerminator: '\\n' })\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v4/replace-import-specifier.cjs",
    "content": "module.exports = (file, api) => {\n  const jscodeshift = api.jscodeshift\n  const root = jscodeshift(file.source)\n\n  const replacements = [\n    { from: 'react-query', to: '@tanstack/react-query' },\n    { from: 'react-query/devtools', to: '@tanstack/react-query-devtools' },\n  ]\n\n  replacements.forEach(({ from, to }) => {\n    root\n      .find(jscodeshift.ImportDeclaration, {\n        source: {\n          value: from,\n        },\n      })\n      .replaceWith(({ node }) => {\n        node.source.value = to\n\n        return node\n      })\n  })\n\n  return root.toSource({ quote: 'single', lineTerminator: '\\n' })\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v4/utils/replacers/key-replacer.cjs",
    "content": "class UnprocessableKeyError extends Error {\n  constructor(message) {\n    super(message)\n    this.name = 'UnprocessableKeyError'\n  }\n}\n\nmodule.exports = ({ jscodeshift, root, filePath, keyName = 'queryKey' }) => {\n  const isArrayExpression = (node) =>\n    jscodeshift.match(node, { type: jscodeshift.ArrayExpression.name })\n\n  const isStringLiteral = (node) =>\n    jscodeshift.match(node, { type: jscodeshift.StringLiteral.name }) ||\n    jscodeshift.match(node, { type: jscodeshift.Literal.name })\n\n  const isTemplateLiteral = (node) =>\n    jscodeshift.match(node, { type: jscodeshift.TemplateLiteral.name })\n\n  const findVariableDeclaration = (node) => {\n    const declarations = root\n      .find(jscodeshift.VariableDeclarator, {\n        id: {\n          type: jscodeshift.Identifier.name,\n          name: node.name,\n        },\n      })\n      .paths()\n\n    return declarations.length > 0 ? declarations[0] : null\n  }\n\n  const createKeyValue = (node) => {\n    // When the node is a string literal we convert it into an array of strings.\n    if (isStringLiteral(node)) {\n      return jscodeshift.arrayExpression([\n        jscodeshift.stringLiteral(node.value),\n      ])\n    }\n\n    // When the node is a template literal we convert it into an array of template literals.\n    if (isTemplateLiteral(node)) {\n      return jscodeshift.arrayExpression([\n        jscodeshift.templateLiteral(node.quasis, node.expressions),\n      ])\n    }\n\n    if (jscodeshift.match(node, { type: jscodeshift.Identifier.name })) {\n      // When the node is an identifier at first, we try to find its declaration, because we will try\n      // to guess its type.\n      const variableDeclaration = findVariableDeclaration(node)\n\n      if (!variableDeclaration) {\n        throw new UnprocessableKeyError(\n          `In file ${filePath} at line ${node.loc.start.line} the type of identifier \\`${node.name}\\` couldn't be recognized, so the codemod couldn't be applied. Please migrate manually.`,\n        )\n      }\n\n      const initializer = variableDeclaration.value.init\n\n      // When it's a string, we just wrap it into an array expression.\n      if (isStringLiteral(initializer) || isTemplateLiteral(initializer)) {\n        return jscodeshift.arrayExpression([node])\n      }\n    }\n\n    throw new UnprocessableKeyError(\n      `In file ${filePath} at line ${node.loc.start.line} the type of the \\`${keyName}\\` couldn't be recognized, so the codemod couldn't be applied. Please migrate manually.`,\n    )\n  }\n\n  const createKeyProperty = (node) =>\n    jscodeshift.property(\n      'init',\n      jscodeshift.identifier(keyName),\n      createKeyValue(node),\n    )\n\n  const getPropertyFromObjectExpression = (objectExpression, propertyName) =>\n    objectExpression.properties.find(\n      (property) => property.key.name === propertyName,\n    ) ?? null\n\n  const buildWithTypeArguments = (node, builder) => {\n    const newNode = builder(node)\n\n    if (node.typeParameters) {\n      newNode.typeArguments = node.typeParameters\n    }\n\n    return newNode\n  }\n\n  return ({ node }) => {\n    // When the node doesn't have the 'original' property, that means the codemod has been already applied,\n    // so we don't need to do any changes.\n    if (!node.original) {\n      return node\n    }\n\n    const methodArguments = node.arguments\n\n    // The method call doesn't have any arguments, we have nothing to do in this case.\n    if (methodArguments.length === 0) {\n      return node\n    }\n\n    try {\n      const [firstArgument, ...restOfTheArguments] = methodArguments\n\n      if (\n        jscodeshift.match(firstArgument, {\n          type: jscodeshift.ObjectExpression.name,\n        })\n      ) {\n        const originalKey = getPropertyFromObjectExpression(\n          firstArgument,\n          keyName,\n        )\n\n        if (!originalKey) {\n          throw new UnprocessableKeyError(\n            `In file ${filePath} at line ${node.loc.start.line} the \\`${keyName}\\` couldn't be found. Did you forget to add it?`,\n          )\n        }\n\n        const restOfTheProperties = firstArgument.properties.filter(\n          (item) => item.key.name !== keyName,\n        )\n\n        return buildWithTypeArguments(node, (originalNode) =>\n          jscodeshift.callExpression(originalNode.original.callee, [\n            jscodeshift.objectExpression([\n              createKeyProperty(originalKey.value),\n              ...restOfTheProperties,\n            ]),\n            ...restOfTheArguments,\n          ]),\n        )\n      }\n\n      // When the node is an array expression we just simply return it because we want query keys to be arrays.\n      if (isArrayExpression(firstArgument)) {\n        return node\n      }\n\n      return buildWithTypeArguments(node, (originalNode) =>\n        jscodeshift.callExpression(originalNode.original.callee, [\n          createKeyValue(firstArgument),\n          ...restOfTheArguments,\n        ]),\n      )\n    } catch (error) {\n      if (error.name === 'UnprocessableKeyError') {\n        if (process.env.NODE_ENV !== 'test') {\n          console.warn(error.message)\n        }\n\n        return node\n      }\n\n      throw error\n    }\n  }\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v5/is-loading/__testfixtures__/default-import.input.tsx",
    "content": "import * as React from 'react'\nimport { useQuery } from '@tanstack/react-query'\n\nexport const WithObjectPattern = () => {\n  const { isError, isLoading, isSuccess, status } = useQuery({\n    queryKey: ['queryKey'],\n    queryFn: () => ['data'],\n  })\n\n  if (isError || isLoading || isSuccess) {\n    console.log('Do something')\n  }\n\n  return <div>{JSON.stringify({ isError, isLoading, isSuccess, status })}</div>\n}\n\nexport const WithObjectPatternAndRename = () => {\n  const { isError, isLoading: isLoadingRenamed, isSuccess, status } = useQuery({\n    queryKey: ['queryKey'],\n    queryFn: () => ['data'],\n  })\n\n  if (isError || isLoadingRenamed || isSuccess) {\n    console.log('Do something')\n  }\n\n  return <div>{JSON.stringify({ isError, isLoadingRenamed, isSuccess, status })}</div>\n}\n\nexport const WithObjectPatternAndRestElement = () => {\n  const { isError, ...rest } = useQuery({\n    queryKey: ['queryKey'],\n    queryFn: () => ['data'],\n  })\n\n  if (isError || rest.isLoading || rest.isSuccess) {\n    console.log('Do something')\n  }\n\n  return <div>{JSON.stringify({ isError, isLoading: rest.isLoading, isSuccess: rest.isSuccess })}</div>\n}\n\nexport const WithIdentifier = () => {\n  const queryResult = useQuery({\n    queryKey: ['queryKey'],\n    queryFn: () => ['data'],\n  })\n\n  if (queryResult.isError || queryResult.isLoading || queryResult.isSuccess) {\n    console.log('Do something')\n  }\n\n  return <div>{JSON.stringify(queryResult)}</div>\n}\n\nexport const WithCombinations = () => {\n  function useSomethingElse() {\n    const { isError, isLoading, isSuccess, status } = useQuery({\n      queryKey: ['somethingElse'],\n      queryFn: () => ['data'],\n    })\n\n    return { isError, isLoading, isSuccess, status }\n  }\n\n  function useAnotherThing() {\n    const { isLoading, ...rest } = useQuery({\n      queryKey: ['anotherThing'],\n      queryFn: () => ['anotherData'],\n    })\n\n    return { isLoading: rest.isLoading, ...rest }\n  }\n\n  const { isError, isLoading: isLoadingRenamed, isSuccess, status } = useQuery({\n    queryKey: ['queryKey'],\n    queryFn: () => ['data'],\n  })\n\n  return isLoadingRenamed\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v5/is-loading/__testfixtures__/default-import.output.tsx",
    "content": "import * as React from 'react'\nimport { useQuery } from '@tanstack/react-query'\n\nexport const WithObjectPattern = () => {\n  const { isError, isPending, isSuccess, status } = useQuery({\n    queryKey: ['queryKey'],\n    queryFn: () => ['data'],\n  })\n\n  if (isError || isPending || isSuccess) {\n    console.log('Do something')\n  }\n\n  return <div>{JSON.stringify({ isError, isPending, isSuccess, status })}</div>;\n}\n\nexport const WithObjectPatternAndRename = () => {\n  const { isError, isPending: isLoadingRenamed, isSuccess, status } = useQuery({\n    queryKey: ['queryKey'],\n    queryFn: () => ['data'],\n  })\n\n  if (isError || isLoadingRenamed || isSuccess) {\n    console.log('Do something')\n  }\n\n  return <div>{JSON.stringify({ isError, isLoadingRenamed, isSuccess, status })}</div>\n}\n\nexport const WithObjectPatternAndRestElement = () => {\n  const { isError, ...rest } = useQuery({\n    queryKey: ['queryKey'],\n    queryFn: () => ['data'],\n  })\n\n  if (isError || rest.isPending || rest.isSuccess) {\n    console.log('Do something')\n  }\n\n  return <div>{JSON.stringify({ isError, isLoading: rest.isPending, isSuccess: rest.isSuccess })}</div>;\n}\n\nexport const WithIdentifier = () => {\n  const queryResult = useQuery({\n    queryKey: ['queryKey'],\n    queryFn: () => ['data'],\n  })\n\n  if (queryResult.isError || queryResult.isPending || queryResult.isSuccess) {\n    console.log('Do something')\n  }\n\n  return <div>{JSON.stringify(queryResult)}</div>\n}\n\nexport const WithCombinations = () => {\n  function useSomethingElse() {\n    const { isError, isPending, isSuccess, status } = useQuery({\n      queryKey: ['somethingElse'],\n      queryFn: () => ['data'],\n    })\n\n    return { isError, isPending, isSuccess, status };\n  }\n\n  function useAnotherThing() {\n    const { isPending, ...rest } = useQuery({\n      queryKey: ['anotherThing'],\n      queryFn: () => ['anotherData'],\n    })\n\n    return { isLoading: rest.isPending, ...rest };\n  }\n\n  const { isError, isPending: isLoadingRenamed, isSuccess, status } = useQuery({\n    queryKey: ['queryKey'],\n    queryFn: () => ['data'],\n  })\n\n  return isLoadingRenamed\n}\n\n"
  },
  {
    "path": "packages/query-codemods/src/v5/is-loading/__testfixtures__/named-import.input.tsx",
    "content": "import * as React from 'react'\nimport { useQuery as useRenamedUseQuery } from '@tanstack/react-query'\n\nexport const WithObjectPattern = () => {\n  const { isError, isLoading, isSuccess, status } = useRenamedUseQuery({\n    queryKey: ['queryKey'],\n    queryFn: () => ['data'],\n  })\n\n  if (isError || isLoading || isSuccess) {\n    console.log('Do something')\n  }\n\n  return <div>{JSON.stringify({ isError, isLoading, isSuccess, status })}</div>\n}\n\nexport const WithObjectPatternAndRename = () => {\n  const { isError, isLoading: isLoadingRenamed, isSuccess, status } = useRenamedUseQuery({\n    queryKey: ['queryKey'],\n    queryFn: () => ['data'],\n  })\n\n  if (isError || isLoadingRenamed || isSuccess) {\n    console.log('Do something')\n  }\n\n  return <div>{JSON.stringify({ isError, isLoadingRenamed, isSuccess, status })}</div>\n}\n\nexport const WithObjectPatternAndRestElement = () => {\n  const { isError, ...rest } = useRenamedUseQuery({\n    queryKey: ['queryKey'],\n    queryFn: () => ['data'],\n  })\n\n  if (isError || rest.isLoading || rest.isSuccess) {\n    console.log('Do something')\n  }\n\n  return <div>{JSON.stringify({ isError, isLoading: rest.isLoading, isSuccess: rest.isSuccess })}</div>\n}\n\nexport const WithIdentifier = () => {\n  const queryResult = useRenamedUseQuery({\n    queryKey: ['queryKey'],\n    queryFn: () => ['data'],\n  })\n\n  if (queryResult.isError || queryResult.isLoading || queryResult.isSuccess) {\n    console.log('Do something')\n  }\n\n  return <div>{JSON.stringify(queryResult)}</div>\n}\n\nexport const WithCombinations = () => {\n  function useSomethingElse() {\n    const { isError, isLoading, isSuccess, status } = useRenamedUseQuery({\n      queryKey: ['somethingElse'],\n      queryFn: () => ['data'],\n    })\n\n    return { isError, isLoading, isSuccess, status }\n  }\n\n  function useAnotherThing() {\n    const { isLoading, ...rest } = useRenamedUseQuery({\n      queryKey: ['anotherThing'],\n      queryFn: () => ['anotherData'],\n    })\n\n    return { isLoading: rest.isLoading, ...rest }\n  }\n\n  const { isError, isLoading: isLoadingRenamed, isSuccess, status } = useRenamedUseQuery({\n    queryKey: ['queryKey'],\n    queryFn: () => ['data'],\n  })\n\n  return isLoadingRenamed\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v5/is-loading/__testfixtures__/named-import.output.tsx",
    "content": "import * as React from 'react'\nimport { useQuery as useRenamedUseQuery } from '@tanstack/react-query'\n\nexport const WithObjectPattern = () => {\n  const { isError, isPending, isSuccess, status } = useRenamedUseQuery({\n    queryKey: ['queryKey'],\n    queryFn: () => ['data'],\n  })\n\n  if (isError || isPending || isSuccess) {\n    console.log('Do something')\n  }\n\n  return <div>{JSON.stringify({ isError, isPending, isSuccess, status })}</div>;\n}\n\nexport const WithObjectPatternAndRename = () => {\n  const { isError, isPending: isLoadingRenamed, isSuccess, status } = useRenamedUseQuery({\n    queryKey: ['queryKey'],\n    queryFn: () => ['data'],\n  })\n\n  if (isError || isLoadingRenamed || isSuccess) {\n    console.log('Do something')\n  }\n\n  return <div>{JSON.stringify({ isError, isLoadingRenamed, isSuccess, status })}</div>\n}\n\nexport const WithObjectPatternAndRestElement = () => {\n  const { isError, ...rest } = useRenamedUseQuery({\n    queryKey: ['queryKey'],\n    queryFn: () => ['data'],\n  })\n\n  if (isError || rest.isPending || rest.isSuccess) {\n    console.log('Do something')\n  }\n\n  return <div>{JSON.stringify({ isError, isLoading: rest.isPending, isSuccess: rest.isSuccess })}</div>;\n}\n\nexport const WithIdentifier = () => {\n  const queryResult = useRenamedUseQuery({\n    queryKey: ['queryKey'],\n    queryFn: () => ['data'],\n  })\n\n  if (queryResult.isError || queryResult.isPending || queryResult.isSuccess) {\n    console.log('Do something')\n  }\n\n  return <div>{JSON.stringify(queryResult)}</div>\n}\n\nexport const WithCombinations = () => {\n  function useSomethingElse() {\n    const { isError, isPending, isSuccess, status } = useRenamedUseQuery({\n      queryKey: ['somethingElse'],\n      queryFn: () => ['data'],\n    })\n\n    return { isError, isPending, isSuccess, status };\n  }\n\n  function useAnotherThing() {\n    const { isPending, ...rest } = useRenamedUseQuery({\n      queryKey: ['anotherThing'],\n      queryFn: () => ['anotherData'],\n    })\n\n    return { isLoading: rest.isPending, ...rest };\n  }\n\n  const { isError, isPending: isLoadingRenamed, isSuccess, status } = useRenamedUseQuery({\n    queryKey: ['queryKey'],\n    queryFn: () => ['data'],\n  })\n\n  return isLoadingRenamed\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v5/is-loading/__tests__/is-loading.test.cjs",
    "content": "const defineTest = require('jscodeshift/dist/testUtils').defineTest\n\ndefineTest(__dirname, 'is-loading.cjs', null, 'default-import', {\n  parser: 'tsx',\n})\n\ndefineTest(__dirname, 'is-loading.cjs', null, 'named-import', {\n  parser: 'tsx',\n})\n"
  },
  {
    "path": "packages/query-codemods/src/v5/is-loading/is-loading.cjs",
    "content": "const createUtilsObject = require('../../utils/index.cjs')\nconst createUseQueryLikeTransformer = require('../../utils/transformers/use-query-like-transformer.cjs')\nconst createQueryClientTransformer = require('../../utils/transformers/query-client-transformer.cjs')\n\nconst originalName = 'isLoading'\nconst newName = 'isPending'\n\n/**\n * @param {import('jscodeshift')} jscodeshift\n * @param {Object} utils\n * @param {import('jscodeshift').Collection} root\n * @param {string} filePath\n * @param {{keyName: \"mutationKey\"|\"queryKey\", queryClientMethods: ReadonlyArray<string>, hooks: ReadonlyArray<string>}} config\n */\nconst transformUsages = ({ jscodeshift, utils, root, filePath, config }) => {\n  /**\n   * @param {import('jscodeshift').CallExpression | import('jscodeshift').ExpressionStatement} node\n   * @returns {{start: number, end: number}}\n   */\n  const getNodeLocation = (node) => {\n    const location = utils.isCallExpression(node) ? node.callee.loc : node.loc\n    const start = location.start.line\n    const end = location.end.line\n\n    return { start, end }\n  }\n\n  /**\n   * @param {import('jscodeshift').ASTNode} node\n   * @returns {boolean}\n   */\n  const isObjectExpression = (node) => {\n    return jscodeshift.match(node, {\n      type: jscodeshift.ObjectExpression.name,\n    })\n  }\n\n  /**\n   * @param {import('jscodeshift').ASTNode} node\n   * @returns {boolean}\n   */\n  const isObjectPattern = (node) => {\n    return jscodeshift.match(node, {\n      type: jscodeshift.ObjectPattern.name,\n    })\n  }\n\n  /**\n   * @param {import('jscodeshift').ASTNode} node\n   * @returns {boolean}\n   */\n  const isVariableDeclarator = (node) => {\n    return jscodeshift.match(node, {\n      type: jscodeshift.VariableDeclarator.name,\n    })\n  }\n\n  /**\n   * @param {import('jscodeshift').Node} node\n   * @param {import('jscodeshift').Identifier} identifier\n   * @returns {Collection<import('jscodeshift').MemberExpression>}\n   */\n  const findIsLoadingPropertiesOfIdentifier = (node, identifier) => {\n    return jscodeshift(node).find(jscodeshift.MemberExpression, {\n      object: {\n        type: jscodeshift.Identifier.name,\n        name: identifier.name,\n      },\n      property: {\n        type: jscodeshift.Identifier.name,\n        name: originalName,\n      },\n    })\n  }\n\n  /**\n   * @param {import('jscodeshift').ObjectPattern} node\n   * @returns {import('jscodeshift').ObjectProperty|null}\n   */\n  const findIsLoadingObjectPropertyInObjectPattern = (node) => {\n    return (\n      node.properties.find((property) =>\n        jscodeshift.match(property, {\n          key: {\n            type: jscodeshift.Identifier.name,\n            name: originalName,\n          },\n        }),\n      ) ?? null\n    )\n  }\n\n  /**\n   * @param {import('jscodeshift').ObjectPattern} node\n   * @returns {import('jscodeshift').RestElement|null}\n   */\n  const findRestElementInObjectPattern = (node) => {\n    return (\n      node.properties.find((property) =>\n        jscodeshift.match(property, {\n          type: jscodeshift.RestElement.name,\n        }),\n      ) ?? null\n    )\n  }\n\n  const replacer = (path, transformNode) => {\n    const node = path.node\n    const parentNode = path.parentPath.value\n    const { start, end } = getNodeLocation(node)\n\n    try {\n      if (!isVariableDeclarator(parentNode)) {\n        // The parent node is not a variable declarator, the transformation will be skipped.\n        return node\n      }\n\n      const lookupNode = path.scope.node\n      const variableDeclaratorId = parentNode.id\n\n      if (isObjectPattern(variableDeclaratorId)) {\n        const isLoadingObjectProperty =\n          findIsLoadingObjectPropertyInObjectPattern(variableDeclaratorId)\n\n        if (isLoadingObjectProperty) {\n          jscodeshift(lookupNode)\n            .find(jscodeshift.ObjectProperty, {\n              key: {\n                type: jscodeshift.Identifier.name,\n                name: originalName,\n              },\n            })\n            .replaceWith((mutablePath) => {\n              if (isObjectPattern(mutablePath.parent)) {\n                const affectedProperty = mutablePath.value.value.shorthand\n                  ? 'value'\n                  : 'key'\n\n                mutablePath.value[affectedProperty].name = newName\n\n                return mutablePath.value\n              }\n\n              if (isObjectExpression(mutablePath.parent)) {\n                const affectedProperty = mutablePath.value.value.shorthand\n                  ? 'key'\n                  : 'value'\n\n                mutablePath.value[affectedProperty].name = newName\n\n                return mutablePath.value\n              }\n\n              return mutablePath.value\n            })\n\n          // Renaming all other 'isLoading' references that are object properties.\n          jscodeshift(lookupNode)\n            .find(jscodeshift.Identifier, { name: originalName })\n            .replaceWith((mutablePath) => {\n              if (\n                !jscodeshift.match(mutablePath.parent, {\n                  type: jscodeshift.ObjectProperty.name,\n                })\n              ) {\n                mutablePath.value.name = newName\n              }\n\n              return mutablePath.value\n            })\n        }\n\n        const restElement = findRestElementInObjectPattern(variableDeclaratorId)\n\n        if (restElement) {\n          findIsLoadingPropertiesOfIdentifier(\n            lookupNode,\n            restElement.argument,\n          ).replaceWith(({ node: mutableNode }) => {\n            mutableNode.property.name = newName\n\n            return mutableNode\n          })\n        }\n\n        return node\n      }\n\n      if (utils.isIdentifier(variableDeclaratorId)) {\n        findIsLoadingPropertiesOfIdentifier(\n          lookupNode,\n          variableDeclaratorId,\n        ).replaceWith(({ node: mutableNode }) => {\n          mutableNode.property.name = newName\n\n          return mutableNode\n        })\n\n        return node\n      }\n\n      utils.warn(\n        `The usage in file \"${filePath}\" at line ${start}:${end} could not be transformed. Please migrate this usage manually.`,\n      )\n\n      return node\n    } catch (error) {\n      utils.warn(\n        `An unknown error occurred while processing the \"${filePath}\" file. Please review this file, because the codemod couldn't be applied.`,\n      )\n\n      return node\n    }\n  }\n\n  createUseQueryLikeTransformer({ jscodeshift, utils, root }).execute(\n    config.hooks,\n    replacer,\n  )\n\n  createQueryClientTransformer({ jscodeshift, utils, root }).execute(\n    config.queryClientMethods,\n    replacer,\n  )\n}\n\nmodule.exports = (file, api) => {\n  const jscodeshift = api.jscodeshift\n  const root = jscodeshift(file.source)\n  const utils = createUtilsObject({ root, jscodeshift })\n  const filePath = file.path\n\n  const dependencies = { jscodeshift, utils, root, filePath }\n\n  transformUsages({\n    ...dependencies,\n    config: {\n      hooks: ['useQuery', 'useMutation'],\n      queryClientMethods: [],\n    },\n  })\n\n  return root.toSource({ quote: 'single', lineTerminator: '\\n' })\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v5/keep-previous-data/README.md",
    "content": "### Intro\n\nThe prerequisite for this code mod is to migrate your usages to the new syntax, so overloads for hooks and `QueryClient` methods shouldn't be available anymore.\n\n### Affected usages\n\nPlease note, this code mod transforms usages only where the first argument is an object expression.\n\nThe following usage should be transformed by the code mod:\n\n```ts\nconst { data } = useQuery({\n  queryKey: ['posts'],\n  queryFn: queryFn,\n  keepPreviousData: true,\n})\n```\n\nBut the following usage won't be transformed by the code mod, because the first argument an identifier:\n\n```ts\nconst hookArgument = {\n  queryKey: ['posts'],\n  queryFn: queryFn,\n  keepPreviousData: true,\n}\nconst { data } = useQuery(hookArgument)\n```\n\n### Troubleshooting\n\nIn case of any errors, feel free to reach us out via Discord or open an issue. If you open an issue, please provide a code snippet as well, because without a snippet we cannot find the bug in the code mod.\n"
  },
  {
    "path": "packages/query-codemods/src/v5/keep-previous-data/__testfixtures__/default.input.tsx",
    "content": "import * as React from 'react'\nimport axios from 'axios'\nimport { QueryClient, useQueries, useQuery, useQueryClient } from '@tanstack/react-query'\n\ntype Post = {\n  id: number\n  title: string\n  body: string\n}\n\nconst queryFn = async (): Promise<Array<Post>> => {\n  const { data } = await axios.get(\n    'https://jsonplaceholder.typicode.com/posts',\n  )\n  return data\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, so the codemod should transform\n * this usage.\n */\nexport const Example1 = () => {\n  const { data } = useQuery({\n    queryKey: ['posts'],\n    queryFn: queryFn,\n    keepPreviousData: true,\n  })\n\n  return <div>{JSON.stringify(data)}</div>\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, but the `placeholderData` is a function.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example2 = () => {\n  const { data } = useQueries({\n    queryKey: ['posts'],\n    queryFn: queryFn,\n    keepPreviousData: true,\n    placeholderData: () => previousData\n  })\n\n  return <div>{JSON.stringify(data)}</div>\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, but the `placeholderData` is a string.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example3 = () => {\n  const { data } = useQueries({\n    queryKey: ['posts'],\n    queryFn: queryFn,\n    keepPreviousData: true,\n    placeholderData: 'somePlaceholderData'\n  })\n\n  return <div>{JSON.stringify(data)}</div>\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `false`.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example4 = () => {\n  const { data } = useQueries({\n    queryKey: ['posts'],\n    queryFn: queryFn,\n    keepPreviousData: false,\n  })\n\n  return <div>{JSON.stringify(data)}</div>\n}\n\n/**\n * The object expression has a `keepPreviousData` property with which is an identifier.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example5 = () => {\n  const keepPreviousDataIdentifier = false\n  const { data } = useQueries({\n    queryKey: ['posts'],\n    queryFn: queryFn,\n    keepPreviousData: keepPreviousDataIdentifier,\n    placeholderData: () => previousData\n  })\n\n  return <div>{JSON.stringify(data)}</div>\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, so the codemod should transform\n * this usage.\n */\nexport const Example6 = () => {\n  const queryClient = new QueryClient()\n\n  queryClient.setQueryDefaults(['key'], {\n    keepPreviousData: true\n  })\n\n  useQueryClient().setQueryDefaults(['key'], {\n    keepPreviousData: true\n  })\n\n  const anotherQueryClient = useQueryClient()\n\n  anotherQueryClient.setQueryDefaults(['key'], {\n    keepPreviousData: true\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, but the `placeholderData` is a function.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example7 = () => {\n  const queryClient = new QueryClient()\n\n  queryClient.setQueryDefaults(['key'], {\n    keepPreviousData: true,\n    placeholderData: () => previousData\n  })\n\n  useQueryClient().setQueryDefaults(['key'], {\n    keepPreviousData: true,\n    placeholderData: () => previousData\n  })\n\n  const anotherQueryClient = useQueryClient()\n\n  anotherQueryClient.setQueryDefaults(['key'], {\n    keepPreviousData: true,\n    placeholderData: () => previousData\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, but the `placeholderData` is a string.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example8 = () => {\n  const queryClient = new QueryClient()\n\n  queryClient.setQueryDefaults(['key'], {\n    keepPreviousData: true,\n    placeholderData: 'somePlaceholderData'\n  })\n\n  useQueryClient().setQueryDefaults(['key'], {\n    keepPreviousData: true,\n    placeholderData: 'somePlaceholderData'\n  })\n\n  const anotherQueryClient = useQueryClient()\n\n  anotherQueryClient.setQueryDefaults(['key'], {\n    keepPreviousData: true,\n    placeholderData: 'somePlaceholderData'\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `false`.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example9 = () => {\n  const queryClient = new QueryClient()\n\n  queryClient.setQueryDefaults(['key'], {\n    keepPreviousData: false,\n  })\n\n  useQueryClient().setQueryDefaults(['key'], {\n    keepPreviousData: false,\n  })\n\n  const anotherQueryClient = useQueryClient()\n\n  anotherQueryClient.setQueryDefaults(['key'], {\n    keepPreviousData: false,\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with which is an identifier.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example10 = () => {\n  const queryClient = new QueryClient()\n  const keepPreviousDataIdentifier = false\n\n  queryClient.setQueryDefaults(['key'], {\n    keepPreviousData: keepPreviousDataIdentifier,\n    placeholderData: () => previousData\n  })\n\n  useQueryClient().setQueryDefaults(['key'], {\n    keepPreviousData: keepPreviousDataIdentifier,\n    placeholderData: () => previousData\n  })\n\n  const anotherQueryClient = useQueryClient()\n\n  anotherQueryClient.setQueryDefaults(['key'], {\n    keepPreviousData: keepPreviousDataIdentifier,\n    placeholderData: () => previousData\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, so the codemod should transform\n * this usage.\n */\nexport const Example11 = () => {\n  new QueryClient({\n    defaultOptions: {\n      queries: {\n        keepPreviousData: true\n      }\n    }\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, but the `placeholderData` is a function.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example12 = () => {\n  new QueryClient({\n    defaultOptions: {\n      queries: {\n        keepPreviousData: true,\n        placeholderData: () => previousData\n      }\n    }\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, but the `placeholderData` is a string.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example13 = () => {\n  new QueryClient({\n    defaultOptions: {\n      queries: {\n        keepPreviousData: true,\n        placeholderData: 'somePlaceholderData'\n      }\n    }\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `false`.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example14 = () => {\n  new QueryClient({\n    defaultOptions: {\n      queries: {\n        keepPreviousData: false,\n      }\n    }\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with which is an identifier.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example15 = () => {\n  const keepPreviousDataIdentifier = false\n  new QueryClient({\n    defaultOptions: {\n      queries: {\n        keepPreviousData: keepPreviousDataIdentifier,\n        placeholderData: () => previousData\n      }\n    }\n  })\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v5/keep-previous-data/__testfixtures__/default.output.tsx",
    "content": "import * as React from 'react'\nimport axios from 'axios'\nimport { keepPreviousData, QueryClient, useQueries, useQuery, useQueryClient } from '@tanstack/react-query';\n\ntype Post = {\n  id: number\n  title: string\n  body: string\n}\n\nconst queryFn = async (): Promise<Array<Post>> => {\n  const { data } = await axios.get(\n    'https://jsonplaceholder.typicode.com/posts',\n  )\n  return data\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, so the codemod should transform\n * this usage.\n */\nexport const Example1 = () => {\n  const { data } = useQuery({\n    queryKey: ['posts'],\n    queryFn: queryFn,\n    placeholderData: keepPreviousData\n  })\n\n  return <div>{JSON.stringify(data)}</div>\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, but the `placeholderData` is a function.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example2 = () => {\n  const { data } = useQueries({\n    queryKey: ['posts'],\n    queryFn: queryFn,\n    keepPreviousData: true,\n    placeholderData: () => previousData\n  })\n\n  return <div>{JSON.stringify(data)}</div>\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, but the `placeholderData` is a string.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example3 = () => {\n  const { data } = useQueries({\n    queryKey: ['posts'],\n    queryFn: queryFn,\n    keepPreviousData: true,\n    placeholderData: 'somePlaceholderData'\n  })\n\n  return <div>{JSON.stringify(data)}</div>\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `false`.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example4 = () => {\n  const { data } = useQueries({\n    queryKey: ['posts'],\n    queryFn: queryFn,\n    keepPreviousData: false,\n  })\n\n  return <div>{JSON.stringify(data)}</div>\n}\n\n/**\n * The object expression has a `keepPreviousData` property with which is an identifier.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example5 = () => {\n  const keepPreviousDataIdentifier = false\n  const { data } = useQueries({\n    queryKey: ['posts'],\n    queryFn: queryFn,\n    keepPreviousData: keepPreviousDataIdentifier,\n    placeholderData: () => previousData\n  })\n\n  return <div>{JSON.stringify(data)}</div>\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, so the codemod should transform\n * this usage.\n */\nexport const Example6 = () => {\n  const queryClient = new QueryClient()\n\n  queryClient.setQueryDefaults(['key'], {\n    placeholderData: keepPreviousData\n  })\n\n  useQueryClient().setQueryDefaults(['key'], {\n    placeholderData: keepPreviousData\n  })\n\n  const anotherQueryClient = useQueryClient()\n\n  anotherQueryClient.setQueryDefaults(['key'], {\n    placeholderData: keepPreviousData\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, but the `placeholderData` is a function.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example7 = () => {\n  const queryClient = new QueryClient()\n\n  queryClient.setQueryDefaults(['key'], {\n    keepPreviousData: true,\n    placeholderData: () => previousData\n  })\n\n  useQueryClient().setQueryDefaults(['key'], {\n    keepPreviousData: true,\n    placeholderData: () => previousData\n  })\n\n  const anotherQueryClient = useQueryClient()\n\n  anotherQueryClient.setQueryDefaults(['key'], {\n    keepPreviousData: true,\n    placeholderData: () => previousData\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, but the `placeholderData` is a string.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example8 = () => {\n  const queryClient = new QueryClient()\n\n  queryClient.setQueryDefaults(['key'], {\n    keepPreviousData: true,\n    placeholderData: 'somePlaceholderData'\n  })\n\n  useQueryClient().setQueryDefaults(['key'], {\n    keepPreviousData: true,\n    placeholderData: 'somePlaceholderData'\n  })\n\n  const anotherQueryClient = useQueryClient()\n\n  anotherQueryClient.setQueryDefaults(['key'], {\n    keepPreviousData: true,\n    placeholderData: 'somePlaceholderData'\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `false`.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example9 = () => {\n  const queryClient = new QueryClient()\n\n  queryClient.setQueryDefaults(['key'], {\n    keepPreviousData: false,\n  })\n\n  useQueryClient().setQueryDefaults(['key'], {\n    keepPreviousData: false,\n  })\n\n  const anotherQueryClient = useQueryClient()\n\n  anotherQueryClient.setQueryDefaults(['key'], {\n    keepPreviousData: false,\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with which is an identifier.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example10 = () => {\n  const queryClient = new QueryClient()\n  const keepPreviousDataIdentifier = false\n\n  queryClient.setQueryDefaults(['key'], {\n    keepPreviousData: keepPreviousDataIdentifier,\n    placeholderData: () => previousData\n  })\n\n  useQueryClient().setQueryDefaults(['key'], {\n    keepPreviousData: keepPreviousDataIdentifier,\n    placeholderData: () => previousData\n  })\n\n  const anotherQueryClient = useQueryClient()\n\n  anotherQueryClient.setQueryDefaults(['key'], {\n    keepPreviousData: keepPreviousDataIdentifier,\n    placeholderData: () => previousData\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, so the codemod should transform\n * this usage.\n */\nexport const Example11 = () => {\n  new QueryClient({\n    defaultOptions: {\n      queries: {\n        placeholderData: keepPreviousData\n      }\n    }\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, but the `placeholderData` is a function.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example12 = () => {\n  new QueryClient({\n    defaultOptions: {\n      queries: {\n        keepPreviousData: true,\n        placeholderData: () => previousData\n      }\n    }\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, but the `placeholderData` is a string.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example13 = () => {\n  new QueryClient({\n    defaultOptions: {\n      queries: {\n        keepPreviousData: true,\n        placeholderData: 'somePlaceholderData'\n      }\n    }\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `false`.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example14 = () => {\n  new QueryClient({\n    defaultOptions: {\n      queries: {\n        keepPreviousData: false,\n      }\n    }\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with which is an identifier.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example15 = () => {\n  const keepPreviousDataIdentifier = false\n  new QueryClient({\n    defaultOptions: {\n      queries: {\n        keepPreviousData: keepPreviousDataIdentifier,\n        placeholderData: () => previousData\n      }\n    }\n  })\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v5/keep-previous-data/__testfixtures__/named.input.tsx",
    "content": "import * as React from 'react'\nimport axios from 'axios'\nimport {\n  QueryClient as RenamedQueryClient,\n  useQueries as useRenamedUseQueries,\n  useQuery as useRenamedUseQuery,\n  useQueryClient as useRenamedUseQueryClient\n} from '@tanstack/react-query'\n\ntype Post = {\n  id: number\n  title: string\n  body: string\n}\n\nconst queryFn = async (): Promise<Array<Post>> => {\n  const { data } = await axios.get(\n    'https://jsonplaceholder.typicode.com/posts',\n  )\n  return data\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, so the codemod should transform\n * this usage.\n */\nexport const Example1 = () => {\n  const { data } = useRenamedUseQuery({\n    queryKey: ['posts'],\n    queryFn: queryFn,\n    keepPreviousData: true,\n  })\n\n  return <div>{JSON.stringify(data)}</div>\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, but the `placeholderData` is a function.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example2 = () => {\n  const { data } = useRenamedUseQuery({\n    queryKey: ['posts'],\n    queryFn: queryFn,\n    keepPreviousData: true,\n    placeholderData: () => previousData\n  })\n\n  return <div>{JSON.stringify(data)}</div>\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, but the `placeholderData` is a string.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example3 = () => {\n  const { data } = useRenamedUseQueries({\n    queryKey: ['posts'],\n    queryFn: queryFn,\n    keepPreviousData: true,\n    placeholderData: 'somePlaceholderData'\n  })\n\n  return <div>{JSON.stringify(data)}</div>\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `false`.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example4 = () => {\n  const { data } = useRenamedUseQueries({\n    queryKey: ['posts'],\n    queryFn: queryFn,\n    keepPreviousData: false,\n  })\n\n  return <div>{JSON.stringify(data)}</div>\n}\n\n/**\n * The object expression has a `keepPreviousData` property with which is an identifier.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example5 = () => {\n  const keepPreviousDataIdentifier = false\n  const { data } = useRenamedUseQueries({\n    queryKey: ['posts'],\n    queryFn: queryFn,\n    keepPreviousData: keepPreviousDataIdentifier,\n    placeholderData: () => previousData\n  })\n\n  return <div>{JSON.stringify(data)}</div>\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, so the codemod should transform\n * this usage.\n */\nexport const Example6 = () => {\n  const queryClient = new RenamedQueryClient()\n\n  queryClient.setQueryDefaults(['key'], {\n    keepPreviousData: true\n  })\n\n  useRenamedUseQueryClient().setQueryDefaults(['key'], {\n    keepPreviousData: true\n  })\n\n  const anotherQueryClient = useRenamedUseQueryClient()\n\n  anotherQueryClient.setQueryDefaults(['key'], {\n    keepPreviousData: true\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, but the `placeholderData` is a function.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example7 = () => {\n  const queryClient = new RenamedQueryClient()\n\n  queryClient.setQueryDefaults(['key'], {\n    keepPreviousData: true,\n    placeholderData: () => previousData\n  })\n\n  useRenamedUseQueryClient().setQueryDefaults(['key'], {\n    keepPreviousData: true,\n    placeholderData: () => previousData\n  })\n\n  const anotherQueryClient = useRenamedUseQueryClient()\n\n  anotherQueryClient.setQueryDefaults(['key'], {\n    keepPreviousData: true,\n    placeholderData: () => previousData\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, but the `placeholderData` is a string.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example8 = () => {\n  const queryClient = new RenamedQueryClient()\n\n  queryClient.setQueryDefaults(['key'], {\n    keepPreviousData: true,\n    placeholderData: 'somePlaceholderData'\n  })\n\n  useRenamedUseQueryClient().setQueryDefaults(['key'], {\n    keepPreviousData: true,\n    placeholderData: 'somePlaceholderData'\n  })\n\n  const anotherQueryClient = useRenamedUseQueryClient()\n\n  anotherQueryClient.setQueryDefaults(['key'], {\n    keepPreviousData: true,\n    placeholderData: 'somePlaceholderData'\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `false`.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example9 = () => {\n  const queryClient = new RenamedQueryClient()\n\n  queryClient.setQueryDefaults(['key'], {\n    keepPreviousData: false,\n  })\n\n  useRenamedUseQueryClient().setQueryDefaults(['key'], {\n    keepPreviousData: false,\n  })\n\n  const anotherQueryClient = useRenamedUseQueryClient()\n\n  anotherQueryClient.setQueryDefaults(['key'], {\n    keepPreviousData: false,\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with which is an identifier.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example10 = () => {\n  const queryClient = new RenamedQueryClient()\n  const keepPreviousDataIdentifier = false\n\n  queryClient.setQueryDefaults(['key'], {\n    keepPreviousData: keepPreviousDataIdentifier,\n    placeholderData: () => previousData\n  })\n\n  useRenamedUseQueryClient().setQueryDefaults(['key'], {\n    keepPreviousData: keepPreviousDataIdentifier,\n    placeholderData: () => previousData\n  })\n\n  const anotherQueryClient = useRenamedUseQueryClient()\n\n  anotherQueryClient.setQueryDefaults(['key'], {\n    keepPreviousData: keepPreviousDataIdentifier,\n    placeholderData: () => previousData\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, so the codemod should transform\n * this usage.\n */\nexport const Example11 = () => {\n  new RenamedQueryClient({\n    defaultOptions: {\n      queries: {\n        keepPreviousData: true\n      }\n    }\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, but the `placeholderData` is a function.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example12 = () => {\n  new RenamedQueryClient({\n    defaultOptions: {\n      queries: {\n        keepPreviousData: true,\n        placeholderData: () => previousData\n      }\n    }\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, but the `placeholderData` is a string.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example13 = () => {\n  new RenamedQueryClient({\n    defaultOptions: {\n      queries: {\n        keepPreviousData: true,\n        placeholderData: 'somePlaceholderData'\n      }\n    }\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `false`.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example14 = () => {\n  new RenamedQueryClient({\n    defaultOptions: {\n      queries: {\n        keepPreviousData: false,\n      }\n    }\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with which is an identifier.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example15 = () => {\n  const keepPreviousDataIdentifier = false\n  new RenamedQueryClient({\n    defaultOptions: {\n      queries: {\n        keepPreviousData: keepPreviousDataIdentifier,\n        placeholderData: () => previousData\n      }\n    }\n  })\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v5/keep-previous-data/__testfixtures__/named.output.tsx",
    "content": "import * as React from 'react'\nimport axios from 'axios'\nimport {\n  keepPreviousData,\n  QueryClient as RenamedQueryClient,\n  useQueries as useRenamedUseQueries,\n  useQuery as useRenamedUseQuery,\n  useQueryClient as useRenamedUseQueryClient,\n} from '@tanstack/react-query';\n\ntype Post = {\n  id: number\n  title: string\n  body: string\n}\n\nconst queryFn = async (): Promise<Array<Post>> => {\n  const { data } = await axios.get(\n    'https://jsonplaceholder.typicode.com/posts',\n  )\n  return data\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, so the codemod should transform\n * this usage.\n */\nexport const Example1 = () => {\n  const { data } = useRenamedUseQuery({\n    queryKey: ['posts'],\n    queryFn: queryFn,\n    placeholderData: keepPreviousData\n  })\n\n  return <div>{JSON.stringify(data)}</div>\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, but the `placeholderData` is a function.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example2 = () => {\n  const { data } = useRenamedUseQuery({\n    queryKey: ['posts'],\n    queryFn: queryFn,\n    keepPreviousData: true,\n    placeholderData: () => previousData\n  })\n\n  return <div>{JSON.stringify(data)}</div>\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, but the `placeholderData` is a string.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example3 = () => {\n  const { data } = useRenamedUseQueries({\n    queryKey: ['posts'],\n    queryFn: queryFn,\n    keepPreviousData: true,\n    placeholderData: 'somePlaceholderData'\n  })\n\n  return <div>{JSON.stringify(data)}</div>\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `false`.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example4 = () => {\n  const { data } = useRenamedUseQueries({\n    queryKey: ['posts'],\n    queryFn: queryFn,\n    keepPreviousData: false,\n  })\n\n  return <div>{JSON.stringify(data)}</div>\n}\n\n/**\n * The object expression has a `keepPreviousData` property with which is an identifier.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example5 = () => {\n  const keepPreviousDataIdentifier = false\n  const { data } = useRenamedUseQueries({\n    queryKey: ['posts'],\n    queryFn: queryFn,\n    keepPreviousData: keepPreviousDataIdentifier,\n    placeholderData: () => previousData\n  })\n\n  return <div>{JSON.stringify(data)}</div>\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, so the codemod should transform\n * this usage.\n */\nexport const Example6 = () => {\n  const queryClient = new RenamedQueryClient()\n\n  queryClient.setQueryDefaults(['key'], {\n    placeholderData: keepPreviousData\n  })\n\n  useRenamedUseQueryClient().setQueryDefaults(['key'], {\n    placeholderData: keepPreviousData\n  })\n\n  const anotherQueryClient = useRenamedUseQueryClient()\n\n  anotherQueryClient.setQueryDefaults(['key'], {\n    placeholderData: keepPreviousData\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, but the `placeholderData` is a function.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example7 = () => {\n  const queryClient = new RenamedQueryClient()\n\n  queryClient.setQueryDefaults(['key'], {\n    keepPreviousData: true,\n    placeholderData: () => previousData\n  })\n\n  useRenamedUseQueryClient().setQueryDefaults(['key'], {\n    keepPreviousData: true,\n    placeholderData: () => previousData\n  })\n\n  const anotherQueryClient = useRenamedUseQueryClient()\n\n  anotherQueryClient.setQueryDefaults(['key'], {\n    keepPreviousData: true,\n    placeholderData: () => previousData\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, but the `placeholderData` is a string.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example8 = () => {\n  const queryClient = new RenamedQueryClient()\n\n  queryClient.setQueryDefaults(['key'], {\n    keepPreviousData: true,\n    placeholderData: 'somePlaceholderData'\n  })\n\n  useRenamedUseQueryClient().setQueryDefaults(['key'], {\n    keepPreviousData: true,\n    placeholderData: 'somePlaceholderData'\n  })\n\n  const anotherQueryClient = useRenamedUseQueryClient()\n\n  anotherQueryClient.setQueryDefaults(['key'], {\n    keepPreviousData: true,\n    placeholderData: 'somePlaceholderData'\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `false`.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example9 = () => {\n  const queryClient = new RenamedQueryClient()\n\n  queryClient.setQueryDefaults(['key'], {\n    keepPreviousData: false,\n  })\n\n  useRenamedUseQueryClient().setQueryDefaults(['key'], {\n    keepPreviousData: false,\n  })\n\n  const anotherQueryClient = useRenamedUseQueryClient()\n\n  anotherQueryClient.setQueryDefaults(['key'], {\n    keepPreviousData: false,\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with which is an identifier.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example10 = () => {\n  const queryClient = new RenamedQueryClient()\n  const keepPreviousDataIdentifier = false\n\n  queryClient.setQueryDefaults(['key'], {\n    keepPreviousData: keepPreviousDataIdentifier,\n    placeholderData: () => previousData\n  })\n\n  useRenamedUseQueryClient().setQueryDefaults(['key'], {\n    keepPreviousData: keepPreviousDataIdentifier,\n    placeholderData: () => previousData\n  })\n\n  const anotherQueryClient = useRenamedUseQueryClient()\n\n  anotherQueryClient.setQueryDefaults(['key'], {\n    keepPreviousData: keepPreviousDataIdentifier,\n    placeholderData: () => previousData\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, so the codemod should transform\n * this usage.\n */\nexport const Example11 = () => {\n  new RenamedQueryClient({\n    defaultOptions: {\n      queries: {\n        placeholderData: keepPreviousData\n      }\n    }\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, but the `placeholderData` is a function.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example12 = () => {\n  new RenamedQueryClient({\n    defaultOptions: {\n      queries: {\n        keepPreviousData: true,\n        placeholderData: () => previousData\n      }\n    }\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `true`, but the `placeholderData` is a string.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example13 = () => {\n  new RenamedQueryClient({\n    defaultOptions: {\n      queries: {\n        keepPreviousData: true,\n        placeholderData: 'somePlaceholderData'\n      }\n    }\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with value `false`.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example14 = () => {\n  new RenamedQueryClient({\n    defaultOptions: {\n      queries: {\n        keepPreviousData: false,\n      }\n    }\n  })\n}\n\n/**\n * The object expression has a `keepPreviousData` property with which is an identifier.\n * The codemod shouldn't transform this case, only warn the user about the manual migration.\n */\nexport const Example15 = () => {\n  const keepPreviousDataIdentifier = false\n  new RenamedQueryClient({\n    defaultOptions: {\n      queries: {\n        keepPreviousData: keepPreviousDataIdentifier,\n        placeholderData: () => previousData\n      }\n    }\n  })\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v5/keep-previous-data/__tests__/keep-previous-data.test.cjs",
    "content": "const defineTest = require('jscodeshift/dist/testUtils').defineTest\n\ndefineTest(__dirname, 'keep-previous-data.cjs', null, 'default', {\n  parser: 'tsx',\n})\n\ndefineTest(__dirname, 'keep-previous-data.cjs', null, 'named', {\n  parser: 'tsx',\n})\n"
  },
  {
    "path": "packages/query-codemods/src/v5/keep-previous-data/keep-previous-data.cjs",
    "content": "const createUtilsObject = require('../../utils/index.cjs')\nconst createUseQueryLikeTransformer = require('../../utils/transformers/use-query-like-transformer.cjs')\nconst createQueryClientTransformer = require('../../utils/transformers/query-client-transformer.cjs')\nconst AlreadyHasPlaceholderDataProperty = require('./utils/already-has-placeholder-data-property.cjs')\n\n/**\n * @param {import('jscodeshift')} jscodeshift\n * @param {Object} utils\n * @param {import('jscodeshift').Collection} root\n * @param {string} filePath\n * @param {{keyName: \"mutationKey\"|\"queryKey\", queryClientMethods: ReadonlyArray<string>, hooks: ReadonlyArray<string>}} config\n */\nconst transformUsages = ({ jscodeshift, utils, root, filePath, config }) => {\n  /**\n   * @param {import('jscodeshift').CallExpression | import('jscodeshift').ExpressionStatement} node\n   * @returns {{start: number, end: number}}\n   */\n  const getNodeLocation = (node) => {\n    const location = utils.isCallExpression(node) ? node.callee.loc : node.loc\n    const start = location.start.line\n    const end = location.end.line\n\n    return { start, end }\n  }\n\n  /**\n   * @param {import('jscodeshift').ObjectProperty} objectProperty\n   * @returns {boolean}\n   */\n  const isKeepPreviousDataObjectProperty = (objectProperty) => {\n    return jscodeshift.match(objectProperty.key, {\n      type: jscodeshift.Identifier.name,\n      name: 'keepPreviousData',\n    })\n  }\n\n  /**\n   * @param {import('jscodeshift').ObjectProperty} objectProperty\n   * @returns {boolean}\n   */\n  const isObjectPropertyHasTrueBooleanLiteralValue = (objectProperty) => {\n    return jscodeshift.match(objectProperty.value, {\n      type: jscodeshift.BooleanLiteral.name,\n      value: true,\n    })\n  }\n\n  /**\n   * @param {import('jscodeshift').ObjectExpression} objectExpression\n   * @returns {Array<import('jscodeshift').ObjectProperty>}\n   */\n  const filterKeepPreviousDataProperty = (objectExpression) => {\n    return objectExpression.properties.filter((objectProperty) => {\n      return !isKeepPreviousDataObjectProperty(objectProperty)\n    })\n  }\n\n  const createPlaceholderDataObjectProperty = () => {\n    return jscodeshift.objectProperty(\n      jscodeshift.identifier('placeholderData'),\n      jscodeshift.identifier('keepPreviousData'),\n    )\n  }\n\n  /**\n   * @param {import('jscodeshift').ObjectExpression} objectExpression\n   * @returns {boolean}\n   */\n  const hasPlaceholderDataProperty = (objectExpression) => {\n    return (\n      objectExpression.properties.findIndex((objectProperty) => {\n        return jscodeshift.match(objectProperty.key, {\n          type: jscodeshift.Identifier.name,\n          name: 'placeholderData',\n        })\n      }) !== -1\n    )\n  }\n\n  /**\n   * @param {import('jscodeshift').ObjectExpression} objectExpression\n   * @returns {import('jscodeshift').ObjectProperty | undefined}\n   */\n  const getKeepPreviousDataProperty = (objectExpression) => {\n    return objectExpression.properties.find(isKeepPreviousDataObjectProperty)\n  }\n\n  let shouldAddKeepPreviousDataImport = false\n\n  const replacer = (path, resolveTargetArgument, transformNode) => {\n    const node = path.node\n    const { start, end } = getNodeLocation(node)\n\n    try {\n      const targetArgument = resolveTargetArgument(node)\n\n      if (targetArgument && utils.isObjectExpression(targetArgument)) {\n        const isPlaceholderDataPropertyPresent =\n          hasPlaceholderDataProperty(targetArgument)\n\n        if (hasPlaceholderDataProperty(targetArgument)) {\n          throw new AlreadyHasPlaceholderDataProperty(node, filePath)\n        }\n\n        const keepPreviousDataProperty =\n          getKeepPreviousDataProperty(targetArgument)\n\n        const keepPreviousDataPropertyHasTrueValue =\n          isObjectPropertyHasTrueBooleanLiteralValue(keepPreviousDataProperty)\n\n        if (!keepPreviousDataPropertyHasTrueValue) {\n          utils.warn(\n            `The usage in file \"${filePath}\" at line ${start}:${end} already contains a \"keepPreviousData\" property but its value is not \"true\". Please migrate this usage manually.`,\n          )\n\n          return node\n        }\n\n        if (keepPreviousDataPropertyHasTrueValue) {\n          // Removing the `keepPreviousData` property from the object.\n          const mutableObjectExpressionProperties =\n            filterKeepPreviousDataProperty(targetArgument)\n\n          if (!isPlaceholderDataPropertyPresent) {\n            shouldAddKeepPreviousDataImport = true\n\n            // When the `placeholderData` property is not present, the `placeholderData: keepPreviousData` property will be added.\n            mutableObjectExpressionProperties.push(\n              createPlaceholderDataObjectProperty(),\n            )\n          }\n\n          return transformNode(\n            node,\n            jscodeshift.objectExpression(mutableObjectExpressionProperties),\n          )\n        }\n      }\n\n      utils.warn(\n        `The usage in file \"${filePath}\" at line ${start}:${end} could not be transformed, because the first parameter is not an object expression. Please migrate this usage manually.`,\n      )\n\n      return node\n    } catch (error) {\n      utils.warn(\n        error.name === AlreadyHasPlaceholderDataProperty.name\n          ? error.message\n          : `An unknown error occurred while processing the \"${filePath}\" file. Please review this file, because the codemod couldn't be applied.`,\n      )\n\n      return node\n    }\n  }\n\n  createUseQueryLikeTransformer({ jscodeshift, utils, root }).execute(\n    config.hooks,\n    (path) => {\n      const resolveTargetArgument = (node) => node.arguments[0] ?? null\n      const transformNode = (node, transformedArgument) =>\n        jscodeshift.callExpression(node.original.callee, [transformedArgument])\n\n      return replacer(path, resolveTargetArgument, transformNode)\n    },\n  )\n\n  createQueryClientTransformer({ jscodeshift, utils, root }).execute(\n    config.queryClientMethods,\n    (path) => {\n      const resolveTargetArgument = (node) => node.arguments[1] ?? null\n      const transformNode = (node, transformedArgument) => {\n        return jscodeshift.callExpression(node.original.callee, [\n          node.arguments[0],\n          transformedArgument,\n          ...node.arguments.slice(2, 0),\n        ])\n      }\n\n      return replacer(path, resolveTargetArgument, transformNode)\n    },\n  )\n\n  const importIdentifierOfQueryClient = utils.getSelectorByImports(\n    utils.locateImports(['QueryClient']),\n    'QueryClient',\n  )\n\n  root\n    .find(jscodeshift.ExpressionStatement, {\n      expression: {\n        type: jscodeshift.NewExpression.name,\n        callee: {\n          type: jscodeshift.Identifier.name,\n          name: importIdentifierOfQueryClient,\n        },\n      },\n    })\n    .filter((path) => path.node.expression)\n    .replaceWith((path) => {\n      const resolveTargetArgument = (node) => {\n        const paths = jscodeshift(node)\n          .find(jscodeshift.ObjectProperty, {\n            key: {\n              type: jscodeshift.Identifier.name,\n              name: 'keepPreviousData',\n            },\n          })\n          .paths()\n\n        return paths.length > 0 ? paths[0].parent.node : null\n      }\n      const transformNode = (node, transformedArgument) => {\n        jscodeshift(node.expression)\n          .find(jscodeshift.ObjectProperty, {\n            key: {\n              type: jscodeshift.Identifier.name,\n              name: 'queries',\n            },\n          })\n          .replaceWith(({ node: mutableNode }) => {\n            mutableNode.value.properties = transformedArgument.properties\n\n            return mutableNode\n          })\n\n        return node\n      }\n\n      return replacer(path, resolveTargetArgument, transformNode)\n    })\n\n  return { shouldAddKeepPreviousDataImport }\n}\n\nmodule.exports = (file, api) => {\n  const jscodeshift = api.jscodeshift\n  const root = jscodeshift(file.source)\n  const utils = createUtilsObject({ root, jscodeshift })\n  const filePath = file.path\n\n  const dependencies = { jscodeshift, utils, root, filePath }\n\n  const { shouldAddKeepPreviousDataImport } = transformUsages({\n    ...dependencies,\n    config: {\n      hooks: ['useInfiniteQuery', 'useQueries', 'useQuery'],\n      queryClientMethods: ['setQueryDefaults'],\n    },\n  })\n\n  if (shouldAddKeepPreviousDataImport) {\n    root\n      .find(jscodeshift.ImportDeclaration, {\n        source: {\n          value: '@tanstack/react-query',\n        },\n      })\n      .replaceWith(({ node: mutableNode }) => {\n        mutableNode.specifiers = [\n          jscodeshift.importSpecifier(\n            jscodeshift.identifier('keepPreviousData'),\n          ),\n          ...mutableNode.specifiers,\n        ]\n\n        return mutableNode\n      })\n  }\n\n  return root.toSource({ quote: 'single', lineTerminator: '\\n' })\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v5/keep-previous-data/utils/already-has-placeholder-data-property.cjs",
    "content": "class AlreadyHasPlaceholderDataProperty extends Error {\n  /**\n   * @param {import('jscodeshift').CallExpression} callExpression\n   * @param {string} filePath\n   */\n  constructor(callExpression, filePath) {\n    super('')\n    this.message = this.buildMessage(callExpression, filePath)\n    this.name = 'AlreadyHasPlaceholderDataProperty'\n  }\n\n  /**\n   * @param {import('jscodeshift').CallExpression} callExpression\n   * @param {string} filePath\n   * @returns {string}\n   */\n  buildMessage(callExpression, filePath) {\n    const location = callExpression.callee.loc\n    const start = location.start.line\n    const end = location.end.line\n\n    return `The usage in file \"${filePath}\" at line ${start}:${end} already contains a \"placeholderData\" property. Please migrate this usage manually.`\n  }\n}\n\nmodule.exports = AlreadyHasPlaceholderDataProperty\n"
  },
  {
    "path": "packages/query-codemods/src/v5/remove-overloads/__testfixtures__/bug-reports.input.tsx",
    "content": "// From: https://github.com/TanStack/query/issues/6204\nexport function useDetails({ groupId }: { groupId?: string }): any {\n  const cacheKey = [\"details\", groupId];\n  const query = () => fetch(`/group/${groupId}`);\n  const queryObject = useQuery(cacheKey, query, {\n    enabled: !!groupId,\n  });\n  return queryObject;\n}\n\n// Based on: https://github.com/TanStack/query/issues/6204\nexport function useDetailsContainsIdentifierAsThirdArgument({ groupId }: { groupId?: string }): any {\n  const cacheKey = [\"details\", groupId];\n  const query = () => fetch(`/group/${groupId}`);\n  const opts = { enabled: !!groupId }\n  const queryObject = useQuery(cacheKey, query, opts);\n  return queryObject;\n}\n\n// From: https://twitter.com/samcook_/status/1715063150184132902\nexport function useWhatever({ thing }: { thing: string }) {\n  return useQuery(\n    ['some-string', someVar],\n    async () => 'foo',\n    { enabled: Boolean(thing) },\n  );\n}\n\n// From: https://github.com/TanStack/query/issues/6548\nexport function useDeleteSomething(): any {\n  return useMutation(({ groupId }: { groupId: string }) => {\n    return fetch(`/api/groups/${groupId}`, {\n      method: 'DELETE',\n    });\n  });\n}\n\n// From: https://github.com/TanStack/query/issues/6548\nexport function useDeleteSomethingWithOnError(): any {\n  return useMutation(\n    ({ groupId }: { groupId: string }) => {\n      return fetch(`/api/groups/${groupId}`, {\n        method: 'DELETE',\n      });\n    },\n    {\n      onError: (_error, _variables, context) => {\n        // An error happened!\n        console.log(\n          `rolling back optimistic delete with id ${context.id}`\n        );\n      },\n    }\n  );\n}\n\n"
  },
  {
    "path": "packages/query-codemods/src/v5/remove-overloads/__testfixtures__/bug-reports.output.tsx",
    "content": "// From: https://github.com/TanStack/query/issues/6204\nexport function useDetails({ groupId }: { groupId?: string }): any {\n  const cacheKey = [\"details\", groupId];\n  const query = () => fetch(`/group/${groupId}`);\n  const queryObject = useQuery({\n    queryKey: cacheKey,\n    queryFn: query,\n    enabled: !!groupId\n  });\n  return queryObject;\n}\n\n// Based on: https://github.com/TanStack/query/issues/6204\nexport function useDetailsContainsIdentifierAsThirdArgument({ groupId }: { groupId?: string }): any {\n  const cacheKey = [\"details\", groupId];\n  const query = () => fetch(`/group/${groupId}`);\n  const opts = { enabled: !!groupId }\n  const queryObject = useQuery({\n    queryKey: cacheKey,\n    queryFn: query,\n    ...opts\n  });\n  return queryObject;\n}\n\n// From: https://twitter.com/samcook_/status/1715063150184132902\nexport function useWhatever({ thing }: { thing: string }) {\n  return useQuery({\n    queryKey: ['some-string', someVar],\n    queryFn: async () => 'foo',\n    enabled: Boolean(thing)\n  });\n}\n\n// From: https://github.com/TanStack/query/issues/6548\nexport function useDeleteSomething(): any {\n  return useMutation({\n    mutationFn: ({ groupId }: { groupId: string }) => {\n      return fetch(`/api/groups/${groupId}`, {\n        method: 'DELETE',\n      });\n    }\n  });\n}\n\n// From: https://github.com/TanStack/query/issues/6548\nexport function useDeleteSomethingWithOnError(): any {\n  return useMutation({\n    mutationFn: ({ groupId }: { groupId: string }) => {\n      return fetch(`/api/groups/${groupId}`, {\n        method: 'DELETE',\n      });\n    },\n\n    onError: (_error, _variables, context) => {\n      // An error happened!\n      console.log(\n        `rolling back optimistic delete with id ${context.id}`\n      );\n    }\n  });\n}\n\n"
  },
  {
    "path": "packages/query-codemods/src/v5/remove-overloads/__testfixtures__/default-import.input.tsx",
    "content": "import * as React from 'react'\nimport {\n  useIsFetching,\n  useIsMutating,\n  useQuery,\n  useQueryClient,\n} from '@tanstack/react-query'\nimport { queryKeysFromAnotherModule } from '../another/module'\n\nexport const WithKnownParameters = () => {\n  useIsFetching(['foo', 'bar'])\n  useIsFetching(['foo', 'bar'], { queryKey: ['todos'], type: 'all', exact: true })\n  useIsFetching(['foo', 'bar'], { queryKey: ['todos'], type: 'all', exact: true }, { context: undefined })\n  useIsFetching(['foo', 'bar'], { type: 'all', exact: true })\n  useIsFetching(['foo', 'bar'], { type: 'all', exact: true }, { context: undefined })\n  useIsFetching({ queryKey: ['foo', 'bar'], type: 'all', exact: true })\n  useIsFetching({ queryKey: ['foo', 'bar'], type: 'all', exact: true }, { context: undefined })\n\n  useIsMutating(['foo', 'bar'])\n  useIsMutating(['foo', 'bar'], { exact: true })\n  useIsMutating(['foo', 'bar'], { exact: true }, { context: undefined })\n  useIsMutating({ mutationKey: ['foo', 'bar'], exact: true })\n  useIsMutating({ mutationKey: ['foo', 'bar'], exact: true }, { context: undefined })\n\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries(['foo', 'bar'])\n  queryClient.cancelQueries(['foo', 'bar'], { queryKey: ['todos'], type: 'all', exact: true })\n  queryClient.cancelQueries(['foo', 'bar'], { queryKey: ['todos'], type: 'all', exact: true }, { silent: true })\n  queryClient.cancelQueries(['foo', 'bar'], { type: 'all', exact: true })\n  queryClient.cancelQueries(['foo', 'bar'], { type: 'all', exact: true }, { silent: true })\n  queryClient.cancelQueries({ queryKey: ['foo', 'bar'], type: 'all', exact: true })\n  queryClient.cancelQueries({ queryKey: ['foo', 'bar'], type: 'all', exact: true }, { silent: true })\n\n  queryClient.getQueriesData(['foo', 'bar'])\n  queryClient.getQueriesData({ queryKey: ['foo', 'bar'], type: 'all', exact: true })\n\n  queryClient.invalidateQueries(['foo', 'bar'])\n  queryClient.invalidateQueries(['foo', 'bar'], { queryKey: ['todos'], type: 'all', exact: true })\n  queryClient.invalidateQueries(['foo', 'bar'], { queryKey: ['todos'], type: 'all', exact: true }, { cancelRefetch: false, throwOnError: true })\n  queryClient.invalidateQueries(['foo', 'bar'], { type: 'all', exact: true })\n  queryClient.invalidateQueries(['foo', 'bar'], { type: 'all', exact: true }, { cancelRefetch: false, throwOnError: true })\n  queryClient.invalidateQueries({ queryKey: ['foo', 'bar'], type: 'all', exact: true })\n  queryClient.invalidateQueries({ queryKey: ['foo', 'bar'], type: 'all', exact: true }, { cancelRefetch: false, throwOnError: true })\n\n  queryClient.isFetching(['foo', 'bar'])\n  queryClient.isFetching(['foo', 'bar'], { queryKey: ['todos'], type: 'all', exact: true })\n  queryClient.isFetching(['foo', 'bar'], { type: 'all', exact: true })\n  queryClient.isFetching({ queryKey: ['foo', 'bar'], type: 'all', exact: true })\n\n  queryClient.refetchQueries(['foo', 'bar'])\n  queryClient.refetchQueries(['foo', 'bar'], { queryKey: ['todos'], type: 'all', exact: true })\n  queryClient.refetchQueries(['foo', 'bar'], { queryKey: ['todos'], type: 'all', exact: true }, { cancelRefetch: false, throwOnError: true })\n  queryClient.refetchQueries(['foo', 'bar'], { type: 'all', exact: true })\n  queryClient.refetchQueries(['foo', 'bar'], { type: 'all', exact: true }, { cancelRefetch: false, throwOnError: true })\n  queryClient.refetchQueries({ queryKey: ['foo', 'bar'], type: 'all', exact: true })\n  queryClient.refetchQueries({ queryKey: ['foo', 'bar'], type: 'all', exact: true }, { cancelRefetch: false, throwOnError: true })\n\n  queryClient.removeQueries(['foo', 'bar'])\n  queryClient.removeQueries(['foo', 'bar'], { queryKey: ['todos'], type: 'all', exact: true })\n  queryClient.removeQueries({ queryKey: ['foo', 'bar'], type: 'all', exact: true })\n\n  queryClient.resetQueries(['foo', 'bar'])\n  queryClient.resetQueries(['foo', 'bar'], { queryKey: ['todos'], type: 'all', exact: true })\n  queryClient.resetQueries(['foo', 'bar'], { queryKey: ['todos'], type: 'all', exact: true }, { cancelRefetch: false, throwOnError: true })\n  queryClient.resetQueries(['foo', 'bar'], { type: 'all', exact: true })\n  queryClient.resetQueries(['foo', 'bar'], { type: 'all', exact: true }, { cancelRefetch: false, throwOnError: true })\n  queryClient.resetQueries({ queryKey: ['foo', 'bar'], exact: true })\n  queryClient.resetQueries({ queryKey: ['foo', 'bar'], exact: true }, { cancelRefetch: false, throwOnError: true })\n\n  queryClient.setQueriesData(['foo', 'bar'], null)\n  queryClient.setQueriesData(['foo', 'bar'], null, { updatedAt: 1000 })\n  queryClient.setQueriesData({ queryKey: ['foo', 'bar'] }, null)\n  queryClient.setQueriesData({ queryKey: ['foo', 'bar'] }, null, { updatedAt: 1000 })\n\n  queryClient.fetchQuery(['foo', 'bar'])\n  queryClient.fetchQuery(['foo', 'bar'], { queryKey: ['todos'], staleTime: 1000 })\n  queryClient.fetchQuery(['foo', 'bar'], { queryKey: ['todos'], queryFn: () => 'data', staleTime: 1000 })\n  queryClient.fetchQuery(['foo', 'bar'], () => 'data', { queryKey: ['todos'], staleTime: 1000 })\n  queryClient.fetchQuery(['foo', 'bar'], function myFn() { return 'data' }, { queryKey: ['todos'], staleTime: 1000 })\n  queryClient.fetchQuery({ queryKey: ['foo', 'bar'], queryFn: () => 'data', retry: true })\n\n  const queryCache = queryClient.getQueryCache()\n\n  queryCache.find(['foo', 'bar'])\n  queryCache.find(['foo', 'bar'], { queryKey: ['todos'], type: 'all', exact: true })\n  queryCache.find(['foo', 'bar'], { type: 'all', exact: true })\n\n  queryCache.findAll(['foo', 'bar'])\n  queryCache.findAll(['foo', 'bar'], { type: 'all', exact: true })\n  queryCache.findAll(['foo', 'bar'], { queryKey: ['todos'], type: 'all', exact: true })\n  queryCache.findAll({ queryKey: ['foo', 'bar'], type: 'all', exact: true })\n\n  return <div>Example Component</div>\n}\n\nconst globalQueryKey = ['module', 'level']\n\nexport const WithIdentifiers = () => {\n  const queryKey = ['foo', 'bar']\n  const mutationKey = ['posts', 'articles']\n  const filters = { type: 'all', exact: true } as const\n  const options = { context: undefined } as const\n  const mutationOptions = { exact: true, fetching: false } as const\n  const cancelOptions = { silent: true } as const\n  const invalidateOptions = { cancelRefetch: true, throwOnError: true } as const\n  const refetchOptions = { cancelRefetch: false, throwOnError: true } as const\n  const resetOptions = { cancelRefetch: false, throwOnError: true } as const\n  const fetchOptions = { queryFn: () => 'data', retry: true } as const\n  const queryFn = () => 'data'\n\n  useIsFetching(queryKey)\n  useIsFetching(queryKey, filters)\n  useIsFetching(queryKey, filters, options)\n  useIsFetching(queryKey, { type: 'all', exact: true })\n  useIsFetching(queryKey, { type: 'all', exact: true }, { context: undefined })\n  useIsFetching(queryKey, { queryKey: ['todos'], ...filters }, options)\n  useIsFetching({ queryKey: queryKey, ...filters })\n  useIsFetching({ queryKey: queryKey, ...filters }, { context: undefined })\n\n  useIsMutating(mutationKey)\n  useIsMutating(mutationKey, { exact: true, status: 'idle' })\n  useIsMutating(mutationKey, { ...mutationOptions, exact: false })\n  useIsMutating({ mutationKey, ...mutationOptions })\n  useIsMutating({ mutationKey: ['foo', 'bar'], exact: true, status: 'idle' })\n\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries(queryKey)\n  queryClient.cancelQueries(queryKey, filters)\n  queryClient.cancelQueries(queryKey, filters, cancelOptions)\n  queryClient.cancelQueries(queryKey, { type: 'all', exact: true })\n  queryClient.cancelQueries(queryKey, { type: 'all', exact: true }, { revert: true })\n  queryClient.cancelQueries(queryKey, { queryKey: ['todos'], ...filters }, cancelOptions)\n  queryClient.cancelQueries({ queryKey: queryKey, type: 'all', exact: true })\n  queryClient.cancelQueries({ queryKey: ['foo', 'bar'], ...filters }, cancelOptions)\n\n  queryClient.getQueriesData(globalQueryKey)\n  queryClient.getQueriesData({ queryKey: globalQueryKey, ...filters })\n  queryClient.getQueriesData({ queryKey: ['foo', 'bar'], type: 'all' })\n\n  queryClient.invalidateQueries(queryKey)\n  queryClient.invalidateQueries(queryKey, filters)\n  queryClient.invalidateQueries(queryKey, filters, invalidateOptions)\n  queryClient.invalidateQueries(queryKey, { queryKey: ['todos'], stale: true, ...filters })\n  queryClient.invalidateQueries(queryKey, { queryKey: ['todos'], stale: true, ...filters }, invalidateOptions)\n  queryClient.invalidateQueries({ queryKey: globalQueryKey, ...filters, stale: true })\n  queryClient.invalidateQueries({ queryKey: globalQueryKey, ...filters, stale: true }, invalidateOptions)\n\n  queryClient.isFetching(globalQueryKey)\n  queryClient.isFetching(globalQueryKey, filters)\n  queryClient.isFetching(globalQueryKey, { queryKey: ['todos'], type: 'all', exact: true })\n  queryClient.isFetching(globalQueryKey, { queryKey: ['todos'], ...filters })\n  queryClient.isFetching({ queryKey: globalQueryKey, ...filters, stale: true })\n  // Stays as it is because the code couldn't infer the type of the \"queryKeysFromAnotherModule\" identifier.\n  queryClient.isFetching(queryKeysFromAnotherModule)\n\n  queryClient.refetchQueries(queryKey)\n  queryClient.refetchQueries(queryKey, filters)\n  queryClient.refetchQueries(queryKey, filters, refetchOptions)\n  queryClient.refetchQueries(queryKey, { queryKey: ['todos'], ...filters }, { ...refetchOptions, cancelRefetch: true })\n  queryClient.refetchQueries({ queryKey: queryKey, ...filters })\n  queryClient.refetchQueries({ queryKey: queryKey, ...filters }, { ...refetchOptions, cancelRefetch: true })\n  // Stays as it is because the code couldn't infer the type of the \"queryKeysFromAnotherModule\" identifier.\n  queryClient.refetchQueries(queryKeysFromAnotherModule)\n  queryClient.refetchQueries(queryKeysFromAnotherModule, filters)\n  queryClient.refetchQueries(queryKeysFromAnotherModule, filters, refetchOptions)\n\n  queryClient.removeQueries(queryKey)\n  queryClient.removeQueries(queryKey, filters)\n  queryClient.removeQueries(queryKey, { queryKey: ['todos'], ...filters, stale: true })\n  queryClient.removeQueries({ queryKey, ...filters, stale: true })\n  // Stays as it is because the code couldn't infer the type of the \"queryKeysFromAnotherModule\" identifier.\n  queryClient.removeQueries(queryKeysFromAnotherModule)\n  queryClient.removeQueries(queryKeysFromAnotherModule, filters)\n\n  queryClient.resetQueries(queryKey)\n  queryClient.resetQueries(queryKey, filters)\n  queryClient.resetQueries(queryKey, filters, resetOptions)\n  queryClient.resetQueries(queryKey, { queryKey: ['todos'], ...filters, stale: true })\n  queryClient.resetQueries(queryKey, { queryKey: ['todos'], ...filters, stale: true }, resetOptions)\n  queryClient.resetQueries({ queryKey, ...filters, stale: true })\n  queryClient.resetQueries({ queryKey, ...filters, stale: true }, resetOptions)\n  // Stays as it is because the code couldn't infer the type of the \"queryKeysFromAnotherModule\" identifier.\n  queryClient.resetQueries(queryKeysFromAnotherModule)\n  queryClient.resetQueries(queryKeysFromAnotherModule, filters)\n  queryClient.resetQueries(queryKeysFromAnotherModule, filters, resetOptions)\n\n  queryClient.fetchQuery(queryKey)\n  queryClient.fetchQuery(queryKey, fetchOptions)\n  queryClient.fetchQuery(queryKey, { networkMode: 'always', ...fetchOptions })\n  queryClient.fetchQuery(queryKey, queryFn, fetchOptions)\n  queryClient.fetchQuery(queryKey, () => 'data', { networkMode: 'always', ...fetchOptions })\n  // Stays as it is because the code couldn't infer the type of the \"queryKeysFromAnotherModule\" identifier.\n  queryClient.fetchQuery(queryKeysFromAnotherModule)\n  queryClient.fetchQuery(queryKeysFromAnotherModule, fetchOptions)\n  queryClient.fetchQuery(queryKeysFromAnotherModule, queryFn, fetchOptions)\n}\n\nexport const SecondArgumentIsAFunctionExample = () => {\n  useQuery(ordersCacheKeys.groupOrders(id), () => api.getPatientGroupOrders(id).then((r) => r.data))\n\n  const rest = 'rest'\n  const of = 1\n  const functionArguments = { foo: 'bar' }\n\n  useQuery(ordersCacheKeys.groupOrders(id), () => api.getPatientGroupOrders(id).then((r) => r.data), rest, of, functionArguments)\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v5/remove-overloads/__testfixtures__/default-import.output.tsx",
    "content": "import * as React from 'react'\nimport {\n  useIsFetching,\n  useIsMutating,\n  useQuery,\n  useQueryClient,\n} from '@tanstack/react-query'\nimport { queryKeysFromAnotherModule } from '../another/module'\n\nexport const WithKnownParameters = () => {\n  useIsFetching({\n    queryKey: ['foo', 'bar']\n  })\n  useIsFetching({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  })\n  useIsFetching({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  }, { context: undefined })\n  useIsFetching({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  })\n  useIsFetching({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  }, { context: undefined })\n  useIsFetching({ queryKey: ['foo', 'bar'], type: 'all', exact: true })\n  useIsFetching({ queryKey: ['foo', 'bar'], type: 'all', exact: true }, { context: undefined })\n\n  useIsMutating({\n    mutationKey: ['foo', 'bar']\n  })\n  useIsMutating({\n    mutationKey: ['foo', 'bar'],\n    exact: true\n  })\n  useIsMutating({\n    mutationKey: ['foo', 'bar'],\n    exact: true\n  }, { context: undefined })\n  useIsMutating({ mutationKey: ['foo', 'bar'], exact: true })\n  useIsMutating({ mutationKey: ['foo', 'bar'], exact: true }, { context: undefined })\n\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries({\n    queryKey: ['foo', 'bar']\n  })\n  queryClient.cancelQueries({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  })\n  queryClient.cancelQueries({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  }, { silent: true })\n  queryClient.cancelQueries({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  })\n  queryClient.cancelQueries({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  }, { silent: true })\n  queryClient.cancelQueries({ queryKey: ['foo', 'bar'], type: 'all', exact: true })\n  queryClient.cancelQueries({ queryKey: ['foo', 'bar'], type: 'all', exact: true }, { silent: true })\n\n  queryClient.getQueriesData({\n    queryKey: ['foo', 'bar']\n  })\n  queryClient.getQueriesData({ queryKey: ['foo', 'bar'], type: 'all', exact: true })\n\n  queryClient.invalidateQueries({\n    queryKey: ['foo', 'bar']\n  })\n  queryClient.invalidateQueries({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  })\n  queryClient.invalidateQueries({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  }, { cancelRefetch: false, throwOnError: true })\n  queryClient.invalidateQueries({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  })\n  queryClient.invalidateQueries({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  }, { cancelRefetch: false, throwOnError: true })\n  queryClient.invalidateQueries({ queryKey: ['foo', 'bar'], type: 'all', exact: true })\n  queryClient.invalidateQueries({ queryKey: ['foo', 'bar'], type: 'all', exact: true }, { cancelRefetch: false, throwOnError: true })\n\n  queryClient.isFetching({\n    queryKey: ['foo', 'bar']\n  })\n  queryClient.isFetching({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  })\n  queryClient.isFetching({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  })\n  queryClient.isFetching({ queryKey: ['foo', 'bar'], type: 'all', exact: true })\n\n  queryClient.refetchQueries({\n    queryKey: ['foo', 'bar']\n  })\n  queryClient.refetchQueries({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  })\n  queryClient.refetchQueries({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  }, { cancelRefetch: false, throwOnError: true })\n  queryClient.refetchQueries({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  })\n  queryClient.refetchQueries({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  }, { cancelRefetch: false, throwOnError: true })\n  queryClient.refetchQueries({ queryKey: ['foo', 'bar'], type: 'all', exact: true })\n  queryClient.refetchQueries({ queryKey: ['foo', 'bar'], type: 'all', exact: true }, { cancelRefetch: false, throwOnError: true })\n\n  queryClient.removeQueries({\n    queryKey: ['foo', 'bar']\n  })\n  queryClient.removeQueries({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  })\n  queryClient.removeQueries({ queryKey: ['foo', 'bar'], type: 'all', exact: true })\n\n  queryClient.resetQueries({\n    queryKey: ['foo', 'bar']\n  })\n  queryClient.resetQueries({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  })\n  queryClient.resetQueries({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  }, { cancelRefetch: false, throwOnError: true })\n  queryClient.resetQueries({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  })\n  queryClient.resetQueries({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  }, { cancelRefetch: false, throwOnError: true })\n  queryClient.resetQueries({ queryKey: ['foo', 'bar'], exact: true })\n  queryClient.resetQueries({ queryKey: ['foo', 'bar'], exact: true }, { cancelRefetch: false, throwOnError: true })\n\n  queryClient.setQueriesData(['foo', 'bar'], null)\n  queryClient.setQueriesData(['foo', 'bar'], null, { updatedAt: 1000 })\n  queryClient.setQueriesData({ queryKey: ['foo', 'bar'] }, null)\n  queryClient.setQueriesData({ queryKey: ['foo', 'bar'] }, null, { updatedAt: 1000 })\n\n  queryClient.fetchQuery({\n    queryKey: ['foo', 'bar']\n  })\n  queryClient.fetchQuery({\n    queryKey: ['foo', 'bar'],\n    staleTime: 1000\n  })\n  queryClient.fetchQuery({\n    queryKey: ['foo', 'bar'],\n    queryFn: () => 'data',\n    staleTime: 1000\n  })\n  queryClient.fetchQuery({\n    queryKey: ['foo', 'bar'],\n    queryFn: () => 'data',\n    staleTime: 1000\n  })\n  queryClient.fetchQuery({\n    queryKey: ['foo', 'bar'],\n    queryFn: function myFn() { return 'data' },\n    staleTime: 1000\n  })\n  queryClient.fetchQuery({ queryKey: ['foo', 'bar'], queryFn: () => 'data', retry: true })\n\n  const queryCache = queryClient.getQueryCache()\n\n  queryCache.find({\n    queryKey: ['foo', 'bar']\n  })\n  queryCache.find({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  })\n  queryCache.find({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  })\n\n  queryCache.findAll({\n    queryKey: ['foo', 'bar']\n  })\n  queryCache.findAll({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  })\n  queryCache.findAll({\n    queryKey: ['foo', 'bar'],\n    type: 'all',\n    exact: true\n  })\n  queryCache.findAll({ queryKey: ['foo', 'bar'], type: 'all', exact: true })\n\n  return <div>Example Component</div>\n}\n\nconst globalQueryKey = ['module', 'level']\n\nexport const WithIdentifiers = () => {\n  const queryKey = ['foo', 'bar']\n  const mutationKey = ['posts', 'articles']\n  const filters = { type: 'all', exact: true } as const\n  const options = { context: undefined } as const\n  const mutationOptions = { exact: true, fetching: false } as const\n  const cancelOptions = { silent: true } as const\n  const invalidateOptions = { cancelRefetch: true, throwOnError: true } as const\n  const refetchOptions = { cancelRefetch: false, throwOnError: true } as const\n  const resetOptions = { cancelRefetch: false, throwOnError: true } as const\n  const fetchOptions = { queryFn: () => 'data', retry: true } as const\n  const queryFn = () => 'data'\n\n  useIsFetching({\n    queryKey: queryKey\n  })\n  useIsFetching({\n    queryKey: queryKey,\n    ...filters\n  })\n  useIsFetching({\n    queryKey: queryKey,\n    ...filters\n  }, options)\n  useIsFetching({\n    queryKey: queryKey,\n    type: 'all',\n    exact: true\n  })\n  useIsFetching({\n    queryKey: queryKey,\n    type: 'all',\n    exact: true\n  }, { context: undefined })\n  useIsFetching({\n    queryKey: queryKey,\n    ...filters\n  }, options)\n  useIsFetching({ queryKey: queryKey, ...filters })\n  useIsFetching({ queryKey: queryKey, ...filters }, { context: undefined })\n\n  useIsMutating({\n    mutationKey: mutationKey\n  })\n  useIsMutating({\n    mutationKey: mutationKey,\n    exact: true,\n    status: 'idle'\n  })\n  useIsMutating({\n    mutationKey: mutationKey,\n    ...mutationOptions,\n    exact: false\n  })\n  useIsMutating({ mutationKey, ...mutationOptions })\n  useIsMutating({ mutationKey: ['foo', 'bar'], exact: true, status: 'idle' })\n\n  // QueryClient methods\n  // --- Instantiated hook call.\n  const queryClient = useQueryClient()\n  queryClient.cancelQueries({\n    queryKey: queryKey\n  })\n  queryClient.cancelQueries({\n    queryKey: queryKey,\n    ...filters\n  })\n  queryClient.cancelQueries({\n    queryKey: queryKey,\n    ...filters\n  }, cancelOptions)\n  queryClient.cancelQueries({\n    queryKey: queryKey,\n    type: 'all',\n    exact: true\n  })\n  queryClient.cancelQueries({\n    queryKey: queryKey,\n    type: 'all',\n    exact: true\n  }, { revert: true })\n  queryClient.cancelQueries({\n    queryKey: queryKey,\n    ...filters\n  }, cancelOptions)\n  queryClient.cancelQueries({ queryKey: queryKey, type: 'all', exact: true })\n  queryClient.cancelQueries({ queryKey: ['foo', 'bar'], ...filters }, cancelOptions)\n\n  queryClient.getQueriesData({\n    queryKey: globalQueryKey\n  })\n  queryClient.getQueriesData({ queryKey: globalQueryKey, ...filters })\n  queryClient.getQueriesData({ queryKey: ['foo', 'bar'], type: 'all' })\n\n  queryClient.invalidateQueries({\n    queryKey: queryKey\n  })\n  queryClient.invalidateQueries({\n    queryKey: queryKey,\n    ...filters\n  })\n  queryClient.invalidateQueries({\n    queryKey: queryKey,\n    ...filters\n  }, invalidateOptions)\n  queryClient.invalidateQueries({\n    queryKey: queryKey,\n    stale: true,\n    ...filters\n  })\n  queryClient.invalidateQueries({\n    queryKey: queryKey,\n    stale: true,\n    ...filters\n  }, invalidateOptions)\n  queryClient.invalidateQueries({ queryKey: globalQueryKey, ...filters, stale: true })\n  queryClient.invalidateQueries({ queryKey: globalQueryKey, ...filters, stale: true }, invalidateOptions)\n\n  queryClient.isFetching({\n    queryKey: globalQueryKey\n  })\n  queryClient.isFetching({\n    queryKey: globalQueryKey,\n    ...filters\n  })\n  queryClient.isFetching({\n    queryKey: globalQueryKey,\n    type: 'all',\n    exact: true\n  })\n  queryClient.isFetching({\n    queryKey: globalQueryKey,\n    ...filters\n  })\n  queryClient.isFetching({ queryKey: globalQueryKey, ...filters, stale: true })\n  // Stays as it is because the code couldn't infer the type of the \"queryKeysFromAnotherModule\" identifier.\n  queryClient.isFetching(queryKeysFromAnotherModule)\n\n  queryClient.refetchQueries({\n    queryKey: queryKey\n  })\n  queryClient.refetchQueries({\n    queryKey: queryKey,\n    ...filters\n  })\n  queryClient.refetchQueries({\n    queryKey: queryKey,\n    ...filters\n  }, refetchOptions)\n  queryClient.refetchQueries({\n    queryKey: queryKey,\n    ...filters\n  }, { ...refetchOptions, cancelRefetch: true })\n  queryClient.refetchQueries({ queryKey: queryKey, ...filters })\n  queryClient.refetchQueries({ queryKey: queryKey, ...filters }, { ...refetchOptions, cancelRefetch: true })\n  // Stays as it is because the code couldn't infer the type of the \"queryKeysFromAnotherModule\" identifier.\n  queryClient.refetchQueries(queryKeysFromAnotherModule)\n  queryClient.refetchQueries(queryKeysFromAnotherModule, filters)\n  queryClient.refetchQueries(queryKeysFromAnotherModule, filters, refetchOptions)\n\n  queryClient.removeQueries({\n    queryKey: queryKey\n  })\n  queryClient.removeQueries({\n    queryKey: queryKey,\n    ...filters\n  })\n  queryClient.removeQueries({\n    queryKey: queryKey,\n    ...filters,\n    stale: true\n  })\n  queryClient.removeQueries({ queryKey, ...filters, stale: true })\n  // Stays as it is because the code couldn't infer the type of the \"queryKeysFromAnotherModule\" identifier.\n  queryClient.removeQueries(queryKeysFromAnotherModule)\n  queryClient.removeQueries(queryKeysFromAnotherModule, filters)\n\n  queryClient.resetQueries({\n    queryKey: queryKey\n  })\n  queryClient.resetQueries({\n    queryKey: queryKey,\n    ...filters\n  })\n  queryClient.resetQueries({\n    queryKey: queryKey,\n    ...filters\n  }, resetOptions)\n  queryClient.resetQueries({\n    queryKey: queryKey,\n    ...filters,\n    stale: true\n  })\n  queryClient.resetQueries({\n    queryKey: queryKey,\n    ...filters,\n    stale: true\n  }, resetOptions)\n  queryClient.resetQueries({ queryKey, ...filters, stale: true })\n  queryClient.resetQueries({ queryKey, ...filters, stale: true }, resetOptions)\n  // Stays as it is because the code couldn't infer the type of the \"queryKeysFromAnotherModule\" identifier.\n  queryClient.resetQueries(queryKeysFromAnotherModule)\n  queryClient.resetQueries(queryKeysFromAnotherModule, filters)\n  queryClient.resetQueries(queryKeysFromAnotherModule, filters, resetOptions)\n\n  queryClient.fetchQuery({\n    queryKey: queryKey\n  })\n  queryClient.fetchQuery({\n    queryKey: queryKey,\n    ...fetchOptions\n  })\n  queryClient.fetchQuery({\n    queryKey: queryKey,\n    networkMode: 'always',\n    ...fetchOptions\n  })\n  queryClient.fetchQuery({\n    queryKey: queryKey,\n    queryFn: queryFn,\n    ...fetchOptions\n  })\n  queryClient.fetchQuery({\n    queryKey: queryKey,\n    queryFn: () => 'data',\n    networkMode: 'always',\n    ...fetchOptions\n  })\n  // Stays as it is because the code couldn't infer the type of the \"queryKeysFromAnotherModule\" identifier.\n  queryClient.fetchQuery(queryKeysFromAnotherModule)\n  queryClient.fetchQuery(queryKeysFromAnotherModule, fetchOptions)\n  queryClient.fetchQuery(queryKeysFromAnotherModule, queryFn, fetchOptions)\n}\n\nexport const SecondArgumentIsAFunctionExample = () => {\n  useQuery({\n    queryKey: ordersCacheKeys.groupOrders(id),\n    queryFn: () => api.getPatientGroupOrders(id).then((r) => r.data)\n  })\n\n  const rest = 'rest'\n  const of = 1\n  const functionArguments = { foo: 'bar' }\n\n  useQuery({\n    queryKey: ordersCacheKeys.groupOrders(id),\n    queryFn: () => api.getPatientGroupOrders(id).then((r) => r.data)\n  }, rest, of, functionArguments)\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v5/remove-overloads/__tests__/remove-overloads.test.cjs",
    "content": "const defineTest = require('jscodeshift/dist/testUtils').defineTest\n\ndefineTest(__dirname, 'remove-overloads.cjs', null, 'default-import', {\n  parser: 'tsx',\n})\n\ndefineTest(__dirname, 'remove-overloads.cjs', null, 'bug-reports', {\n  parser: 'tsx',\n})\n"
  },
  {
    "path": "packages/query-codemods/src/v5/remove-overloads/remove-overloads.cjs",
    "content": "const createUtilsObject = require('../../utils/index.cjs')\nconst transformFilterAwareUsages = require('./transformers/filter-aware-usage-transformer.cjs')\nconst transformQueryFnAwareUsages = require('./transformers/query-fn-aware-usage-transformer.cjs')\n\nmodule.exports = (file, api) => {\n  const jscodeshift = api.jscodeshift\n  const root = jscodeshift(file.source)\n  const utils = createUtilsObject({ root, jscodeshift })\n  const filePath = file.path\n\n  const dependencies = { jscodeshift, utils, root, filePath }\n\n  transformFilterAwareUsages({\n    ...dependencies,\n    config: {\n      keyName: 'queryKey',\n      fnName: 'queryFn',\n      queryClientMethods: [\n        'cancelQueries',\n        'getQueriesData',\n        'invalidateQueries',\n        'isFetching',\n        'refetchQueries',\n        'removeQueries',\n        'resetQueries',\n        // 'setQueriesData',\n      ],\n      hooks: ['useIsFetching', 'useQuery'],\n    },\n  })\n\n  transformFilterAwareUsages({\n    ...dependencies,\n    config: {\n      keyName: 'mutationKey',\n      fnName: 'mutationFn',\n      queryClientMethods: [],\n      hooks: ['useIsMutating', 'useMutation'],\n    },\n  })\n\n  transformQueryFnAwareUsages({\n    ...dependencies,\n    config: {\n      keyName: 'queryKey',\n      queryClientMethods: [\n        'ensureQueryData',\n        'fetchQuery',\n        'prefetchQuery',\n        'fetchInfiniteQuery',\n        'prefetchInfiniteQuery',\n      ],\n      hooks: [],\n    },\n  })\n\n  return root.toSource({ quote: 'single', lineTerminator: '\\n' })\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v5/remove-overloads/transformers/filter-aware-usage-transformer.cjs",
    "content": "const createV5UtilsObject = require('../utils/index.cjs')\nconst UnknownUsageError = require('../utils/unknown-usage-error.cjs')\nconst createQueryClientTransformer = require('../../../utils/transformers/query-client-transformer.cjs')\nconst createQueryCacheTransformer = require('../../../utils/transformers/query-cache-transformer.cjs')\nconst createUseQueryLikeTransformer = require('../../../utils/transformers/use-query-like-transformer.cjs')\n\n/**\n * @param {import('jscodeshift').api} jscodeshift\n * @param {Object} utils\n * @param {import('jscodeshift').Collection} root\n * @param {string} filePath\n * @param {{keyName: \"mutationKey\"|\"queryKey\", fnName: \"mutationFn\"|\"queryFn\", queryClientMethods: ReadonlyArray<string>, hooks: ReadonlyArray<string>}} config\n */\nconst transformFilterAwareUsages = ({\n  jscodeshift,\n  utils,\n  root,\n  filePath,\n  config,\n}) => {\n  const v5Utils = createV5UtilsObject({ jscodeshift, utils })\n\n  /**\n   * @param {import('jscodeshift').CallExpression} node\n   * @param {\"mutationKey\"|\"queryKey\"} keyName\n   * @param {\"mutationFn\"|\"queryFn\"} fnName\n   * @returns {boolean}\n   */\n  const canSkipReplacement = (node, keyName, fnName) => {\n    const callArguments = node.arguments\n\n    const hasKeyOrFnProperty = () =>\n      callArguments[0].properties.some(\n        (property) =>\n          utils.isObjectProperty(property) &&\n          property.key.name !== keyName &&\n          property.key.name !== fnName,\n      )\n\n    /**\n     * This call has at least one argument. If it's an object expression and contains the \"queryKey\" or \"mutationKey\"\n     * field, the transformation can be skipped, because it's already matching the expected signature.\n     */\n    return (\n      callArguments.length > 0 &&\n      utils.isObjectExpression(callArguments[0]) &&\n      hasKeyOrFnProperty()\n    )\n  }\n\n  /**\n   * This function checks whether the given object property is a spread element or a property that's not named\n   * \"queryKey\" or \"mutationKey\".\n   *\n   * @param {import('jscodeshift').ObjectProperty} property\n   * @returns {boolean}\n   */\n  const predicate = (property) => {\n    const isSpreadElement = utils.isSpreadElement(property)\n    const isObjectProperty = utils.isObjectProperty(property)\n\n    return (\n      isSpreadElement ||\n      (isObjectProperty && property.key.name !== config.keyName)\n    )\n  }\n\n  const replacer = (path) => {\n    const node = path.node\n\n    const isFunctionDefinition = (functionArgument) => {\n      if (utils.isFunctionDefinition(functionArgument)) {\n        return true\n      }\n\n      if (utils.isIdentifier(functionArgument)) {\n        const binding = v5Utils.getBindingFromScope(\n          path,\n          functionArgument.name,\n          filePath,\n        )\n\n        const isVariableDeclarator = jscodeshift.match(binding, {\n          type: jscodeshift.VariableDeclarator.name,\n        })\n\n        return isVariableDeclarator && utils.isFunctionDefinition(binding.init)\n      }\n    }\n\n    try {\n      // If the given method/function call matches certain criteria, the node doesn't need to be replaced, this step can be skipped.\n      if (canSkipReplacement(node, config.keyName, config.fnName)) {\n        return node\n      }\n\n      /**\n       * Here we attempt to determine the first parameter of the function call.\n       * If it's a function definition, we can create an object property from it (the mutation fn).\n       */\n      const firstArgument = node.arguments[0]\n      if (isFunctionDefinition(firstArgument)) {\n        const objectExpression = jscodeshift.objectExpression([\n          jscodeshift.property(\n            'init',\n            jscodeshift.identifier(config.fnName),\n            firstArgument,\n          ),\n        ])\n\n        const secondArgument = node.arguments[1]\n\n        if (secondArgument) {\n          // If it's an object expression, we can copy the properties from it to the newly created object expression.\n          if (utils.isObjectExpression(secondArgument)) {\n            v5Utils.copyPropertiesFromSource(\n              secondArgument,\n              objectExpression,\n              predicate,\n            )\n          } else {\n            // Otherwise, we simply spread the second argument in the newly created object expression.\n            objectExpression.properties.push(\n              jscodeshift.spreadElement(secondArgument),\n            )\n          }\n        }\n\n        return jscodeshift.callExpression(node.original.callee, [\n          objectExpression,\n        ])\n      }\n\n      /**\n       * If, instead, the first parameter is an array expression or an identifier that references\n       * an array expression, then we create an object property from it (the query or mutation key).\n       *\n       * @type {import('jscodeshift').Property|undefined}\n       */\n      const keyProperty = v5Utils.transformArgumentToKey(\n        path,\n        node.arguments[0],\n        config.keyName,\n        filePath,\n      )\n\n      /**\n       * The first parameter couldn't be transformed into an object property, so it's time to throw an exception,\n       * it will notify the consumers that they need to rewrite this usage manually.\n       */\n      if (!keyProperty) {\n        const secondArgument =\n          node.arguments.length > 1 ? node.arguments[1] : null\n\n        if (!secondArgument) {\n          throw new UnknownUsageError(node, filePath)\n        }\n\n        if (utils.isFunctionDefinition(secondArgument)) {\n          const originalArguments = node.arguments\n          const firstArgument = jscodeshift.objectExpression([\n            jscodeshift.property(\n              'init',\n              jscodeshift.identifier(config.keyName),\n              originalArguments[0],\n            ),\n            jscodeshift.property(\n              'init',\n              jscodeshift.identifier(config.fnName),\n              secondArgument,\n            ),\n          ])\n\n          return jscodeshift.callExpression(node.original.callee, [\n            firstArgument,\n            ...originalArguments.slice(2),\n          ])\n        }\n      }\n\n      const functionArguments = [jscodeshift.objectExpression([keyProperty])]\n      const secondParameter = node.arguments[1]\n\n      if (secondParameter) {\n        const createdObjectExpression = functionArguments[0]\n\n        if (isFunctionDefinition(secondParameter)) {\n          const objectExpression = jscodeshift.objectExpression([\n            jscodeshift.property(\n              'init',\n              jscodeshift.identifier(config.keyName),\n              node.arguments[0],\n            ),\n            jscodeshift.property(\n              'init',\n              jscodeshift.identifier(config.fnName),\n              secondParameter,\n            ),\n          ])\n\n          const thirdArgument = node.arguments[2]\n\n          if (thirdArgument) {\n            // If it's an object expression, we can copy the properties from it to the newly created object expression.\n            if (utils.isObjectExpression(thirdArgument)) {\n              v5Utils.copyPropertiesFromSource(\n                thirdArgument,\n                objectExpression,\n                predicate,\n              )\n            } else {\n              // Otherwise, we simply spread the third argument in the newly created object expression.\n              objectExpression.properties.push(\n                jscodeshift.spreadElement(thirdArgument),\n              )\n            }\n          }\n\n          return jscodeshift.callExpression(node.original.callee, [\n            objectExpression,\n          ])\n        }\n\n        /**\n         * If it has a second argument, and it's an object expression, then we get the properties from it\n         * (except the \"queryKey\" or \"mutationKey\" properties), because these arguments will also be moved to the\n         * newly created object expression.\n         */\n        if (utils.isObjectExpression(secondParameter)) {\n          v5Utils.copyPropertiesFromSource(\n            secondParameter,\n            createdObjectExpression,\n            predicate,\n          )\n        } else {\n          // Otherwise, we simply spread the second parameter in the newly created object expression.\n          createdObjectExpression.properties.push(\n            jscodeshift.spreadElement(secondParameter),\n          )\n        }\n      }\n\n      // The rest of the function arguments can be simply pushed to the function arguments object so all will be kept.\n      functionArguments.push(...node.arguments.slice(2))\n\n      return jscodeshift.callExpression(node.original.callee, functionArguments)\n    } catch (error) {\n      utils.warn(\n        error.name === UnknownUsageError.name\n          ? error.message\n          : `An unknown error occurred while processing the \"${filePath}\" file. Please review this file, because the codemod couldn't be applied.`,\n      )\n\n      return node\n    }\n  }\n\n  createQueryClientTransformer({ jscodeshift, utils, root }).execute(\n    config.queryClientMethods,\n    replacer,\n  )\n\n  createUseQueryLikeTransformer({ jscodeshift, utils, root }).execute(\n    config.hooks,\n    replacer,\n  )\n\n  createQueryCacheTransformer({ jscodeshift, utils, root }).execute(replacer)\n}\n\nmodule.exports = transformFilterAwareUsages\n"
  },
  {
    "path": "packages/query-codemods/src/v5/remove-overloads/transformers/query-fn-aware-usage-transformer.cjs",
    "content": "const createV5UtilsObject = require('../utils/index.cjs')\nconst UnknownUsageError = require('../utils/unknown-usage-error.cjs')\nconst createQueryClientTransformer = require('../../../utils/transformers/query-client-transformer.cjs')\n\n/**\n * @param {import('jscodeshift').api} jscodeshift\n * @param {Object} utils\n * @param {import('jscodeshift').Collection} root\n * @param {string} filePath\n * @param {{keyName: \"mutationKey\"|\"queryKey\", queryClientMethods: ReadonlyArray<string>, hooks: ReadonlyArray<string>}} config\n */\nconst transformQueryFnAwareUsages = ({\n  jscodeshift,\n  utils,\n  root,\n  filePath,\n  config,\n}) => {\n  const v5Utils = createV5UtilsObject({ jscodeshift, utils })\n\n  /**\n   * @param {import('jscodeshift').CallExpression} node\n   * @returns {boolean}\n   */\n  const canSkipReplacement = (node) => {\n    const callArguments = node.arguments\n\n    const hasKeyProperty = () =>\n      callArguments[0].properties.some(\n        (property) =>\n          utils.isObjectProperty(property) &&\n          [config.keyName, 'queryFn'].includes(property.key.name),\n      )\n\n    return (\n      callArguments.length > 0 &&\n      utils.isObjectExpression(callArguments[0]) &&\n      hasKeyProperty()\n    )\n  }\n\n  const predicate = (property) => {\n    const isSpreadElement = utils.isSpreadElement(property)\n    const isObjectProperty = utils.isObjectProperty(property)\n\n    return (\n      isSpreadElement ||\n      (isObjectProperty && property.key.name !== config.keyName)\n    )\n  }\n\n  const transformArgumentToQueryFunction = (path, node) => {\n    const isIdentifier = utils.isIdentifier(node)\n    const isFunctionDefinition = utils.isFunctionDefinition(node)\n\n    if (!isIdentifier && !isFunctionDefinition) {\n      return undefined\n    }\n\n    if (isFunctionDefinition) {\n      return jscodeshift.property(\n        'init',\n        jscodeshift.identifier('queryFn'),\n        node,\n      )\n    }\n\n    const binding = v5Utils.getBindingFromScope(path, node.name, filePath)\n    const initializer = v5Utils.getInitializerByDeclarator(binding)\n\n    if (!utils.isFunctionDefinition(initializer)) {\n      return undefined\n    }\n\n    return jscodeshift.property(\n      'init',\n      jscodeshift.identifier('queryFn'),\n      binding.id,\n    )\n  }\n\n  const transformArgumentToOptionsObject = (path, node) => {\n    if (!utils.isIdentifier(node)) {\n      return undefined\n    }\n\n    const binding = v5Utils.getBindingFromScope(path, node.name, filePath)\n    const initializer = v5Utils.getInitializerByDeclarator(binding)\n\n    if (utils.isObjectExpression(initializer)) {\n      return jscodeshift.spreadElement(binding.id)\n    }\n  }\n\n  const replacer = (path) => {\n    const node = path.node\n\n    try {\n      // If the given method/function call matches certain criteria, the node doesn't need to be replaced, this step can be skipped.\n      if (canSkipReplacement(node)) {\n        return node\n      }\n\n      const keyProperty = v5Utils.transformArgumentToKey(\n        path,\n        node.arguments[0],\n        config.keyName,\n        filePath,\n      )\n\n      if (!keyProperty) {\n        throw new UnknownUsageError(node, filePath)\n      }\n\n      const parameters = [jscodeshift.objectExpression([keyProperty])]\n      const createdObjectExpression = parameters[0]\n      const secondParameter = node.arguments[1]\n\n      if (secondParameter) {\n        const queryFnProperty = transformArgumentToQueryFunction(\n          path,\n          secondParameter,\n        )\n\n        if (queryFnProperty) {\n          createdObjectExpression.properties.push(queryFnProperty)\n\n          const thirdParameter = node.arguments[2]\n\n          if (utils.isObjectExpression(thirdParameter)) {\n            v5Utils.copyPropertiesFromSource(\n              thirdParameter,\n              createdObjectExpression,\n              predicate,\n            )\n          } else {\n            createdObjectExpression.properties.push(\n              jscodeshift.spreadElement(thirdParameter),\n            )\n          }\n\n          return jscodeshift.callExpression(node.original.callee, parameters)\n        }\n\n        const optionsProperty = transformArgumentToOptionsObject(\n          path,\n          secondParameter,\n        )\n\n        if (optionsProperty) {\n          createdObjectExpression.properties.push(optionsProperty)\n\n          return jscodeshift.callExpression(node.original.callee, parameters)\n        }\n\n        if (utils.isObjectExpression(secondParameter)) {\n          v5Utils.copyPropertiesFromSource(\n            secondParameter,\n            createdObjectExpression,\n            predicate,\n          )\n        }\n\n        return jscodeshift.callExpression(node.original.callee, parameters)\n      }\n\n      return jscodeshift.callExpression(node.original.callee, parameters)\n    } catch (error) {\n      utils.warn(\n        error.name === UnknownUsageError.name\n          ? error.message\n          : `An unknown error occurred while processing the \"${filePath}\" file. Please review this file, because the codemod couldn't be applied.`,\n      )\n\n      return node\n    }\n  }\n\n  createQueryClientTransformer({ jscodeshift, utils, root }).execute(\n    config.queryClientMethods,\n    replacer,\n  )\n}\n\nmodule.exports = transformQueryFnAwareUsages\n"
  },
  {
    "path": "packages/query-codemods/src/v5/remove-overloads/utils/index.cjs",
    "content": "const UnknownUsageError = require('./unknown-usage-error.cjs')\n\nmodule.exports = ({ jscodeshift, utils }) => {\n  /**\n   *\n   * @param {import('jscodeshift').ObjectExpression} source\n   * @param {import('jscodeshift').ObjectExpression} target\n   * @param {(node: import('jscodeshift').Node) => boolean} predicate\n   */\n  const copyPropertiesFromSource = (source, target, predicate) => {\n    source.properties.forEach((property) => {\n      if (predicate(property)) {\n        target.properties.push(property)\n      }\n    })\n  }\n\n  /**\n   * @param {import('jscodeshift').NodePath} path\n   * @param {string} argumentName\n   * @param {string} filePath\n   * @returns {*}\n   */\n  const getBindingFromScope = (path, argumentName, filePath) => {\n    /**\n     * If the current scope contains the declaration then we can use the actual one else we attempt to find the\n     * binding from above.\n     */\n    const scope = path.scope.declares(argumentName)\n      ? path.scope\n      : path.scope.lookup(argumentName)\n\n    /**\n     * The declaration couldn't be found for some reason, time to move on. We warn the user it needs to be rewritten\n     * by themselves.\n     */\n    if (!scope) {\n      return undefined\n    }\n\n    const binding = scope.bindings[argumentName]\n      .filter((item) => utils.isIdentifier(item.value))\n      .map((item) => item.parentPath.value)\n      .at(0)\n\n    if (!binding) {\n      throw new UnknownUsageError(path.node, filePath)\n    }\n\n    return binding\n  }\n\n  /**\n   * @param {import('jscodeshift').VariableDeclarator} binding\n   * @returns {import('jscodeshift').Node|undefined}\n   */\n  const getInitializerByDeclarator = (binding) => {\n    const isVariableDeclaration = jscodeshift.match(binding, {\n      type: jscodeshift.VariableDeclarator.name,\n    })\n\n    if (!isVariableDeclaration) {\n      return undefined\n    }\n\n    const isTSAsExpression = jscodeshift.match(binding.init, {\n      type: jscodeshift.TSAsExpression.name,\n    })\n\n    return isTSAsExpression ? binding.init.expression : binding.init\n  }\n\n  /**\n   * @param {import('jscodeshift').Node} node\n   * @returns {boolean}\n   */\n  const isArrayExpressionVariable = (node) =>\n    jscodeshift.match(node, {\n      type: jscodeshift.VariableDeclarator.name,\n      init: {\n        type: jscodeshift.ArrayExpression.name,\n      },\n    })\n\n  /**\n   * @param {import('jscodeshift').NodePath} path\n   * @param {import('jscodeshift').Node} node\n   * @param {\"queryKey\"|\"mutationKey\"} keyName\n   * @param {string} filePath\n   * @returns {import('jscodeshift').Property|undefined}\n   */\n  const transformArgumentToKey = (path, node, keyName, filePath) => {\n    // If the first argument is an identifier we have to infer its type if possible.\n    if (utils.isIdentifier(node)) {\n      const binding = getBindingFromScope(path, node.name, filePath)\n\n      if (isArrayExpressionVariable(binding)) {\n        return jscodeshift.property(\n          'init',\n          jscodeshift.identifier(keyName),\n          jscodeshift.identifier(binding.id.name),\n        )\n      }\n    }\n\n    // If the first argument is an array, then it matches the following overload:\n    // methodName(queryKey?: QueryKey, firstObject?: TFirstObject, secondObject?: TSecondObject)\n    if (utils.isArrayExpression(node)) {\n      // Then we create the 'queryKey' property based on it, because it will be passed to the first argument\n      // that should be an object according to the new signature.\n      return jscodeshift.property('init', jscodeshift.identifier(keyName), node)\n    }\n\n    return undefined\n  }\n\n  return {\n    copyPropertiesFromSource,\n    getInitializerByDeclarator,\n    getBindingFromScope,\n    transformArgumentToKey,\n  }\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v5/remove-overloads/utils/unknown-usage-error.cjs",
    "content": "class UnknownUsageError extends Error {\n  /**\n   * @param {import('jscodeshift').CallExpression} callExpression\n   * @param {string} filePath\n   */\n  constructor(callExpression, filePath) {\n    super('')\n    this.message = this.buildMessage(callExpression, filePath)\n    this.name = 'UnknownUsageError'\n  }\n\n  /**\n   *\n   * @param {import('jscodeshift').CallExpression} callExpression\n   * @param {string} filePath\n   * @returns {string}\n   */\n  buildMessage(callExpression, filePath) {\n    const location = callExpression.callee.loc\n    const start = location.start.line\n    const end = location.end.line\n\n    return `The usage in file \"${filePath}\" at line ${start}:${end} could not be transformed into the new syntax. Please do this manually.`\n  }\n}\n\nmodule.exports = UnknownUsageError\n"
  },
  {
    "path": "packages/query-codemods/src/v5/rename-hydrate/__testfixtures__/default-import.input.tsx",
    "content": "import * as React from 'react'\nimport {\n  Hydrate,\n  QueryClient,\n  QueryClientProvider,\n} from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\n\nexport default function MyApp({ Component, pageProps }) {\n  const [queryClient] = React.useState(() => new QueryClient())\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      <Hydrate state={pageProps.dehydratedState}>\n        <Component {...pageProps} />\n      </Hydrate>\n      <ReactQueryDevtools />\n    </QueryClientProvider>\n  )\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v5/rename-hydrate/__testfixtures__/default-import.output.tsx",
    "content": "import * as React from 'react'\nimport {\n  HydrationBoundary,\n  QueryClient,\n  QueryClientProvider,\n} from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\n\nexport default function MyApp({ Component, pageProps }) {\n  const [queryClient] = React.useState(() => new QueryClient())\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      <HydrationBoundary state={pageProps.dehydratedState}>\n        <Component {...pageProps} />\n      </HydrationBoundary>\n      <ReactQueryDevtools />\n    </QueryClientProvider>\n  );\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v5/rename-hydrate/__testfixtures__/named-import.input.tsx",
    "content": "import * as React from 'react'\nimport {\n  Hydrate as RenamedHydrate,\n  QueryClient as RenamedQueryClient,\n  QueryClientProvider as RenamedQueryClientProvider,\n} from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\n\nexport default function MyApp({ Component, pageProps }) {\n  const [queryClient] = React.useState(() => new RenamedQueryClient())\n\n  return (\n    <RenamedQueryClientProvider client={queryClient}>\n      <RenamedHydrate state={pageProps.dehydratedState}>\n        <Component {...pageProps} />\n      </RenamedHydrate>\n      <ReactQueryDevtools />\n    </RenamedQueryClientProvider>\n  )\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v5/rename-hydrate/__testfixtures__/named-import.output.tsx",
    "content": "import * as React from 'react'\nimport {\n  HydrationBoundary as RenamedHydrate,\n  QueryClient as RenamedQueryClient,\n  QueryClientProvider as RenamedQueryClientProvider,\n} from '@tanstack/react-query'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\n\nexport default function MyApp({ Component, pageProps }) {\n  const [queryClient] = React.useState(() => new RenamedQueryClient())\n\n  return (\n    <RenamedQueryClientProvider client={queryClient}>\n      <RenamedHydrate state={pageProps.dehydratedState}>\n        <Component {...pageProps} />\n      </RenamedHydrate>\n      <ReactQueryDevtools />\n    </RenamedQueryClientProvider>\n  )\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v5/rename-hydrate/__tests__/rename-hydrate.test.cjs",
    "content": "const defineTest = require('jscodeshift/dist/testUtils').defineTest\n\ndefineTest(__dirname, 'rename-hydrate.cjs', null, 'default-import', {\n  parser: 'tsx',\n})\n\ndefineTest(__dirname, 'rename-hydrate.cjs', null, 'named-import', {\n  parser: 'tsx',\n})\n"
  },
  {
    "path": "packages/query-codemods/src/v5/rename-hydrate/rename-hydrate.cjs",
    "content": "module.exports = (file, api) => {\n  const jscodeshift = api.jscodeshift\n  const root = jscodeshift(file.source)\n\n  const importSpecifiers = root\n    .find(jscodeshift.ImportDeclaration, {\n      source: {\n        value: '@tanstack/react-query',\n      },\n    })\n    .find(jscodeshift.ImportSpecifier, {\n      imported: {\n        name: 'Hydrate',\n      },\n    })\n\n  if (importSpecifiers.length > 0) {\n    const names = {\n      searched: 'Hydrate', // By default, we want to replace the `Hydrate` usages.\n      target: 'HydrationBoundary', // We want to replace them with `HydrationBoundary`.\n    }\n\n    importSpecifiers.replaceWith(({ node: mutableNode }) => {\n      /**\n       * When the local and imported names match which means the code doesn't contain import aliases, we need\n       * to replace only the import specifier.\n       * @type {boolean}\n       */\n      const usesDefaultImport =\n        mutableNode.local.name === mutableNode.imported.name\n\n      if (!usesDefaultImport) {\n        // If the code uses import aliases, we must re-use the alias.\n        names.searched = mutableNode.local.name\n        names.target = mutableNode.local.name\n      }\n\n      // Override the import specifier.\n      mutableNode.imported.name = 'HydrationBoundary'\n\n      return mutableNode\n    })\n\n    root\n      .findJSXElements(names.searched)\n      .replaceWith(({ node: mutableNode }) => {\n        mutableNode.openingElement.name.name = names.target\n        mutableNode.closingElement.name.name = names.target\n\n        return mutableNode\n      })\n  }\n\n  return root.toSource({ quote: 'single', lineTerminator: '\\n' })\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v5/rename-properties/__testfixtures__/rename-cache-time.input.tsx",
    "content": "import * as React from 'react'\nimport { QueryClient, useInfiniteQuery } from '@tanstack/react-query'\nimport { search } from './algolia'\n\n// Since the `cacheTime` property is string literal and not computed, the codemod should change it.\nexport type UseAlgoliaOptionsButWithStringLiterals = {\n  'indexName': string\n  'query': string\n  'hitsPerPage'?: number\n  'staleTime'?: number\n  'cacheTime'?: number\n  'enabled'?: boolean\n}\n\n// Since the `cacheTime` property is an identifier and not computed, the codemod should change it.\nexport type UseAlgoliaOptions = {\n  indexName: string\n  query: string\n  hitsPerPage?: number\n  staleTime?: number\n  cacheTime?: number\n  enabled?: boolean\n}\n\n// Since the `cacheTime` property is an identifier and not computed, and shorthand, the codemod should change it.\nexport function useAlgolia<TData>({\n  indexName,\n  query,\n  hitsPerPage = 10,\n  staleTime,\n  cacheTime,\n  enabled,\n}: UseAlgoliaOptions) {\n  const queryInfo = useInfiniteQuery({\n    queryKey: ['algolia', indexName, query, hitsPerPage],\n    queryFn: ({ pageParam }) =>\n      search<TData>({ indexName, query, pageParam, hitsPerPage }),\n    initialPageParam: 0,\n    getNextPageParam: (lastPage) => lastPage?.nextPage,\n    staleTime,\n    cacheTime,\n    enabled,\n  })\n\n  const hits = queryInfo.data?.pages.map((page) => page.hits).flat()\n\n  return { ...queryInfo, hits }\n}\n\n// Since the `cacheTime` property is an identifier and not computed, the codemod should change it.\nexport const asIdentifierExample = () =>\n  new QueryClient({\n    defaultOptions: {\n      queries: {\n        cacheTime: 1000 * 60 * 60 * 24, // 24 hours\n      },\n    },\n  })\n\n// Since the `cacheTime` property is a string literal and not computed, the codemod should change it.\nexport const asStringLiteralExample = () =>\n  new QueryClient({\n    defaultOptions: {\n      queries: {\n        'cacheTime': 1000 * 60 * 60 * 24, // 24 hours\n      },\n    },\n  })\n\n// Since the `cacheTime` property is computed, the codemod shouldn't touch this example.\nexport const asComputedExample = () => {\n  const cacheTime = 'foo'\n\n  return new QueryClient({\n    defaultOptions: {\n      queries: {\n        [cacheTime]: 1000 * 60 * 60 * 24, // 24 hours\n      },\n    },\n  })\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v5/rename-properties/__testfixtures__/rename-cache-time.output.tsx",
    "content": "import * as React from 'react'\nimport { QueryClient, useInfiniteQuery } from '@tanstack/react-query'\nimport { search } from './algolia'\n\n// Since the `cacheTime` property is string literal and not computed, the codemod should change it.\nexport type UseAlgoliaOptionsButWithStringLiterals = {\n  'indexName': string\n  'query': string\n  'hitsPerPage'?: number\n  'staleTime'?: number\n  'gcTime'?: number\n  'enabled'?: boolean\n}\n\n// Since the `cacheTime` property is an identifier and not computed, the codemod should change it.\nexport type UseAlgoliaOptions = {\n  indexName: string\n  query: string\n  hitsPerPage?: number\n  staleTime?: number\n  gcTime?: number\n  enabled?: boolean\n}\n\n// Since the `cacheTime` property is an identifier and not computed, and shorthand, the codemod should change it.\nexport function useAlgolia<TData>({\n  indexName,\n  query,\n  hitsPerPage = 10,\n  staleTime,\n  gcTime,\n  enabled,\n}: UseAlgoliaOptions) {\n  const queryInfo = useInfiniteQuery({\n    queryKey: ['algolia', indexName, query, hitsPerPage],\n    queryFn: ({ pageParam }) =>\n      search<TData>({ indexName, query, pageParam, hitsPerPage }),\n    initialPageParam: 0,\n    getNextPageParam: (lastPage) => lastPage?.nextPage,\n    staleTime,\n    gcTime,\n    enabled,\n  })\n\n  const hits = queryInfo.data?.pages.map((page) => page.hits).flat()\n\n  return { ...queryInfo, hits }\n}\n\n// Since the `cacheTime` property is an identifier and not computed, the codemod should change it.\nexport const asIdentifierExample = () =>\n  new QueryClient({\n    defaultOptions: {\n      queries: {\n        gcTime: 1000 * 60 * 60 * 24, // 24 hours\n      },\n    },\n  })\n\n// Since the `cacheTime` property is a string literal and not computed, the codemod should change it.\nexport const asStringLiteralExample = () =>\n  new QueryClient({\n    defaultOptions: {\n      queries: {\n        'gcTime': 1000 * 60 * 60 * 24, // 24 hours\n      },\n    },\n  })\n\n// Since the `cacheTime` property is computed, the codemod shouldn't touch this example.\nexport const asComputedExample = () => {\n  const cacheTime = 'foo'\n\n  return new QueryClient({\n    defaultOptions: {\n      queries: {\n        [cacheTime]: 1000 * 60 * 60 * 24, // 24 hours\n      },\n    },\n  })\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v5/rename-properties/__testfixtures__/rename-use-error-boundary.input.tsx",
    "content": "import * as React from 'react'\n\n// Since the `useErrorBoundary` property is string literal and not computed, the codemod should change it.\nexport type Type1 = {\n  'useErrorBoundary'?: boolean\n}\n\n// Since the `useErrorBoundary` property is an identifier and not computed, the codemod should change it.\nexport type Type2 = {\n  useErrorBoundary?: boolean\n}\n\n// Since the `useErrorBoundary` property is an identifier and not computed, and shorthand, the codemod should change it.\nexport function useSomething() {\n  const queryInfo = useSomethingElse({\n    useErrorBoundary,\n    enabled,\n  })\n\n  return queryInfo\n}\n\n// Since the `useErrorBoundary` property is an identifier and not computed, the codemod should change it.\nexport const asIdentifierExample = () => {\n  return {\n    useErrorBoundary: true\n  }\n}\n\n// Since the `useErrorBoundary` property is a string literal and not computed, the codemod should change it.\nexport const asStringLiteralExample = () => {\n  return {\n    'useErrorBoundary': true\n  }\n}\n\n// Since the `useErrorBoundary` property is computed, the codemod shouldn't touch this example.\nexport const asComputedExample = () => {\n  const useErrorBoundary = 'foo'\n\n  return {\n    [useErrorBoundary]: false\n  }\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v5/rename-properties/__testfixtures__/rename-use-error-boundary.output.tsx",
    "content": "import * as React from 'react'\n\n// Since the `useErrorBoundary` property is string literal and not computed, the codemod should change it.\nexport type Type1 = {\n  'throwOnError'?: boolean\n}\n\n// Since the `useErrorBoundary` property is an identifier and not computed, the codemod should change it.\nexport type Type2 = {\n  throwOnError?: boolean\n}\n\n// Since the `useErrorBoundary` property is an identifier and not computed, and shorthand, the codemod should change it.\nexport function useSomething() {\n  const queryInfo = useSomethingElse({\n    throwOnError,\n    enabled,\n  })\n\n  return queryInfo\n}\n\n// Since the `useErrorBoundary` property is an identifier and not computed, the codemod should change it.\nexport const asIdentifierExample = () => {\n  return {\n    throwOnError: true\n  };\n}\n\n// Since the `useErrorBoundary` property is a string literal and not computed, the codemod should change it.\nexport const asStringLiteralExample = () => {\n  return {\n    'throwOnError': true\n  };\n}\n\n// Since the `useErrorBoundary` property is computed, the codemod shouldn't touch this example.\nexport const asComputedExample = () => {\n  const useErrorBoundary = 'foo'\n\n  return {\n    [useErrorBoundary]: false\n  }\n}\n"
  },
  {
    "path": "packages/query-codemods/src/v5/rename-properties/__tests__/rename-properties.test.cjs",
    "content": "const defineTest = require('jscodeshift/dist/testUtils').defineTest\n\ndefineTest(__dirname, 'rename-properties.cjs', null, 'rename-cache-time', {\n  parser: 'tsx',\n})\n\ndefineTest(\n  __dirname,\n  'rename-properties.cjs',\n  null,\n  'rename-use-error-boundary',\n  {\n    parser: 'tsx',\n  },\n)\n"
  },
  {
    "path": "packages/query-codemods/src/v5/rename-properties/rename-properties.cjs",
    "content": "module.exports = (file, api) => {\n  const jscodeshift = api.jscodeshift\n  const root = jscodeshift(file.source)\n\n  const baseRenameLogic = (kind, from, to) => {\n    root\n      .find(kind, (node) => {\n        return (\n          node.computed === false &&\n          (node.key?.name === from || node.key?.value === from)\n        )\n      })\n      .replaceWith(({ node: mutableNode }) => {\n        if (mutableNode.key.name !== undefined) {\n          mutableNode.key.name = to\n        }\n\n        if (mutableNode.key.value !== undefined) {\n          mutableNode.key.value = to\n        }\n\n        return mutableNode\n      })\n  }\n\n  const renameObjectProperty = (from, to) => {\n    baseRenameLogic(jscodeshift.ObjectProperty, from, to)\n  }\n\n  const renameTypeScriptPropertySignature = (from, to) => {\n    baseRenameLogic(jscodeshift.TSPropertySignature, from, to)\n  }\n\n  renameObjectProperty('cacheTime', 'gcTime')\n  renameObjectProperty('useErrorBoundary', 'throwOnError')\n\n  renameTypeScriptPropertySignature('cacheTime', 'gcTime')\n  renameTypeScriptPropertySignature('useErrorBoundary', 'throwOnError')\n\n  return root.toSource({ quote: 'single', lineTerminator: '\\n' })\n}\n"
  },
  {
    "path": "packages/query-codemods/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\"\n  },\n  \"include\": [\"src\", \"*.config.*\", \"package.json\"]\n}\n"
  },
  {
    "path": "packages/query-codemods/vite.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nimport packageJson from './package.json'\n\nexport default defineConfig({\n  // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660\n  resolve: {\n    conditions: ['@tanstack/custom-condition'],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        conditions: ['@tanstack/custom-condition'],\n      },\n    },\n  },\n  test: {\n    name: packageJson.name,\n    dir: './src',\n    watch: false,\n    globals: true,\n    coverage: {\n      enabled: true,\n      provider: 'istanbul',\n      include: ['src/**/*.{js,ts,cjs,mjs,jsx,tsx}'],\n    },\n    typecheck: { enabled: true },\n    restoreMocks: true,\n  },\n})\n"
  },
  {
    "path": "packages/query-core/CHANGELOG.md",
    "content": "# @tanstack/query-core\n\n## 5.91.2\n\n### Patch Changes\n\n- fix(streamedQuery): maintain error state on reset refetch with initialData defined ([#10287](https://github.com/TanStack/query/pull/10287))\n\n## 5.91.1\n\n### Patch Changes\n\n- fix(core): cancel paused initial fetch when last observer unsubscribes ([#10291](https://github.com/TanStack/query/pull/10291))\n\n## 5.91.0\n\n### Minor Changes\n\n- feat: environmentManager ([#10199](https://github.com/TanStack/query/pull/10199))\n\n## 5.90.20\n\n### Patch Changes\n\n- Fix: onMutate callback now runs synchronously when mutationCache.config.onMutate is not defined ([#10066](https://github.com/TanStack/query/pull/10066))\n\n## 5.90.19\n\n### Patch Changes\n\n- fix stable combine reference not updating when queries change dynamically ([#9954](https://github.com/TanStack/query/pull/9954))\n\n## 5.90.18\n\n### Patch Changes\n\n- Align experimental_prefetchInRender promise rejection with Suspense behavior by only throwing when no data is available. ([#10025](https://github.com/TanStack/query/pull/10025))\n\n## 5.90.17\n\n### Patch Changes\n\n- fix(query-core): replaceEqualDeep max depth ([#10032](https://github.com/TanStack/query/pull/10032))\n\n## 5.90.16\n\n### Patch Changes\n\n- fix useQueries race condition on queries length change (#9971) ([#9973](https://github.com/TanStack/query/pull/9973))\n\n## 5.90.15\n\n### Patch Changes\n\n- Fix: Always treat existing data as stale when query goes into error state. ([#9927](https://github.com/TanStack/query/pull/9927))\n\n## 5.90.14\n\n### Patch Changes\n\n- Fix streamedQuery reducer being called twice ([#9970](https://github.com/TanStack/query/pull/9970))\n\n## 5.90.13\n\n### Patch Changes\n\n- Made context.signal consume aware with streamedQuery ([#9963](https://github.com/TanStack/query/pull/9963))\n\n## 5.90.12\n\n### Patch Changes\n\n- fix: update react and nextJs ([#9944](https://github.com/TanStack/query/pull/9944))\n\n## 5.90.11\n\n### Patch Changes\n\n- Prevent infinite render loops when useSuspenseQueries has duplicate queryKeys ([#9886](https://github.com/TanStack/query/pull/9886))\n\n## 5.90.10\n\n### Patch Changes\n\n- fix(types): allow QueryFilters union with different lengths ([#9878](https://github.com/TanStack/query/pull/9878))\n\n- Fix streamedQuery to avoid returning undefined when the stream yields no values ([#9876](https://github.com/TanStack/query/pull/9876))\n\n## 5.90.9\n\n### Patch Changes\n\n- fix(types): do not drop readonly for partial QueryFilter matching ([#9872](https://github.com/TanStack/query/pull/9872))\n\n## 5.90.8\n\n### Patch Changes\n\n- fix: allow partial query keys in `QueryFilters` ([#9686](https://github.com/TanStack/query/pull/9686))\n\n## 5.90.7\n\n### Patch Changes\n\n- fix(core): only attach .then and .catch onto a promise if it gets dehydrated ([#9847](https://github.com/TanStack/query/pull/9847))\n\n## 5.90.6\n\n### Patch Changes\n\n- Fixed isFetchedAfterMount in cases where initialData is applied ([#9743](https://github.com/TanStack/query/pull/9743))\n\n## 5.90.5\n\n### Patch Changes\n\n- fix: observing \"promise\" needs to implicitly observe \"data\" ([#9772](https://github.com/TanStack/query/pull/9772))\n\n## 5.90.4\n\n### Patch Changes\n\n- fix(types): remove duplicate Array condition in MutationKey type ([#9754](https://github.com/TanStack/query/pull/9754))\n\n## 5.90.3\n\n### Patch Changes\n\n- Avoid unhandled promise rejection errors during de/rehydration of pending queries. ([#9752](https://github.com/TanStack/query/pull/9752))\n"
  },
  {
    "path": "packages/query-core/eslint.config.js",
    "content": "// @ts-check\n\nimport rootConfig from './root.eslint.config.js'\n\nexport default [...rootConfig]\n"
  },
  {
    "path": "packages/query-core/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-core\",\n  \"version\": \"5.91.2\",\n  \"description\": \"The framework agnostic core that powers TanStack Query\",\n  \"author\": \"tannerlinsley\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/query-core\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"scripts\": {\n    \"clean\": \"premove ./build ./coverage ./dist-ts\",\n    \"compile\": \"tsc --build\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:types\": \"npm-run-all --serial test:types:*\",\n    \"test:types:ts54\": \"node ../../node_modules/typescript54/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts55\": \"node ../../node_modules/typescript55/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts56\": \"node ../../node_modules/typescript56/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts57\": \"node ../../node_modules/typescript57/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts58\": \"node ../../node_modules/typescript58/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts59\": \"node ../../node_modules/typescript59/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:tscurrent\": \"tsc --build\",\n    \"test:types:ts60\": \"node ../../node_modules/typescript60/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:lib\": \"vitest\",\n    \"test:lib:dev\": \"pnpm run test:lib --watch\",\n    \"test:build\": \"publint --strict && attw --pack\",\n    \"build\": \"tsup --tsconfig tsconfig.prod.json\"\n  },\n  \"type\": \"module\",\n  \"types\": \"build/legacy/index.d.ts\",\n  \"main\": \"build/legacy/index.cjs\",\n  \"module\": \"build/legacy/index.js\",\n  \"react-native\": \"src/index.ts\",\n  \"exports\": {\n    \".\": {\n      \"@tanstack/custom-condition\": \"./src/index.ts\",\n      \"import\": {\n        \"types\": \"./build/modern/index.d.ts\",\n        \"default\": \"./build/modern/index.js\"\n      },\n      \"require\": {\n        \"types\": \"./build/modern/index.d.cts\",\n        \"default\": \"./build/modern/index.cjs\"\n      }\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"sideEffects\": false,\n  \"files\": [\n    \"build\",\n    \"src\",\n    \"!src/__tests__\"\n  ],\n  \"devDependencies\": {\n    \"@tanstack/query-test-utils\": \"workspace:*\",\n    \"npm-run-all2\": \"^5.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/query-core/src/__tests__/OmitKeyof.test-d.ts",
    "content": "import { describe, expectTypeOf, it } from 'vitest'\nimport type { OmitKeyof } from '..'\n\ndescribe('OmitKeyof', () => {\n  it(\"'s string key type check\", () => {\n    type A = {\n      x: string\n      y: number\n    }\n\n    type ExpectedType = {\n      x: string\n    }\n\n    // Bad point\n    // 1. original Omit can use 'z' as type parameter with no type error\n    // 2. original Omit have no auto complete for 2nd type parameter\n    expectTypeOf<Omit<A, 'z' | 'y'>>().toEqualTypeOf<ExpectedType>()\n\n    // Solution\n\n    // 1. strictly\n    expectTypeOf<\n      OmitKeyof<\n        A,\n        // OmitKeyof can't use 'z' as type parameter with type error because A don't have key 'z'\n        // @ts-expect-error Type does not satisfy the constraint keyof A\n        'z' | 'y'\n      >\n    >().toEqualTypeOf<ExpectedType>()\n    expectTypeOf<\n      OmitKeyof<\n        A,\n        // OmitKeyof can't use 'z' as type parameter with type error because A don't have key 'z'\n        // @ts-expect-error Type does not satisfy the constraint keyof A\n        'z' | 'y',\n        'strictly'\n      >\n    >().toEqualTypeOf<ExpectedType>()\n\n    // 2. safely\n    expectTypeOf<\n      OmitKeyof<\n        A,\n        // OmitKeyof can't use 'z' as type parameter type error with strictly parameter or default parameter\n        // @ts-expect-error Type does not satisfy the constraint keyof A\n        'z' | 'y'\n      >\n    >().toEqualTypeOf<ExpectedType>()\n    expectTypeOf<\n      OmitKeyof<\n        A,\n        // With 'safely', OmitKeyof can use 'z' as type parameter like original Omit but This support autocomplete too yet for DX.\n        'z' | 'y',\n        'safely'\n      >\n    >().toEqualTypeOf<ExpectedType>()\n  })\n\n  it(\"'s number key type check\", () => {\n    type A = {\n      [1]: string\n      [2]: number\n    }\n\n    type ExpectedType = {\n      [1]: string\n    }\n\n    // Bad point\n    // 1. original Omit can use 3 as type parameter with no type error\n    // 2. original Omit have no auto complete for 2nd type parameter\n    expectTypeOf<Omit<A, 3 | 2>>().toEqualTypeOf<ExpectedType>()\n\n    // Solution\n\n    // 1. strictly\n    expectTypeOf<\n      OmitKeyof<\n        A,\n        // OmitKeyof can't use 3 as type parameter with type error because A don't have key 3\n        // @ts-expect-error Type does not satisfy the constraint keyof A\n        3 | 2\n      >\n    >().toEqualTypeOf<ExpectedType>()\n    expectTypeOf<\n      OmitKeyof<\n        A,\n        // OmitKeyof can't use 3 as type parameter with type error because A don't have key 3\n        // @ts-expect-error Type does not satisfy the constraint keyof A\n        3 | 2,\n        'strictly'\n      >\n    >().toEqualTypeOf<ExpectedType>()\n\n    // 2. safely\n    expectTypeOf<\n      OmitKeyof<\n        A,\n        // OmitKeyof can't use 3 as type parameter type error with strictly parameter or default parameter\n        // @ts-expect-error Type does not satisfy the constraint keyof A\n        3 | 2\n      >\n    >().toEqualTypeOf<ExpectedType>()\n    expectTypeOf<\n      OmitKeyof<\n        A,\n        // With 'safely', OmitKeyof can use 3 as type parameter like original Omit but This support autocomplete too yet for DX.\n        3 | 2,\n        'safely'\n      >\n    >().toEqualTypeOf<ExpectedType>()\n  })\n\n  it(\"'s symbol key type check\", () => {\n    const symbol1 = Symbol()\n    const symbol2 = Symbol()\n    const symbol3 = Symbol()\n\n    type A = {\n      [symbol1]: string\n      [symbol2]: number\n    }\n\n    type ExpectedType = {\n      [symbol1]: string\n    }\n\n    // Bad point\n    // 1. original Omit can use symbol3 as type parameter with no type error\n    // 2. original Omit have no auto complete for 2nd type parameter\n    expectTypeOf<\n      Omit<A, typeof symbol3 | typeof symbol2>\n    >().toEqualTypeOf<ExpectedType>()\n\n    // Solution\n\n    // 1. strictly\n    expectTypeOf<\n      OmitKeyof<\n        A,\n        // OmitKeyof can't use symbol3 as type parameter with type error because A don't have key symbol3\n        // @ts-expect-error Type does not satisfy the constraint keyof A\n        typeof symbol3 | typeof symbol2\n      >\n    >().toEqualTypeOf<ExpectedType>()\n    expectTypeOf<\n      OmitKeyof<\n        A,\n        // OmitKeyof can't use symbol3 as type parameter with type error because A don't have key symbol3\n        // @ts-expect-error Type does not satisfy the constraint keyof A\n        typeof symbol3 | typeof symbol2,\n        'strictly'\n      >\n    >().toEqualTypeOf<ExpectedType>()\n\n    // 2. safely\n    expectTypeOf<\n      OmitKeyof<\n        A,\n        // OmitKeyof can't use symbol3 as type parameter type error with strictly parameter or default parameter\n        // @ts-expect-error Type does not satisfy the constraint keyof A\n        typeof symbol3 | typeof symbol2\n      >\n    >().toEqualTypeOf<ExpectedType>()\n    expectTypeOf<\n      OmitKeyof<\n        A,\n        // With 'safely', OmitKeyof can use symbol3 as type parameter like original Omit but This support autocomplete too yet for DX.\n        typeof symbol3 | typeof symbol2,\n        'safely'\n      >\n    >().toEqualTypeOf<ExpectedType>()\n  })\n})\n"
  },
  {
    "path": "packages/query-core/src/__tests__/environmentManager.test.tsx",
    "content": "import { afterEach, describe, expect, test } from 'vitest'\nimport { environmentManager, isServer } from '..'\n\ndescribe('environmentManager', () => {\n  afterEach(() => {\n    environmentManager.setIsServer(() => isServer)\n  })\n\n  test('should use the default isServer detection', () => {\n    expect(environmentManager.isServer()).toBe(isServer)\n  })\n\n  test('should allow overriding isServer globally', () => {\n    environmentManager.setIsServer(() => true)\n    expect(environmentManager.isServer()).toBe(true)\n\n    environmentManager.setIsServer(() => false)\n    expect(environmentManager.isServer()).toBe(false)\n  })\n\n  test('should allow overriding isServer with a function', () => {\n    let server = true\n    environmentManager.setIsServer(() => server)\n    expect(environmentManager.isServer()).toBe(true)\n\n    server = false\n    expect(environmentManager.isServer()).toBe(false)\n  })\n})\n"
  },
  {
    "path": "packages/query-core/src/__tests__/focusManager.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, test, vi } from 'vitest'\nimport { FocusManager } from '../focusManager'\n\ndescribe('focusManager', () => {\n  let focusManager: FocusManager\n  beforeEach(() => {\n    vi.useFakeTimers()\n    vi.resetModules()\n    focusManager = new FocusManager()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should call previous remove handler when replacing an event listener', () => {\n    const remove1Spy = vi.fn()\n    const remove2Spy = vi.fn()\n\n    focusManager.setEventListener(() => remove1Spy)\n    focusManager.setEventListener(() => remove2Spy)\n\n    expect(remove1Spy).toHaveBeenCalledTimes(1)\n    expect(remove2Spy).not.toHaveBeenCalled()\n  })\n\n  it('should use focused boolean arg', () => {\n    let count = 0\n\n    const setup = (setFocused: (focused?: boolean) => void) => {\n      setTimeout(() => {\n        count++\n        setFocused(true)\n      }, 20)\n      return () => void 0\n    }\n\n    focusManager.setEventListener(setup)\n\n    vi.advanceTimersByTime(20)\n    expect(count).toEqual(1)\n    expect(focusManager.isFocused()).toBeTruthy()\n  })\n\n  it('should return true for isFocused if document is undefined', () => {\n    const { document } = globalThis\n\n    // @ts-expect-error\n    delete globalThis.document\n\n    focusManager.setFocused()\n    expect(focusManager.isFocused()).toBeTruthy()\n    globalThis.document = document\n  })\n\n  test('cleanup (removeEventListener) should not be called if window is not defined', () => {\n    const windowSpy = vi.spyOn(globalThis, 'window', 'get')\n    windowSpy.mockImplementation(\n      () => undefined as unknown as Window & typeof globalThis,\n    )\n    const removeEventListenerSpy = vi.spyOn(globalThis, 'removeEventListener')\n\n    const subscribe = () => focusManager.subscribe(() => undefined)\n    let firstUnsubscribe: (() => void) | undefined\n\n    expect(() => {\n      firstUnsubscribe = subscribe()\n    }).not.toThrow()\n    const secondUnsubscribe = subscribe()\n\n    firstUnsubscribe?.()\n    secondUnsubscribe()\n\n    expect(removeEventListenerSpy).not.toHaveBeenCalled()\n\n    windowSpy.mockRestore()\n  })\n\n  test('cleanup (removeEventListener) should not be called if window.addEventListener is not defined', () => {\n    const { addEventListener } = globalThis.window\n\n    // @ts-expect-error\n    globalThis.window.addEventListener = undefined\n\n    const removeEventListenerSpy = vi.spyOn(globalThis, 'removeEventListener')\n\n    const unsubscribe = focusManager.subscribe(() => undefined)\n\n    unsubscribe()\n\n    expect(removeEventListenerSpy).not.toHaveBeenCalled()\n\n    globalThis.window.addEventListener = addEventListener\n  })\n\n  it('should replace default window listener when a new event listener is set', () => {\n    const unsubscribeSpy = vi.fn().mockImplementation(() => undefined)\n    const handlerSpy = vi.fn().mockImplementation(() => unsubscribeSpy)\n\n    focusManager.setEventListener(() => handlerSpy())\n\n    const unsubscribe = focusManager.subscribe(() => undefined)\n\n    // Should call the custom event once\n    expect(handlerSpy).toHaveBeenCalledTimes(1)\n\n    unsubscribe()\n\n    // Should unsubscribe our event listener once\n    expect(unsubscribeSpy).toHaveBeenCalledTimes(1)\n\n    handlerSpy.mockRestore()\n    unsubscribeSpy.mockRestore()\n  })\n\n  test('should call removeEventListener when last listener unsubscribes', () => {\n    const addEventListenerSpy = vi.spyOn(globalThis.window, 'addEventListener')\n\n    const removeEventListenerSpy = vi.spyOn(\n      globalThis.window,\n      'removeEventListener',\n    )\n\n    const unsubscribe1 = focusManager.subscribe(() => undefined)\n    const unsubscribe2 = focusManager.subscribe(() => undefined)\n    expect(addEventListenerSpy).toHaveBeenCalledTimes(1) // visibilitychange event\n\n    unsubscribe1()\n    expect(removeEventListenerSpy).toHaveBeenCalledTimes(0)\n    unsubscribe2()\n    expect(removeEventListenerSpy).toHaveBeenCalledTimes(1) // visibilitychange event\n  })\n\n  test('should keep setup function even if last listener unsubscribes', () => {\n    const setupSpy = vi.fn().mockImplementation(() => () => undefined)\n\n    focusManager.setEventListener(setupSpy)\n\n    const unsubscribe1 = focusManager.subscribe(() => undefined)\n\n    expect(setupSpy).toHaveBeenCalledTimes(1)\n\n    unsubscribe1()\n\n    const unsubscribe2 = focusManager.subscribe(() => undefined)\n\n    expect(setupSpy).toHaveBeenCalledTimes(2)\n\n    unsubscribe2()\n  })\n\n  test('should call listeners when setFocused is called', () => {\n    const listener = vi.fn()\n\n    focusManager.subscribe(listener)\n\n    focusManager.setFocused(true)\n    focusManager.setFocused(true)\n\n    expect(listener).toHaveBeenCalledTimes(1)\n    expect(listener).toHaveBeenNthCalledWith(1, true)\n\n    focusManager.setFocused(false)\n    focusManager.setFocused(false)\n\n    expect(listener).toHaveBeenCalledTimes(2)\n    expect(listener).toHaveBeenNthCalledWith(2, false)\n\n    focusManager.setFocused(undefined)\n    focusManager.setFocused(undefined)\n\n    expect(listener).toHaveBeenCalledTimes(3)\n    expect(listener).toHaveBeenNthCalledWith(3, true)\n  })\n})\n"
  },
  {
    "path": "packages/query-core/src/__tests__/hydration.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { QueryClient } from '../queryClient'\nimport { QueryCache } from '../queryCache'\nimport { dehydrate, hydrate } from '../hydration'\nimport { MutationCache } from '../mutationCache'\nimport { executeMutation, mockOnlineManagerIsOnline } from './utils'\n\ndescribe('dehydration and rehydration', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('should work with serializable values', async () => {\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({ queryCache })\n    await vi.waitFor(() =>\n      queryClient.prefetchQuery({\n        queryKey: ['string'],\n        queryFn: () => sleep(0).then(() => 'string'),\n      }),\n    )\n    await vi.waitFor(() =>\n      queryClient.prefetchQuery({\n        queryKey: ['number'],\n        queryFn: () => sleep(0).then(() => 1),\n      }),\n    )\n\n    await vi.waitFor(() =>\n      queryClient.prefetchQuery({\n        queryKey: ['boolean'],\n        queryFn: () => sleep(0).then(() => true),\n      }),\n    )\n    await vi.waitFor(() =>\n      queryClient.prefetchQuery({\n        queryKey: ['null'],\n        queryFn: () => sleep(0).then(() => null),\n      }),\n    )\n    await vi.waitFor(() =>\n      queryClient.prefetchQuery({\n        queryKey: ['array'],\n        queryFn: () => sleep(0).then(() => ['string', 0]),\n      }),\n    )\n    await vi.waitFor(() =>\n      queryClient.prefetchQuery({\n        queryKey: ['nested'],\n        queryFn: () => sleep(0).then(() => ({ key: [{ nestedKey: 1 }] })),\n      }),\n    )\n    const dehydrated = dehydrate(queryClient)\n    const stringified = JSON.stringify(dehydrated)\n\n    // ---\n\n    const parsed = JSON.parse(stringified)\n    const hydrationCache = new QueryCache()\n    const hydrationClient = new QueryClient({\n      queryCache: hydrationCache,\n    })\n    hydrate(hydrationClient, parsed)\n    expect(hydrationCache.find({ queryKey: ['string'] })?.state.data).toBe(\n      'string',\n    )\n    expect(hydrationCache.find({ queryKey: ['number'] })?.state.data).toBe(1)\n    expect(hydrationCache.find({ queryKey: ['boolean'] })?.state.data).toBe(\n      true,\n    )\n    expect(hydrationCache.find({ queryKey: ['null'] })?.state.data).toBe(null)\n    expect(hydrationCache.find({ queryKey: ['array'] })?.state.data).toEqual([\n      'string',\n      0,\n    ])\n    expect(hydrationCache.find({ queryKey: ['nested'] })?.state.data).toEqual({\n      key: [{ nestedKey: 1 }],\n    })\n\n    const fetchDataAfterHydration =\n      vi.fn<(...args: Array<unknown>) => unknown>()\n    await hydrationClient.prefetchQuery({\n      queryKey: ['string'],\n      queryFn: fetchDataAfterHydration,\n      staleTime: 1000,\n    })\n    await hydrationClient.prefetchQuery({\n      queryKey: ['number'],\n      queryFn: fetchDataAfterHydration,\n      staleTime: 1000,\n    })\n    await hydrationClient.prefetchQuery({\n      queryKey: ['boolean'],\n      queryFn: fetchDataAfterHydration,\n      staleTime: 1000,\n    })\n    await hydrationClient.prefetchQuery({\n      queryKey: ['null'],\n      queryFn: fetchDataAfterHydration,\n      staleTime: 1000,\n    })\n    await hydrationClient.prefetchQuery({\n      queryKey: ['array'],\n      queryFn: fetchDataAfterHydration,\n      staleTime: 1000,\n    })\n    await hydrationClient.prefetchQuery({\n      queryKey: ['nested'],\n      queryFn: fetchDataAfterHydration,\n      staleTime: 1000,\n    })\n    expect(fetchDataAfterHydration).toHaveBeenCalledTimes(0)\n\n    queryClient.clear()\n    hydrationClient.clear()\n  })\n\n  test('should not dehydrate queries if dehydrateQueries is set to false', () => {\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({ queryCache })\n    vi.waitFor(() =>\n      queryClient.prefetchQuery({\n        queryKey: ['string'],\n        queryFn: () => sleep(0).then(() => 'string'),\n      }),\n    )\n\n    const dehydrated = dehydrate(queryClient, {\n      shouldDehydrateQuery: () => false,\n    })\n\n    expect(dehydrated.queries.length).toBe(0)\n\n    queryClient.clear()\n  })\n\n  test('should use the garbage collection time from the client', async () => {\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({ queryCache })\n    await vi.waitFor(() =>\n      queryClient.prefetchQuery({\n        queryKey: ['string'],\n        queryFn: () => sleep(0).then(() => 'string'),\n        gcTime: 50,\n      }),\n    )\n    const dehydrated = dehydrate(queryClient)\n    const stringified = JSON.stringify(dehydrated)\n\n    await vi.advanceTimersByTimeAsync(20)\n\n    // ---\n\n    const parsed = JSON.parse(stringified)\n    const hydrationCache = new QueryCache()\n    const hydrationClient = new QueryClient({ queryCache: hydrationCache })\n    hydrate(hydrationClient, parsed)\n    expect(hydrationCache.find({ queryKey: ['string'] })?.state.data).toBe(\n      'string',\n    )\n    await vi.advanceTimersByTimeAsync(100)\n    expect(hydrationCache.find({ queryKey: ['string'] })).toBeTruthy()\n\n    queryClient.clear()\n    hydrationClient.clear()\n  })\n\n  test('should be able to provide default options for the hydrated queries', async () => {\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({ queryCache })\n    await vi.waitFor(() =>\n      queryClient.prefetchQuery({\n        queryKey: ['string'],\n        queryFn: () => sleep(0).then(() => 'string'),\n      }),\n    )\n    const dehydrated = dehydrate(queryClient)\n    const stringified = JSON.stringify(dehydrated)\n    const parsed = JSON.parse(stringified)\n    const hydrationCache = new QueryCache()\n    const hydrationClient = new QueryClient({ queryCache: hydrationCache })\n    hydrate(hydrationClient, parsed, {\n      defaultOptions: { queries: { retry: 10 } },\n    })\n    expect(hydrationCache.find({ queryKey: ['string'] })?.options.retry).toBe(\n      10,\n    )\n    queryClient.clear()\n    hydrationClient.clear()\n  })\n\n  test('should respect query defaultOptions specified on the QueryClient', async () => {\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({\n      queryCache,\n      defaultOptions: {\n        dehydrate: { shouldDehydrateQuery: () => true },\n      },\n    })\n    await vi.waitFor(() =>\n      queryClient.prefetchQuery({\n        queryKey: ['string'],\n        retry: 0,\n        queryFn: () => Promise.reject(new Error('error')),\n      }),\n    )\n    const dehydrated = dehydrate(queryClient)\n    expect(dehydrated.queries.length).toBe(1)\n    expect(dehydrated.queries[0]?.state.error).toStrictEqual(new Error('error'))\n    const stringified = JSON.stringify(dehydrated)\n    const parsed = JSON.parse(stringified)\n    const hydrationCache = new QueryCache()\n    const hydrationClient = new QueryClient({\n      queryCache: hydrationCache,\n      defaultOptions: { hydrate: { queries: { retry: 10 } } },\n    })\n    hydrate(hydrationClient, parsed, {\n      defaultOptions: { queries: { gcTime: 10 } },\n    })\n    expect(hydrationCache.find({ queryKey: ['string'] })?.options.retry).toBe(\n      10,\n    )\n    expect(hydrationCache.find({ queryKey: ['string'] })?.options.gcTime).toBe(\n      10,\n    )\n    queryClient.clear()\n    hydrationClient.clear()\n  })\n\n  test('should respect mutation defaultOptions specified on the QueryClient', async () => {\n    const mutationCache = new MutationCache()\n    const queryClient = new QueryClient({\n      mutationCache,\n      defaultOptions: {\n        dehydrate: {\n          shouldDehydrateMutation: (mutation) => mutation.state.data === 'done',\n        },\n      },\n    })\n    await executeMutation(\n      queryClient,\n      {\n        mutationKey: ['string'],\n        mutationFn: () => Promise.resolve('done'),\n      },\n      undefined,\n    )\n\n    const dehydrated = dehydrate(queryClient)\n    expect(dehydrated.mutations.length).toBe(1)\n    expect(dehydrated.mutations[0]?.state.data).toBe('done')\n    const stringified = JSON.stringify(dehydrated)\n    const parsed = JSON.parse(stringified)\n    const hydrationCache = new MutationCache()\n    const hydrationClient = new QueryClient({\n      mutationCache: hydrationCache,\n      defaultOptions: { hydrate: { mutations: { retry: 10 } } },\n    })\n    hydrate(hydrationClient, parsed, {\n      defaultOptions: { mutations: { gcTime: 10 } },\n    })\n    expect(\n      hydrationCache.find({ mutationKey: ['string'] })?.options.retry,\n    ).toBe(10)\n    expect(\n      hydrationCache.find({ mutationKey: ['string'] })?.options.gcTime,\n    ).toBe(10)\n    queryClient.clear()\n    hydrationClient.clear()\n  })\n\n  test('should work with complex keys', async () => {\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({ queryCache })\n    await vi.waitFor(() =>\n      queryClient.prefetchQuery({\n        queryKey: ['string', { key: ['string'], key2: 0 }],\n        queryFn: () => sleep(0).then(() => 'string'),\n      }),\n    )\n    const dehydrated = dehydrate(queryClient)\n    const stringified = JSON.stringify(dehydrated)\n\n    // ---\n\n    const parsed = JSON.parse(stringified)\n    const hydrationCache = new QueryCache()\n    const hydrationClient = new QueryClient({ queryCache: hydrationCache })\n    hydrate(hydrationClient, parsed)\n    expect(\n      hydrationCache.find({\n        queryKey: ['string', { key: ['string'], key2: 0 }],\n      })?.state.data,\n    ).toBe('string')\n\n    const fetchDataAfterHydration =\n      vi.fn<(...args: Array<unknown>) => unknown>()\n    await vi.waitFor(() =>\n      hydrationClient.prefetchQuery({\n        queryKey: ['string', { key: ['string'], key2: 0 }],\n        queryFn: fetchDataAfterHydration,\n        staleTime: 100,\n      }),\n    )\n    expect(fetchDataAfterHydration).toHaveBeenCalledTimes(0)\n\n    queryClient.clear()\n    hydrationClient.clear()\n  })\n\n  test('should only hydrate successful queries by default', async () => {\n    const consoleMock = vi.spyOn(console, 'error')\n    consoleMock.mockImplementation(() => undefined)\n\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({ queryCache })\n    await vi.waitFor(() =>\n      queryClient.prefetchQuery({\n        queryKey: ['success'],\n        queryFn: () => sleep(0).then(() => 'success'),\n      }),\n    )\n    queryClient.prefetchQuery({\n      queryKey: ['loading'],\n      queryFn: () => sleep(10000).then(() => 'loading'),\n    })\n    await vi.waitFor(() =>\n      queryClient.prefetchQuery({\n        queryKey: ['error'],\n        queryFn: () => {\n          throw new Error()\n        },\n      }),\n    )\n    const dehydrated = dehydrate(queryClient)\n    const stringified = JSON.stringify(dehydrated)\n\n    // ---\n\n    const parsed = JSON.parse(stringified)\n    const hydrationCache = new QueryCache()\n    const hydrationClient = new QueryClient({ queryCache: hydrationCache })\n    hydrate(hydrationClient, parsed)\n\n    expect(hydrationCache.find({ queryKey: ['success'] })).toBeTruthy()\n    expect(hydrationCache.find({ queryKey: ['loading'] })).toBeFalsy()\n    expect(hydrationCache.find({ queryKey: ['error'] })).toBeFalsy()\n\n    queryClient.clear()\n    hydrationClient.clear()\n    consoleMock.mockRestore()\n  })\n\n  test('should filter queries via dehydrateQuery', async () => {\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({ queryCache })\n    await vi.waitFor(() =>\n      queryClient.prefetchQuery({\n        queryKey: ['string'],\n        queryFn: () => sleep(0).then(() => 'string'),\n      }),\n    )\n    await vi.waitFor(() =>\n      queryClient.prefetchQuery({\n        queryKey: ['number'],\n        queryFn: () => sleep(0).then(() => 1),\n      }),\n    )\n    const dehydrated = dehydrate(queryClient, {\n      shouldDehydrateQuery: (query) => query.queryKey[0] !== 'string',\n    })\n\n    // This is testing implementation details that can change and are not\n    // part of the public API, but is important for keeping the payload small\n    const dehydratedQuery = dehydrated.queries.find(\n      (query) => query.queryKey[0] === 'string',\n    )\n    expect(dehydratedQuery).toBeUndefined()\n\n    const stringified = JSON.stringify(dehydrated)\n\n    // ---\n\n    const parsed = JSON.parse(stringified)\n    const hydrationCache = new QueryCache()\n    const hydrationClient = new QueryClient({ queryCache: hydrationCache })\n    hydrate(hydrationClient, parsed)\n    expect(hydrationCache.find({ queryKey: ['string'] })).toBeUndefined()\n    expect(hydrationCache.find({ queryKey: ['number'] })?.state.data).toBe(1)\n\n    queryClient.clear()\n    hydrationClient.clear()\n  })\n\n  test('should not overwrite query in cache if hydrated query is older', async () => {\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({ queryCache })\n    await vi.waitFor(() =>\n      queryClient.prefetchQuery({\n        queryKey: ['string'],\n        queryFn: () => sleep(5).then(() => 'string-older'),\n      }),\n    )\n    const dehydrated = dehydrate(queryClient)\n    const stringified = JSON.stringify(dehydrated)\n\n    // ---\n\n    const parsed = JSON.parse(stringified)\n    const hydrationCache = new QueryCache()\n    const hydrationClient = new QueryClient({ queryCache: hydrationCache })\n    await vi.waitFor(() =>\n      hydrationClient.prefetchQuery({\n        queryKey: ['string'],\n        queryFn: () => sleep(5).then(() => 'string-newer'),\n      }),\n    )\n\n    hydrate(hydrationClient, parsed)\n    expect(hydrationCache.find({ queryKey: ['string'] })?.state.data).toBe(\n      'string-newer',\n    )\n\n    queryClient.clear()\n    hydrationClient.clear()\n  })\n\n  test('should overwrite query in cache if hydrated query is newer', async () => {\n    const hydrationCache = new QueryCache()\n    const hydrationClient = new QueryClient({ queryCache: hydrationCache })\n    await vi.waitFor(() =>\n      hydrationClient.prefetchQuery({\n        queryKey: ['string'],\n        queryFn: () => sleep(5).then(() => 'string-older'),\n      }),\n    )\n\n    // ---\n\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({ queryCache })\n    await vi.waitFor(() =>\n      queryClient.prefetchQuery({\n        queryKey: ['string'],\n        queryFn: () => sleep(5).then(() => 'string-newer'),\n      }),\n    )\n    const dehydrated = dehydrate(queryClient)\n    const stringified = JSON.stringify(dehydrated)\n\n    // ---\n\n    const parsed = JSON.parse(stringified)\n    hydrate(hydrationClient, parsed)\n    expect(hydrationCache.find({ queryKey: ['string'] })?.state.data).toBe(\n      'string-newer',\n    )\n\n    queryClient.clear()\n    hydrationClient.clear()\n  })\n\n  test('should be able to dehydrate mutations and continue on hydration', async () => {\n    const consoleMock = vi.spyOn(console, 'error')\n    consoleMock.mockImplementation(() => undefined)\n    const onlineMock = mockOnlineManagerIsOnline(false)\n\n    const serverAddTodo = vi\n      .fn()\n      .mockImplementation(() => Promise.reject(new Error('offline')))\n    const serverOnMutate = vi\n      .fn()\n      .mockImplementation((variables: { text: string }) => {\n        const optimisticTodo = { id: 1, text: variables.text }\n        return { optimisticTodo }\n      })\n    const serverOnSuccess = vi.fn()\n\n    const serverClient = new QueryClient()\n\n    serverClient.setMutationDefaults(['addTodo'], {\n      mutationFn: serverAddTodo,\n      onMutate: serverOnMutate,\n      onSuccess: serverOnSuccess,\n      retry: 3,\n      retryDelay: 10,\n    })\n\n    executeMutation(\n      serverClient,\n      {\n        mutationKey: ['addTodo'],\n      },\n      { text: 'text' },\n    ).catch(() => undefined)\n\n    await vi.advanceTimersByTimeAsync(50)\n\n    const dehydrated = dehydrate(serverClient)\n    const stringified = JSON.stringify(dehydrated)\n\n    serverClient.clear()\n\n    // ---\n\n    onlineMock.mockReturnValue(true)\n\n    const parsed = JSON.parse(stringified)\n    const client = new QueryClient()\n\n    const clientAddTodo = vi\n      .fn()\n      .mockImplementation((variables: { text: string }) => {\n        return { id: 2, text: variables.text }\n      })\n    const clientOnMutate = vi\n      .fn()\n      .mockImplementation((variables: { text: string }) => {\n        const optimisticTodo = { id: 1, text: variables.text }\n        return { optimisticTodo }\n      })\n    const clientOnSuccess = vi.fn()\n\n    client.setMutationDefaults(['addTodo'], {\n      mutationFn: clientAddTodo,\n      onMutate: clientOnMutate,\n      onSuccess: clientOnSuccess,\n      retry: 3,\n      retryDelay: 10,\n    })\n\n    hydrate(client, parsed)\n\n    await client.resumePausedMutations()\n\n    expect(clientAddTodo).toHaveBeenCalledTimes(1)\n    expect(clientOnMutate).not.toHaveBeenCalled()\n    expect(clientOnSuccess).toHaveBeenCalledTimes(1)\n    expect(clientOnSuccess).toHaveBeenCalledWith(\n      { id: 2, text: 'text' },\n      { text: 'text' },\n      { optimisticTodo: { id: 1, text: 'text' } },\n      { client: client, meta: undefined, mutationKey: ['addTodo'] },\n    )\n\n    client.clear()\n    consoleMock.mockRestore()\n    onlineMock.mockRestore()\n  })\n\n  test('should not dehydrate mutations if dehydrateMutations is set to false', async () => {\n    const consoleMock = vi.spyOn(console, 'error')\n    consoleMock.mockImplementation(() => undefined)\n\n    const serverAddTodo = vi\n      .fn()\n      .mockImplementation(() => Promise.reject(new Error('offline')))\n\n    const queryClient = new QueryClient()\n\n    queryClient.setMutationDefaults(['addTodo'], {\n      mutationFn: serverAddTodo,\n      retry: false,\n    })\n\n    executeMutation(\n      queryClient,\n      {\n        mutationKey: ['addTodo'],\n      },\n      { text: 'text' },\n    ).catch(() => undefined)\n\n    await vi.advanceTimersByTimeAsync(1)\n    const dehydrated = dehydrate(queryClient, {\n      shouldDehydrateMutation: () => false,\n    })\n\n    expect(dehydrated.mutations.length).toBe(0)\n\n    queryClient.clear()\n    consoleMock.mockRestore()\n  })\n\n  test('should not dehydrate mutation if mutation state is set to pause', async () => {\n    const consoleMock = vi.spyOn(console, 'error')\n    consoleMock.mockImplementation(() => undefined)\n\n    const serverAddTodo = vi\n      .fn()\n      .mockImplementation(() => Promise.reject(new Error('offline')))\n\n    const queryClient = new QueryClient()\n\n    queryClient.setMutationDefaults(['addTodo'], {\n      mutationFn: serverAddTodo,\n      retry: 1,\n      retryDelay: 20,\n    })\n\n    executeMutation(\n      queryClient,\n      {\n        mutationKey: ['addTodo'],\n      },\n      { text: 'text' },\n    ).catch(() => undefined)\n\n    // Dehydrate mutation between retries\n    await vi.advanceTimersByTimeAsync(1)\n    const dehydrated = dehydrate(queryClient)\n\n    expect(dehydrated.mutations.length).toBe(0)\n\n    await vi.advanceTimersByTimeAsync(30)\n    queryClient.clear()\n    consoleMock.mockRestore()\n  })\n\n  test('should not hydrate if the hydratedState is null or is not an object', () => {\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({ queryCache })\n\n    expect(() => hydrate(queryClient, null)).not.toThrow()\n    expect(() => hydrate(queryClient, 'invalid')).not.toThrow()\n\n    queryClient.clear()\n  })\n\n  test('should support hydratedState with undefined queries and mutations', () => {\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({ queryCache })\n\n    expect(() => hydrate(queryClient, {})).not.toThrow()\n    expect(() => hydrate(queryClient, {})).not.toThrow()\n\n    queryClient.clear()\n  })\n\n  test('should set the fetchStatus to idle when creating a query with dehydrate', async () => {\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({ queryCache })\n\n    let isInitialFetch = true\n    let resolvePromise: (value: unknown) => void = () => undefined\n\n    const customFetchData = () => {\n      const promise = new Promise((resolve) => {\n        resolvePromise = resolve\n      })\n      // Resolve the promise in initial fetch\n      // because we are awaiting the query first time\n      if (isInitialFetch) {\n        resolvePromise('string')\n      }\n      isInitialFetch = false\n      return promise\n    }\n\n    await queryClient.prefetchQuery({\n      queryKey: ['string'],\n      queryFn: () => customFetchData(),\n    })\n\n    queryClient.refetchQueries({ queryKey: ['string'] })\n\n    const dehydrated = dehydrate(queryClient)\n    resolvePromise('string')\n    expect(\n      dehydrated.queries.find((q) => q.queryHash === '[\"string\"]')?.state\n        .fetchStatus,\n    ).toBe('fetching')\n    const stringified = JSON.stringify(dehydrated)\n\n    // ---\n    const parsed = JSON.parse(stringified)\n    const hydrationCache = new QueryCache()\n    const hydrationClient = new QueryClient({ queryCache: hydrationCache })\n    hydrate(hydrationClient, parsed)\n    expect(\n      hydrationCache.find({ queryKey: ['string'] })?.state.fetchStatus,\n    ).toBe('idle')\n  })\n\n  test('should dehydrate and hydrate meta for queries', async () => {\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({ queryCache })\n    await vi.waitFor(() =>\n      queryClient.prefetchQuery({\n        queryKey: ['meta'],\n        queryFn: () => Promise.resolve('meta'),\n        meta: {\n          some: 'meta',\n        },\n      }),\n    )\n    await vi.waitFor(() =>\n      queryClient.prefetchQuery({\n        queryKey: ['no-meta'],\n        queryFn: () => Promise.resolve('no-meta'),\n      }),\n    )\n\n    const dehydrated = dehydrate(queryClient)\n\n    expect(\n      dehydrated.queries.find((q) => q.queryHash === '[\"meta\"]')?.meta,\n    ).toEqual({\n      some: 'meta',\n    })\n\n    expect(\n      dehydrated.queries.find((q) => q.queryHash === '[\"no-meta\"]')?.meta,\n    ).toEqual(undefined)\n\n    expect(\n      Object.keys(\n        dehydrated.queries.find((q) => q.queryHash === '[\"no-meta\"]')!,\n      ),\n    ).not.toEqual(expect.arrayContaining(['meta']))\n\n    const stringified = JSON.stringify(dehydrated)\n\n    // ---\n\n    const parsed = JSON.parse(stringified)\n    const hydrationCache = new QueryCache()\n    const hydrationClient = new QueryClient({\n      queryCache: hydrationCache,\n    })\n    hydrate(hydrationClient, parsed)\n    expect(hydrationCache.find({ queryKey: ['meta'] })?.meta).toEqual({\n      some: 'meta',\n    })\n    expect(hydrationCache.find({ queryKey: ['no-meta'] })?.meta).toEqual(\n      undefined,\n    )\n  })\n\n  test('should dehydrate and hydrate meta for mutations', async () => {\n    const mutationCache = new MutationCache()\n    const queryClient = new QueryClient({ mutationCache })\n\n    await executeMutation(\n      queryClient,\n      {\n        mutationKey: ['meta'],\n        mutationFn: () => Promise.resolve('meta'),\n        meta: {\n          some: 'meta',\n        },\n      },\n      undefined,\n    )\n\n    await executeMutation(\n      queryClient,\n      {\n        mutationKey: ['no-meta'],\n        mutationFn: () => Promise.resolve('no-meta'),\n      },\n      undefined,\n    )\n\n    const dehydrated = dehydrate(queryClient, {\n      shouldDehydrateMutation: () => true,\n    })\n\n    expect(Object.keys(dehydrated.mutations[0]!)).toEqual(\n      expect.arrayContaining(['meta']),\n    )\n    expect(dehydrated.mutations[0]?.meta).toEqual({\n      some: 'meta',\n    })\n\n    expect(Object.keys(dehydrated.mutations[1]!)).not.toEqual(\n      expect.arrayContaining(['meta']),\n    )\n    expect(dehydrated.mutations[1]?.meta).toEqual(undefined)\n\n    const stringified = JSON.stringify(dehydrated)\n\n    // ---\n\n    const parsed = JSON.parse(stringified)\n    const hydrationCache = new MutationCache()\n    const hydrationClient = new QueryClient({\n      mutationCache: hydrationCache,\n    })\n    hydrate(hydrationClient, parsed)\n    expect(hydrationCache.find({ mutationKey: ['meta'] })?.meta).toEqual({\n      some: 'meta',\n    })\n    expect(hydrationCache.find({ mutationKey: ['no-meta'] })?.meta).toEqual(\n      undefined,\n    )\n  })\n\n  test('should not change fetchStatus when updating a query with dehydrate', async () => {\n    const queryClient = new QueryClient()\n\n    const options = {\n      queryKey: ['string'],\n      queryFn: async () => {\n        await sleep(10)\n        return 'string'\n      },\n    } as const\n\n    await vi.waitFor(() => queryClient.prefetchQuery(options))\n\n    const dehydrated = dehydrate(queryClient)\n    expect(\n      dehydrated.queries.find((q) => q.queryHash === '[\"string\"]')?.state\n        .fetchStatus,\n    ).toBe('idle')\n    const stringified = JSON.stringify(dehydrated)\n\n    // ---\n    const parsed = JSON.parse(stringified)\n    const hydrationCache = new QueryCache()\n    const hydrationClient = new QueryClient({ queryCache: hydrationCache })\n\n    const promise = hydrationClient.prefetchQuery(options)\n    hydrate(hydrationClient, parsed)\n    expect(\n      hydrationCache.find({ queryKey: ['string'] })?.state.fetchStatus,\n    ).toBe('fetching')\n    await vi.waitFor(() => promise)\n    expect(\n      hydrationCache.find({ queryKey: ['string'] })?.state.fetchStatus,\n    ).toBe('idle')\n  })\n\n  test('should dehydrate and hydrate mutation scopes', () => {\n    const queryClient = new QueryClient()\n    const onlineMock = mockOnlineManagerIsOnline(false)\n\n    void executeMutation(\n      queryClient,\n      {\n        mutationKey: ['mutation'],\n        mutationFn: () => {\n          return Promise.resolve('mutation')\n        },\n        scope: {\n          id: 'scope',\n        },\n      },\n      'vars',\n    )\n\n    const dehydrated = dehydrate(queryClient)\n    expect(dehydrated.mutations[0]?.scope?.id).toBe('scope')\n    const stringified = JSON.stringify(dehydrated)\n\n    // ---\n    const parsed = JSON.parse(stringified)\n    const hydrationCache = new MutationCache()\n    const hydrationClient = new QueryClient({ mutationCache: hydrationCache })\n\n    hydrate(hydrationClient, parsed)\n\n    expect(dehydrated.mutations[0]?.scope?.id).toBe('scope')\n\n    onlineMock.mockRestore()\n  })\n\n  test('should dehydrate promises for pending queries', async () => {\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({\n      queryCache,\n      defaultOptions: { dehydrate: { shouldDehydrateQuery: () => true } },\n    })\n    await vi.waitFor(() =>\n      queryClient.prefetchQuery({\n        queryKey: ['success'],\n        queryFn: () => sleep(0).then(() => 'success'),\n      }),\n    )\n\n    const promise = queryClient.prefetchQuery({\n      queryKey: ['pending'],\n      queryFn: () => sleep(10).then(() => 'pending'),\n    })\n    const dehydrated = dehydrate(queryClient)\n\n    expect(dehydrated.queries[0]?.promise).toBeUndefined()\n    expect(dehydrated.queries[1]?.promise).toBeInstanceOf(Promise)\n\n    await vi.waitFor(() => promise)\n    queryClient.clear()\n  })\n\n  test('should hydrate promises even without observers', async () => {\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({\n      queryCache,\n      defaultOptions: { dehydrate: { shouldDehydrateQuery: () => true } },\n    })\n    await vi.waitFor(() =>\n      queryClient.prefetchQuery({\n        queryKey: ['success'],\n        queryFn: () => sleep(0).then(() => 'success'),\n      }),\n    )\n\n    void queryClient.prefetchQuery({\n      queryKey: ['pending'],\n      queryFn: () => sleep(20).then(() => 'pending'),\n    })\n    const dehydrated = dehydrate(queryClient)\n    // no stringify/parse here because promises can't be serialized to json\n    // but nextJs still can do it\n\n    const hydrationCache = new QueryCache()\n    const hydrationClient = new QueryClient({\n      queryCache: hydrationCache,\n    })\n\n    hydrate(hydrationClient, dehydrated)\n\n    expect(hydrationCache.find({ queryKey: ['success'] })?.state.data).toBe(\n      'success',\n    )\n\n    expect(hydrationCache.find({ queryKey: ['pending'] })?.state).toMatchObject(\n      {\n        data: undefined,\n        dataUpdateCount: 0,\n        dataUpdatedAt: 0,\n        error: null,\n        errorUpdateCount: 0,\n        errorUpdatedAt: 0,\n        fetchFailureCount: 0,\n        fetchFailureReason: null,\n        fetchMeta: null,\n        fetchStatus: 'fetching',\n        isInvalidated: false,\n        status: 'pending',\n      },\n    )\n\n    await vi.waitFor(() =>\n      expect(\n        hydrationCache.find({ queryKey: ['pending'] })?.state,\n      ).toMatchObject({\n        data: 'pending',\n        dataUpdateCount: 1,\n        dataUpdatedAt: expect.any(Number),\n        error: null,\n        errorUpdateCount: 0,\n        errorUpdatedAt: 0,\n        fetchFailureCount: 0,\n        fetchFailureReason: null,\n        fetchMeta: null,\n        fetchStatus: 'idle',\n        isInvalidated: false,\n        status: 'success',\n      }),\n    )\n  })\n\n  test('should transform promise result', async () => {\n    const queryClient = new QueryClient({\n      defaultOptions: {\n        dehydrate: {\n          shouldDehydrateQuery: () => true,\n          serializeData: (data) => data.toISOString(),\n        },\n      },\n    })\n\n    const promise = queryClient.prefetchQuery({\n      queryKey: ['transformedStringToDate'],\n      queryFn: () => sleep(20).then(() => new Date('2024-01-01T00:00:00.000Z')),\n    })\n    const dehydrated = dehydrate(queryClient)\n    expect(dehydrated.queries[0]?.promise).toBeInstanceOf(Promise)\n\n    const hydrationClient = new QueryClient({\n      defaultOptions: {\n        hydrate: {\n          deserializeData: (data) => new Date(data),\n        },\n      },\n    })\n\n    hydrate(hydrationClient, dehydrated)\n    await vi.waitFor(() => promise)\n    await vi.waitFor(() =>\n      expect(\n        hydrationClient.getQueryData(['transformedStringToDate']),\n      ).toBeInstanceOf(Date),\n    )\n\n    queryClient.clear()\n  })\n\n  test('should transform query data if promise is already resolved', async () => {\n    const queryClient = new QueryClient({\n      defaultOptions: {\n        dehydrate: {\n          shouldDehydrateQuery: () => true,\n          serializeData: (data) => data.toISOString(),\n        },\n      },\n    })\n\n    const promise = queryClient.prefetchQuery({\n      queryKey: ['transformedStringToDate'],\n      queryFn: () => sleep(0).then(() => new Date('2024-01-01T00:00:00.000Z')),\n    })\n    await vi.advanceTimersByTimeAsync(20)\n    const dehydrated = dehydrate(queryClient)\n\n    const hydrationClient = new QueryClient({\n      defaultOptions: {\n        hydrate: {\n          deserializeData: (data) => new Date(data),\n        },\n      },\n    })\n\n    hydrate(hydrationClient, dehydrated)\n    await vi.waitFor(() => promise)\n    await vi.waitFor(() =>\n      expect(\n        hydrationClient.getQueryData(['transformedStringToDate']),\n      ).toBeInstanceOf(Date),\n    )\n\n    queryClient.clear()\n  })\n\n  test('should overwrite query in cache if hydrated query is newer (with transformation)', async () => {\n    const hydrationClient = new QueryClient({\n      defaultOptions: {\n        hydrate: {\n          deserializeData: (data) => new Date(data),\n        },\n      },\n    })\n    await vi.waitFor(() =>\n      hydrationClient.prefetchQuery({\n        queryKey: ['date'],\n        queryFn: () =>\n          sleep(5).then(() => new Date('2024-01-01T00:00:00.000Z')),\n      }),\n    )\n\n    // ---\n\n    const queryClient = new QueryClient({\n      defaultOptions: {\n        dehydrate: {\n          shouldDehydrateQuery: () => true,\n          serializeData: (data) => data.toISOString(),\n        },\n      },\n    })\n    await vi.waitFor(() =>\n      queryClient.prefetchQuery({\n        queryKey: ['date'],\n        queryFn: () =>\n          sleep(10).then(() => new Date('2024-01-02T00:00:00.000Z')),\n      }),\n    )\n    const dehydrated = dehydrate(queryClient)\n\n    // ---\n\n    hydrate(hydrationClient, dehydrated)\n\n    expect(hydrationClient.getQueryData(['date'])).toStrictEqual(\n      new Date('2024-01-02T00:00:00.000Z'),\n    )\n\n    queryClient.clear()\n    hydrationClient.clear()\n  })\n\n  test('should overwrite query in cache if hydrated query is newer (with promise)', async () => {\n    // --- server ---\n\n    const serverQueryClient = new QueryClient({\n      defaultOptions: {\n        dehydrate: {\n          shouldDehydrateQuery: () => true,\n        },\n      },\n    })\n\n    const promise = serverQueryClient.prefetchQuery({\n      queryKey: ['data'],\n      queryFn: async () => {\n        await sleep(10)\n        return 'server data'\n      },\n    })\n\n    const dehydrated = dehydrate(serverQueryClient)\n\n    // --- client ---\n\n    const clientQueryClient = new QueryClient()\n\n    clientQueryClient.setQueryData(['data'], 'old data', { updatedAt: 10 })\n\n    hydrate(clientQueryClient, dehydrated)\n\n    await vi.waitFor(() => promise)\n    await vi.waitFor(() =>\n      expect(clientQueryClient.getQueryData(['data'])).toBe('server data'),\n    )\n\n    clientQueryClient.clear()\n    serverQueryClient.clear()\n  })\n\n  test('should not overwrite query in cache if existing query is newer (with promise)', async () => {\n    // --- server ---\n\n    const serverQueryClient = new QueryClient({\n      defaultOptions: {\n        dehydrate: {\n          shouldDehydrateQuery: () => true,\n        },\n      },\n    })\n\n    const promise = serverQueryClient.prefetchQuery({\n      queryKey: ['data'],\n      queryFn: async () => {\n        await sleep(10)\n        return 'server data'\n      },\n    })\n\n    const dehydrated = dehydrate(serverQueryClient)\n\n    await vi.advanceTimersByTimeAsync(10)\n    await promise\n\n    // Pretend the output of this server part is cached for a long time\n\n    // --- client ---\n\n    await vi.advanceTimersByTimeAsync(10_000) // Arbitrary time in the future\n\n    const clientQueryClient = new QueryClient()\n\n    clientQueryClient.setQueryData(['data'], 'newer data', {\n      updatedAt: Date.now(),\n    })\n\n    hydrate(clientQueryClient, dehydrated)\n\n    // If the query was hydrated in error, it would still take some time for it\n    // to end up in the cache, so for the test to fail properly on regressions,\n    // wait for the fetchStatus to be idle\n    await vi.waitFor(() =>\n      expect(clientQueryClient.getQueryState(['data'])?.fetchStatus).toBe(\n        'idle',\n      ),\n    )\n    await vi.waitFor(() =>\n      expect(clientQueryClient.getQueryData(['data'])).toBe('newer data'),\n    )\n\n    clientQueryClient.clear()\n    serverQueryClient.clear()\n  })\n\n  test('should overwrite data when a new promise is streamed in', async () => {\n    const serializeDataMock = vi.fn((data: any) => data)\n    const deserializeDataMock = vi.fn((data: any) => data)\n\n    const countRef = { current: 0 }\n    // --- server ---\n    const serverQueryClient = new QueryClient({\n      defaultOptions: {\n        dehydrate: {\n          shouldDehydrateQuery: () => true,\n          serializeData: serializeDataMock,\n        },\n      },\n    })\n\n    const query = {\n      queryKey: ['data'],\n      queryFn: async () => {\n        await sleep(10)\n        return countRef.current\n      },\n    }\n\n    const promise = serverQueryClient.prefetchQuery(query)\n\n    let dehydrated = dehydrate(serverQueryClient)\n\n    // --- client ---\n\n    const clientQueryClient = new QueryClient({\n      defaultOptions: {\n        hydrate: {\n          deserializeData: deserializeDataMock,\n        },\n      },\n    })\n\n    hydrate(clientQueryClient, dehydrated)\n\n    await vi.waitFor(() => promise)\n    await vi.waitFor(() =>\n      expect(clientQueryClient.getQueryData(query.queryKey)).toBe(0),\n    )\n\n    expect(serializeDataMock).toHaveBeenCalledTimes(1)\n    expect(serializeDataMock).toHaveBeenCalledWith(0)\n\n    expect(deserializeDataMock).toHaveBeenCalledTimes(1)\n    expect(deserializeDataMock).toHaveBeenCalledWith(0)\n\n    // --- server ---\n    countRef.current++\n    serverQueryClient.clear()\n    const promise2 = serverQueryClient.prefetchQuery(query)\n\n    dehydrated = dehydrate(serverQueryClient)\n\n    // --- client ---\n\n    hydrate(clientQueryClient, dehydrated)\n\n    await vi.waitFor(() => promise2)\n    await vi.waitFor(() =>\n      expect(clientQueryClient.getQueryData(query.queryKey)).toBe(1),\n    )\n\n    expect(serializeDataMock).toHaveBeenCalledTimes(2)\n    expect(serializeDataMock).toHaveBeenCalledWith(1)\n\n    expect(deserializeDataMock).toHaveBeenCalledTimes(2)\n    expect(deserializeDataMock).toHaveBeenCalledWith(1)\n\n    clientQueryClient.clear()\n    serverQueryClient.clear()\n  })\n\n  test('should not redact errors when shouldRedactErrors returns false', async () => {\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({\n      queryCache,\n      defaultOptions: {\n        dehydrate: {\n          shouldDehydrateQuery: () => true,\n          shouldRedactErrors: () => false,\n        },\n      },\n    })\n\n    const testError = new Error('original error')\n\n    const promise = queryClient\n      .prefetchQuery({\n        queryKey: ['error'],\n        queryFn: () => Promise.reject(testError),\n        retry: false,\n      })\n      .catch(() => undefined)\n\n    const dehydrated = dehydrate(queryClient)\n\n    expect(dehydrated.queries[0]?.promise).toBeInstanceOf(Promise)\n    await expect(dehydrated.queries[0]?.promise).rejects.toBe(testError)\n    await promise\n  })\n\n  test('should handle errors in promises for pending queries', async () => {\n    const consoleMock = vi.spyOn(console, 'error')\n    consoleMock.mockImplementation(() => undefined)\n\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({\n      queryCache,\n      defaultOptions: {\n        dehydrate: {\n          shouldDehydrateQuery: () => true,\n        },\n      },\n    })\n\n    const promise = queryClient\n      .prefetchQuery({\n        queryKey: ['error'],\n        queryFn: () => Promise.reject(new Error('test error')),\n        retry: false,\n      })\n      .catch(() => undefined)\n\n    const dehydrated = dehydrate(queryClient)\n\n    expect(dehydrated.queries[0]?.promise).toBeInstanceOf(Promise)\n\n    await expect(dehydrated.queries[0]?.promise).rejects.toThrow('redacted')\n    await promise\n    consoleMock.mockRestore()\n  })\n\n  test('should log error in development environment when redacting errors', async () => {\n    const originalNodeEnv = process.env.NODE_ENV\n    process.env.NODE_ENV = 'development'\n\n    const consoleMock = vi.spyOn(console, 'error')\n    consoleMock.mockImplementation(() => undefined)\n\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({\n      queryCache,\n      defaultOptions: {\n        dehydrate: {\n          shouldDehydrateQuery: () => true,\n          shouldRedactErrors: () => true,\n        },\n      },\n    })\n\n    const testError = new Error('test error')\n\n    const promise = queryClient\n      .prefetchQuery({\n        queryKey: ['error'],\n        queryFn: () => Promise.reject(testError),\n        retry: false,\n      })\n      .catch(() => undefined)\n\n    const dehydrated = dehydrate(queryClient)\n\n    await expect(dehydrated.queries[0]?.promise).rejects.toThrow('redacted')\n    expect(consoleMock).toHaveBeenCalledWith(\n      expect.stringContaining('test error'),\n    )\n    await promise\n\n    process.env.NODE_ENV = originalNodeEnv\n    consoleMock.mockRestore()\n  })\n\n  // When React hydrates promises across RSC/client boundaries, it passes\n  // them as special ReactPromise types. There are situations where the\n  // promise might have time to resolve before we end up hydrating it, in\n  // which case React will have made it a special synchronous thenable where\n  // .then() resolves immediately.\n  // In these cases it's important we hydrate the data synchronously, or else\n  // the data in the cache wont match the content that was rendered on the server.\n  // What can end up happening otherwise is that the content is visible from the\n  // server, but the client renders a Suspense fallback, only to immediately show\n  // the data again.\n  test('should rehydrate synchronous thenable immediately', async () => {\n    // --- server ---\n\n    const serverQueryClient = new QueryClient({\n      defaultOptions: {\n        dehydrate: {\n          shouldDehydrateQuery: () => true,\n        },\n      },\n    })\n    const originalPromise = serverQueryClient.prefetchQuery({\n      queryKey: ['data'],\n      queryFn: () => null,\n    })\n\n    const dehydrated = dehydrate(serverQueryClient)\n\n    // --- server end ---\n\n    // Simulate a synchronous thenable\n    // @ts-expect-error\n    dehydrated.queries[0].promise.then = (cb) => {\n      cb?.('server data')\n    }\n\n    // --- client ---\n\n    const clientQueryClient = new QueryClient()\n    hydrate(clientQueryClient, dehydrated)\n\n    // If data is already resolved, it should end up in the cache immediately\n    expect(clientQueryClient.getQueryData(['data'])).toBe('server data')\n\n    // Need to await the original promise or else it will get a cancellation\n    // error and test will fail\n    await originalPromise\n  })\n})\n"
  },
  {
    "path": "packages/query-core/src/__tests__/infiniteQueryBehavior.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { CancelledError, InfiniteQueryObserver, QueryClient } from '..'\nimport type { InfiniteData, InfiniteQueryObserverResult, QueryCache } from '..'\n\ndescribe('InfiniteQueryBehavior', () => {\n  let queryClient: QueryClient\n  let queryCache: QueryCache\n\n  beforeEach(() => {\n    vi.useFakeTimers()\n    queryClient = new QueryClient()\n    queryCache = queryClient.getQueryCache()\n    queryClient.mount()\n  })\n\n  afterEach(() => {\n    queryClient.clear()\n    vi.useRealTimers()\n  })\n\n  test('should throw an error if the queryFn is not defined', async () => {\n    const key = queryKey()\n\n    const observer = new InfiniteQueryObserver(queryClient, {\n      queryKey: key,\n      retry: false,\n      initialPageParam: 1,\n      getNextPageParam: () => 2,\n    })\n\n    let observerResult:\n      | InfiniteQueryObserverResult<unknown, unknown>\n      | undefined\n\n    const unsubscribe = observer.subscribe((result) => {\n      observerResult = result\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n    const query = queryCache.find({ queryKey: key })!\n    expect(observerResult).toMatchObject({\n      isError: true,\n      error: new Error(`Missing queryFn: '${query.queryHash}'`),\n    })\n\n    unsubscribe()\n  })\n\n  test('should apply the maxPages option to limit the number of pages', async () => {\n    const key = queryKey()\n    let abortSignal: AbortSignal | null = null\n\n    const queryFnSpy = vi.fn().mockImplementation(({ pageParam, signal }) => {\n      abortSignal = signal\n      return pageParam\n    })\n\n    const observer = new InfiniteQueryObserver<number>(queryClient, {\n      queryKey: key,\n      queryFn: queryFnSpy,\n      getNextPageParam: (lastPage) => lastPage + 1,\n      getPreviousPageParam: (firstPage) => firstPage - 1,\n      maxPages: 2,\n      initialPageParam: 1,\n    })\n\n    let observerResult:\n      | InfiniteQueryObserverResult<unknown, unknown>\n      | undefined\n\n    const unsubscribe = observer.subscribe((result) => {\n      observerResult = result\n    })\n\n    // Wait for the first page to be fetched\n    await vi.advanceTimersByTimeAsync(0)\n    expect(observerResult).toMatchObject({\n      isFetching: false,\n      data: { pages: [1], pageParams: [1] },\n    })\n\n    expect(queryFnSpy).toHaveBeenNthCalledWith(1, {\n      queryKey: key,\n      client: queryClient,\n      pageParam: 1,\n      meta: undefined,\n      direction: 'forward',\n      signal: abortSignal,\n    })\n\n    queryFnSpy.mockClear()\n\n    // Fetch the second page\n    await observer.fetchNextPage()\n\n    expect(queryFnSpy).toHaveBeenNthCalledWith(1, {\n      queryKey: key,\n      client: queryClient,\n      pageParam: 2,\n      direction: 'forward',\n      meta: undefined,\n      signal: abortSignal,\n    })\n\n    expect(observerResult).toMatchObject({\n      isFetching: false,\n      data: { pages: [1, 2], pageParams: [1, 2] },\n    })\n\n    queryFnSpy.mockClear()\n\n    // Fetch the page before the first page\n    await observer.fetchPreviousPage()\n\n    expect(queryFnSpy).toHaveBeenNthCalledWith(1, {\n      queryKey: key,\n      client: queryClient,\n      pageParam: 0,\n      direction: 'backward',\n      meta: undefined,\n      signal: abortSignal,\n    })\n\n    // Only first two pages should be in the data\n    expect(observerResult).toMatchObject({\n      isFetching: false,\n      data: { pages: [0, 1], pageParams: [0, 1] },\n    })\n\n    queryFnSpy.mockClear()\n\n    // Fetch the page before\n    await observer.fetchPreviousPage()\n\n    expect(queryFnSpy).toHaveBeenNthCalledWith(1, {\n      queryKey: key,\n      client: queryClient,\n      pageParam: -1,\n      meta: undefined,\n      direction: 'backward',\n      signal: abortSignal,\n    })\n\n    expect(observerResult).toMatchObject({\n      isFetching: false,\n      data: { pages: [-1, 0], pageParams: [-1, 0] },\n    })\n\n    queryFnSpy.mockClear()\n\n    // Fetch the page after\n    await observer.fetchNextPage()\n\n    expect(queryFnSpy).toHaveBeenNthCalledWith(1, {\n      queryKey: key,\n      client: queryClient,\n      pageParam: 1,\n      meta: undefined,\n      direction: 'forward',\n      signal: abortSignal,\n    })\n\n    expect(observerResult).toMatchObject({\n      isFetching: false,\n      data: { pages: [0, 1] },\n    })\n\n    queryFnSpy.mockClear()\n\n    // Refetch the infinite query\n    await observer.refetch()\n\n    // Only 2 pages should refetch\n    expect(queryFnSpy).toHaveBeenCalledTimes(2)\n\n    expect(queryFnSpy).toHaveBeenNthCalledWith(1, {\n      queryKey: key,\n      client: queryClient,\n      pageParam: 0,\n      meta: undefined,\n      direction: 'forward',\n      signal: abortSignal,\n    })\n\n    expect(queryFnSpy).toHaveBeenNthCalledWith(2, {\n      queryKey: key,\n      client: queryClient,\n      pageParam: 1,\n      meta: undefined,\n      direction: 'forward',\n      signal: abortSignal,\n    })\n\n    unsubscribe()\n  })\n\n  test('should support query cancellation', async () => {\n    const key = queryKey()\n    let abortSignal: AbortSignal | null = null\n\n    const queryFnSpy = vi.fn().mockImplementation(({ pageParam, signal }) => {\n      abortSignal = signal\n      sleep(10)\n      return pageParam\n    })\n\n    const observer = new InfiniteQueryObserver<number>(queryClient, {\n      queryKey: key,\n      queryFn: queryFnSpy,\n      getNextPageParam: (lastPage) => lastPage + 1,\n      getPreviousPageParam: (firstPage) => firstPage - 1,\n      initialPageParam: 1,\n    })\n\n    let observerResult:\n      | InfiniteQueryObserverResult<unknown, unknown>\n      | undefined\n\n    const unsubscribe = observer.subscribe((result) => {\n      observerResult = result\n    })\n\n    const query = observer.getCurrentQuery()\n    query.cancel()\n\n    // Wait for the first page to be cancelled\n    await vi.advanceTimersByTimeAsync(0)\n    expect(observerResult).toMatchObject({\n      isFetching: false,\n      isError: true,\n      error: new CancelledError(),\n      data: undefined,\n    })\n\n    expect(queryFnSpy).toHaveBeenCalledTimes(1)\n\n    expect(queryFnSpy).toHaveBeenNthCalledWith(1, {\n      queryKey: key,\n      client: queryClient,\n      pageParam: 1,\n      meta: undefined,\n      direction: 'forward',\n      signal: abortSignal,\n    })\n\n    unsubscribe()\n  })\n\n  test('should not refetch pages if the query is cancelled', async () => {\n    const key = queryKey()\n    let abortSignal: AbortSignal | null = null\n\n    let queryFnSpy = vi.fn().mockImplementation(({ pageParam, signal }) => {\n      abortSignal = signal\n      return pageParam\n    })\n\n    const observer = new InfiniteQueryObserver<number>(queryClient, {\n      queryKey: key,\n      queryFn: queryFnSpy,\n      getNextPageParam: (lastPage) => lastPage + 1,\n      getPreviousPageParam: (firstPage) => firstPage - 1,\n      initialPageParam: 1,\n    })\n\n    let observerResult:\n      | InfiniteQueryObserverResult<unknown, unknown>\n      | undefined\n\n    const unsubscribe = observer.subscribe((result) => {\n      observerResult = result\n    })\n\n    // Wait for the first page to be fetched\n    await vi.advanceTimersByTimeAsync(0)\n    expect(observerResult).toMatchObject({\n      isFetching: false,\n      data: { pages: [1], pageParams: [1] },\n    })\n\n    queryFnSpy.mockClear()\n\n    // Fetch the second page\n    await observer.fetchNextPage()\n\n    expect(observerResult).toMatchObject({\n      isFetching: false,\n      data: { pages: [1, 2], pageParams: [1, 2] },\n    })\n\n    expect(queryFnSpy).toHaveBeenCalledTimes(1)\n\n    expect(queryFnSpy).toHaveBeenNthCalledWith(1, {\n      queryKey: key,\n      client: queryClient,\n      pageParam: 2,\n      meta: undefined,\n      direction: 'forward',\n      signal: abortSignal,\n    })\n\n    queryFnSpy = vi.fn().mockImplementation(({ pageParam = 1, signal }) => {\n      abortSignal = signal\n      sleep(10)\n      return pageParam\n    })\n\n    // Refetch the query\n    observer.refetch()\n    expect(observerResult).toMatchObject({\n      isFetching: true,\n      isError: false,\n    })\n\n    // Cancel the query\n    const query = observer.getCurrentQuery()\n    await query.cancel()\n\n    vi.advanceTimersByTime(10)\n\n    expect(observerResult).toMatchObject({\n      isFetching: false,\n      isError: true,\n      error: new CancelledError(),\n      data: { pages: [1, 2], pageParams: [1, 2] },\n    })\n\n    // Pages should not have been fetched\n    expect(queryFnSpy).toHaveBeenCalledTimes(0)\n\n    unsubscribe()\n  })\n\n  test('should not enter an infinite loop when a page errors while retry is on #8046', async () => {\n    let errorCount = 0\n    const key = queryKey()\n\n    interface TestResponse {\n      data: Array<{ id: string }>\n      nextToken?: number\n    }\n\n    const fakeData = [\n      { data: [{ id: 'item-1' }], nextToken: 1 },\n      { data: [{ id: 'item-2' }], nextToken: 2 },\n      { data: [{ id: 'item-3' }], nextToken: 3 },\n      { data: [{ id: 'item-4' }] },\n    ]\n\n    const fetchData = async ({ nextToken = 0 }: { nextToken?: number }) =>\n      new Promise<TestResponse>((resolve, reject) => {\n        setTimeout(() => {\n          if (nextToken == 2 && errorCount < 3) {\n            errorCount += 1\n            reject({ statusCode: 429 })\n            return\n          }\n          resolve(fakeData[nextToken] as TestResponse)\n        }, 10)\n      })\n\n    const observer = new InfiniteQueryObserver<\n      TestResponse,\n      Error,\n      InfiniteData<TestResponse>,\n      typeof key,\n      number\n    >(queryClient, {\n      retry: 5,\n      staleTime: 0,\n      retryDelay: 10,\n\n      queryKey: key,\n      initialPageParam: 1,\n      getNextPageParam: (lastPage) => lastPage.nextToken,\n      queryFn: ({ pageParam }) => fetchData({ nextToken: pageParam }),\n    })\n\n    // Fetch Page 1\n    const fetchPage1Promise = observer.fetchNextPage()\n    await vi.advanceTimersByTimeAsync(10)\n    const page1Data = await fetchPage1Promise\n    expect(page1Data.data?.pageParams).toEqual([1])\n\n    // Fetch Page 2, as per the queryFn, this will reject 2 times then resolves\n    const fetchPage2Promise = observer.fetchNextPage()\n    await vi.advanceTimersByTimeAsync(70)\n    const page2Data = await fetchPage2Promise\n    expect(page2Data.data?.pageParams).toEqual([1, 2])\n\n    // Fetch Page 3\n    const fetchPage3Promise = observer.fetchNextPage()\n    await vi.advanceTimersByTimeAsync(10)\n    const page3Data = await fetchPage3Promise\n    expect(page3Data.data?.pageParams).toEqual([1, 2, 3])\n\n    // Now the real deal; re-fetching this query **should not** stamp into an\n    // infinite loop where the retryer every time restarts from page 1\n    // once it reaches the page where it errors.\n    // For this to work, we'd need to reset the error count so we actually retry\n    errorCount = 0\n    const reFetchPromise = observer.fetchNextPage()\n    await vi.advanceTimersByTimeAsync(10)\n    const reFetchedData = await reFetchPromise\n    expect(reFetchedData.data?.pageParams).toEqual([1, 2, 3])\n  })\n\n  test('should fetch even if initialPageParam is null', async () => {\n    const key = queryKey()\n\n    const observer = new InfiniteQueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => 'data',\n      getNextPageParam: () => null,\n      initialPageParam: null,\n    })\n\n    let observerResult:\n      | InfiniteQueryObserverResult<unknown, unknown>\n      | undefined\n\n    const unsubscribe = observer.subscribe((result) => {\n      observerResult = result\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(observerResult).toMatchObject({\n      isFetching: false,\n      data: { pages: ['data'], pageParams: [null] },\n    })\n\n    unsubscribe()\n  })\n\n  test('should not fetch next page when getNextPageParam returns null', async () => {\n    const key = queryKey()\n\n    const observer = new InfiniteQueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: ({ pageParam }) => sleep(0).then(() => pageParam),\n      getNextPageParam: (lastPage) => (lastPage === 1 ? null : lastPage + 1),\n      initialPageParam: 1,\n    })\n\n    let observerResult:\n      | InfiniteQueryObserverResult<InfiniteData<number, unknown>, Error>\n      | undefined\n\n    const unsubscribe = observer.subscribe((result) => {\n      observerResult = result\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(observerResult).toMatchObject({\n      isFetching: false,\n      data: { pages: [1], pageParams: [1] },\n    })\n\n    await observer.fetchNextPage()\n\n    expect(observerResult).toMatchObject({\n      isFetching: false,\n      data: { pages: [1], pageParams: [1] },\n    })\n\n    unsubscribe()\n  })\n\n  test('should use persister when provided', async () => {\n    const key = queryKey()\n\n    const persisterSpy = vi.fn().mockImplementation(async (fn) => {\n      return await fn()\n    })\n\n    const observer = new InfiniteQueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: ({ pageParam }) => sleep(0).then(() => pageParam),\n      getNextPageParam: (lastPage) => lastPage + 1,\n      initialPageParam: 1,\n      persister: persisterSpy,\n    })\n\n    const unsubscribe = observer.subscribe(() => {})\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(persisterSpy).toHaveBeenCalledTimes(1)\n\n    unsubscribe()\n  })\n})\n"
  },
  {
    "path": "packages/query-core/src/__tests__/infiniteQueryObserver.test-d.tsx",
    "content": "import { afterEach, beforeEach, describe, expectTypeOf, it, vi } from 'vitest'\nimport { queryKey } from '@tanstack/query-test-utils'\nimport { InfiniteQueryObserver, QueryClient } from '..'\nimport type { InfiniteData } from '..'\n\ndescribe('InfiniteQueryObserver', () => {\n  let queryClient: QueryClient\n\n  beforeEach(() => {\n    queryClient = new QueryClient()\n    queryClient.mount()\n  })\n\n  afterEach(() => {\n    queryClient.clear()\n  })\n\n  it('should be inferred as a correct result type', () => {\n    const next: number | undefined = 2\n    const queryFn = vi.fn(({ pageParam }) => String(pageParam))\n    const observer = new InfiniteQueryObserver(queryClient, {\n      queryKey: queryKey(),\n      queryFn,\n      initialPageParam: 1,\n      getNextPageParam: () => next,\n    })\n\n    const result = observer.getCurrentResult()\n\n    if (result.isPending) {\n      expectTypeOf(result.data).toEqualTypeOf<undefined>()\n      expectTypeOf(result.error).toEqualTypeOf<null>()\n      expectTypeOf(result.isLoading).toEqualTypeOf<boolean>()\n      expectTypeOf(result.status).toEqualTypeOf<'pending'>()\n      expectTypeOf(result.isPlaceholderData).toEqualTypeOf<false>()\n    }\n\n    if (result.isLoading) {\n      expectTypeOf(result.data).toEqualTypeOf<undefined>()\n      expectTypeOf(result.error).toEqualTypeOf<null>()\n      expectTypeOf(result.isPending).toEqualTypeOf<true>()\n      expectTypeOf(result.status).toEqualTypeOf<'pending'>()\n      expectTypeOf(result.isPlaceholderData).toEqualTypeOf<false>()\n    }\n\n    if (result.isLoadingError) {\n      expectTypeOf(result.data).toEqualTypeOf<undefined>()\n      expectTypeOf(result.error).toEqualTypeOf<Error>()\n      expectTypeOf(result.status).toEqualTypeOf<'error'>()\n      expectTypeOf(result.isPlaceholderData).toEqualTypeOf<false>()\n    }\n\n    if (result.isRefetchError) {\n      expectTypeOf(result.data).toEqualTypeOf<InfiniteData<string, unknown>>()\n      expectTypeOf(result.error).toEqualTypeOf<Error>()\n      expectTypeOf(result.status).toEqualTypeOf<'error'>()\n      expectTypeOf(result.isFetchNextPageError).toEqualTypeOf<boolean>()\n      expectTypeOf(result.isFetchPreviousPageError).toEqualTypeOf<boolean>()\n      expectTypeOf(result.isPlaceholderData).toEqualTypeOf<false>()\n    }\n\n    if (result.isSuccess) {\n      expectTypeOf(result.data).toEqualTypeOf<InfiniteData<string, unknown>>()\n      expectTypeOf(result.error).toEqualTypeOf<null>()\n      expectTypeOf(result.status).toEqualTypeOf<'success'>()\n      expectTypeOf(result.isPlaceholderData).toEqualTypeOf<boolean>()\n    }\n\n    if (result.isPlaceholderData) {\n      expectTypeOf(result.data).toEqualTypeOf<InfiniteData<string, unknown>>()\n      expectTypeOf(result.error).toEqualTypeOf<null>()\n      expectTypeOf(result.status).toEqualTypeOf<'success'>()\n    }\n  })\n})\n"
  },
  {
    "path": "packages/query-core/src/__tests__/infiniteQueryObserver.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { InfiniteQueryObserver, QueryClient } from '..'\nimport type {\n  DefaultedInfiniteQueryObserverOptions,\n  InfiniteData,\n} from '../types'\n\ndescribe('InfiniteQueryObserver', () => {\n  let queryClient: QueryClient\n\n  beforeEach(() => {\n    vi.useFakeTimers()\n    queryClient = new QueryClient()\n    queryClient.mount()\n  })\n\n  afterEach(() => {\n    queryClient.clear()\n    vi.useRealTimers()\n  })\n\n  test('should be able to fetch an infinite query with selector', async () => {\n    const key = queryKey()\n    const observer = new InfiniteQueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 1),\n      select: (data) => ({\n        pages: data.pages.map((x) => `${x}`),\n        pageParams: data.pageParams,\n      }),\n      initialPageParam: 1,\n      getNextPageParam: () => 2,\n    })\n    let observerResult\n    const unsubscribe = observer.subscribe((result) => {\n      observerResult = result\n    })\n    await vi.advanceTimersByTimeAsync(10)\n    unsubscribe()\n    expect(observerResult).toMatchObject({\n      data: { pages: ['1'], pageParams: [1] },\n    })\n  })\n\n  test('should pass the meta option to the queryFn', async () => {\n    const meta = {\n      it: 'works',\n    }\n\n    const key = queryKey()\n    const queryFn = vi.fn(() => sleep(10).then(() => 1))\n    const observer = new InfiniteQueryObserver(queryClient, {\n      meta,\n      queryKey: key,\n      queryFn,\n      select: (data) => ({\n        pages: data.pages.map((x) => `${x}`),\n        pageParams: data.pageParams,\n      }),\n      initialPageParam: 1,\n      getNextPageParam: () => 2,\n    })\n    let observerResult\n    const unsubscribe = observer.subscribe((result) => {\n      observerResult = result\n    })\n    await vi.advanceTimersByTimeAsync(10)\n    unsubscribe()\n    expect(observerResult).toMatchObject({\n      data: { pages: ['1'], pageParams: [1] },\n    })\n    expect(queryFn).toBeCalledWith(expect.objectContaining({ meta }))\n  })\n\n  test('should make getNextPageParam and getPreviousPageParam receive current pageParams', async () => {\n    const key = queryKey()\n    let single: Array<string> = []\n    let all: Array<string> = []\n    const observer = new InfiniteQueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: ({ pageParam }) => sleep(10).then(() => String(pageParam)),\n      initialPageParam: 1,\n      getNextPageParam: (_, __, lastPageParam, allPageParams) => {\n        single.push('next' + lastPageParam)\n        all.push('next' + allPageParams.join(','))\n        return lastPageParam + 1\n      },\n      getPreviousPageParam: (_, __, firstPageParam, allPageParams) => {\n        single.push('prev' + firstPageParam)\n        all.push('prev' + allPageParams.join(','))\n        return firstPageParam - 1\n      },\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    observer.fetchNextPage()\n    await vi.advanceTimersByTimeAsync(10)\n    observer.fetchPreviousPage()\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(single).toEqual(['next1', 'prev1', 'prev1', 'next1', 'prev0'])\n    expect(all).toEqual(['next1', 'prev1', 'prev1', 'next0,1', 'prev0,1'])\n\n    single = []\n    all = []\n\n    observer.refetch()\n    await vi.advanceTimersByTimeAsync(20)\n\n    expect(single).toEqual(['next0', 'next1', 'prev0'])\n    expect(all).toEqual(['next0', 'next0,1', 'prev0,1'])\n  })\n\n  test('should not invoke getNextPageParam and getPreviousPageParam on empty pages', () => {\n    const key = queryKey()\n\n    const getNextPageParam = vi.fn()\n    const getPreviousPageParam = vi.fn()\n\n    const observer = new InfiniteQueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: ({ pageParam }) => sleep(10).then(() => String(pageParam)),\n      initialPageParam: 1,\n      getNextPageParam: getNextPageParam.mockImplementation(\n        (_, __, lastPageParam) => lastPageParam + 1,\n      ),\n      getPreviousPageParam: getPreviousPageParam.mockImplementation(\n        (_, __, firstPageParam) => firstPageParam - 1,\n      ),\n    })\n\n    const unsubscribe = observer.subscribe(() => {})\n\n    getNextPageParam.mockClear()\n    getPreviousPageParam.mockClear()\n\n    queryClient.setQueryData(key, { pages: [], pageParams: [] })\n\n    expect(getNextPageParam).toHaveBeenCalledTimes(0)\n    expect(getPreviousPageParam).toHaveBeenCalledTimes(0)\n\n    unsubscribe()\n  })\n\n  test('should stop refetching if undefined is returned from getNextPageParam', async () => {\n    const key = queryKey()\n    let next: number | undefined = 2\n    const queryFn = vi.fn<(...args: Array<any>) => any>(({ pageParam }) =>\n      sleep(10).then(() => String(pageParam)),\n    )\n    const observer = new InfiniteQueryObserver(queryClient, {\n      queryKey: key,\n      queryFn,\n      initialPageParam: 1,\n      getNextPageParam: () => next,\n    })\n\n    observer.fetchNextPage()\n    await vi.advanceTimersByTimeAsync(10)\n    observer.fetchNextPage()\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(observer.getCurrentResult().data?.pages).toEqual(['1', '2'])\n    expect(queryFn).toBeCalledTimes(2)\n    expect(observer.getCurrentResult().hasNextPage).toBe(true)\n\n    next = undefined\n\n    observer.refetch()\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(observer.getCurrentResult().data?.pages).toEqual(['1'])\n    expect(queryFn).toBeCalledTimes(3)\n    expect(observer.getCurrentResult().hasNextPage).toBe(false)\n  })\n\n  test('should stop refetching if null is returned from getNextPageParam', async () => {\n    const key = queryKey()\n    let next: number | null = 2\n    const queryFn = vi.fn<(...args: Array<any>) => any>(({ pageParam }) =>\n      sleep(10).then(() => String(pageParam)),\n    )\n    const observer = new InfiniteQueryObserver(queryClient, {\n      queryKey: key,\n      queryFn,\n      initialPageParam: 1,\n      getNextPageParam: () => next,\n    })\n\n    observer.fetchNextPage()\n    await vi.advanceTimersByTimeAsync(10)\n    observer.fetchNextPage()\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(observer.getCurrentResult().data?.pages).toEqual(['1', '2'])\n    expect(queryFn).toBeCalledTimes(2)\n    expect(observer.getCurrentResult().hasNextPage).toBe(true)\n\n    next = null\n\n    observer.refetch()\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(observer.getCurrentResult().data?.pages).toEqual(['1'])\n    expect(queryFn).toBeCalledTimes(3)\n    expect(observer.getCurrentResult().hasNextPage).toBe(false)\n  })\n\n  test('should set infinite query behavior via getOptimisticResult and return the initial state', () => {\n    const key = queryKey()\n    const observer = new InfiniteQueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 1),\n      initialPageParam: 1,\n      getNextPageParam: () => 2,\n    })\n\n    const options: DefaultedInfiniteQueryObserverOptions<\n      number,\n      Error,\n      InfiniteData<number>,\n      typeof key,\n      number\n    > = {\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 1),\n      initialPageParam: 1,\n      getNextPageParam: () => 2,\n      throwOnError: true,\n      refetchOnReconnect: false,\n      queryHash: key.join(''),\n      behavior: undefined,\n    }\n\n    const result = observer.getOptimisticResult(options)\n\n    expect(options.behavior).toBeDefined()\n    expect(options.behavior?.onFetch).toBeDefined()\n\n    expect(result).toMatchObject({\n      data: undefined,\n      hasNextPage: false,\n      hasPreviousPage: false,\n      isFetching: false,\n      isFetchingNextPage: false,\n      isFetchingPreviousPage: false,\n      isError: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n  })\n})\n"
  },
  {
    "path": "packages/query-core/src/__tests__/mutation.test-d.tsx",
    "content": "import { describe, expectTypeOf, it } from 'vitest'\nimport { QueryClient } from '../queryClient'\nimport { MutationObserver } from '../mutationObserver'\n\ndescribe('mutation', () => {\n  describe('onMutate', () => {\n    it('should have onMutateResult undefined if undefined is explicitly returned', () => {\n      new MutationObserver(new QueryClient(), {\n        mutationFn: (variables: number) => {\n          return Promise.resolve(String(variables))\n        },\n        onMutate: () => {\n          return undefined\n        },\n        onSuccess: (data, variables, onMutateResult) => {\n          expectTypeOf(data).toEqualTypeOf<string>()\n          expectTypeOf(variables).toEqualTypeOf<number>()\n          expectTypeOf(onMutateResult).toEqualTypeOf<undefined>()\n        },\n        onError: (_data, _variables, onMutateResult) => {\n          expectTypeOf(onMutateResult).toEqualTypeOf<undefined>()\n        },\n        onSettled: (_data, _error, _variables, onMutateResult) => {\n          expectTypeOf(onMutateResult).toEqualTypeOf<undefined>()\n        },\n      })\n    })\n\n    it('should have unknown onMutateResult if onMutate is left out', () => {\n      new MutationObserver(new QueryClient(), {\n        mutationFn: (variables: number) => {\n          return Promise.resolve(String(variables))\n        },\n        onSuccess: (_data, _variables, onMutateResult) => {\n          expectTypeOf(onMutateResult).toEqualTypeOf<unknown>()\n        },\n        onError: (_data, _variables, onMutateResult) => {\n          expectTypeOf(onMutateResult).toEqualTypeOf<unknown>()\n        },\n        onSettled: (_data, _error, _variables, onMutateResult) => {\n          expectTypeOf(onMutateResult).toEqualTypeOf<unknown>()\n        },\n      })\n    })\n\n    it('should infer onMutateResult', () => {\n      new MutationObserver(new QueryClient(), {\n        mutationFn: (variables: number) => {\n          return Promise.resolve(String(variables))\n        },\n        onMutate: () => {\n          return Promise.resolve({ foo: 'bar' })\n        },\n        onSuccess: (_data, _variables, onMutateResult) => {\n          expectTypeOf(onMutateResult).toEqualTypeOf<{ foo: string }>()\n        },\n        onError: (_data, _variables, onMutateResult) => {\n          expectTypeOf(onMutateResult).toEqualTypeOf<\n            { foo: string } | undefined\n          >()\n        },\n        onSettled: (_data, _error, _variables, onMutateResult) => {\n          expectTypeOf(onMutateResult).toEqualTypeOf<\n            { foo: string } | undefined\n          >()\n        },\n      })\n    })\n\n    it('should include undefined in the union if explicitly returned', () => {\n      new MutationObserver(new QueryClient(), {\n        mutationFn: (variables: number) => {\n          return Promise.resolve(String(variables))\n        },\n        onMutate: () => {\n          return Math.random() > 0.5 ? { foo: 'bar' } : undefined\n        },\n        onSuccess: (_data, _variables, onMutateResult) => {\n          expectTypeOf(onMutateResult).toEqualTypeOf<\n            { foo: string } | undefined\n          >()\n        },\n        onError: (_data, _variables, onMutateResult) => {\n          expectTypeOf(onMutateResult).toEqualTypeOf<\n            { foo: string } | undefined\n          >()\n        },\n        onSettled: (_data, _error, _variables, onMutateResult) => {\n          expectTypeOf(onMutateResult).toEqualTypeOf<\n            { foo: string } | undefined\n          >()\n        },\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/query-core/src/__tests__/mutationCache.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { MutationCache, MutationObserver, QueryClient } from '..'\nimport { executeMutation } from './utils'\n\ndescribe('mutationCache', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  describe('MutationCacheConfig error callbacks', () => {\n    test('should call onError and onSettled when a mutation errors', async () => {\n      const key = queryKey()\n      const onError = vi.fn()\n      const onSuccess = vi.fn()\n      const onSettled = vi.fn()\n      const testCache = new MutationCache({ onError, onSuccess, onSettled })\n      const testClient = new QueryClient({ mutationCache: testCache })\n\n      executeMutation(\n        testClient,\n        {\n          mutationKey: key,\n          mutationFn: () =>\n            sleep(10).then(() => Promise.reject(new Error('error'))),\n          onMutate: () => 'result',\n        },\n        'vars',\n      ).catch(() => undefined)\n      await vi.advanceTimersByTimeAsync(10)\n\n      const mutation = testCache.getAll()[0]\n\n      expect(onError).toHaveBeenCalledTimes(1)\n      expect(onError).toHaveBeenCalledWith(\n        new Error('error'),\n        'vars',\n        'result',\n        mutation,\n        {\n          client: testClient,\n          meta: undefined,\n          mutationKey: key,\n        },\n      )\n      expect(onSuccess).not.toHaveBeenCalled()\n      expect(onSettled).toHaveBeenCalledTimes(1)\n      expect(onSettled).toHaveBeenCalledWith(\n        undefined,\n        new Error('error'),\n        'vars',\n        'result',\n        mutation,\n        {\n          client: testClient,\n          meta: undefined,\n          mutationKey: key,\n        },\n      )\n    })\n\n    test('should be awaited', async () => {\n      const key = queryKey()\n      const states: Array<number> = []\n      const onError = () =>\n        sleep(10).then(() => {\n          states.push(1)\n          states.push(2)\n        })\n      const onSettled = () =>\n        sleep(10).then(() => {\n          states.push(5)\n          states.push(6)\n        })\n\n      const testCache = new MutationCache({ onError, onSettled })\n      const testClient = new QueryClient({ mutationCache: testCache })\n\n      executeMutation(\n        testClient,\n        {\n          mutationKey: key,\n          mutationFn: () =>\n            sleep(10).then(() => Promise.reject(new Error('error'))),\n          onError: () =>\n            sleep(10).then(() => {\n              states.push(3)\n              states.push(4)\n            }),\n          onSettled: () =>\n            sleep(10).then(() => {\n              states.push(7)\n              states.push(8)\n            }),\n        },\n        'vars',\n      ).catch(() => undefined)\n      await vi.advanceTimersByTimeAsync(50)\n\n      expect(states).toEqual([1, 2, 3, 4, 5, 6, 7, 8])\n    })\n  })\n\n  describe('MutationCacheConfig success callbacks', () => {\n    test('should call onSuccess and onSettled when a mutation is successful', async () => {\n      const key = queryKey()\n      const onError = vi.fn()\n      const onSuccess = vi.fn()\n      const onSettled = vi.fn()\n      const testCache = new MutationCache({ onError, onSuccess, onSettled })\n      const testClient = new QueryClient({ mutationCache: testCache })\n\n      executeMutation(\n        testClient,\n        {\n          mutationKey: key,\n          mutationFn: () => sleep(10).then(() => ({ data: 5 })),\n          onMutate: () => 'result',\n        },\n        'vars',\n      )\n      await vi.advanceTimersByTimeAsync(10)\n\n      const mutation = testCache.getAll()[0]\n\n      expect(onSuccess).toHaveBeenCalledTimes(1)\n      expect(onSuccess).toHaveBeenCalledWith(\n        { data: 5 },\n        'vars',\n        'result',\n        mutation,\n        {\n          client: testClient,\n          meta: undefined,\n          mutationKey: key,\n        },\n      )\n      expect(onError).not.toHaveBeenCalled()\n      expect(onSettled).toHaveBeenCalledTimes(1)\n      expect(onSettled).toHaveBeenCalledWith(\n        { data: 5 },\n        null,\n        'vars',\n        'result',\n        mutation,\n        {\n          client: testClient,\n          meta: undefined,\n          mutationKey: key,\n        },\n      )\n    })\n\n    test('should be awaited', async () => {\n      const key = queryKey()\n      const states: Array<number> = []\n      const onSuccess = () =>\n        sleep(10).then(() => {\n          states.push(1)\n          states.push(2)\n        })\n      const onSettled = () =>\n        sleep(10).then(() => {\n          states.push(5)\n          states.push(6)\n        })\n      const testCache = new MutationCache({ onSuccess, onSettled })\n      const testClient = new QueryClient({ mutationCache: testCache })\n\n      executeMutation(\n        testClient,\n        {\n          mutationKey: key,\n          mutationFn: () => sleep(10).then(() => ({ data: 5 })),\n          onSuccess: () =>\n            sleep(10).then(() => {\n              states.push(3)\n              states.push(4)\n            }),\n          onSettled: () =>\n            sleep(10).then(() => {\n              states.push(7)\n              states.push(8)\n            }),\n        },\n        'vars',\n      )\n      await vi.advanceTimersByTimeAsync(50)\n\n      expect(states).toEqual([1, 2, 3, 4, 5, 6, 7, 8])\n    })\n  })\n\n  describe('MutationCacheConfig.onMutate', () => {\n    test('should be called before a mutation executes', () => {\n      const key = queryKey()\n      const onMutate = vi.fn()\n      const testCache = new MutationCache({ onMutate })\n      const testClient = new QueryClient({ mutationCache: testCache })\n\n      executeMutation(\n        testClient,\n        {\n          mutationKey: key,\n          mutationFn: () => sleep(10).then(() => ({ data: 5 })),\n          onMutate: () => 'result',\n        },\n        'vars',\n      )\n\n      const mutation = testCache.getAll()[0]\n\n      expect(onMutate).toHaveBeenCalledWith('vars', mutation, {\n        client: testClient,\n        meta: undefined,\n        mutationKey: key,\n      })\n    })\n\n    test('should be awaited', async () => {\n      const key = queryKey()\n      const states: Array<number> = []\n      const onMutate = () =>\n        sleep(10).then(() => {\n          states.push(1)\n          states.push(2)\n        })\n      const testCache = new MutationCache({ onMutate })\n      const testClient = new QueryClient({ mutationCache: testCache })\n\n      executeMutation(\n        testClient,\n        {\n          mutationKey: key,\n          mutationFn: () => sleep(10).then(() => ({ data: 5 })),\n          onMutate: () =>\n            sleep(10).then(() => {\n              states.push(3)\n              states.push(4)\n            }),\n        },\n        'vars',\n      )\n      await vi.advanceTimersByTimeAsync(20)\n\n      expect(states).toEqual([1, 2, 3, 4])\n    })\n\n    test('options.onMutate should run synchronously when mutationCache.config.onMutate is not defined', () => {\n      const key = queryKey()\n      const states: Array<string> = []\n\n      // No onMutate in cache config\n      const testCache = new MutationCache({})\n      const testClient = new QueryClient({ mutationCache: testCache })\n\n      executeMutation(\n        testClient,\n        {\n          mutationKey: key,\n          mutationFn: () => sleep(10).then(() => ({ data: 5 })),\n          onMutate: () => {\n            states.push('onMutate')\n            return 'context'\n          },\n        },\n        'vars',\n      )\n\n      expect(states).toEqual(['onMutate'])\n    })\n  })\n\n  describe('find', () => {\n    test('should filter correctly', () => {\n      const testCache = new MutationCache()\n      const testClient = new QueryClient({ mutationCache: testCache })\n      const key = ['mutation', 'vars']\n\n      executeMutation(\n        testClient,\n        {\n          mutationKey: key,\n          mutationFn: () => sleep(10).then(() => undefined),\n        },\n        'vars',\n      )\n\n      const [mutation] = testCache.getAll()\n\n      expect(testCache.find({ mutationKey: key })).toEqual(mutation)\n      expect(\n        testCache.find({ mutationKey: ['mutation'], exact: false }),\n      ).toEqual(mutation)\n      expect(testCache.find({ mutationKey: ['unknown'] })).toEqual(undefined)\n      expect(\n        testCache.find({\n          predicate: (m) => m.options.mutationKey?.[0] === key[0],\n        }),\n      ).toEqual(mutation)\n    })\n  })\n\n  describe('findAll', () => {\n    test('should filter correctly', () => {\n      const testCache = new MutationCache()\n      const testClient = new QueryClient({ mutationCache: testCache })\n\n      executeMutation(\n        testClient,\n        {\n          mutationKey: ['a', 1],\n          mutationFn: () => sleep(10).then(() => undefined),\n        },\n        1,\n      )\n      executeMutation(\n        testClient,\n        {\n          mutationKey: ['a', 2],\n          mutationFn: () => sleep(10).then(() => undefined),\n        },\n        2,\n      )\n      executeMutation(\n        testClient,\n        {\n          mutationKey: ['b'],\n          mutationFn: () => sleep(10).then(() => undefined),\n        },\n        3,\n      )\n\n      const [mutation1, mutation2] = testCache.getAll()\n\n      expect(\n        testCache.findAll({ mutationKey: ['a'], exact: false }),\n      ).toHaveLength(2)\n      expect(testCache.find({ mutationKey: ['a', 1] })).toEqual(mutation1)\n      expect(\n        testCache.findAll({\n          predicate: (m) => m.options.mutationKey?.[1] === 2,\n        }),\n      ).toEqual([mutation2])\n      expect(testCache.findAll({ mutationKey: ['unknown'] })).toEqual([])\n    })\n  })\n\n  describe('garbage collection', () => {\n    test('should remove unused mutations after gcTime has elapsed', async () => {\n      const testCache = new MutationCache()\n      const testClient = new QueryClient({ mutationCache: testCache })\n      const onSuccess = vi.fn()\n\n      executeMutation(\n        testClient,\n        {\n          mutationKey: ['a', 1],\n          gcTime: 10,\n          mutationFn: () => sleep(10).then(() => undefined),\n          onSuccess,\n        },\n        1,\n      )\n      await vi.advanceTimersByTimeAsync(10)\n\n      expect(testCache.getAll()).toHaveLength(1)\n\n      await vi.advanceTimersByTimeAsync(10)\n      expect(testCache.getAll()).toHaveLength(0)\n      expect(onSuccess).toHaveBeenCalledTimes(1)\n    })\n\n    test('should not remove mutations if there are active observers', async () => {\n      const queryClient = new QueryClient()\n      const observer = new MutationObserver(queryClient, {\n        gcTime: 10,\n        mutationFn: (input: number) => sleep(10).then(() => input),\n      })\n      const unsubscribe = observer.subscribe(() => undefined)\n\n      expect(queryClient.getMutationCache().getAll()).toHaveLength(0)\n\n      observer.mutate(1)\n\n      expect(queryClient.getMutationCache().getAll()).toHaveLength(1)\n\n      await vi.advanceTimersByTimeAsync(10)\n      expect(queryClient.getMutationCache().getAll()).toHaveLength(1)\n\n      unsubscribe()\n\n      expect(queryClient.getMutationCache().getAll()).toHaveLength(1)\n\n      await vi.advanceTimersByTimeAsync(10)\n      expect(queryClient.getMutationCache().getAll()).toHaveLength(0)\n    })\n\n    test('should be garbage collected later when unsubscribed and mutation is pending', async () => {\n      const queryClient = new QueryClient()\n      const onSuccess = vi.fn()\n      const observer = new MutationObserver(queryClient, {\n        gcTime: 10,\n        mutationFn: () => sleep(10).then(() => 'data'),\n        onSuccess,\n      })\n      const unsubscribe = observer.subscribe(() => undefined)\n\n      observer.mutate(1)\n\n      unsubscribe()\n\n      expect(queryClient.getMutationCache().getAll()).toHaveLength(1)\n\n      await vi.advanceTimersByTimeAsync(10)\n      // unsubscribe should not remove even though gcTime has elapsed b/c mutation is still pending\n      expect(queryClient.getMutationCache().getAll()).toHaveLength(1)\n\n      await vi.advanceTimersByTimeAsync(10)\n      // should be removed after an additional gcTime wait\n      expect(queryClient.getMutationCache().getAll()).toHaveLength(0)\n      expect(onSuccess).toHaveBeenCalledTimes(1)\n    })\n\n    test('should call callbacks even with gcTime 0 and mutation still pending', async () => {\n      const queryClient = new QueryClient()\n      const onSuccess = vi.fn()\n      const observer = new MutationObserver(queryClient, {\n        gcTime: 0,\n        mutationFn: () => sleep(10).then(() => 'data'),\n        onSuccess,\n      })\n      const unsubscribe = observer.subscribe(() => undefined)\n\n      observer.mutate(1)\n\n      unsubscribe()\n\n      await vi.advanceTimersByTimeAsync(10)\n      expect(queryClient.getMutationCache().getAll()).toHaveLength(0)\n      expect(onSuccess).toHaveBeenCalledTimes(1)\n    })\n  })\n\n  describe('remove', () => {\n    test('should remove only the target mutation from scope when multiple scoped mutations exist', () => {\n      const testCache = new MutationCache()\n      const testClient = new QueryClient({ mutationCache: testCache })\n\n      const mutation1 = testCache.build(testClient, {\n        scope: { id: 'scope1' },\n        mutationFn: () => Promise.resolve('data1'),\n      })\n      const mutation2 = testCache.build(testClient, {\n        scope: { id: 'scope1' },\n        mutationFn: () => Promise.resolve('data2'),\n      })\n\n      expect(testCache.getAll()).toHaveLength(2)\n\n      testCache.remove(mutation1)\n\n      expect(testCache.getAll()).toHaveLength(1)\n      expect(testCache.getAll()).toEqual([mutation2])\n    })\n\n    test('should delete scope when removing the only mutation in that scope', () => {\n      const testCache = new MutationCache()\n      const testClient = new QueryClient({ mutationCache: testCache })\n\n      const mutation = testCache.build(testClient, {\n        scope: { id: 'scope1' },\n        mutationFn: () => Promise.resolve('data'),\n      })\n\n      expect(testCache.getAll()).toHaveLength(1)\n\n      testCache.remove(mutation)\n\n      expect(testCache.getAll()).toHaveLength(0)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/query-core/src/__tests__/mutationObserver.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { MutationObserver, QueryClient } from '..'\n\ndescribe('mutationObserver', () => {\n  let queryClient: QueryClient\n\n  beforeEach(() => {\n    vi.useFakeTimers()\n    queryClient = new QueryClient()\n    queryClient.mount()\n  })\n\n  afterEach(() => {\n    queryClient.clear()\n    vi.useRealTimers()\n  })\n\n  test('onUnsubscribe should not remove the current mutation observer if there is still a subscription', async () => {\n    const mutation = new MutationObserver(queryClient, {\n      mutationFn: (text: string) => sleep(20).then(() => text),\n    })\n\n    const subscription1Handler = vi.fn()\n    const subscription2Handler = vi.fn()\n\n    const unsubscribe1 = mutation.subscribe(subscription1Handler)\n    const unsubscribe2 = mutation.subscribe(subscription2Handler)\n\n    mutation.mutate('input')\n\n    unsubscribe1()\n\n    expect(subscription1Handler).toBeCalledTimes(1)\n    expect(subscription2Handler).toBeCalledTimes(1)\n\n    await vi.advanceTimersByTimeAsync(20)\n    expect(subscription1Handler).toBeCalledTimes(1)\n    expect(subscription2Handler).toBeCalledTimes(2)\n\n    unsubscribe2()\n  })\n\n  test('unsubscribe should remove observer to trigger GC', async () => {\n    const mutation = new MutationObserver(queryClient, {\n      mutationFn: (text: string) => sleep(5).then(() => text),\n      gcTime: 10,\n    })\n\n    const subscriptionHandler = vi.fn()\n\n    const unsubscribe = mutation.subscribe(subscriptionHandler)\n\n    mutation.mutate('input')\n\n    await vi.advanceTimersByTimeAsync(5)\n    expect(queryClient.getMutationCache().findAll()).toHaveLength(1)\n\n    unsubscribe()\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(queryClient.getMutationCache().findAll()).toHaveLength(0)\n  })\n\n  test('reset should remove observer to trigger GC', async () => {\n    const mutation = new MutationObserver(queryClient, {\n      mutationFn: (text: string) => sleep(5).then(() => text),\n      gcTime: 10,\n    })\n\n    const subscriptionHandler = vi.fn()\n\n    const unsubscribe = mutation.subscribe(subscriptionHandler)\n\n    mutation.mutate('input')\n\n    await vi.advanceTimersByTimeAsync(5)\n    expect(queryClient.getMutationCache().findAll()).toHaveLength(1)\n\n    mutation.reset()\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(queryClient.getMutationCache().findAll()).toHaveLength(0)\n\n    unsubscribe()\n  })\n\n  test('changing mutation keys should reset the observer', async () => {\n    const key = queryKey()\n    const mutation = new MutationObserver(queryClient, {\n      mutationKey: [...key, '1'],\n      mutationFn: (text: string) => sleep(5).then(() => text),\n    })\n\n    const subscriptionHandler = vi.fn()\n\n    const unsubscribe = mutation.subscribe(subscriptionHandler)\n\n    mutation.mutate('input')\n\n    await vi.advanceTimersByTimeAsync(5)\n    expect(mutation.getCurrentResult()).toMatchObject({\n      status: 'success',\n      data: 'input',\n    })\n\n    mutation.setOptions({\n      mutationKey: [...key, '2'],\n    })\n\n    expect(mutation.getCurrentResult()).toMatchObject({\n      status: 'idle',\n    })\n\n    unsubscribe()\n  })\n\n  test('changing mutation keys should not affect already existing mutations', async () => {\n    const key = queryKey()\n    const mutationObserver = new MutationObserver(queryClient, {\n      mutationKey: [...key, '1'],\n      mutationFn: (text: string) => sleep(5).then(() => text),\n    })\n\n    const subscriptionHandler = vi.fn()\n\n    const unsubscribe = mutationObserver.subscribe(subscriptionHandler)\n\n    mutationObserver.mutate('input')\n\n    await vi.advanceTimersByTimeAsync(5)\n    expect(\n      queryClient.getMutationCache().find({ mutationKey: [...key, '1'] }),\n    ).toMatchObject({\n      options: { mutationKey: [...key, '1'] },\n      state: {\n        status: 'success',\n        data: 'input',\n      },\n    })\n\n    mutationObserver.setOptions({\n      mutationKey: [...key, '2'],\n    })\n\n    expect(\n      queryClient.getMutationCache().find({ mutationKey: [...key, '1'] }),\n    ).toMatchObject({\n      options: { mutationKey: [...key, '1'] },\n      state: {\n        status: 'success',\n        data: 'input',\n      },\n    })\n\n    unsubscribe()\n  })\n\n  test('changing mutation meta should not affect successful mutations', async () => {\n    const mutationObserver = new MutationObserver(queryClient, {\n      meta: { a: 1 },\n      mutationFn: (text: string) => sleep(5).then(() => text),\n    })\n\n    const subscriptionHandler = vi.fn()\n\n    const unsubscribe = mutationObserver.subscribe(subscriptionHandler)\n\n    mutationObserver.mutate('input')\n\n    await vi.advanceTimersByTimeAsync(5)\n    expect(queryClient.getMutationCache().find({})).toMatchObject({\n      options: { meta: { a: 1 } },\n      state: {\n        status: 'success',\n        data: 'input',\n      },\n    })\n\n    mutationObserver.setOptions({\n      meta: { a: 2 },\n    })\n\n    expect(queryClient.getMutationCache().find({})).toMatchObject({\n      options: { meta: { a: 1 } },\n      state: {\n        status: 'success',\n        data: 'input',\n      },\n    })\n\n    unsubscribe()\n  })\n\n  test('mutation cache should have different meta when updated between mutations', async () => {\n    const mutationFn = (text: string) => sleep(5).then(() => text)\n    const mutationObserver = new MutationObserver(queryClient, {\n      meta: { a: 1 },\n      mutationFn,\n    })\n\n    const subscriptionHandler = vi.fn()\n\n    const unsubscribe = mutationObserver.subscribe(subscriptionHandler)\n\n    mutationObserver.mutate('input')\n    await vi.advanceTimersByTimeAsync(5)\n\n    mutationObserver.setOptions({\n      meta: { a: 2 },\n      mutationFn,\n    })\n\n    mutationObserver.mutate('input')\n    await vi.advanceTimersByTimeAsync(5)\n\n    const mutations = queryClient.getMutationCache().findAll()\n    expect(mutations[0]).toMatchObject({\n      options: { meta: { a: 1 } },\n      state: {\n        status: 'success',\n        data: 'input',\n      },\n    })\n    expect(mutations[1]).toMatchObject({\n      options: { meta: { a: 2 } },\n      state: {\n        status: 'success',\n        data: 'input',\n      },\n    })\n\n    unsubscribe()\n  })\n\n  test('changing mutation meta should not affect rejected mutations', async () => {\n    const mutationObserver = new MutationObserver(queryClient, {\n      meta: { a: 1 },\n      mutationFn: (_: string) =>\n        sleep(5).then(() => Promise.reject(new Error('err'))),\n    })\n\n    const subscriptionHandler = vi.fn()\n\n    const unsubscribe = mutationObserver.subscribe(subscriptionHandler)\n\n    mutationObserver.mutate('input').catch(() => undefined)\n\n    await vi.advanceTimersByTimeAsync(5)\n    expect(queryClient.getMutationCache().find({})).toMatchObject({\n      options: { meta: { a: 1 } },\n      state: {\n        status: 'error',\n      },\n    })\n\n    mutationObserver.setOptions({\n      meta: { a: 2 },\n    })\n\n    expect(queryClient.getMutationCache().find({})).toMatchObject({\n      options: { meta: { a: 1 } },\n      state: {\n        status: 'error',\n      },\n    })\n\n    unsubscribe()\n  })\n\n  test('changing mutation meta should affect pending mutations', async () => {\n    const mutationObserver = new MutationObserver(queryClient, {\n      meta: { a: 1 },\n      mutationFn: (text: string) => sleep(20).then(() => text),\n    })\n\n    const subscriptionHandler = vi.fn()\n\n    const unsubscribe = mutationObserver.subscribe(subscriptionHandler)\n\n    mutationObserver.mutate('input')\n    await vi.advanceTimersByTimeAsync(5)\n    expect(queryClient.getMutationCache().find({})).toMatchObject({\n      options: { meta: { a: 1 } },\n      state: {\n        status: 'pending',\n      },\n    })\n\n    mutationObserver.setOptions({\n      meta: { a: 2 },\n    })\n\n    expect(queryClient.getMutationCache().find({})).toMatchObject({\n      options: { meta: { a: 2 } },\n      state: {\n        status: 'pending',\n      },\n    })\n\n    unsubscribe()\n  })\n\n  test('mutation callbacks should be called in correct order with correct arguments for success case', async () => {\n    const onSuccess = vi.fn()\n    const onSettled = vi.fn()\n\n    const mutationObserver = new MutationObserver(queryClient, {\n      mutationFn: (text: string) => Promise.resolve(text.toUpperCase()),\n    })\n\n    const subscriptionHandler = vi.fn()\n    const unsubscribe = mutationObserver.subscribe(subscriptionHandler)\n\n    mutationObserver.mutate('success', {\n      onSuccess,\n      onSettled,\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(onSuccess).toHaveBeenCalledTimes(1)\n    expect(onSuccess).toHaveBeenCalledWith('SUCCESS', 'success', undefined, {\n      client: queryClient,\n      meta: undefined,\n      mutationKey: undefined,\n    })\n    expect(onSettled).toHaveBeenCalledTimes(1)\n    expect(onSettled).toHaveBeenCalledWith(\n      'SUCCESS',\n      null,\n      'success',\n      undefined,\n      {\n        client: queryClient,\n        meta: undefined,\n        mutationKey: undefined,\n      },\n    )\n\n    unsubscribe()\n  })\n\n  test('mutation callbacks should be called in correct order with correct arguments for error case', async () => {\n    const onError = vi.fn()\n    const onSettled = vi.fn()\n\n    const error = new Error('error')\n    const mutationObserver = new MutationObserver(queryClient, {\n      mutationFn: (_: string) => Promise.reject(error),\n    })\n\n    const subscriptionHandler = vi.fn()\n    const unsubscribe = mutationObserver.subscribe(subscriptionHandler)\n\n    mutationObserver\n      .mutate('error', {\n        onError,\n        onSettled,\n      })\n      .catch(() => {})\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(onError).toHaveBeenCalledTimes(1)\n    expect(onError).toHaveBeenCalledWith(error, 'error', undefined, {\n      client: queryClient,\n      meta: undefined,\n      mutationKey: undefined,\n    })\n    expect(onSettled).toHaveBeenCalledTimes(1)\n    expect(onSettled).toHaveBeenCalledWith(\n      undefined,\n      error,\n      'error',\n      undefined,\n      {\n        client: queryClient,\n        meta: undefined,\n        mutationKey: undefined,\n      },\n    )\n\n    unsubscribe()\n  })\n\n  describe('erroneous mutation callback', () => {\n    test('onSuccess and onSettled is transferred to different execution context where it is reported', async ({\n      onTestFinished,\n    }) => {\n      const unhandledRejectionFn = vi.fn()\n      process.on('unhandledRejection', (error) => unhandledRejectionFn(error))\n      onTestFinished(() => {\n        process.off('unhandledRejection', unhandledRejectionFn)\n      })\n\n      const onSuccessError = new Error('onSuccess-error')\n      const onSuccess = vi.fn(() => {\n        throw onSuccessError\n      })\n      const onSettledError = new Error('onSettled-error')\n      const onSettled = vi.fn(() => {\n        throw onSettledError\n      })\n\n      const mutationObserver = new MutationObserver(queryClient, {\n        mutationFn: (text: string) => Promise.resolve(text.toUpperCase()),\n      })\n\n      const subscriptionHandler = vi.fn()\n      const unsubscribe = mutationObserver.subscribe(subscriptionHandler)\n\n      mutationObserver.mutate('success', {\n        onSuccess,\n        onSettled,\n      })\n\n      await vi.advanceTimersByTimeAsync(0)\n\n      expect(onSuccess).toHaveBeenCalledTimes(1)\n      expect(onSettled).toHaveBeenCalledTimes(1)\n\n      expect(unhandledRejectionFn).toHaveBeenCalledTimes(2)\n      expect(unhandledRejectionFn).toHaveBeenNthCalledWith(1, onSuccessError)\n      expect(unhandledRejectionFn).toHaveBeenNthCalledWith(2, onSettledError)\n\n      expect(subscriptionHandler).toHaveBeenCalledTimes(2)\n\n      unsubscribe()\n    })\n\n    test('onError and onSettled is transferred to different execution context where it is reported', async ({\n      onTestFinished,\n    }) => {\n      const unhandledRejectionFn = vi.fn()\n      process.on('unhandledRejection', (error) => unhandledRejectionFn(error))\n      onTestFinished(() => {\n        process.off('unhandledRejection', unhandledRejectionFn)\n      })\n\n      const onErrorError = new Error('onError-error')\n      const onError = vi.fn(() => {\n        throw onErrorError\n      })\n      const onSettledError = new Error('onSettled-error')\n      const onSettled = vi.fn(() => {\n        throw onSettledError\n      })\n\n      const error = new Error('error')\n      const mutationObserver = new MutationObserver(queryClient, {\n        mutationFn: (_: string) => Promise.reject(error),\n      })\n\n      const subscriptionHandler = vi.fn()\n      const unsubscribe = mutationObserver.subscribe(subscriptionHandler)\n\n      mutationObserver\n        .mutate('error', {\n          onError,\n          onSettled,\n        })\n        .catch(() => {})\n\n      await vi.advanceTimersByTimeAsync(0)\n\n      expect(onError).toHaveBeenCalledTimes(1)\n      expect(onSettled).toHaveBeenCalledTimes(1)\n\n      expect(unhandledRejectionFn).toHaveBeenCalledTimes(2)\n      expect(unhandledRejectionFn).toHaveBeenNthCalledWith(1, onErrorError)\n      expect(unhandledRejectionFn).toHaveBeenNthCalledWith(2, onSettledError)\n\n      expect(subscriptionHandler).toHaveBeenCalledTimes(2)\n\n      unsubscribe()\n    })\n  })\n\n  test('should not notify cache when setOptions is called with same options', () => {\n    const mutationObserver = new MutationObserver(queryClient, {\n      mutationFn: (text: string) => Promise.resolve(text),\n    })\n\n    const notifySpy = vi.spyOn(queryClient.getMutationCache(), 'notify')\n\n    const unsubscribe = mutationObserver.subscribe(() => undefined)\n\n    notifySpy.mockClear()\n\n    // Call setOptions with the same options\n    mutationObserver.setOptions({\n      mutationFn: mutationObserver.options.mutationFn,\n    })\n\n    expect(notifySpy).not.toHaveBeenCalledWith(\n      expect.objectContaining({ type: 'observerOptionsUpdated' }),\n    )\n\n    unsubscribe()\n  })\n})\n"
  },
  {
    "path": "packages/query-core/src/__tests__/mutations.test.tsx",
    "content": "import { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { MutationCache, QueryClient } from '..'\nimport { MutationObserver } from '../mutationObserver'\nimport { executeMutation } from './utils'\nimport type { MutationState } from '../mutation'\n\ndescribe('mutations', () => {\n  let queryClient: QueryClient\n\n  beforeEach(() => {\n    vi.useFakeTimers()\n    queryClient = new QueryClient()\n    queryClient.mount()\n  })\n\n  afterEach(() => {\n    queryClient.clear()\n    vi.useRealTimers()\n  })\n\n  test('mutate should accept null values', async () => {\n    let variables\n\n    const mutation = new MutationObserver(queryClient, {\n      mutationFn: (vars: unknown) => {\n        variables = vars\n        return Promise.resolve(vars)\n      },\n    })\n\n    mutation.mutate(null)\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(variables).toBe(null)\n  })\n\n  test('setMutationDefaults should be able to set defaults', async () => {\n    const key = queryKey()\n    const fn = vi.fn()\n\n    queryClient.setMutationDefaults(key, {\n      mutationFn: fn,\n    })\n\n    executeMutation(\n      queryClient,\n      {\n        mutationKey: key,\n      },\n      'vars',\n    )\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(fn).toHaveBeenCalledTimes(1)\n    expect(fn).toHaveBeenCalledWith('vars', {\n      client: queryClient,\n      meta: undefined,\n      mutationKey: key,\n    })\n  })\n\n  test('mutation should set correct success states', async () => {\n    const mutation = new MutationObserver(queryClient, {\n      mutationFn: (text: string) => sleep(10).then(() => text),\n      onMutate: (text) => text,\n    })\n\n    expect(mutation.getCurrentResult()).toEqual({\n      context: undefined,\n      data: undefined,\n      error: null,\n      failureCount: 0,\n      failureReason: null,\n      isError: false,\n      isIdle: true,\n      isPending: false,\n      isPaused: false,\n      isSuccess: false,\n      mutate: expect.any(Function),\n      reset: expect.any(Function),\n      status: 'idle',\n      variables: undefined,\n      submittedAt: 0,\n    })\n\n    const states: Array<MutationState<string, unknown, string, string>> = []\n\n    mutation.subscribe((state) => {\n      states.push(state)\n    })\n\n    mutation.mutate('todo')\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(states[0]).toEqual({\n      context: undefined,\n      data: undefined,\n      error: null,\n      failureCount: 0,\n      failureReason: null,\n      isError: false,\n      isIdle: false,\n      isPending: true,\n      isPaused: false,\n      isSuccess: false,\n      mutate: expect.any(Function),\n      reset: expect.any(Function),\n      status: 'pending',\n      variables: 'todo',\n      submittedAt: expect.any(Number),\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(states[1]).toEqual({\n      context: 'todo',\n      data: undefined,\n      error: null,\n      failureCount: 0,\n      failureReason: null,\n      isError: false,\n      isIdle: false,\n      isPending: true,\n      isPaused: false,\n      isSuccess: false,\n      mutate: expect.any(Function),\n      reset: expect.any(Function),\n      status: 'pending',\n      variables: 'todo',\n      submittedAt: expect.any(Number),\n    })\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states[2]).toEqual({\n      context: 'todo',\n      data: 'todo',\n      error: null,\n      failureCount: 0,\n      failureReason: null,\n      isError: false,\n      isIdle: false,\n      isPending: false,\n      isPaused: false,\n      isSuccess: true,\n      mutate: expect.any(Function),\n      reset: expect.any(Function),\n      status: 'success',\n      variables: 'todo',\n      submittedAt: expect.any(Number),\n    })\n  })\n\n  test('mutation should set correct error states', async () => {\n    const mutation = new MutationObserver(queryClient, {\n      mutationFn: (_: string) =>\n        sleep(20).then(() => Promise.reject(new Error('err'))),\n      onMutate: (text) => text,\n      retry: 1,\n      retryDelay: 10,\n    })\n\n    const states: Array<MutationState<string, unknown, string, string>> = []\n\n    mutation.subscribe((state) => {\n      states.push(state)\n    })\n\n    mutation.mutate('todo').catch(() => undefined)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(states[0]).toEqual({\n      context: undefined,\n      data: undefined,\n      error: null,\n      failureCount: 0,\n      failureReason: null,\n      isError: false,\n      isIdle: false,\n      isPending: true,\n      isPaused: false,\n      isSuccess: false,\n      mutate: expect.any(Function),\n      reset: expect.any(Function),\n      status: 'pending',\n      variables: 'todo',\n      submittedAt: expect.any(Number),\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(states[1]).toEqual({\n      context: 'todo',\n      data: undefined,\n      error: null,\n      failureCount: 0,\n      failureReason: null,\n      isError: false,\n      isIdle: false,\n      isPending: true,\n      isPaused: false,\n      isSuccess: false,\n      mutate: expect.any(Function),\n      reset: expect.any(Function),\n      status: 'pending',\n      variables: 'todo',\n      submittedAt: expect.any(Number),\n    })\n\n    await vi.advanceTimersByTimeAsync(20)\n\n    expect(states[2]).toEqual({\n      context: 'todo',\n      data: undefined,\n      error: null,\n      failureCount: 1,\n      failureReason: new Error('err'),\n      isError: false,\n      isIdle: false,\n      isPending: true,\n      isPaused: false,\n      isSuccess: false,\n      mutate: expect.any(Function),\n      reset: expect.any(Function),\n      status: 'pending',\n      variables: 'todo',\n      submittedAt: expect.any(Number),\n    })\n\n    await vi.advanceTimersByTimeAsync(30)\n\n    expect(states[3]).toEqual({\n      context: 'todo',\n      data: undefined,\n      error: new Error('err'),\n      failureCount: 2,\n      failureReason: new Error('err'),\n      isError: true,\n      isIdle: false,\n      isPending: false,\n      isPaused: false,\n      isSuccess: false,\n      mutate: expect.any(Function),\n      reset: expect.any(Function),\n      status: 'error',\n      variables: 'todo',\n      submittedAt: expect.any(Number),\n    })\n  })\n\n  test('should be able to restore a mutation', async () => {\n    const key = queryKey()\n\n    const onMutate = vi.fn()\n    const onSuccess = vi.fn()\n    const onSettled = vi.fn()\n\n    queryClient.setMutationDefaults(key, {\n      mutationFn: (text: string) => sleep(10).then(() => text),\n      onMutate,\n      onSuccess,\n      onSettled,\n    })\n\n    const mutation = queryClient\n      .getMutationCache()\n      .build<string, unknown, string, string>(\n        queryClient,\n        {\n          mutationKey: key,\n        },\n        {\n          context: 'todo',\n          data: undefined,\n          error: null,\n          failureCount: 1,\n          failureReason: 'err',\n          isPaused: true,\n          status: 'pending',\n          variables: 'todo',\n          submittedAt: 1,\n        },\n      )\n\n    expect(mutation.state).toEqual({\n      context: 'todo',\n      data: undefined,\n      error: null,\n      failureCount: 1,\n      failureReason: 'err',\n      isPaused: true,\n      status: 'pending',\n      variables: 'todo',\n      submittedAt: 1,\n    })\n\n    void queryClient.resumePausedMutations()\n\n    // check that the mutation is correctly resumed\n    expect(mutation.state).toEqual({\n      context: 'todo',\n      data: undefined,\n      error: null,\n      failureCount: 1,\n      failureReason: 'err',\n      isPaused: false,\n      status: 'pending',\n      variables: 'todo',\n      submittedAt: 1,\n    })\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(mutation.state).toEqual({\n      context: 'todo',\n      data: 'todo',\n      error: null,\n      failureCount: 0,\n      failureReason: null,\n      isPaused: false,\n      status: 'success',\n      variables: 'todo',\n      submittedAt: 1,\n    })\n\n    expect(onMutate).not.toHaveBeenCalled()\n    expect(onSuccess).toHaveBeenCalled()\n    expect(onSettled).toHaveBeenCalled()\n  })\n\n  test('addObserver should not add an existing observer', () => {\n    const mutationCache = queryClient.getMutationCache()\n    const observer = new MutationObserver(queryClient, {})\n    const currentMutation = mutationCache.build(queryClient, {})\n\n    const fn = vi.fn()\n\n    const unsubscribe = mutationCache.subscribe((event) => {\n      fn(event.type)\n    })\n\n    currentMutation.addObserver(observer)\n    currentMutation.addObserver(observer)\n\n    expect(fn).toHaveBeenCalledTimes(1)\n    expect(fn).toHaveBeenCalledWith('observerAdded')\n\n    unsubscribe()\n  })\n\n  test('mutate should throw an error if no mutationFn found', async () => {\n    const mutation = new MutationObserver(queryClient, {\n      mutationFn: undefined,\n      retry: false,\n    })\n\n    let error: any\n    try {\n      await mutation.mutate()\n    } catch (err) {\n      error = err\n    }\n    expect(error).toEqual(new Error('No mutationFn found'))\n  })\n\n  test('mutate update the mutation state even without an active subscription 1', async () => {\n    const onSuccess = vi.fn()\n    const onSettled = vi.fn()\n\n    const mutation = new MutationObserver(queryClient, {\n      mutationFn: () => {\n        return Promise.resolve('update')\n      },\n    })\n\n    mutation.mutate(undefined, { onSuccess, onSettled })\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(mutation.getCurrentResult().data).toEqual('update')\n    expect(onSuccess).not.toHaveBeenCalled()\n    expect(onSettled).not.toHaveBeenCalled()\n  })\n\n  test('mutate update the mutation state even without an active subscription 2', async () => {\n    const onSuccess = vi.fn()\n    const onSettled = vi.fn()\n\n    const mutation = new MutationObserver(queryClient, {\n      mutationFn: () => {\n        return Promise.resolve('update')\n      },\n    })\n\n    mutation.mutate(undefined, { onSuccess, onSettled })\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(mutation.getCurrentResult().data).toEqual('update')\n    expect(onSuccess).not.toHaveBeenCalled()\n    expect(onSettled).not.toHaveBeenCalled()\n  })\n\n  test('mutation callbacks should see updated options', async () => {\n    const onSuccess = vi.fn()\n\n    const mutation = new MutationObserver(queryClient, {\n      mutationFn: async () => {\n        await sleep(100)\n        return Promise.resolve('update')\n      },\n      onSuccess: () => {\n        onSuccess(1)\n      },\n    })\n\n    void mutation.mutate()\n\n    mutation.setOptions({\n      mutationFn: async () => {\n        await sleep(100)\n        return Promise.resolve('update')\n      },\n      onSuccess: () => {\n        onSuccess(2)\n      },\n    })\n\n    await vi.advanceTimersByTimeAsync(100)\n    expect(onSuccess).toHaveBeenCalledTimes(1)\n\n    expect(onSuccess).toHaveBeenCalledWith(2)\n  })\n\n  describe('scoped mutations', () => {\n    test('mutations in the same scope should run in serial', async () => {\n      const key1 = queryKey()\n      const key2 = queryKey()\n\n      const results: Array<string> = []\n\n      executeMutation(\n        queryClient,\n        {\n          mutationKey: key1,\n          scope: {\n            id: 'scope',\n          },\n          mutationFn: async () => {\n            results.push('start-A')\n            await sleep(10)\n            results.push('finish-A')\n            return 'a'\n          },\n        },\n        'vars1',\n      )\n\n      expect(\n        queryClient.getMutationCache().find({ mutationKey: key1 })?.state,\n      ).toMatchObject({\n        status: 'pending',\n        isPaused: false,\n      })\n\n      executeMutation(\n        queryClient,\n        {\n          mutationKey: key2,\n          scope: {\n            id: 'scope',\n          },\n          mutationFn: async () => {\n            results.push('start-B')\n            await sleep(10)\n            results.push('finish-B')\n            return 'b'\n          },\n        },\n        'vars2',\n      )\n\n      expect(\n        queryClient.getMutationCache().find({ mutationKey: key2 })?.state,\n      ).toMatchObject({\n        status: 'pending',\n        isPaused: true,\n      })\n\n      await vi.advanceTimersByTimeAsync(20)\n\n      expect(results).toStrictEqual([\n        'start-A',\n        'finish-A',\n        'start-B',\n        'finish-B',\n      ])\n    })\n  })\n\n  test('mutations without scope should run in parallel', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    const results: Array<string> = []\n\n    executeMutation(\n      queryClient,\n      {\n        mutationKey: key1,\n        mutationFn: async () => {\n          results.push('start-A')\n          await sleep(10)\n          results.push('finish-A')\n          return 'a'\n        },\n      },\n      'vars1',\n    )\n\n    executeMutation(\n      queryClient,\n      {\n        mutationKey: key2,\n        mutationFn: async () => {\n          results.push('start-B')\n          await sleep(10)\n          results.push('finish-B')\n          return 'b'\n        },\n      },\n      'vars2',\n    )\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(results).toStrictEqual([\n      'start-A',\n      'start-B',\n      'finish-A',\n      'finish-B',\n    ])\n  })\n\n  test('each scope should run in parallel, serial within scope', async () => {\n    const results: Array<string> = []\n\n    executeMutation(\n      queryClient,\n      {\n        scope: {\n          id: '1',\n        },\n        mutationFn: async () => {\n          results.push('start-A1')\n          await sleep(10)\n          results.push('finish-A1')\n          return 'a'\n        },\n      },\n      'vars1',\n    )\n\n    executeMutation(\n      queryClient,\n      {\n        scope: {\n          id: '1',\n        },\n        mutationFn: async () => {\n          results.push('start-B1')\n          await sleep(10)\n          results.push('finish-B1')\n          return 'b'\n        },\n      },\n      'vars2',\n    )\n\n    executeMutation(\n      queryClient,\n      {\n        scope: {\n          id: '2',\n        },\n        mutationFn: async () => {\n          results.push('start-A2')\n          await sleep(10)\n          results.push('finish-A2')\n          return 'a'\n        },\n      },\n      'vars1',\n    )\n\n    executeMutation(\n      queryClient,\n      {\n        scope: {\n          id: '2',\n        },\n        mutationFn: async () => {\n          results.push('start-B2')\n          await sleep(10)\n          results.push('finish-B2')\n          return 'b'\n        },\n      },\n      'vars2',\n    )\n\n    await vi.advanceTimersByTimeAsync(20)\n\n    expect(results).toStrictEqual([\n      'start-A1',\n      'start-A2',\n      'finish-A1',\n      'start-B1',\n      'finish-A2',\n      'start-B2',\n      'finish-B1',\n      'finish-B2',\n    ])\n  })\n\n  describe('callback return types', () => {\n    test('should handle all sync callback patterns', async () => {\n      const key = queryKey()\n      const results: Array<string> = []\n\n      executeMutation(\n        queryClient,\n        {\n          mutationKey: key,\n          mutationFn: () => Promise.resolve('success'),\n          onMutate: () => {\n            results.push('onMutate-sync')\n            return { backup: 'data' } // onMutate can return a result\n          },\n          onSuccess: () => {\n            results.push('onSuccess-implicit-void')\n            // Implicit void return\n          },\n          onError: () => {\n            results.push('onError-explicit-void')\n            return // Explicit void return\n          },\n          onSettled: () => {\n            results.push('onSettled-return-value')\n            return 'ignored-value' // Non-void return (should be ignored)\n          },\n        },\n        'vars',\n      )\n\n      await vi.advanceTimersByTimeAsync(0)\n\n      expect(results).toEqual([\n        'onMutate-sync',\n        'onSuccess-implicit-void',\n        'onSettled-return-value',\n      ])\n    })\n\n    test('should handle all async callback patterns', async () => {\n      const key = queryKey()\n      const results: Array<string> = []\n\n      executeMutation(\n        queryClient,\n        {\n          mutationKey: key,\n          mutationFn: () => Promise.resolve('success'),\n          onMutate: async () => {\n            results.push('onMutate-async')\n            await sleep(10)\n            return { backup: 'async-data' }\n          },\n          onSuccess: async () => {\n            results.push('onSuccess-async-start')\n            await sleep(20)\n            results.push('onSuccess-async-end')\n            // Implicit void return from async\n          },\n          onSettled: () => {\n            results.push('onSettled-promise')\n            return Promise.resolve('also-ignored') // Promise<string> (should be ignored)\n          },\n        },\n        'vars',\n      )\n\n      await vi.advanceTimersByTimeAsync(30)\n\n      expect(results).toEqual([\n        'onMutate-async',\n        'onSuccess-async-start',\n        'onSuccess-async-end',\n        'onSettled-promise',\n      ])\n    })\n\n    test('should handle Promise.all() and Promise.allSettled() patterns', async () => {\n      const key = queryKey()\n      const results: Array<string> = []\n\n      executeMutation(\n        queryClient,\n        {\n          mutationKey: key,\n          mutationFn: () => Promise.resolve('success'),\n          onSuccess: () => {\n            results.push('onSuccess-start')\n            return Promise.all([\n              sleep(20).then(() => results.push('invalidate-queries')),\n              sleep(10).then(() => results.push('track-analytics')),\n            ])\n          },\n          onSettled: () => {\n            results.push('onSettled-start')\n            return Promise.allSettled([\n              sleep(10).then(() => results.push('cleanup-1')),\n              Promise.reject('error').catch(() =>\n                results.push('cleanup-2-failed'),\n              ),\n            ])\n          },\n        },\n        'vars',\n      )\n\n      await vi.advanceTimersByTimeAsync(30)\n\n      expect(results).toEqual([\n        'onSuccess-start',\n        'track-analytics',\n        'invalidate-queries',\n        'onSettled-start',\n        'cleanup-2-failed',\n        'cleanup-1',\n      ])\n    })\n\n    test('should handle mixed sync/async patterns and return value isolation', async () => {\n      const key = queryKey()\n      const results: Array<string> = []\n\n      const mutationPromise = executeMutation(\n        queryClient,\n        {\n          mutationKey: key,\n          mutationFn: () => Promise.resolve('actual-result'),\n          onMutate: () => {\n            results.push('sync-onMutate')\n            return { rollback: 'data' }\n          },\n          onSuccess: async () => {\n            results.push('async-onSuccess')\n            await sleep(10)\n            return 'success-return-ignored'\n          },\n          onError: () => {\n            results.push('sync-onError')\n            return Promise.resolve('error-return-ignored')\n          },\n          onSettled: (_data, _error, _variables, onMutateResult) => {\n            results.push(`settled-onMutateResult-${onMutateResult?.rollback}`)\n            return Promise.all([\n              Promise.resolve('cleanup-1'),\n              Promise.resolve('cleanup-2'),\n            ])\n          },\n        },\n        'vars',\n      )\n\n      await vi.advanceTimersByTimeAsync(10)\n\n      const mutationResult = await mutationPromise\n\n      // Verify mutation returns its own result, not callback returns\n      expect(mutationResult).toBe('actual-result')\n      console.log(results)\n      expect(results).toEqual([\n        'sync-onMutate',\n        'async-onSuccess',\n        'settled-onMutateResult-data',\n      ])\n    })\n\n    test('should handle error cases with all callback patterns', async () => {\n      const key = queryKey()\n      const results: Array<string> = []\n\n      const newMutationError = new Error('mutation-error')\n      let mutationError: Error | undefined\n      executeMutation(\n        queryClient,\n        {\n          mutationKey: key,\n          mutationFn: () => Promise.reject(newMutationError),\n          onMutate: () => {\n            results.push('onMutate')\n            return { backup: 'error-data' }\n          },\n          onSuccess: () => {\n            results.push('onSuccess-should-not-run')\n          },\n          onError: async () => {\n            results.push('onError-async')\n            await sleep(10)\n            // Test Promise.all() in error callback\n            return Promise.all([\n              sleep(10).then(() => results.push('error-cleanup-1')),\n              sleep(20).then(() => results.push('error-cleanup-2')),\n            ])\n          },\n          onSettled: (_data, _error, _variables, onMutateResult) => {\n            results.push(`settled-error-${onMutateResult?.backup}`)\n            return Promise.allSettled([\n              Promise.resolve('settled-cleanup'),\n              Promise.reject('settled-error'),\n            ])\n          },\n        },\n        'vars',\n      ).catch((error) => {\n        mutationError = error\n      })\n\n      await vi.advanceTimersByTimeAsync(30)\n\n      expect(results).toEqual([\n        'onMutate',\n        'onError-async',\n        'error-cleanup-1',\n        'error-cleanup-2',\n        'settled-error-error-data',\n      ])\n\n      expect(mutationError).toEqual(newMutationError)\n    })\n  })\n\n  describe('erroneous mutation callback', () => {\n    test('error by global onSuccess triggers onError callback', async () => {\n      const newMutationError = new Error('mutation-error')\n\n      queryClient = new QueryClient({\n        mutationCache: new MutationCache({\n          onSuccess: () => {\n            throw newMutationError\n          },\n        }),\n      })\n      queryClient.mount()\n\n      const key = queryKey()\n      const results: Array<string> = []\n\n      let mutationError: Error | undefined\n      executeMutation(\n        queryClient,\n        {\n          mutationKey: key,\n          mutationFn: () => Promise.resolve('success'),\n          onMutate: async () => {\n            results.push('onMutate-async')\n            await sleep(10)\n            return { backup: 'async-data' }\n          },\n          onSuccess: async () => {\n            results.push('onSuccess-async-start')\n            await sleep(10)\n            throw newMutationError\n          },\n          onError: async () => {\n            results.push('onError-async-start')\n            await sleep(10)\n            results.push('onError-async-end')\n          },\n          onSettled: () => {\n            results.push('onSettled-promise')\n            return Promise.resolve('also-ignored') // Promise<string> (should be ignored)\n          },\n        },\n        'vars',\n      ).catch((error) => {\n        mutationError = error\n      })\n\n      await vi.advanceTimersByTimeAsync(30)\n\n      expect(results).toEqual([\n        'onMutate-async',\n        'onError-async-start',\n        'onError-async-end',\n        'onSettled-promise',\n      ])\n\n      expect(mutationError).toEqual(newMutationError)\n    })\n\n    test('error by mutations onSuccess triggers onError callback', async () => {\n      const key = queryKey()\n      const results: Array<string> = []\n\n      const newMutationError = new Error('mutation-error')\n\n      let mutationError: Error | undefined\n      executeMutation(\n        queryClient,\n        {\n          mutationKey: key,\n          mutationFn: () => Promise.resolve('success'),\n          onMutate: async () => {\n            results.push('onMutate-async')\n            await sleep(10)\n            return { backup: 'async-data' }\n          },\n          onSuccess: async () => {\n            results.push('onSuccess-async-start')\n            await sleep(10)\n            throw newMutationError\n          },\n          onError: async () => {\n            results.push('onError-async-start')\n            await sleep(10)\n            results.push('onError-async-end')\n          },\n          onSettled: () => {\n            results.push('onSettled-promise')\n            return Promise.resolve('also-ignored') // Promise<string> (should be ignored)\n          },\n        },\n        'vars',\n      ).catch((error) => {\n        mutationError = error\n      })\n\n      await vi.advanceTimersByTimeAsync(30)\n\n      expect(results).toEqual([\n        'onMutate-async',\n        'onSuccess-async-start',\n        'onError-async-start',\n        'onError-async-end',\n        'onSettled-promise',\n      ])\n\n      expect(mutationError).toEqual(newMutationError)\n    })\n\n    test('error by global onSettled triggers onError callback, calling global onSettled callback twice', async ({\n      onTestFinished,\n    }) => {\n      const newMutationError = new Error('mutation-error')\n\n      queryClient = new QueryClient({\n        mutationCache: new MutationCache({\n          onSettled: async () => {\n            results.push('global-onSettled')\n            await sleep(10)\n            throw newMutationError\n          },\n        }),\n      })\n      queryClient.mount()\n\n      const unhandledRejectionFn = vi.fn()\n      process.on('unhandledRejection', (error) => unhandledRejectionFn(error))\n      onTestFinished(() => {\n        process.off('unhandledRejection', unhandledRejectionFn)\n      })\n\n      const key = queryKey()\n      const results: Array<string> = []\n\n      let mutationError: Error | undefined\n      executeMutation(\n        queryClient,\n        {\n          mutationKey: key,\n          mutationFn: () => Promise.resolve('success'),\n          onMutate: async () => {\n            results.push('onMutate-async')\n            await sleep(10)\n            return { backup: 'async-data' }\n          },\n          onSuccess: async () => {\n            results.push('onSuccess-async-start')\n            await sleep(10)\n            results.push('onSuccess-async-end')\n          },\n          onError: async () => {\n            results.push('onError-async-start')\n            await sleep(10)\n            results.push('onError-async-end')\n          },\n          onSettled: () => {\n            results.push('local-onSettled')\n          },\n        },\n        'vars',\n      ).catch((error) => {\n        mutationError = error\n      })\n\n      await vi.advanceTimersByTimeAsync(50)\n\n      expect(results).toEqual([\n        'onMutate-async',\n        'onSuccess-async-start',\n        'onSuccess-async-end',\n        'global-onSettled',\n        'onError-async-start',\n        'onError-async-end',\n        'global-onSettled',\n        'local-onSettled',\n      ])\n\n      expect(unhandledRejectionFn).toHaveBeenCalledTimes(1)\n      expect(unhandledRejectionFn).toHaveBeenNthCalledWith(1, newMutationError)\n\n      expect(mutationError).toEqual(newMutationError)\n    })\n\n    test('error by mutations onSettled triggers onError callback, calling both onSettled callbacks twice', async ({\n      onTestFinished,\n    }) => {\n      const unhandledRejectionFn = vi.fn()\n      process.on('unhandledRejection', (error) => unhandledRejectionFn(error))\n      onTestFinished(() => {\n        process.off('unhandledRejection', unhandledRejectionFn)\n      })\n\n      const key = queryKey()\n      const results: Array<string> = []\n\n      const newMutationError = new Error('mutation-error')\n\n      let mutationError: Error | undefined\n      executeMutation(\n        queryClient,\n        {\n          mutationKey: key,\n          mutationFn: () => Promise.resolve('success'),\n          onMutate: async () => {\n            results.push('onMutate-async')\n            await sleep(10)\n            return { backup: 'async-data' }\n          },\n          onSuccess: async () => {\n            results.push('onSuccess-async-start')\n            await sleep(10)\n            results.push('onSuccess-async-end')\n          },\n          onError: async () => {\n            results.push('onError-async-start')\n            await sleep(10)\n            results.push('onError-async-end')\n          },\n          onSettled: async () => {\n            results.push('onSettled-async-promise')\n            await sleep(10)\n            throw newMutationError\n          },\n        },\n        'vars',\n      ).catch((error) => {\n        mutationError = error\n      })\n\n      await vi.advanceTimersByTimeAsync(50)\n\n      expect(results).toEqual([\n        'onMutate-async',\n        'onSuccess-async-start',\n        'onSuccess-async-end',\n        'onSettled-async-promise',\n        'onError-async-start',\n        'onError-async-end',\n        'onSettled-async-promise',\n      ])\n\n      expect(unhandledRejectionFn).toHaveBeenCalledTimes(1)\n      expect(unhandledRejectionFn).toHaveBeenNthCalledWith(1, newMutationError)\n\n      expect(mutationError).toEqual(newMutationError)\n    })\n\n    test('errors by onError and consecutive onSettled callbacks are transferred to different execution context where it are reported', async ({\n      onTestFinished,\n    }) => {\n      const unhandledRejectionFn = vi.fn()\n      process.on('unhandledRejection', (error) => unhandledRejectionFn(error))\n      onTestFinished(() => {\n        process.off('unhandledRejection', unhandledRejectionFn)\n      })\n\n      const globalErrorError = new Error('global-error-error')\n      const globalSettledError = new Error('global-settled-error')\n\n      queryClient = new QueryClient({\n        mutationCache: new MutationCache({\n          onError: () => {\n            throw globalErrorError\n          },\n          onSettled: () => {\n            throw globalSettledError\n          },\n        }),\n      })\n      queryClient.mount()\n\n      const key = queryKey()\n      const results: Array<string> = []\n\n      const newMutationError = new Error('mutation-error')\n      const newErrorError = new Error('error-error')\n      const newSettledError = new Error('settled-error')\n\n      let mutationError: Error | undefined\n      executeMutation(\n        queryClient,\n        {\n          mutationKey: key,\n          mutationFn: () => Promise.resolve('success'),\n          onMutate: async () => {\n            results.push('onMutate-async')\n            await sleep(10)\n            throw newMutationError\n          },\n          onSuccess: () => {\n            results.push('onSuccess-async-start')\n          },\n          onError: async () => {\n            results.push('onError-async-start')\n            await sleep(10)\n            throw newErrorError\n          },\n          onSettled: async () => {\n            results.push('onSettled-promise')\n            await sleep(10)\n            throw newSettledError\n          },\n        },\n        'vars',\n      ).catch((error) => {\n        mutationError = error\n      })\n\n      await vi.advanceTimersByTimeAsync(30)\n\n      expect(results).toEqual([\n        'onMutate-async',\n        'onError-async-start',\n        'onSettled-promise',\n      ])\n\n      expect(mutationError).toEqual(newMutationError)\n\n      expect(unhandledRejectionFn).toHaveBeenCalledTimes(4)\n      expect(unhandledRejectionFn).toHaveBeenNthCalledWith(1, globalErrorError)\n      expect(unhandledRejectionFn).toHaveBeenNthCalledWith(2, newErrorError)\n      expect(unhandledRejectionFn).toHaveBeenNthCalledWith(\n        3,\n        globalSettledError,\n      )\n      expect(unhandledRejectionFn).toHaveBeenNthCalledWith(4, newSettledError)\n    })\n  })\n\n  test('should not remove mutation when one observer is removed but another still exists', async () => {\n    const observer1 = new MutationObserver(queryClient, {\n      gcTime: 10,\n      mutationFn: () => sleep(10).then(() => 'data'),\n    })\n    const unsubscribe1 = observer1.subscribe(() => undefined)\n\n    observer1.mutate()\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(queryClient.getMutationCache().getAll()).toHaveLength(1)\n\n    const mutation = queryClient.getMutationCache().getAll()[0]!\n    const observer2 = new MutationObserver(queryClient, {\n      gcTime: 10,\n      mutationFn: () => sleep(10).then(() => 'data'),\n    })\n    mutation.addObserver(observer2)\n\n    unsubscribe1()\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(queryClient.getMutationCache().getAll()).toHaveLength(1)\n  })\n})\n"
  },
  {
    "path": "packages/query-core/src/__tests__/notifyManager.test.tsx",
    "content": "import {\n  afterEach,\n  assertType,\n  beforeEach,\n  describe,\n  expect,\n  expectTypeOf,\n  it,\n  vi,\n} from 'vitest'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { createNotifyManager } from '../notifyManager'\n\ndescribe('notifyManager', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should use default notifyFn', async () => {\n    const notifyManagerTest = createNotifyManager()\n    const callbackSpy = vi.fn()\n    notifyManagerTest.schedule(callbackSpy)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(callbackSpy).toHaveBeenCalled()\n  })\n\n  it('should use default batchNotifyFn', async () => {\n    const notifyManagerTest = createNotifyManager()\n    const callbackScheduleSpy = vi.fn().mockImplementation(() => sleep(20))\n    const callbackBatchLevel2Spy = vi.fn().mockImplementation(() => {\n      notifyManagerTest.schedule(callbackScheduleSpy)\n    })\n    const callbackBatchLevel1Spy = vi.fn().mockImplementation(() => {\n      notifyManagerTest.batch(callbackBatchLevel2Spy)\n    })\n    notifyManagerTest.batch(callbackBatchLevel1Spy)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(callbackBatchLevel1Spy).toHaveBeenCalledTimes(1)\n    expect(callbackBatchLevel2Spy).toHaveBeenCalledTimes(1)\n    expect(callbackScheduleSpy).toHaveBeenCalledTimes(1)\n  })\n\n  it('should use a custom scheduler when configured', async () => {\n    const customCallback = vi.fn((cb) => queueMicrotask(cb))\n\n    const notifyManagerTest = createNotifyManager()\n    const notifySpy = vi.fn()\n    notifyManagerTest.setScheduler(customCallback)\n    notifyManagerTest.setNotifyFunction(notifySpy)\n\n    notifyManagerTest.batch(() => notifyManagerTest.schedule(vi.fn))\n\n    expect(customCallback).toHaveBeenCalledOnce()\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(notifySpy).toHaveBeenCalledTimes(1)\n  })\n\n  it('should notify if error is thrown', async () => {\n    const notifyManagerTest = createNotifyManager()\n    const notifySpy = vi.fn()\n\n    notifyManagerTest.setNotifyFunction(notifySpy)\n\n    try {\n      notifyManagerTest.batch(() => {\n        notifyManagerTest.schedule(vi.fn)\n        throw new Error('Foo')\n      })\n    } catch {}\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(notifySpy).toHaveBeenCalledTimes(1)\n  })\n\n  it('typeDefs should catch proper signatures', () => {\n    const notifyManagerTest = createNotifyManager()\n\n    // we define some fn with its signature:\n    const fn: (a: string, b: number) => string = (a, b) => a + b\n\n    // now someFn expect to be called with args [a: string, b: number]\n    const someFn = notifyManagerTest.batchCalls(fn)\n\n    expectTypeOf(someFn).parameters.toEqualTypeOf<Parameters<typeof fn>>()\n    assertType<Parameters<typeof someFn>>(['im happy', 4])\n    assertType<Parameters<typeof someFn>>([\n      'im not happy',\n      // @ts-expect-error\n      false,\n    ])\n  })\n\n  it('should use custom batch notify function', async () => {\n    const notifyManagerTest = createNotifyManager()\n    const batchNotifySpy = vi.fn((cb) => cb())\n    const callbackSpy1 = vi.fn()\n    const callbackSpy2 = vi.fn()\n\n    notifyManagerTest.setBatchNotifyFunction(batchNotifySpy)\n\n    notifyManagerTest.batch(() => {\n      notifyManagerTest.schedule(callbackSpy1)\n      notifyManagerTest.schedule(callbackSpy2)\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(batchNotifySpy).toHaveBeenCalled()\n    expect(callbackSpy1).toHaveBeenCalled()\n    expect(callbackSpy2).toHaveBeenCalled()\n  })\n\n  it('should batch calls correctly', async () => {\n    const notifyManagerTest = createNotifyManager()\n    const callbackSpy = vi.fn()\n\n    const batchedFn = notifyManagerTest.batchCalls((a: number, b: string) => {\n      callbackSpy(a, b)\n    })\n\n    batchedFn(1, 'test')\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(callbackSpy).toHaveBeenCalledWith(1, 'test')\n  })\n})\n"
  },
  {
    "path": "packages/query-core/src/__tests__/onlineManager.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { OnlineManager } from '../onlineManager'\n\ndescribe('onlineManager', () => {\n  let onlineManager: OnlineManager\n\n  beforeEach(() => {\n    vi.useFakeTimers()\n    onlineManager = new OnlineManager()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('isOnline should return true if navigator is undefined', () => {\n    const navigatorSpy = vi.spyOn(globalThis, 'navigator', 'get')\n\n    // Force navigator to be undefined\n    // @ts-expect-error\n    navigatorSpy.mockImplementation(() => undefined)\n    expect(onlineManager.isOnline()).toBeTruthy()\n\n    navigatorSpy.mockRestore()\n  })\n\n  test('isOnline should return true if navigator.onLine is true', () => {\n    const navigatorSpy = vi.spyOn(navigator, 'onLine', 'get')\n    navigatorSpy.mockImplementation(() => true)\n\n    expect(onlineManager.isOnline()).toBeTruthy()\n\n    navigatorSpy.mockRestore()\n  })\n\n  test('setEventListener should use online boolean arg', () => {\n    let count = 0\n\n    const setup = (setOnline: (online: boolean) => void) => {\n      setTimeout(() => {\n        count++\n        setOnline(false)\n      }, 20)\n      return () => void 0\n    }\n\n    onlineManager.setEventListener(setup)\n\n    vi.advanceTimersByTime(20)\n    expect(count).toEqual(1)\n    expect(onlineManager.isOnline()).toBeFalsy()\n  })\n\n  test('setEventListener should call previous remove handler when replacing an event listener', () => {\n    const remove1Spy = vi.fn()\n    const remove2Spy = vi.fn()\n\n    onlineManager.setEventListener(() => remove1Spy)\n    onlineManager.setEventListener(() => remove2Spy)\n\n    expect(remove1Spy).toHaveBeenCalledTimes(1)\n    expect(remove2Spy).not.toHaveBeenCalled()\n  })\n\n  test('cleanup (removeEventListener) should not be called if window is not defined', () => {\n    const windowSpy = vi.spyOn(globalThis, 'window', 'get')\n    windowSpy.mockImplementation(\n      () => undefined as unknown as Window & typeof globalThis,\n    )\n    const removeEventListenerSpy = vi.spyOn(globalThis, 'removeEventListener')\n\n    const unsubscribe = onlineManager.subscribe(() => undefined)\n    expect(unsubscribe).toBeInstanceOf(Function)\n\n    unsubscribe()\n\n    expect(removeEventListenerSpy).not.toHaveBeenCalled()\n\n    windowSpy.mockRestore()\n  })\n\n  test('cleanup (removeEventListener) should not be called if window.addEventListener is not defined', () => {\n    const { addEventListener } = globalThis.window\n\n    // @ts-expect-error\n    globalThis.window.addEventListener = undefined\n\n    const removeEventListenerSpy = vi.spyOn(globalThis, 'removeEventListener')\n\n    const unsubscribe = onlineManager.subscribe(() => undefined)\n\n    unsubscribe()\n\n    expect(removeEventListenerSpy).not.toHaveBeenCalled()\n\n    globalThis.window.addEventListener = addEventListener\n  })\n\n  test('it should replace default window listener when a new event listener is set', () => {\n    const addEventListenerSpy = vi.spyOn(globalThis.window, 'addEventListener')\n\n    const removeEventListenerSpy = vi.spyOn(\n      globalThis.window,\n      'removeEventListener',\n    )\n\n    // Should set the default event listener with window event listeners\n    const unsubscribe = onlineManager.subscribe(() => undefined)\n    expect(addEventListenerSpy).toHaveBeenCalledTimes(2)\n\n    // Should replace the window default event listener by a new one\n    // and it should call window.removeEventListener twice\n    onlineManager.setEventListener(() => {\n      return () => void 0\n    })\n\n    expect(removeEventListenerSpy).toHaveBeenCalledTimes(2)\n\n    unsubscribe()\n    addEventListenerSpy.mockRestore()\n    removeEventListenerSpy.mockRestore()\n  })\n\n  test('should call removeEventListener when last listener unsubscribes', () => {\n    const addEventListenerSpy = vi.spyOn(globalThis.window, 'addEventListener')\n\n    const removeEventListenerSpy = vi.spyOn(\n      globalThis.window,\n      'removeEventListener',\n    )\n\n    const unsubscribe1 = onlineManager.subscribe(() => undefined)\n    const unsubscribe2 = onlineManager.subscribe(() => undefined)\n    expect(addEventListenerSpy).toHaveBeenCalledTimes(2) // online + offline\n\n    unsubscribe1()\n    expect(removeEventListenerSpy).toHaveBeenCalledTimes(0)\n    unsubscribe2()\n    expect(removeEventListenerSpy).toHaveBeenCalledTimes(2) // online + offline\n  })\n\n  test('should keep setup function even if last listener unsubscribes', () => {\n    const setupSpy = vi.fn().mockImplementation(() => () => undefined)\n\n    onlineManager.setEventListener(setupSpy)\n\n    const unsubscribe1 = onlineManager.subscribe(() => undefined)\n\n    expect(setupSpy).toHaveBeenCalledTimes(1)\n\n    unsubscribe1()\n\n    const unsubscribe2 = onlineManager.subscribe(() => undefined)\n\n    expect(setupSpy).toHaveBeenCalledTimes(2)\n\n    unsubscribe2()\n  })\n\n  test('should call listeners when setOnline is called', () => {\n    const listener = vi.fn()\n\n    onlineManager.subscribe(listener)\n\n    onlineManager.setOnline(false)\n    onlineManager.setOnline(false)\n\n    expect(listener).toHaveBeenNthCalledWith(1, false)\n\n    onlineManager.setOnline(true)\n    onlineManager.setOnline(true)\n\n    expect(listener).toHaveBeenCalledTimes(2)\n    expect(listener).toHaveBeenNthCalledWith(2, true)\n  })\n})\n"
  },
  {
    "path": "packages/query-core/src/__tests__/queriesObserver.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { QueriesObserver, QueryClient, QueryObserver } from '..'\nimport type { QueryObserverResult } from '..'\n\ndescribe('queriesObserver', () => {\n  let queryClient: QueryClient\n\n  beforeEach(() => {\n    vi.useFakeTimers()\n    queryClient = new QueryClient()\n    queryClient.mount()\n  })\n\n  afterEach(() => {\n    queryClient.clear()\n    vi.useRealTimers()\n  })\n\n  test('should return an array with all query results', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const queryFn1 = vi.fn().mockReturnValue(1)\n    const queryFn2 = vi.fn().mockReturnValue(2)\n    const observer = new QueriesObserver(queryClient, [\n      { queryKey: key1, queryFn: queryFn1 },\n      { queryKey: key2, queryFn: queryFn2 },\n    ])\n    let observerResult\n    const unsubscribe = observer.subscribe((result) => {\n      observerResult = result\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    unsubscribe()\n\n    expect(observerResult).toMatchObject([{ data: 1 }, { data: 2 }])\n  })\n\n  test('should return current queries via getQueries', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const queryFn1 = vi.fn().mockReturnValue(1)\n    const queryFn2 = vi.fn().mockReturnValue(2)\n    const observer = new QueriesObserver(queryClient, [\n      { queryKey: key1, queryFn: queryFn1 },\n      { queryKey: key2, queryFn: queryFn2 },\n    ])\n    const unsubscribe = observer.subscribe(() => undefined)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    const queries = observer.getQueries()\n\n    expect(queries).toHaveLength(2)\n    expect(queries[0]?.queryKey).toEqual(key1)\n    expect(queries[1]?.queryKey).toEqual(key2)\n\n    unsubscribe()\n  })\n\n  test('should update when a query updates', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const queryFn1 = vi.fn().mockReturnValue(1)\n    const queryFn2 = vi.fn().mockReturnValue(2)\n    const observer = new QueriesObserver(queryClient, [\n      { queryKey: key1, queryFn: queryFn1 },\n      { queryKey: key2, queryFn: queryFn2 },\n    ])\n    const results: Array<Array<QueryObserverResult>> = []\n    results.push(observer.getCurrentResult())\n    const unsubscribe = observer.subscribe((result) => {\n      results.push(result)\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n    queryClient.setQueryData(key2, 3)\n    unsubscribe()\n\n    expect(results.length).toBe(6)\n    expect(results[0]).toMatchObject([\n      { status: 'pending', fetchStatus: 'idle', data: undefined },\n      { status: 'pending', fetchStatus: 'idle', data: undefined },\n    ])\n    expect(results[1]).toMatchObject([\n      { status: 'pending', fetchStatus: 'fetching', data: undefined },\n      { status: 'pending', fetchStatus: 'idle', data: undefined },\n    ])\n    expect(results[2]).toMatchObject([\n      { status: 'pending', fetchStatus: 'fetching', data: undefined },\n      { status: 'pending', fetchStatus: 'fetching', data: undefined },\n    ])\n    expect(results[3]).toMatchObject([\n      { status: 'success', data: 1 },\n      { status: 'pending', fetchStatus: 'fetching', data: undefined },\n    ])\n    expect(results[4]).toMatchObject([\n      { status: 'success', data: 1 },\n      { status: 'success', data: 2 },\n    ])\n    expect(results[5]).toMatchObject([\n      { status: 'success', data: 1 },\n      { status: 'success', data: 3 },\n    ])\n  })\n\n  test('should return current observers via getObservers', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const queryFn1 = vi.fn().mockReturnValue(1)\n    const queryFn2 = vi.fn().mockReturnValue(2)\n    const observer = new QueriesObserver(queryClient, [\n      { queryKey: key1, queryFn: queryFn1 },\n      { queryKey: key2, queryFn: queryFn2 },\n    ])\n    const unsubscribe = observer.subscribe(() => undefined)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    const observers = observer.getObservers()\n\n    expect(observers).toHaveLength(2)\n    expect(observers[0]).toBeInstanceOf(QueryObserver)\n    expect(observers[1]).toBeInstanceOf(QueryObserver)\n\n    unsubscribe()\n  })\n\n  test('should update when a query is removed', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const queryFn1 = vi.fn().mockReturnValue(1)\n    const queryFn2 = vi.fn().mockReturnValue(2)\n    const observer = new QueriesObserver(queryClient, [\n      { queryKey: key1, queryFn: queryFn1 },\n      { queryKey: key2, queryFn: queryFn2 },\n    ])\n    const results: Array<Array<QueryObserverResult>> = []\n    results.push(observer.getCurrentResult())\n    const unsubscribe = observer.subscribe((result) => {\n      results.push(result)\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n    observer.setQueries([{ queryKey: key2, queryFn: queryFn2 }])\n\n    const queryCache = queryClient.getQueryCache()\n\n    expect(queryCache.find({ queryKey: key1, type: 'active' })).toBeUndefined()\n    expect(queryCache.find({ queryKey: key2, type: 'active' })).toBeDefined()\n    unsubscribe()\n    expect(queryCache.find({ queryKey: key1, type: 'active' })).toBeUndefined()\n    expect(queryCache.find({ queryKey: key2, type: 'active' })).toBeUndefined()\n    expect(results.length).toBe(6)\n    expect(results[0]).toMatchObject([\n      { status: 'pending', fetchStatus: 'idle', data: undefined },\n      { status: 'pending', fetchStatus: 'idle', data: undefined },\n    ])\n    expect(results[1]).toMatchObject([\n      { status: 'pending', fetchStatus: 'fetching', data: undefined },\n      { status: 'pending', fetchStatus: 'idle', data: undefined },\n    ])\n    expect(results[2]).toMatchObject([\n      { status: 'pending', fetchStatus: 'fetching', data: undefined },\n      { status: 'pending', fetchStatus: 'fetching', data: undefined },\n    ])\n    expect(results[3]).toMatchObject([\n      { status: 'success', data: 1 },\n      { status: 'pending', fetchStatus: 'fetching', data: undefined },\n    ])\n    expect(results[4]).toMatchObject([\n      { status: 'success', data: 1 },\n      { status: 'success', data: 2 },\n    ])\n    expect(results[5]).toMatchObject([{ status: 'success', data: 2 }])\n  })\n\n  test('should update when a query changed position', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const queryFn1 = vi.fn().mockReturnValue(1)\n    const queryFn2 = vi.fn().mockReturnValue(2)\n    const observer = new QueriesObserver(queryClient, [\n      { queryKey: key1, queryFn: queryFn1 },\n      { queryKey: key2, queryFn: queryFn2 },\n    ])\n    const results: Array<Array<QueryObserverResult>> = []\n    results.push(observer.getCurrentResult())\n    const unsubscribe = observer.subscribe((result) => {\n      results.push(result)\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n    observer.setQueries([\n      { queryKey: key2, queryFn: queryFn2 },\n      { queryKey: key1, queryFn: queryFn1 },\n    ])\n\n    unsubscribe()\n\n    expect(results.length).toBe(6)\n    expect(results[0]).toMatchObject([\n      { status: 'pending', fetchStatus: 'idle', data: undefined },\n      { status: 'pending', fetchStatus: 'idle', data: undefined },\n    ])\n    expect(results[1]).toMatchObject([\n      { status: 'pending', fetchStatus: 'fetching', data: undefined },\n      { status: 'pending', fetchStatus: 'idle', data: undefined },\n    ])\n    expect(results[2]).toMatchObject([\n      { status: 'pending', fetchStatus: 'fetching', data: undefined },\n      { status: 'pending', fetchStatus: 'fetching', data: undefined },\n    ])\n    expect(results[3]).toMatchObject([\n      { status: 'success', data: 1 },\n      { status: 'pending', fetchStatus: 'fetching', data: undefined },\n    ])\n    expect(results[4]).toMatchObject([\n      { status: 'success', data: 1 },\n      { status: 'success', data: 2 },\n    ])\n    expect(results[5]).toMatchObject([\n      { status: 'success', data: 2 },\n      { status: 'success', data: 1 },\n    ])\n  })\n\n  test('should not update when nothing has changed', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const queryFn1 = vi.fn().mockReturnValue(1)\n    const queryFn2 = vi.fn().mockReturnValue(2)\n    const observer = new QueriesObserver(queryClient, [\n      { queryKey: key1, queryFn: queryFn1 },\n      { queryKey: key2, queryFn: queryFn2 },\n    ])\n    const results: Array<Array<QueryObserverResult>> = []\n    results.push(observer.getCurrentResult())\n    const unsubscribe = observer.subscribe((result) => {\n      results.push(result)\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n    observer.setQueries([\n      { queryKey: key1, queryFn: queryFn1 },\n      { queryKey: key2, queryFn: queryFn2 },\n    ])\n\n    unsubscribe()\n\n    expect(results.length).toBe(5)\n    expect(results[0]).toMatchObject([\n      { status: 'pending', fetchStatus: 'idle', data: undefined },\n      { status: 'pending', fetchStatus: 'idle', data: undefined },\n    ])\n    expect(results[1]).toMatchObject([\n      { status: 'pending', fetchStatus: 'fetching', data: undefined },\n      { status: 'pending', fetchStatus: 'idle', data: undefined },\n    ])\n    expect(results[2]).toMatchObject([\n      { status: 'pending', fetchStatus: 'fetching', data: undefined },\n      { status: 'pending', fetchStatus: 'fetching', data: undefined },\n    ])\n    expect(results[3]).toMatchObject([\n      { status: 'success', data: 1 },\n      { status: 'pending', fetchStatus: 'fetching', data: undefined },\n    ])\n    expect(results[4]).toMatchObject([\n      { status: 'success', data: 1 },\n      { status: 'success', data: 2 },\n    ])\n  })\n\n  test('should trigger all fetches when subscribed', () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const queryFn1 = vi.fn().mockReturnValue(1)\n    const queryFn2 = vi.fn().mockReturnValue(2)\n    const observer = new QueriesObserver(queryClient, [\n      { queryKey: key1, queryFn: queryFn1 },\n      { queryKey: key2, queryFn: queryFn2 },\n    ])\n\n    const unsubscribe = observer.subscribe(() => undefined)\n\n    unsubscribe()\n\n    expect(queryFn1).toHaveBeenCalledTimes(1)\n    expect(queryFn2).toHaveBeenCalledTimes(1)\n  })\n\n  test('should not destroy the observer if there is still a subscription', async () => {\n    const key1 = queryKey()\n    const observer = new QueriesObserver(queryClient, [\n      {\n        queryKey: key1,\n        queryFn: async () => {\n          await sleep(20)\n          return 1\n        },\n      },\n    ])\n\n    const subscription1Handler = vi.fn()\n    const subscription2Handler = vi.fn()\n\n    const unsubscribe1 = observer.subscribe(subscription1Handler)\n    const unsubscribe2 = observer.subscribe(subscription2Handler)\n\n    unsubscribe1()\n\n    await vi.advanceTimersByTimeAsync(20)\n\n    // 1 call: pending\n    expect(subscription1Handler).toBeCalledTimes(1)\n    // 1 call: success\n    expect(subscription2Handler).toBeCalledTimes(1)\n\n    // Clean-up\n    unsubscribe2()\n  })\n\n  test('should handle duplicate query keys in different positions', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const queryFn1 = vi.fn().mockReturnValue(1)\n    const queryFn2 = vi.fn().mockReturnValue(2)\n\n    const observer = new QueriesObserver(queryClient, [\n      { queryKey: key1, queryFn: queryFn1 },\n      { queryKey: key2, queryFn: queryFn2 },\n      { queryKey: key1, queryFn: queryFn1 },\n    ])\n\n    const results: Array<Array<QueryObserverResult>> = []\n\n    results.push(\n      observer.getOptimisticResult(\n        [\n          { queryKey: key1, queryFn: queryFn1 },\n          { queryKey: key2, queryFn: queryFn2 },\n          { queryKey: key1, queryFn: queryFn1 },\n        ],\n        undefined,\n      )[0],\n    )\n\n    const unsubscribe = observer.subscribe((result) => {\n      results.push(result)\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    unsubscribe()\n\n    expect(results.length).toBe(6)\n    expect(results[0]).toMatchObject([\n      { status: 'pending', fetchStatus: 'idle', data: undefined },\n      { status: 'pending', fetchStatus: 'idle', data: undefined },\n      { status: 'pending', fetchStatus: 'idle', data: undefined },\n    ])\n    expect(results[1]).toMatchObject([\n      { status: 'pending', fetchStatus: 'fetching', data: undefined },\n      { status: 'pending', fetchStatus: 'idle', data: undefined },\n      { status: 'pending', fetchStatus: 'idle', data: undefined },\n    ])\n    expect(results[2]).toMatchObject([\n      { status: 'pending', fetchStatus: 'fetching', data: undefined },\n      { status: 'pending', fetchStatus: 'fetching', data: undefined },\n      { status: 'pending', fetchStatus: 'idle', data: undefined },\n    ])\n    expect(results[3]).toMatchObject([\n      { status: 'success', fetchStatus: 'idle', data: 1 },\n      { status: 'pending', fetchStatus: 'fetching', data: undefined },\n      { status: 'pending', fetchStatus: 'idle', data: undefined },\n    ])\n    expect(results[4]).toMatchObject([\n      { status: 'success', fetchStatus: 'idle', data: 1 },\n      { status: 'pending', fetchStatus: 'fetching', data: undefined },\n      { status: 'success', fetchStatus: 'idle', data: 1 },\n    ])\n    expect(results[5]).toMatchObject([\n      { status: 'success', fetchStatus: 'idle', data: 1 },\n      { status: 'success', fetchStatus: 'idle', data: 2 },\n      { status: 'success', fetchStatus: 'idle', data: 1 },\n    ])\n\n    // Verify that queryFn1 was only called once despite being used twice\n    expect(queryFn1).toHaveBeenCalledTimes(1)\n    expect(queryFn2).toHaveBeenCalledTimes(1)\n  })\n\n  test('should notify when results change during early return', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const queryFn1 = vi.fn().mockReturnValue(1)\n    const queryFn2 = vi.fn().mockReturnValue(2)\n\n    queryClient.setQueryData(key1, 1)\n    queryClient.setQueryData(key2, 2)\n\n    const observer = new QueriesObserver(queryClient, [\n      { queryKey: key1, queryFn: queryFn1 },\n      { queryKey: key2, queryFn: queryFn2 },\n    ])\n\n    const results: Array<Array<QueryObserverResult>> = []\n    results.push(observer.getCurrentResult())\n\n    const onUpdate = vi.fn((result: Array<QueryObserverResult>) => {\n      results.push(result)\n    })\n    const unsubscribe = observer.subscribe(onUpdate)\n    const baseline = results.length\n\n    observer.setQueries([\n      {\n        queryKey: key1,\n        queryFn: queryFn1,\n        select: (d: any) => d + 100,\n      },\n      {\n        queryKey: key2,\n        queryFn: queryFn2,\n        select: (d: any) => d + 100,\n      },\n    ])\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    unsubscribe()\n\n    expect(results.length).toBeGreaterThan(baseline)\n    expect(results[results.length - 1]).toMatchObject([\n      { status: 'success', data: 101 },\n      { status: 'success', data: 102 },\n    ])\n  })\n\n  test('should update combined result when queries are added with stable combine reference', () => {\n    const combine = vi.fn((results: Array<QueryObserverResult>) => ({\n      count: results.length,\n      results,\n    }))\n\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const queryFn1 = vi.fn().mockReturnValue(1)\n    const queryFn2 = vi.fn().mockReturnValue(2)\n\n    const observer = new QueriesObserver<{\n      count: number\n      results: Array<QueryObserverResult>\n    }>(queryClient, [{ queryKey: key1, queryFn: queryFn1 }], { combine })\n\n    const [initialRaw, getInitialCombined] = observer.getOptimisticResult(\n      [{ queryKey: key1, queryFn: queryFn1 }],\n      combine,\n    )\n    const initialCombined = getInitialCombined(initialRaw)\n\n    expect(initialCombined.count).toBe(1)\n\n    const newQueries = [\n      { queryKey: key1, queryFn: queryFn1 },\n      { queryKey: key2, queryFn: queryFn2 },\n    ]\n    const [newRaw, getNewCombined] = observer.getOptimisticResult(\n      newQueries,\n      combine,\n    )\n    const newCombined = getNewCombined(newRaw)\n\n    expect(newCombined.count).toBe(2)\n  })\n\n  test('should handle queries being removed with stable combine reference', () => {\n    const combine = vi.fn((results: Array<QueryObserverResult>) => ({\n      count: results.length,\n      results,\n    }))\n\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const queryFn1 = vi.fn().mockReturnValue(1)\n    const queryFn2 = vi.fn().mockReturnValue(2)\n\n    const observer = new QueriesObserver<{\n      count: number\n      results: Array<QueryObserverResult>\n    }>(\n      queryClient,\n      [\n        { queryKey: key1, queryFn: queryFn1 },\n        { queryKey: key2, queryFn: queryFn2 },\n      ],\n      { combine },\n    )\n\n    const [initialRaw, getInitialCombined] = observer.getOptimisticResult(\n      [\n        { queryKey: key1, queryFn: queryFn1 },\n        { queryKey: key2, queryFn: queryFn2 },\n      ],\n      combine,\n    )\n    const initialCombined = getInitialCombined(initialRaw)\n\n    expect(initialCombined.count).toBe(2)\n\n    const newQueries = [{ queryKey: key1, queryFn: queryFn1 }]\n    const [newRaw, getNewCombined] = observer.getOptimisticResult(\n      newQueries,\n      combine,\n    )\n    const newCombined = getNewCombined(newRaw)\n\n    expect(newCombined.count).toBe(1)\n  })\n\n  test('should update combined result when queries are replaced with different ones (same length)', () => {\n    const combine = vi.fn((results: Array<QueryObserverResult>) => ({\n      keys: results.map((r) => r.status),\n      results,\n    }))\n\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const queryFn1 = vi.fn().mockReturnValue(1)\n    const queryFn2 = vi.fn().mockReturnValue(2)\n\n    queryClient.setQueryData(key1, 'cached-1')\n\n    const observer = new QueriesObserver<{\n      keys: Array<string>\n      results: Array<QueryObserverResult>\n    }>(queryClient, [{ queryKey: key1, queryFn: queryFn1 }], { combine })\n\n    const [initialRaw, getInitialCombined] = observer.getOptimisticResult(\n      [{ queryKey: key1, queryFn: queryFn1 }],\n      combine,\n    )\n    const initialCombined = getInitialCombined(initialRaw)\n\n    expect(initialCombined.keys).toEqual(['success'])\n\n    const [newRaw, getNewCombined] = observer.getOptimisticResult(\n      [{ queryKey: key2, queryFn: queryFn2 }],\n      combine,\n    )\n    const newCombined = getNewCombined(newRaw)\n\n    expect(newCombined.keys).toEqual(['pending'])\n  })\n\n  test('should track properties on all observers when trackResult is called', () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const queryFn1 = () => 'data1'\n    const queryFn2 = () => 'data2'\n\n    const observer = new QueriesObserver(queryClient, [\n      { queryKey: key1, queryFn: queryFn1 },\n      { queryKey: key2, queryFn: queryFn2 },\n    ])\n\n    const trackPropSpy = vi.spyOn(QueryObserver.prototype, 'trackProp')\n\n    const [, , trackResult] = observer.getOptimisticResult(\n      [\n        { queryKey: key1, queryFn: queryFn1 },\n        { queryKey: key2, queryFn: queryFn2 },\n      ],\n      undefined,\n    )\n\n    const trackedResults = trackResult()\n\n    expect(trackedResults).toHaveLength(2)\n\n    // Accessing a property on the first result should trigger trackProp on all observers\n    void trackedResults[0]!.status\n\n    // 1 direct call from the accessed observer's proxy +\n    // 2 synchronized calls from onPropTracked callback (one per observer)\n    expect(trackPropSpy).toHaveBeenCalledWith('status')\n    expect(trackPropSpy).toHaveBeenCalledTimes(3)\n\n    trackPropSpy.mockRestore()\n  })\n\n  test('should subscribe to new observers when a query is added while subscribed', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const key3 = queryKey()\n    const queryFn1 = vi.fn().mockReturnValue(1)\n    const queryFn2 = vi.fn().mockReturnValue(2)\n    const queryFn3 = vi.fn(() => sleep(10).then(() => 3))\n    const observer = new QueriesObserver(queryClient, [\n      { queryKey: key1, queryFn: queryFn1 },\n      { queryKey: key2, queryFn: queryFn2 },\n    ])\n    const results: Array<Array<QueryObserverResult>> = []\n    const unsubscribe = observer.subscribe((result) => {\n      results.push(result)\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(results[results.length - 1]).toMatchObject([\n      { status: 'success', data: 1 },\n      { status: 'success', data: 2 },\n    ])\n\n    observer.setQueries([\n      { queryKey: key1, queryFn: queryFn1 },\n      { queryKey: key2, queryFn: queryFn2 },\n      { queryKey: key3, queryFn: queryFn3 },\n    ])\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    unsubscribe()\n\n    expect(results[results.length - 1]).toMatchObject([\n      { status: 'success', data: 1 },\n      { status: 'success', data: 2 },\n      { status: 'success', data: 3 },\n    ])\n  })\n})\n"
  },
  {
    "path": "packages/query-core/src/__tests__/query.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, test, vi } from 'vitest'\nimport {\n  mockVisibilityState,\n  queryKey,\n  sleep,\n} from '@tanstack/query-test-utils'\nimport {\n  CancelledError,\n  Query,\n  QueryClient,\n  QueryObserver,\n  dehydrate,\n  hydrate,\n} from '..'\nimport { hashQueryKeyByOptions } from '../utils'\nimport { mockOnlineManagerIsOnline, setIsServer } from './utils'\nimport type {\n  QueryCache,\n  QueryFunctionContext,\n  QueryKey,\n  QueryObserverResult,\n} from '..'\n\ndescribe('query', () => {\n  let queryClient: QueryClient\n  let queryCache: QueryCache\n\n  beforeEach(() => {\n    vi.useFakeTimers()\n    queryClient = new QueryClient()\n    queryCache = queryClient.getQueryCache()\n    queryClient.mount()\n  })\n\n  afterEach(() => {\n    queryClient.clear()\n    vi.useRealTimers()\n  })\n\n  test('should use the longest garbage collection time it has seen', async () => {\n    const key = queryKey()\n    await queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => 'data',\n      gcTime: 100,\n    })\n    await queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => 'data',\n      gcTime: 200,\n    })\n    await queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => 'data',\n      gcTime: 10,\n    })\n    const query = queryCache.find({ queryKey: key })!\n    expect(query.gcTime).toBe(200)\n  })\n\n  it('should continue retry after focus regain and resolve all promises', async () => {\n    const key = queryKey()\n\n    // make page unfocused\n    const visibilityMock = mockVisibilityState('hidden')\n\n    let count = 0\n    let result\n\n    const promise = queryClient.fetchQuery({\n      queryKey: key,\n      queryFn: () => {\n        count++\n\n        if (count === 3) {\n          return `data${count}`\n        }\n\n        throw new Error(`error${count}`)\n      },\n      retry: 3,\n      retryDelay: 1,\n    })\n\n    promise.then((data) => {\n      result = data\n    })\n\n    // Check if we do not have a result\n    expect(result).toBeUndefined()\n\n    // Check if the query is really paused\n    await vi.advanceTimersByTimeAsync(50)\n    expect(result).toBeUndefined()\n\n    // Reset visibilityState to original value\n    visibilityMock.mockRestore()\n    window.dispatchEvent(new Event('visibilitychange'))\n\n    // There should not be a result yet\n    expect(result).toBeUndefined()\n\n    // By now we should have a value\n    await vi.advanceTimersByTimeAsync(50)\n    expect(result).toBe('data3')\n  })\n\n  it('should continue retry after reconnect and resolve all promises', async () => {\n    const key = queryKey()\n\n    const onlineMock = mockOnlineManagerIsOnline(false)\n\n    let count = 0\n    let result\n\n    const promise = queryClient.fetchQuery({\n      queryKey: key,\n      queryFn: () => {\n        count++\n\n        if (count === 3) {\n          return `data${count}`\n        }\n\n        throw new Error(`error${count}`)\n      },\n      retry: 3,\n      retryDelay: 1,\n    })\n\n    promise.then((data) => {\n      result = data\n    })\n\n    // Check if we do not have a result\n    expect(result).toBeUndefined()\n\n    // Check if the query is really paused\n    await vi.advanceTimersByTimeAsync(1)\n    expect(result).toBeUndefined()\n\n    // Reset navigator to original value\n    onlineMock.mockReturnValue(true)\n    // trigger online event\n    queryClient.getQueryCache().onOnline()\n\n    // There should not be a result yet\n    expect(result).toBeUndefined()\n\n    // Promise should eventually be resolved\n    await vi.advanceTimersByTimeAsync(2)\n    expect(result).toBe('data3')\n    onlineMock.mockRestore()\n  })\n\n  it('should throw a CancelledError when a paused query is cancelled', async () => {\n    const key = queryKey()\n\n    // make page unfocused\n    const visibilityMock = mockVisibilityState('hidden')\n    let count = 0\n\n    const promise = queryClient.fetchQuery({\n      queryKey: key,\n      queryFn: (): Promise<unknown> => {\n        count++\n        throw new Error(`error${count}`)\n      },\n      retry: 3,\n      retryDelay: 1,\n    })\n\n    const query = queryCache.find({ queryKey: key })!\n\n    // Check if the query is really paused\n    await vi.advanceTimersByTimeAsync(50)\n    expect(query.state.fetchStatus).toBe('paused')\n\n    // Cancel query\n    query.cancel()\n\n    // Check if the error is set to the cancelled error\n    try {\n      await expect(promise).rejects.toBeInstanceOf(CancelledError)\n    } finally {\n      // Reset visibilityState to original value\n      visibilityMock.mockRestore()\n    }\n  })\n\n  it('should cancel a paused initial fetch when the last observer unsubscribes', async () => {\n    const key = queryKey()\n    const onlineMock = mockOnlineManagerIsOnline(false)\n    let count = 0\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: async ({ signal: _signal }) => {\n        count++\n        await sleep(10)\n        return `data${count}`\n      },\n    })\n\n    const unsubscribe = observer.subscribe(() => undefined)\n    const query = queryCache.find({ queryKey: key })!\n\n    expect(query.state).toMatchObject({\n      fetchStatus: 'paused',\n      status: 'pending',\n    })\n\n    unsubscribe()\n\n    expect(query.state).toMatchObject({\n      fetchStatus: 'idle',\n      status: 'pending',\n    })\n\n    onlineMock.mockReturnValue(true)\n    queryClient.getQueryCache().onOnline()\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(query.state).toMatchObject({\n      fetchStatus: 'idle',\n      status: 'pending',\n    })\n    expect(count).toBe(0)\n\n    onlineMock.mockRestore()\n  })\n\n  test('should not throw a CancelledError when fetchQuery is in progress and the last observer unsubscribes when AbortSignal is consumed', async () => {\n    const key = queryKey()\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: async () => {\n        await sleep(100)\n        return 'data'\n      },\n    })\n\n    const unsubscribe = observer.subscribe(() => undefined)\n    await vi.advanceTimersByTimeAsync(100)\n\n    expect(queryCache.find({ queryKey: key })?.state.data).toBe('data')\n\n    const promise = queryClient.fetchQuery({\n      queryKey: key,\n      queryFn: async ({ signal }) => {\n        await sleep(100)\n        return 'data2' + String(signal)\n      },\n    })\n\n    // Ensure the fetch is in progress\n    await vi.advanceTimersByTimeAsync(10)\n\n    // Unsubscribe while fetch is in progress\n    unsubscribe()\n    // await queryClient.cancelQueries()\n\n    await vi.advanceTimersByTimeAsync(90)\n\n    // Fetch should complete successfully without throwing a CancelledError\n    await expect(promise).resolves.toBe('data')\n\n    expect(queryCache.find({ queryKey: key })?.state.data).toBe('data')\n  })\n\n  test('should provide context to queryFn', () => {\n    const key = queryKey()\n\n    const queryFn = vi\n      .fn<\n        (\n          context: QueryFunctionContext<ReturnType<typeof queryKey>>,\n        ) => Promise<'data'>\n      >()\n      .mockResolvedValue('data')\n\n    queryClient.prefetchQuery({ queryKey: key, queryFn })\n\n    expect(queryFn).toHaveBeenCalledTimes(1)\n    const args = queryFn.mock.calls[0]![0]\n    expect(args).toBeDefined()\n    expect(args.pageParam).toBeUndefined()\n    expect(args.queryKey).toEqual(key)\n    expect(args.signal).toBeInstanceOf(AbortSignal)\n    expect(args.client).toEqual(queryClient)\n  })\n\n  test('should continue if cancellation is not supported and signal is not consumed', async () => {\n    const key = queryKey()\n\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(100).then(() => 'data'),\n    })\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    // Subscribe and unsubscribe to simulate cancellation because the last observer unsubscribed\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      enabled: false,\n    })\n    const unsubscribe = observer.subscribe(() => undefined)\n    unsubscribe()\n\n    await vi.advanceTimersByTimeAsync(90)\n\n    const query = queryCache.find({ queryKey: key })!\n\n    expect(query.state).toMatchObject({\n      data: 'data',\n      status: 'success',\n      dataUpdateCount: 1,\n    })\n  })\n\n  test('should not continue when last observer unsubscribed if the signal was consumed', async () => {\n    const key = queryKey()\n\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: async ({ signal }) => {\n        await sleep(100)\n        return signal.aborted ? 'aborted' : 'data'\n      },\n    })\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    // Subscribe and unsubscribe to simulate cancellation because the last observer unsubscribed\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      enabled: false,\n    })\n    const unsubscribe = observer.subscribe(() => undefined)\n    unsubscribe()\n\n    await vi.advanceTimersByTimeAsync(90)\n\n    const query = queryCache.find({ queryKey: key })!\n\n    expect(query.state).toMatchObject({\n      data: undefined,\n      status: 'pending',\n      fetchStatus: 'idle',\n    })\n  })\n\n  test('should provide an AbortSignal to the queryFn that provides info about the cancellation state', async () => {\n    const key = queryKey()\n\n    const queryFn =\n      vi.fn<\n        (\n          context: QueryFunctionContext<ReturnType<typeof queryKey>>,\n        ) => Promise<unknown>\n      >()\n    const onAbort = vi.fn()\n    const abortListener = vi.fn()\n    let error\n\n    queryFn.mockImplementation(async ({ signal }) => {\n      signal.onabort = onAbort\n      signal.addEventListener('abort', abortListener)\n      await sleep(10)\n      signal.onabort = null\n      signal.removeEventListener('abort', abortListener)\n      throw new Error()\n    })\n\n    const promise = queryClient.fetchQuery({\n      queryKey: key,\n      queryFn,\n      retry: 3,\n      retryDelay: 10,\n    })\n\n    promise.catch((e) => {\n      error = e\n    })\n\n    const query = queryCache.find({ queryKey: key })!\n\n    expect(queryFn).toHaveBeenCalledTimes(1)\n\n    const signal = queryFn.mock.calls[0]![0].signal\n    expect(signal.aborted).toBe(false)\n    expect(onAbort).not.toHaveBeenCalled()\n    expect(abortListener).not.toHaveBeenCalled()\n\n    query.cancel()\n\n    await vi.advanceTimersByTimeAsync(100)\n\n    expect(signal.aborted).toBe(true)\n    expect(onAbort).toHaveBeenCalledTimes(1)\n    expect(abortListener).toHaveBeenCalledTimes(1)\n    expect(error).toBeInstanceOf(CancelledError)\n  })\n\n  test('should not continue if explicitly cancelled', async () => {\n    const key = queryKey()\n\n    const queryFn = vi.fn<(...args: Array<unknown>) => unknown>()\n\n    queryFn.mockImplementation(async () => {\n      await sleep(10)\n      throw new Error()\n    })\n\n    let error\n\n    const promise = queryClient.fetchQuery({\n      queryKey: key,\n      queryFn,\n      retry: 3,\n      retryDelay: 10,\n    })\n\n    promise.catch((e) => {\n      error = e\n    })\n\n    const query = queryCache.find({ queryKey: key })!\n    query.cancel()\n\n    await vi.advanceTimersByTimeAsync(100)\n\n    expect(queryFn).toHaveBeenCalledTimes(1)\n    expect(error).toBeInstanceOf(CancelledError)\n  })\n\n  test('should not error if reset while pending', async () => {\n    const key = queryKey()\n\n    const queryFn = vi.fn<(...args: Array<unknown>) => unknown>()\n\n    queryFn.mockImplementation(async () => {\n      await sleep(10)\n      throw new Error()\n    })\n\n    let error\n\n    queryClient\n      .fetchQuery({\n        queryKey: key,\n        queryFn,\n        retry: 3,\n        retryDelay: 10,\n      })\n      .catch((e) => {\n        error = e\n      })\n\n    // Ensure the query is pending\n    const query = queryCache.find({ queryKey: key })!\n    expect(query.state.status).toBe('pending')\n\n    // Reset the query while it is pending\n    query.reset()\n\n    await vi.advanceTimersByTimeAsync(100)\n\n    // The query should\n    expect(queryFn).toHaveBeenCalledTimes(1) // have been called,\n    expect(query.state.error).toBe(null) // not have an error, and\n    expect(query.state.fetchStatus).toBe('idle') // not be loading any longer\n    expect(query.state.data).toBe(undefined) // have no data\n\n    // the call to fetchQuery must reject\n    // because it was reset and not reverted\n    // so it would resolve with undefined otherwise\n    expect(error).toBeInstanceOf(CancelledError)\n  })\n\n  test('should reset to default state when created from hydration', async () => {\n    const client = new QueryClient()\n    await client.prefetchQuery({\n      queryKey: ['string'],\n      queryFn: () => Promise.resolve('string'),\n    })\n\n    const dehydrated = dehydrate(client)\n\n    const hydrationClient = new QueryClient()\n    hydrate(hydrationClient, dehydrated)\n\n    expect(hydrationClient.getQueryData(['string'])).toBe('string')\n\n    const query = hydrationClient.getQueryCache().find({ queryKey: ['string'] })\n    query?.reset()\n\n    expect(hydrationClient.getQueryData(['string'])).toBe(undefined)\n  })\n\n  test('should be able to refetch a cancelled query', async () => {\n    const key = queryKey()\n\n    const queryFn = vi.fn<(...args: Array<unknown>) => unknown>()\n\n    queryFn.mockImplementation(() => sleep(50).then(() => 'data'))\n\n    queryClient.prefetchQuery({ queryKey: key, queryFn })\n    const query = queryCache.find({ queryKey: key })!\n    await vi.advanceTimersByTimeAsync(10)\n    query.cancel()\n    await vi.advanceTimersByTimeAsync(100)\n\n    expect(queryFn).toHaveBeenCalledTimes(1)\n    expect(query.state.error).toBeInstanceOf(CancelledError)\n    const result = query.fetch()\n    await vi.advanceTimersByTimeAsync(50)\n    await expect(result).resolves.toBe('data')\n    expect(query.state.error).toBe(null)\n    expect(queryFn).toHaveBeenCalledTimes(2)\n  })\n\n  test('cancelling a resolved query should not have any effect', async () => {\n    const key = queryKey()\n    await queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => 'data',\n    })\n    const query = queryCache.find({ queryKey: key })!\n    query.cancel()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(query.state.data).toBe('data')\n  })\n\n  test('cancelling a rejected query should not have any effect', async () => {\n    const key = queryKey()\n    const error = new Error('error')\n\n    await queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => Promise.reject(error),\n    })\n    const query = queryCache.find({ queryKey: key })!\n    query.cancel()\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(query.state.error).toBe(error)\n    expect(query.state.error).not.toBeInstanceOf(CancelledError)\n  })\n\n  test('the previous query status should be kept when refetching', async () => {\n    const key = queryKey()\n\n    await queryClient.prefetchQuery({ queryKey: key, queryFn: () => 'data' })\n    const query = queryCache.find({ queryKey: key })!\n    expect(query.state.status).toBe('success')\n\n    await queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => Promise.reject<string>('reject'),\n      retry: false,\n    })\n    expect(query.state.status).toBe('error')\n\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => Promise.reject<unknown>('reject')),\n      retry: false,\n    })\n    expect(query.state.status).toBe('error')\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(query.state.status).toBe('error')\n  })\n\n  test('queries with gcTime 0 should be removed immediately after unsubscribing', async () => {\n    const key = queryKey()\n    let count = 0\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => {\n        count++\n        return 'data'\n      },\n      gcTime: 0,\n      staleTime: Infinity,\n    })\n    const unsubscribe1 = observer.subscribe(() => undefined)\n    unsubscribe1()\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(queryCache.find({ queryKey: key })).toBeUndefined()\n    const unsubscribe2 = observer.subscribe(() => undefined)\n    unsubscribe2()\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(queryCache.find({ queryKey: key })).toBeUndefined()\n    expect(count).toBe(1)\n  })\n\n  test('should be garbage collected when unsubscribed to', async () => {\n    const key = queryKey()\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => 'data',\n      gcTime: 0,\n    })\n    expect(queryCache.find({ queryKey: key })).toBeDefined()\n    const unsubscribe = observer.subscribe(() => undefined)\n    expect(queryCache.find({ queryKey: key })).toBeDefined()\n    unsubscribe()\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(queryCache.find({ queryKey: key })).toBeUndefined()\n  })\n\n  test('should be garbage collected later when unsubscribed and query is fetching', async () => {\n    const key = queryKey()\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => sleep(20).then(() => 'data'),\n      gcTime: 10,\n    })\n    const unsubscribe = observer.subscribe(() => undefined)\n    await vi.advanceTimersByTimeAsync(20)\n    expect(queryCache.find({ queryKey: key })).toBeDefined()\n    observer.refetch()\n    unsubscribe()\n    // unsubscribe should not remove even though gcTime has elapsed b/c query is still fetching\n    expect(queryCache.find({ queryKey: key })).toBeDefined()\n    // should be removed after an additional staleTime wait\n    await vi.advanceTimersByTimeAsync(30)\n    expect(queryCache.find({ queryKey: key })).toBeUndefined()\n  })\n\n  test('should not be garbage collected unless there are no subscribers', async () => {\n    const key = queryKey()\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => 'data',\n      gcTime: 0,\n    })\n    expect(queryCache.find({ queryKey: key })).toBeDefined()\n    const unsubscribe = observer.subscribe(() => undefined)\n    await vi.advanceTimersByTimeAsync(100)\n    expect(queryCache.find({ queryKey: key })).toBeDefined()\n    unsubscribe()\n    await vi.advanceTimersByTimeAsync(100)\n    expect(queryCache.find({ queryKey: key })).toBeUndefined()\n    queryClient.setQueryData(key, 'data')\n    await vi.advanceTimersByTimeAsync(100)\n    expect(queryCache.find({ queryKey: key })).toBeDefined()\n  })\n\n  test('should return proper count of observers', () => {\n    const key = queryKey()\n    const options = { queryKey: key, queryFn: () => 'data' }\n    const observer = new QueryObserver(queryClient, options)\n    const observer2 = new QueryObserver(queryClient, options)\n    const observer3 = new QueryObserver(queryClient, options)\n    const query = queryCache.find({ queryKey: key })\n\n    expect(query?.getObserversCount()).toEqual(0)\n\n    const unsubscribe1 = observer.subscribe(() => undefined)\n    const unsubscribe2 = observer2.subscribe(() => undefined)\n    const unsubscribe3 = observer3.subscribe(() => undefined)\n    expect(query?.getObserversCount()).toEqual(3)\n\n    unsubscribe3()\n    expect(query?.getObserversCount()).toEqual(2)\n\n    unsubscribe2()\n    expect(query?.getObserversCount()).toEqual(1)\n\n    unsubscribe1()\n    expect(query?.getObserversCount()).toEqual(0)\n  })\n\n  test('stores meta object in query', async () => {\n    const meta = {\n      it: 'works',\n    }\n\n    const key = queryKey()\n\n    await queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => 'data',\n      meta,\n    })\n\n    const query = queryCache.find({ queryKey: key })!\n\n    expect(query.meta).toBe(meta)\n    expect(query.options.meta).toBe(meta)\n  })\n\n  test('updates meta object on change', async () => {\n    const meta = {\n      it: 'works',\n    }\n\n    const key = queryKey()\n    const queryFn = () => 'data'\n\n    await queryClient.prefetchQuery({ queryKey: key, queryFn, meta })\n\n    await queryClient.prefetchQuery({ queryKey: key, queryFn, meta: undefined })\n\n    const query = queryCache.find({ queryKey: key })!\n\n    expect(query.meta).toBeUndefined()\n    expect(query.options.meta).toBeUndefined()\n  })\n\n  test('can use default meta', async () => {\n    const meta = {\n      it: 'works',\n    }\n\n    const key = queryKey()\n    const queryFn = () => 'data'\n\n    queryClient.setQueryDefaults(key, { meta })\n\n    await queryClient.prefetchQuery({ queryKey: key, queryFn })\n\n    const query = queryCache.find({ queryKey: key })!\n\n    expect(query.meta).toBe(meta)\n  })\n\n  test('provides meta object inside query function', async () => {\n    const meta = {\n      it: 'works',\n    }\n\n    const queryFn = vi.fn(() => 'data')\n\n    const key = queryKey()\n\n    await queryClient.prefetchQuery({ queryKey: key, queryFn, meta })\n\n    expect(queryFn).toBeCalledWith(\n      expect.objectContaining({\n        meta,\n      }),\n    )\n  })\n\n  test('should refetch the observer when online method is called', () => {\n    const key = queryKey()\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => 'data',\n    })\n\n    const refetchSpy = vi.spyOn(observer, 'refetch')\n    const unsubscribe = observer.subscribe(() => undefined)\n    queryCache.onOnline()\n\n    // Should refetch the observer\n    expect(refetchSpy).toHaveBeenCalledTimes(1)\n\n    unsubscribe()\n    refetchSpy.mockRestore()\n  })\n\n  test('should not add an existing observer', async () => {\n    const key = queryKey()\n\n    await queryClient.prefetchQuery({ queryKey: key, queryFn: () => 'data' })\n    const query = queryCache.find({ queryKey: key })!\n    expect(query.getObserversCount()).toEqual(0)\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n    })\n    expect(query.getObserversCount()).toEqual(0)\n\n    query.addObserver(observer)\n    expect(query.getObserversCount()).toEqual(1)\n\n    query.addObserver(observer)\n    expect(query.getObserversCount()).toEqual(1)\n  })\n\n  test('should not try to remove an observer that does not exist', async () => {\n    const key = queryKey()\n\n    await queryClient.prefetchQuery({ queryKey: key, queryFn: () => 'data' })\n    const query = queryCache.find({ queryKey: key })!\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n    })\n    expect(query.getObserversCount()).toEqual(0)\n\n    const notifySpy = vi.spyOn(queryCache, 'notify')\n    expect(() => query.removeObserver(observer)).not.toThrow()\n    expect(notifySpy).not.toHaveBeenCalled()\n\n    notifySpy.mockRestore()\n  })\n\n  test('should not change state on invalidate() if already invalidated', async () => {\n    const key = queryKey()\n\n    await queryClient.prefetchQuery({ queryKey: key, queryFn: () => 'data' })\n    const query = queryCache.find({ queryKey: key })!\n\n    query.invalidate()\n    expect(query.state.isInvalidated).toBeTruthy()\n\n    const previousState = query.state\n\n    query.invalidate()\n\n    expect(query.state).toBe(previousState)\n  })\n\n  test('fetch should not dispatch \"fetch\" query is already fetching', async () => {\n    const key = queryKey()\n\n    const queryFn = () => sleep(10).then(() => 'data')\n\n    const updates: Array<string> = []\n\n    queryClient.prefetchQuery({ queryKey: key, queryFn })\n    await vi.advanceTimersByTimeAsync(10)\n    const query = queryCache.find({ queryKey: key })!\n\n    const unsubscribe = queryClient.getQueryCache().subscribe((event) => {\n      updates.push(event.type)\n    })\n\n    void query.fetch({\n      queryKey: key,\n      queryFn,\n    })\n\n    query.fetch({\n      queryKey: key,\n      queryFn,\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(updates).toEqual([\n      'updated', // type: 'fetch'\n      'updated', // type: 'success'\n    ])\n    unsubscribe()\n  })\n\n  test('fetch should throw an error if the queryFn is not defined', async () => {\n    const key = queryKey()\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: undefined,\n      retry: false,\n    })\n\n    const unsubscribe = observer.subscribe(() => undefined)\n\n    await vi.advanceTimersByTimeAsync(10)\n    const query = queryCache.find({ queryKey: key })!\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'error',\n      error: new Error(`Missing queryFn: '${query.queryHash}'`),\n    })\n    unsubscribe()\n  })\n\n  test('fetch should dispatch an error if the queryFn returns undefined', async () => {\n    const consoleMock = vi.spyOn(console, 'error')\n    consoleMock.mockImplementation(() => undefined)\n    const key = queryKey()\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => undefined,\n      retry: false,\n    })\n\n    let observerResult: QueryObserverResult<unknown, unknown> | undefined\n\n    const unsubscribe = observer.subscribe((result) => {\n      observerResult = result\n    })\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    const error = new Error(`${JSON.stringify(key)} data is undefined`)\n\n    expect(observerResult).toMatchObject({\n      isError: true,\n      error,\n    })\n\n    expect(consoleMock).toHaveBeenCalledWith(\n      `Query data cannot be undefined. Please make sure to return a value other than undefined from your query function. Affected query key: [\"${key}\"]`,\n    )\n    unsubscribe()\n    consoleMock.mockRestore()\n  })\n\n  it('should not retry on the server', async () => {\n    const resetIsServer = setIsServer(true)\n\n    const key = queryKey()\n    let count = 0\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => {\n        count++\n        return Promise.reject(new Error('error'))\n      },\n    })\n\n    await observer.refetch()\n\n    expect(count).toBe(1)\n\n    resetIsServer()\n  })\n\n  test('constructor should call initialDataUpdatedAt if defined as a function', async () => {\n    const key = queryKey()\n\n    const initialDataUpdatedAtSpy = vi.fn()\n\n    await queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => 'data',\n      initialData: 'initial',\n      initialDataUpdatedAt: initialDataUpdatedAtSpy,\n    })\n\n    expect(initialDataUpdatedAtSpy).toHaveBeenCalled()\n  })\n\n  test('should work with initialDataUpdatedAt set to zero', async () => {\n    const key = queryKey()\n\n    await queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => 'data',\n      staleTime: Infinity,\n      initialData: 'initial',\n      initialDataUpdatedAt: 0,\n    })\n\n    expect(queryCache.find({ queryKey: key })?.state).toMatchObject({\n      data: 'initial',\n      status: 'success',\n      dataUpdatedAt: 0,\n    })\n  })\n\n  test('queries should be garbage collected even if they never fetched', async () => {\n    const key = queryKey()\n\n    queryClient.setQueryDefaults(key, { gcTime: 10 })\n\n    const fn = vi.fn()\n\n    const unsubscribe = queryClient.getQueryCache().subscribe(fn)\n\n    queryClient.setQueryData(key, 'data')\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(fn).toHaveBeenCalledWith(\n      expect.objectContaining({\n        type: 'removed',\n      }),\n    )\n\n    expect(queryClient.getQueryCache().findAll()).toHaveLength(0)\n\n    unsubscribe()\n  })\n\n  test('should always revert to idle state (#5968)', async () => {\n    let mockedData = [1]\n\n    const key = queryKey()\n\n    const queryFn = vi\n      .fn<\n        (\n          context: QueryFunctionContext<ReturnType<typeof queryKey>>,\n        ) => Promise<unknown>\n      >()\n      .mockImplementation(\n        ({ signal }) =>\n          new Promise((resolve, reject) => {\n            const abortListener = () => {\n              clearTimeout(timerId)\n              reject(signal.reason)\n            }\n            signal.addEventListener('abort', abortListener)\n\n            const timerId = setTimeout(() => {\n              signal.removeEventListener('abort', abortListener)\n              resolve(mockedData.join(' - '))\n            }, 50)\n          }),\n      )\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn,\n    })\n    const unsubscribe = observer.subscribe(() => undefined)\n    await vi.advanceTimersByTimeAsync(50) // let it resolve\n\n    expect(observer.getCurrentResult().data).toBe('1')\n    expect(observer.getCurrentResult().fetchStatus).toBe('idle')\n\n    mockedData = [1, 2] // update \"server\" state in the background\n\n    void queryClient.invalidateQueries({ queryKey: key })\n    await vi.advanceTimersByTimeAsync(5)\n    void queryClient.invalidateQueries({ queryKey: key })\n    await vi.advanceTimersByTimeAsync(5)\n    unsubscribe() // unsubscribe to simulate unmount\n    await vi.advanceTimersByTimeAsync(5)\n\n    // reverted to previous data and idle fetchStatus\n    expect(queryCache.find({ queryKey: key })?.state).toMatchObject({\n      status: 'success',\n      data: '1',\n      fetchStatus: 'idle',\n    })\n\n    // set up a new observer to simulate a mount of new component\n    const newObserver = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn,\n    })\n    const spy = vi.fn()\n    newObserver.subscribe(({ data }) => spy(data))\n    await vi.advanceTimersByTimeAsync(60) // let it resolve\n    expect(spy).toHaveBeenCalledWith('1 - 2')\n  })\n\n  test('should not reject a promise when silently cancelled in the background', async () => {\n    const key = queryKey()\n\n    let x = 0\n\n    queryClient.setQueryData(key, 'initial')\n    const queryFn = vi.fn().mockImplementation(async () => {\n      await sleep(100)\n      return 'data' + x\n    })\n\n    const promise = queryClient.fetchQuery({\n      queryKey: key,\n      queryFn,\n    })\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(queryFn).toHaveBeenCalledTimes(1)\n\n    x = 1\n\n    // cancel ongoing re-fetches\n    void queryClient.refetchQueries({ queryKey: key }, { cancelRefetch: true })\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    // The promise should not reject\n    await vi.waitFor(() => expect(promise).resolves.toBe('data1'))\n\n    expect(queryFn).toHaveBeenCalledTimes(2)\n  })\n\n  it('should have an error log when queryFn data is not serializable', async () => {\n    const consoleMock = vi.spyOn(console, 'error')\n\n    consoleMock.mockImplementation(() => undefined)\n\n    const key = queryKey()\n\n    const queryFn = vi.fn()\n\n    const initialData = {\n      foo: 'bar',\n    }\n\n    const data = {\n      get foo(): void {\n        return this.foo\n      },\n    }\n\n    queryFn.mockImplementation(() => sleep(10).then(() => data))\n\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn,\n      initialData,\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const query = queryCache.find({ queryKey: key })!\n\n    expect(queryFn).toHaveBeenCalledTimes(1)\n\n    expect(query.state.status).toBe('error')\n    expect(\n      query.state.error?.message.includes('Maximum call stack size exceeded'),\n    ).toBeTruthy()\n\n    expect(consoleMock).toHaveBeenCalledWith(\n      expect.stringContaining(\n        'Structural sharing requires data to be JSON serializable',\n      ),\n    )\n\n    consoleMock.mockRestore()\n  })\n\n  it('should have an error status when setData has any error inside', async () => {\n    const key = queryKey()\n\n    const queryFn = vi\n      .fn<() => Promise<string>>()\n      .mockImplementation(() => sleep(10).then(() => 'data'))\n\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn,\n      structuralSharing: () => {\n        throw Error('Any error')\n      },\n    })\n\n    const query = queryCache.find({ queryKey: key })!\n\n    expect(queryFn).toHaveBeenCalledTimes(1)\n    await vi.advanceTimersByTimeAsync(10)\n    expect(query.state.status).toBe('error')\n  })\n\n  test('should use persister if provided', async () => {\n    const key = queryKey()\n\n    await queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => 'data',\n      persister: () => Promise.resolve('persisted data'),\n    })\n\n    const query = queryCache.find({ queryKey: key })!\n    expect(query.state.data).toBe('persisted data')\n  })\n\n  test('should use queryFn from observer if not provided in options', async () => {\n    const key = queryKey()\n    const queryFn = () => Promise.resolve('data')\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: queryFn,\n    })\n\n    const query = new Query({\n      client: queryClient,\n      queryKey: key,\n      queryHash: hashQueryKeyByOptions(key),\n    })\n\n    query.addObserver(observer)\n\n    await query.fetch()\n    const result = await query.state.data\n    expect(result).toBe('data')\n    expect(query.options.queryFn).toBe(queryFn)\n  })\n\n  test('should log error when queryKey is not an array', async () => {\n    const consoleMock = vi.spyOn(console, 'error')\n    const key: unknown = 'string-key'\n\n    await queryClient.prefetchQuery({\n      queryKey: key as QueryKey,\n      queryFn: () => 'data',\n    })\n\n    expect(consoleMock).toHaveBeenCalledWith(\n      \"As of v4, queryKey needs to be an Array. If you are using a string like 'repoData', please change it to an Array, e.g. ['repoData']\",\n    )\n\n    consoleMock.mockRestore()\n  })\n\n  test('should call initialData function when it is a function', () => {\n    const key = queryKey()\n    const initialDataFn = vi.fn(() => 'initial data')\n\n    const query = new Query({\n      client: queryClient,\n      queryKey: key,\n      queryHash: hashQueryKeyByOptions(key),\n      options: {\n        queryFn: () => 'data',\n        initialData: initialDataFn,\n      },\n    })\n\n    expect(initialDataFn).toHaveBeenCalledTimes(1)\n    expect(query.state.data).toBe('initial data')\n  })\n\n  test('should update initialData when Query exists without data', async () => {\n    const key = queryKey()\n    const queryFn = vi.fn(async () => {\n      await sleep(100)\n      return 'data'\n    })\n\n    const promise = queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn,\n      staleTime: 1000,\n    })\n\n    vi.advanceTimersByTime(50)\n\n    expect(queryClient.getQueryState(key)).toMatchObject({\n      data: undefined,\n      status: 'pending',\n      fetchStatus: 'fetching',\n    })\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn,\n      staleTime: 1000,\n      initialData: 'initialData',\n      initialDataUpdatedAt: 10,\n    })\n\n    const unsubscribe = observer.subscribe(vi.fn())\n\n    expect(queryClient.getQueryState(key)).toMatchObject({\n      data: 'initialData',\n      dataUpdatedAt: 10,\n      status: 'success',\n      fetchStatus: 'fetching',\n    })\n\n    vi.advanceTimersByTime(50)\n\n    await promise\n\n    expect(queryClient.getQueryState(key)).toMatchObject({\n      data: 'data',\n      status: 'success',\n      fetchStatus: 'idle',\n    })\n\n    expect(queryFn).toHaveBeenCalledTimes(1)\n\n    unsubscribe()\n\n    // resetting should get us back ot 'initialData'\n    queryClient.getQueryCache().find({ queryKey: key })!.reset()\n\n    expect(queryClient.getQueryState(key)).toMatchObject({\n      data: 'initialData',\n      status: 'success',\n      fetchStatus: 'idle',\n    })\n  })\n\n  test('should not override fetching state when revert happens after new observer subscribes', async () => {\n    const key = queryKey()\n    let count = 0\n\n    const queryFn = vi.fn(async ({ signal: _signal }) => {\n      // Destructure `signal` to intentionally consume it so observer-removal uses revert-cancel path\n      await sleep(50)\n      return 'data' + count++\n    })\n\n    const query = new Query({\n      client: queryClient,\n      queryKey: key,\n      queryHash: hashQueryKeyByOptions(key),\n      options: { queryFn },\n    })\n\n    const observer1 = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn,\n    })\n\n    query.addObserver(observer1)\n    const promise1 = query.fetch()\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    query.removeObserver(observer1)\n\n    const observer2 = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn,\n    })\n\n    query.addObserver(observer2)\n\n    query.fetch()\n\n    await expect(promise1).rejects.toBeInstanceOf(CancelledError)\n    await vi.waitFor(() => expect(query.state.fetchStatus).toBe('idle'))\n\n    expect(queryFn).toHaveBeenCalledTimes(2)\n\n    expect(query.state).toMatchObject({\n      fetchStatus: 'idle',\n      status: 'success',\n      data: 'data1',\n    })\n  })\n\n  test('should not increment dataUpdateCount when setting initialData on prefetched query', async () => {\n    const key = queryKey()\n    const queryFn = vi.fn().mockImplementation(() => 'fetched-data')\n\n    // First prefetch the query (creates query without data)\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn,\n    })\n\n    const query = queryCache.find({ queryKey: key })!\n    expect(query.state.data).toBeUndefined()\n    expect(query.state.dataUpdateCount).toBe(0)\n\n    // Now create an observer with initialData\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn,\n      initialData: 'initial-data',\n    })\n\n    // The query should now have the initial data but dataUpdateCount should still be 0\n    // since this was not fetched data but initial data\n    expect(query.state.data).toBe('initial-data')\n    expect(query.state.dataUpdateCount).toBe(0)\n\n    // Get the initial state as captured by the observer\n    const result = observer.getCurrentResult()\n    expect(result.data).toBe('initial-data')\n    expect(result.isFetchedAfterMount).toBe(false) // This should be false since no actual fetch occurred\n\n    // Now trigger a refetch through the observer to simulate real-world usage\n    await observer.refetch()\n\n    // After actual fetch, dataUpdateCount should increment\n    expect(query.state.dataUpdateCount).toBe(1)\n    expect(query.state.data).toBe('fetched-data')\n\n    // And isFetchedAfterMount should now be true\n    const updatedResult = observer.getCurrentResult()\n    expect(updatedResult.isFetchedAfterMount).toBe(true)\n  })\n})\n"
  },
  {
    "path": "packages/query-core/src/__tests__/queryCache.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { QueryCache, QueryClient, QueryObserver, hashKey } from '..'\n\ndescribe('queryCache', () => {\n  let queryClient: QueryClient\n  let queryCache: QueryCache\n\n  beforeEach(() => {\n    vi.useFakeTimers()\n    queryClient = new QueryClient()\n    queryCache = queryClient.getQueryCache()\n  })\n\n  afterEach(() => {\n    queryClient.clear()\n    vi.useRealTimers()\n  })\n\n  describe('subscribe', () => {\n    test('should pass the correct query', () => {\n      const key = queryKey()\n      const subscriber = vi.fn()\n      const unsubscribe = queryCache.subscribe(subscriber)\n      queryClient.setQueryData(key, 'foo')\n      const query = queryCache.find({ queryKey: key })\n      expect(subscriber).toHaveBeenCalledWith({ query, type: 'added' })\n      unsubscribe()\n    })\n\n    test('should notify listeners when new query is added', async () => {\n      const key = queryKey()\n      const callback = vi.fn()\n      queryCache.subscribe(callback)\n      queryClient.prefetchQuery({\n        queryKey: key,\n        queryFn: () => sleep(100).then(() => 'data'),\n      })\n      await vi.advanceTimersByTimeAsync(100)\n      expect(callback).toHaveBeenCalled()\n    })\n\n    test('should notify query cache when a query becomes stale', async () => {\n      const key = queryKey()\n      const events: Array<string> = []\n      const queries: Array<unknown> = []\n      const unsubscribe = queryCache.subscribe((event) => {\n        events.push(event.type)\n        queries.push(event.query)\n      })\n\n      const observer = new QueryObserver(queryClient, {\n        queryKey: key,\n        queryFn: () => 'data',\n        staleTime: 10,\n      })\n\n      const unsubScribeObserver = observer.subscribe(vi.fn())\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(events.length).toBe(8)\n\n      expect(events).toEqual([\n        'added', // 1. Query added -> loading\n        'observerResultsUpdated', // 2. Observer result updated -> loading\n        'observerAdded', // 3. Observer added\n        'observerResultsUpdated', // 4. Observer result updated -> fetching\n        'updated', // 5. Query updated -> fetching\n        'observerResultsUpdated', // 6. Observer result updated -> success\n        'updated', // 7. Query updated -> success\n        'observerResultsUpdated', // 8. Observer result updated -> stale\n      ])\n\n      queries.forEach((query) => {\n        expect(query).toBeDefined()\n      })\n\n      unsubscribe()\n      unsubScribeObserver()\n    })\n\n    test('should include the queryCache and query when notifying listeners', async () => {\n      const key = queryKey()\n      const callback = vi.fn()\n      queryCache.subscribe(callback)\n      queryClient.prefetchQuery({\n        queryKey: key,\n        queryFn: () => sleep(100).then(() => 'data'),\n      })\n      await vi.advanceTimersByTimeAsync(100)\n      const query = queryCache.find({ queryKey: key })\n      expect(callback).toHaveBeenCalledWith({ query, type: 'added' })\n    })\n\n    test('should notify subscribers when new query with initialData is added', async () => {\n      const key = queryKey()\n      const callback = vi.fn()\n      queryCache.subscribe(callback)\n      queryClient.prefetchQuery({\n        queryKey: key,\n        queryFn: () => sleep(100).then(() => 'data'),\n        initialData: 'initial',\n      })\n      await vi.advanceTimersByTimeAsync(100)\n      expect(callback).toHaveBeenCalled()\n    })\n\n    test('should be able to limit cache size', async () => {\n      const testCache = new QueryCache()\n\n      const unsubscribe = testCache.subscribe((event) => {\n        if (event.type === 'added') {\n          if (testCache.getAll().length > 2) {\n            testCache\n              .findAll({\n                type: 'inactive',\n                predicate: (q) => q !== event.query,\n              })\n              .forEach((query) => {\n                testCache.remove(query)\n              })\n          }\n        }\n      })\n\n      const testClient = new QueryClient({ queryCache: testCache })\n\n      testClient.prefetchQuery({\n        queryKey: ['key1'],\n        queryFn: () => sleep(100).then(() => 'data1'),\n      })\n      expect(testCache.findAll().length).toBe(1)\n      testClient.prefetchQuery({\n        queryKey: ['key2'],\n        queryFn: () => sleep(100).then(() => 'data2'),\n      })\n      expect(testCache.findAll().length).toBe(2)\n      testClient.prefetchQuery({\n        queryKey: ['key3'],\n        queryFn: () => sleep(100).then(() => 'data3'),\n      })\n      await vi.advanceTimersByTimeAsync(100)\n      expect(testCache.findAll().length).toBe(1)\n      expect(testCache.findAll()[0]!.state.data).toBe('data3')\n\n      unsubscribe()\n    })\n  })\n\n  describe('find', () => {\n    test('find should filter correctly', async () => {\n      const key = queryKey()\n      queryClient.prefetchQuery({\n        queryKey: key,\n        queryFn: () => sleep(100).then(() => 'data1'),\n      })\n      await vi.advanceTimersByTimeAsync(100)\n      const query = queryCache.find({ queryKey: key })!\n      expect(query).toBeDefined()\n    })\n\n    test('find should filter correctly with exact set to false', async () => {\n      const key = queryKey()\n      queryClient.prefetchQuery({\n        queryKey: key,\n        queryFn: () => sleep(100).then(() => 'data1'),\n      })\n      await vi.advanceTimersByTimeAsync(100)\n      const query = queryCache.find({ queryKey: key, exact: false })!\n      expect(query).toBeDefined()\n    })\n  })\n\n  describe('findAll', () => {\n    test('should filter correctly', async () => {\n      const key1 = queryKey()\n      const key2 = queryKey()\n      const keyFetching = queryKey()\n      queryClient.prefetchQuery({\n        queryKey: key1,\n        queryFn: () => sleep(100).then(() => 'data1'),\n      })\n      queryClient.prefetchQuery({\n        queryKey: key2,\n        queryFn: () => sleep(100).then(() => 'data2'),\n      })\n      queryClient.prefetchQuery({\n        queryKey: [{ a: 'a', b: 'b' }],\n        queryFn: () => sleep(100).then(() => 'data3'),\n      })\n      queryClient.prefetchQuery({\n        queryKey: ['posts', 1],\n        queryFn: () => sleep(100).then(() => 'data4'),\n      })\n      await vi.advanceTimersByTimeAsync(100)\n      queryClient.invalidateQueries({ queryKey: key2 })\n      const query1 = queryCache.find({ queryKey: key1 })!\n      const query2 = queryCache.find({ queryKey: key2 })!\n      const query3 = queryCache.find({ queryKey: [{ a: 'a', b: 'b' }] })!\n      const query4 = queryCache.find({ queryKey: ['posts', 1] })!\n\n      expect(queryCache.findAll({ queryKey: key1 })).toEqual([query1])\n      // wrapping in an extra array doesn't yield the same results anymore since v4 because keys need to be an array\n      expect(queryCache.findAll({ queryKey: [key1] })).toEqual([])\n      expect(queryCache.findAll()).toEqual([query1, query2, query3, query4])\n      expect(queryCache.findAll({})).toEqual([query1, query2, query3, query4])\n      expect(queryCache.findAll({ queryKey: key1, type: 'inactive' })).toEqual([\n        query1,\n      ])\n      expect(queryCache.findAll({ queryKey: key1, type: 'active' })).toEqual([])\n      expect(queryCache.findAll({ queryKey: key1, stale: true })).toEqual([])\n      expect(queryCache.findAll({ queryKey: key1, stale: false })).toEqual([\n        query1,\n      ])\n      expect(\n        queryCache.findAll({ queryKey: key1, stale: false, type: 'active' }),\n      ).toEqual([])\n      expect(\n        queryCache.findAll({\n          queryKey: key1,\n          stale: false,\n          type: 'inactive',\n        }),\n      ).toEqual([query1])\n      expect(\n        queryCache.findAll({\n          queryKey: key1,\n          stale: false,\n          type: 'inactive',\n          exact: true,\n        }),\n      ).toEqual([query1])\n\n      expect(queryCache.findAll({ queryKey: key2 })).toEqual([query2])\n      expect(queryCache.findAll({ queryKey: key2, stale: undefined })).toEqual([\n        query2,\n      ])\n      expect(queryCache.findAll({ queryKey: key2, stale: true })).toEqual([\n        query2,\n      ])\n      expect(queryCache.findAll({ queryKey: key2, stale: false })).toEqual([])\n      expect(queryCache.findAll({ queryKey: [{ b: 'b' }] })).toEqual([query3])\n      expect(\n        queryCache.findAll({ queryKey: [{ a: 'a' }], exact: false }),\n      ).toEqual([query3])\n      expect(\n        queryCache.findAll({ queryKey: [{ a: 'a' }], exact: true }),\n      ).toEqual([])\n      expect(\n        queryCache.findAll({ queryKey: [{ a: 'a', b: 'b' }], exact: true }),\n      ).toEqual([query3])\n      expect(queryCache.findAll({ queryKey: [{ a: 'a', b: 'b' }] })).toEqual([\n        query3,\n      ])\n      expect(\n        queryCache.findAll({ queryKey: [{ a: 'a', b: 'b', c: 'c' }] }),\n      ).toEqual([])\n      expect(\n        queryCache.findAll({ queryKey: [{ a: 'a' }], stale: false }),\n      ).toEqual([query3])\n      expect(\n        queryCache.findAll({ queryKey: [{ a: 'a' }], stale: true }),\n      ).toEqual([])\n      expect(\n        queryCache.findAll({ queryKey: [{ a: 'a' }], type: 'active' }),\n      ).toEqual([])\n      expect(\n        queryCache.findAll({ queryKey: [{ a: 'a' }], type: 'inactive' }),\n      ).toEqual([query3])\n      expect(\n        queryCache.findAll({ predicate: (query) => query === query3 }),\n      ).toEqual([query3])\n      expect(queryCache.findAll({ queryKey: ['posts'] })).toEqual([query4])\n\n      expect(queryCache.findAll({ fetchStatus: 'idle' })).toEqual([\n        query1,\n        query2,\n        query3,\n        query4,\n      ])\n      expect(\n        queryCache.findAll({ queryKey: key2, fetchStatus: undefined }),\n      ).toEqual([query2])\n\n      queryClient.prefetchQuery({\n        queryKey: keyFetching,\n        queryFn: () => sleep(20).then(() => 'dataFetching'),\n      })\n      expect(queryCache.findAll({ fetchStatus: 'fetching' })).toEqual([\n        queryCache.find({ queryKey: keyFetching }),\n      ])\n      await vi.advanceTimersByTimeAsync(20)\n      expect(queryCache.findAll({ fetchStatus: 'fetching' })).toEqual([])\n    })\n\n    test('should return all the queries when no filters are defined', async () => {\n      const key1 = queryKey()\n      const key2 = queryKey()\n      await queryClient.prefetchQuery({\n        queryKey: key1,\n        queryFn: () => 'data1',\n      })\n      await queryClient.prefetchQuery({\n        queryKey: key2,\n        queryFn: () => 'data2',\n      })\n      expect(queryCache.findAll().length).toBe(2)\n    })\n  })\n\n  describe('QueryCacheConfig error callbacks', () => {\n    test('should call onError and onSettled when a query errors', async () => {\n      const key = queryKey()\n      const onSuccess = vi.fn()\n      const onSettled = vi.fn()\n      const onError = vi.fn()\n      const testCache = new QueryCache({ onSuccess, onError, onSettled })\n      const testClient = new QueryClient({ queryCache: testCache })\n      testClient.prefetchQuery({\n        queryKey: key,\n        queryFn: () => sleep(100).then(() => Promise.reject<unknown>('error')),\n      })\n      await vi.advanceTimersByTimeAsync(100)\n      const query = testCache.find({ queryKey: key })\n      expect(onError).toHaveBeenCalledWith('error', query)\n      expect(onError).toHaveBeenCalledTimes(1)\n      expect(onSuccess).not.toHaveBeenCalled()\n      expect(onSettled).toHaveBeenCalledTimes(1)\n      expect(onSettled).toHaveBeenCalledWith(undefined, 'error', query)\n    })\n  })\n\n  describe('QueryCacheConfig success callbacks', () => {\n    test('should call onSuccess and onSettled when a query is successful', async () => {\n      const key = queryKey()\n      const onSuccess = vi.fn()\n      const onSettled = vi.fn()\n      const onError = vi.fn()\n      const testCache = new QueryCache({ onSuccess, onError, onSettled })\n      const testClient = new QueryClient({ queryCache: testCache })\n      testClient.prefetchQuery({\n        queryKey: key,\n        queryFn: () => sleep(100).then(() => ({ data: 5 })),\n      })\n      await vi.advanceTimersByTimeAsync(100)\n      const query = testCache.find({ queryKey: key })\n      expect(onSuccess).toHaveBeenCalledWith({ data: 5 }, query)\n      expect(onSuccess).toHaveBeenCalledTimes(1)\n      expect(onError).not.toHaveBeenCalled()\n      expect(onSettled).toHaveBeenCalledTimes(1)\n      expect(onSettled).toHaveBeenCalledWith({ data: 5 }, null, query)\n    })\n  })\n\n  describe('build', () => {\n    test('should compute queryHash from queryKey when queryHash is not provided', () => {\n      const key = queryKey()\n\n      const query = queryCache.build(queryClient, {\n        queryKey: key,\n      })\n\n      expect(query.queryHash).toBe(hashKey(key))\n    })\n\n    test('should use provided queryHash instead of computing it', () => {\n      const key = queryKey()\n      const customHash = 'custom-hash'\n\n      const query = queryCache.build(queryClient, {\n        queryKey: key,\n        queryHash: customHash,\n      })\n\n      expect(query.queryHash).toBe(customHash)\n      expect(query.queryHash).not.toBe(hashKey(key))\n    })\n  })\n\n  describe('QueryCache.add', () => {\n    test('should not try to add a query already added to the cache', async () => {\n      const key = queryKey()\n\n      queryClient.prefetchQuery({\n        queryKey: key,\n        queryFn: () => sleep(100).then(() => 'data1'),\n      })\n      await vi.advanceTimersByTimeAsync(100)\n\n      const query = queryCache.findAll()[0]!\n      const queryClone = Object.assign({}, query)\n\n      queryCache.add(queryClone)\n      expect(queryCache.getAll().length).toEqual(1)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/query-core/src/__tests__/queryClient.test-d.tsx",
    "content": "import { assertType, describe, expectTypeOf, it } from 'vitest'\nimport { QueryClient } from '../queryClient'\nimport type { MutationFilters, QueryFilters, Updater } from '../utils'\nimport type { Mutation } from '../mutation'\nimport type { Query, QueryState } from '../query'\nimport type {\n  DataTag,\n  DefaultError,\n  DefaultedQueryObserverOptions,\n  EnsureQueryDataOptions,\n  FetchInfiniteQueryOptions,\n  InfiniteData,\n  MutationOptions,\n  OmitKeyof,\n  QueryKey,\n  QueryObserverOptions,\n} from '../types'\n\ndescribe('getQueryData', () => {\n  it('should be typed if key is tagged', () => {\n    const queryKey = ['key'] as DataTag<Array<string>, number>\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryData(queryKey)\n\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n\n  it('should infer unknown if key is not tagged', () => {\n    const queryKey = ['key'] as const\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryData(queryKey)\n\n    expectTypeOf(data).toEqualTypeOf<unknown>()\n  })\n\n  it('should infer passed generic if passed', () => {\n    const queryKey = ['key'] as const\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryData<number>(queryKey)\n\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n\n  it('should only allow Arrays to be passed', () => {\n    assertType<Parameters<QueryClient['getQueryData']>>([\n      // @ts-expect-error TS2345: Argument of type 'string' is not assignable to parameter of type 'QueryKey'\n      { queryKey: 'key' },\n    ])\n  })\n})\n\ndescribe('setQueryData', () => {\n  it('updater should be typed if key is tagged', () => {\n    const queryKey = ['key'] as DataTag<Array<string>, number>\n    const queryClient = new QueryClient()\n    const data = queryClient.setQueryData(queryKey, (prev) => {\n      expectTypeOf(prev).toEqualTypeOf<number | undefined>()\n      return prev\n    })\n\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n\n  it('value should be typed if key is tagged', () => {\n    const queryKey = ['key'] as DataTag<Array<string>, number>\n    const queryClient = new QueryClient()\n\n    // @ts-expect-error value should be a number\n    queryClient.setQueryData(queryKey, '1')\n\n    // @ts-expect-error value should be a number\n    queryClient.setQueryData(queryKey, () => '1')\n\n    const data = queryClient.setQueryData(queryKey, 1)\n\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n\n  it('should infer unknown for updater if key is not tagged', () => {\n    const queryKey = ['key'] as const\n    const queryClient = new QueryClient()\n    const data = queryClient.setQueryData(queryKey, (prev) => {\n      expectTypeOf(prev).toEqualTypeOf<unknown>()\n      return prev\n    })\n\n    expectTypeOf(data).toEqualTypeOf<unknown>()\n  })\n\n  it('should infer unknown for value if key is not tagged', () => {\n    const queryKey = ['key'] as const\n    const queryClient = new QueryClient()\n    const data = queryClient.setQueryData(queryKey, 'foo')\n\n    expectTypeOf(data).toEqualTypeOf<unknown>()\n  })\n\n  it('should infer passed generic if passed', () => {\n    const queryKey = ['key'] as const\n    const queryClient = new QueryClient()\n    const data = queryClient.setQueryData<string>(queryKey, (prev) => {\n      expectTypeOf(prev).toEqualTypeOf<string | undefined>()\n      return prev\n    })\n\n    expectTypeOf(data).toEqualTypeOf<string | undefined>()\n  })\n\n  it('should infer passed generic for value', () => {\n    const queryKey = ['key'] as const\n    const queryClient = new QueryClient()\n    const data = queryClient.setQueryData<string>(queryKey, 'foo')\n\n    expectTypeOf(data).toEqualTypeOf<string | undefined>()\n  })\n\n  it('should preserve updater parameter type inference when used in functions with explicit return types', () => {\n    const queryKey = ['key'] as DataTag<Array<string>, number>\n    const queryClient = new QueryClient()\n\n    // Simulate usage inside a function with explicit return type\n    // The outer function returns 'unknown' but this shouldn't affect the updater's type inference\n    ;(() =>\n      queryClient.setQueryData(queryKey, (data) => {\n        expectTypeOf(data).toEqualTypeOf<number | undefined>()\n        return data\n      })) satisfies () => unknown\n  })\n})\n\ndescribe('getQueryState', () => {\n  it('should be loose typed without tag', () => {\n    const queryKey = ['key'] as const\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryState(queryKey)\n\n    expectTypeOf(data).toEqualTypeOf<QueryState<unknown, Error> | undefined>()\n  })\n\n  it('should be typed if key is tagged', () => {\n    const queryKey = ['key'] as DataTag<Array<string>, number>\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryState(queryKey)\n\n    expectTypeOf(data).toEqualTypeOf<QueryState<number, Error> | undefined>()\n  })\n\n  it('should be typed including error if key is tagged', () => {\n    type CustomError = Error & { customError: string }\n    const queryKey = ['key'] as DataTag<Array<string>, number, CustomError>\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryState(queryKey)\n\n    expectTypeOf(data).toEqualTypeOf<\n      QueryState<number, CustomError> | undefined\n    >()\n  })\n})\n\ndescribe('fetchInfiniteQuery', () => {\n  it('should allow passing pages', async () => {\n    const data = await new QueryClient().fetchInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n      pages: 5,\n    })\n\n    expectTypeOf(data).toEqualTypeOf<InfiniteData<string, number>>()\n  })\n\n  it('should not allow passing getNextPageParam without pages', () => {\n    assertType<Parameters<QueryClient['fetchInfiniteQuery']>>([\n      {\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve('string'),\n        initialPageParam: 1,\n        getNextPageParam: () => 1,\n      },\n    ])\n  })\n\n  it('should not allow passing pages without getNextPageParam', () => {\n    assertType<Parameters<QueryClient['fetchInfiniteQuery']>>([\n      // @ts-expect-error Property 'getNextPageParam' is missing\n      {\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve('string'),\n        initialPageParam: 1,\n        pages: 5,\n      },\n    ])\n  })\n})\n\ndescribe('defaultOptions', () => {\n  it('should have a typed QueryFunctionContext', () => {\n    new QueryClient({\n      defaultOptions: {\n        queries: {\n          queryFn: (context) => {\n            expectTypeOf(context).toEqualTypeOf<{\n              client: QueryClient\n              queryKey: QueryKey\n              meta: Record<string, unknown> | undefined\n              signal: AbortSignal\n              pageParam?: unknown\n              direction?: unknown\n            }>()\n            return Promise.resolve('data')\n          },\n        },\n      },\n    })\n  })\n})\n\ndescribe('fully typed usage', () => {\n  it('type-checks various methods with data & error included in the type', async () => {\n    const queryClient = new QueryClient()\n\n    type TData = { foo: string }\n    type TError = DefaultError & { bar: string }\n\n    //\n    // Construct typed arguments\n    //\n\n    const queryOptions: EnsureQueryDataOptions<TData, TError> = {\n      queryKey: ['key'] as any,\n    }\n    const fetchInfiniteQueryOptions: FetchInfiniteQueryOptions<TData, TError> =\n      {\n        queryKey: ['key'] as any,\n        pages: 5,\n        getNextPageParam: (lastPage) => {\n          expectTypeOf(lastPage).toEqualTypeOf<TData>()\n          return 0\n        },\n        initialPageParam: 0,\n      }\n    const mutationOptions: MutationOptions<TData, TError> = {}\n\n    const queryFilters: QueryFilters<DataTag<QueryKey, TData, TError>> = {\n      predicate(query) {\n        expectTypeOf(query).toEqualTypeOf<\n          Query<unknown, Error, unknown, ReadonlyArray<unknown>>\n        >()\n        expectTypeOf(query.state.data).toEqualTypeOf<unknown>()\n        expectTypeOf(query.state.error).toEqualTypeOf<Error | null>()\n        return false\n      },\n    }\n    const queryKey = queryFilters.queryKey!\n\n    const mutationFilters: MutationFilters<TData, TError> = {\n      predicate(mutation) {\n        expectTypeOf(mutation).toEqualTypeOf<Mutation<TData, TError>>()\n        expectTypeOf(mutation.state.data).toEqualTypeOf<TData | undefined>()\n        expectTypeOf(mutation.state.error).toEqualTypeOf<TError | null>()\n        return false\n      },\n    }\n    const mutationKey = mutationOptions.mutationKey!\n\n    //\n    // Method type tests\n    //\n\n    const state = queryClient.getQueryState(queryKey)\n    expectTypeOf(state).toEqualTypeOf<QueryState<TData, TError> | undefined>()\n\n    const queryData1 = queryClient.getQueryData(queryKey)\n    expectTypeOf(queryData1).toEqualTypeOf<TData | undefined>()\n\n    const queryData2 = await queryClient.ensureQueryData(queryOptions)\n    expectTypeOf(queryData2).toEqualTypeOf<TData>()\n\n    const queriesData = queryClient.getQueriesData(queryFilters)\n    expectTypeOf(queriesData).toEqualTypeOf<\n      Array<[ReadonlyArray<unknown>, unknown]>\n    >()\n\n    const queryData3 = queryClient.setQueryData(queryKey, { foo: '' })\n    type SetQueryDataUpdaterArg = Parameters<\n      typeof queryClient.setQueryData<unknown, typeof queryKey>\n    >[1]\n\n    expectTypeOf<SetQueryDataUpdaterArg>().toEqualTypeOf<\n      Updater<TData | undefined, TData | undefined>\n    >()\n    expectTypeOf(queryData3).toEqualTypeOf<TData | undefined>()\n\n    const queriesData2 = queryClient.setQueriesData(queryFilters, { foo: '' }) // TODO: types here are wrong and coming up undefined\n    type SetQueriesDataUpdaterArg = Parameters<\n      typeof queryClient.setQueriesData<unknown, typeof queryFilters>\n    >[1]\n\n    expectTypeOf<SetQueriesDataUpdaterArg>().toEqualTypeOf<\n      Updater<unknown, unknown>\n    >()\n    expectTypeOf(queriesData2).toEqualTypeOf<Array<[QueryKey, unknown]>>()\n\n    const queryState = queryClient.getQueryState(queryKey)\n    expectTypeOf(queryState).toEqualTypeOf<\n      QueryState<TData, TError> | undefined\n    >()\n\n    const fetchedQuery = await queryClient.fetchQuery(queryOptions)\n    expectTypeOf(fetchedQuery).toEqualTypeOf<TData>()\n\n    queryClient.prefetchQuery(queryOptions)\n\n    const infiniteQuery = await queryClient.fetchInfiniteQuery(\n      fetchInfiniteQueryOptions,\n    )\n    expectTypeOf(infiniteQuery).toEqualTypeOf<InfiniteData<TData, unknown>>()\n\n    const infiniteQueryData = await queryClient.ensureInfiniteQueryData(\n      fetchInfiniteQueryOptions,\n    )\n    expectTypeOf(infiniteQueryData).toEqualTypeOf<\n      InfiniteData<TData, unknown>\n    >()\n\n    const defaultQueryOptions = queryClient.defaultQueryOptions(queryOptions)\n    expectTypeOf(defaultQueryOptions).toEqualTypeOf<\n      DefaultedQueryObserverOptions<TData, TError, TData, TData, QueryKey>\n    >()\n\n    const mutationOptions2 = queryClient.defaultMutationOptions(mutationOptions)\n    expectTypeOf(mutationOptions2).toEqualTypeOf<\n      MutationOptions<TData, TError, void, unknown>\n    >()\n\n    queryClient.setMutationDefaults(mutationKey, {\n      onSettled(data, error, variables, context) {\n        expectTypeOf(data).toEqualTypeOf<unknown>()\n        expectTypeOf(error).toEqualTypeOf<DefaultError | null>()\n        expectTypeOf(variables).toEqualTypeOf<void>()\n        expectTypeOf(context).toEqualTypeOf<unknown>()\n      },\n    })\n\n    const queryDefaults = queryClient.getQueryDefaults(queryKey)\n    expectTypeOf(queryDefaults).toEqualTypeOf<\n      OmitKeyof<QueryObserverOptions<any, any, any, any, any>, 'queryKey'>\n    >()\n\n    // Voids and Untyped returns\n    queryClient.invalidateQueries(queryFilters)\n    queryClient.isFetching(queryFilters)\n    queryClient.isMutating(mutationFilters)\n    queryClient.removeQueries(queryFilters)\n    queryClient.resetQueries(queryFilters)\n    queryClient.cancelQueries(queryFilters)\n    queryClient.invalidateQueries(queryFilters)\n    queryClient.refetchQueries(queryFilters)\n    queryClient.prefetchInfiniteQuery(fetchInfiniteQueryOptions)\n    queryClient.setQueryDefaults(queryKey, {} as any)\n    queryClient.getMutationDefaults(mutationKey)\n  })\n\n  it('type-checks various methods with untyped arguments', async () => {\n    const queryClient = new QueryClient()\n\n    //\n    // Construct typed arguments\n    //\n\n    const queryOptions: EnsureQueryDataOptions = {\n      queryKey: ['key'] as any,\n    }\n    const fetchInfiniteQueryOptions: FetchInfiniteQueryOptions = {\n      queryKey: ['key'] as any,\n      pages: 5,\n      getNextPageParam: (lastPage) => {\n        expectTypeOf(lastPage).toEqualTypeOf<unknown>()\n        return 0\n      },\n      initialPageParam: 0,\n    }\n    const mutationOptions: MutationOptions = {}\n\n    const queryFilters: QueryFilters = {\n      predicate(query) {\n        expectTypeOf(query).toEqualTypeOf<Query<unknown, DefaultError>>()\n        expectTypeOf(query.state.data).toEqualTypeOf<unknown>()\n        expectTypeOf(query.state.error).toEqualTypeOf<DefaultError | null>()\n        return false\n      },\n    }\n    const queryKey = queryFilters.queryKey!\n\n    const mutationFilters: MutationFilters = {\n      predicate(mutation) {\n        expectTypeOf(mutation).toEqualTypeOf<Mutation>()\n        expectTypeOf(mutation.state.data).toEqualTypeOf<unknown>()\n        expectTypeOf(mutation.state.error).toEqualTypeOf<DefaultError | null>()\n        return false\n      },\n    }\n    const mutationKey = mutationOptions.mutationKey!\n\n    //\n    // Method type tests\n    //\n\n    const state = queryClient.getQueryState(queryKey)\n    expectTypeOf(state).toEqualTypeOf<\n      QueryState<unknown, DefaultError> | undefined\n    >()\n\n    const queryData1 = queryClient.getQueryData(queryKey)\n    expectTypeOf(queryData1).toEqualTypeOf<unknown>()\n\n    const queryData2 = await queryClient.ensureQueryData(queryOptions)\n    expectTypeOf(queryData2).toEqualTypeOf<unknown>()\n\n    const queriesData = queryClient.getQueriesData(queryFilters)\n    expectTypeOf(queriesData).toEqualTypeOf<Array<[QueryKey, unknown]>>()\n\n    const queryData3 = queryClient.setQueryData(queryKey, { foo: '' })\n    type SetQueryDataUpdaterArg = Parameters<\n      typeof queryClient.setQueryData<unknown, typeof queryKey>\n    >[1]\n\n    expectTypeOf<SetQueryDataUpdaterArg>().toEqualTypeOf<\n      Updater<unknown, unknown>\n    >()\n    expectTypeOf(queryData3).toEqualTypeOf<unknown>()\n\n    const queriesData2 = queryClient.setQueriesData(queryFilters, { foo: '' }) // TODO: types here are wrong and coming up undefined\n    type SetQueriesDataUpdaterArg = Parameters<\n      typeof queryClient.setQueriesData<unknown, typeof queryFilters>\n    >[1]\n\n    expectTypeOf<SetQueriesDataUpdaterArg>().toEqualTypeOf<\n      Updater<unknown, unknown>\n    >()\n    expectTypeOf(queriesData2).toEqualTypeOf<Array<[QueryKey, unknown]>>()\n\n    const queryState = queryClient.getQueryState(queryKey)\n    expectTypeOf(queryState).toEqualTypeOf<\n      QueryState<unknown, DefaultError> | undefined\n    >()\n\n    const fetchedQuery = await queryClient.fetchQuery(queryOptions)\n    expectTypeOf(fetchedQuery).toEqualTypeOf<unknown>()\n\n    queryClient.prefetchQuery(queryOptions)\n\n    const infiniteQuery = await queryClient.fetchInfiniteQuery(\n      fetchInfiniteQueryOptions,\n    )\n    expectTypeOf(infiniteQuery).toEqualTypeOf<InfiniteData<unknown, unknown>>()\n\n    const infiniteQueryData = await queryClient.ensureInfiniteQueryData(\n      fetchInfiniteQueryOptions,\n    )\n    expectTypeOf(infiniteQueryData).toEqualTypeOf<\n      InfiniteData<unknown, unknown>\n    >()\n\n    const defaultQueryOptions = queryClient.defaultQueryOptions(queryOptions)\n    expectTypeOf(defaultQueryOptions).toEqualTypeOf<\n      DefaultedQueryObserverOptions<\n        unknown,\n        DefaultError,\n        unknown,\n        unknown,\n        QueryKey\n      >\n    >()\n\n    const mutationOptions2 = queryClient.defaultMutationOptions(mutationOptions)\n    expectTypeOf(mutationOptions2).toEqualTypeOf<\n      MutationOptions<unknown, DefaultError, void, unknown>\n    >()\n\n    queryClient.setMutationDefaults(mutationKey, {\n      onSettled(data, error, variables, context) {\n        expectTypeOf(data).toEqualTypeOf<unknown>()\n        expectTypeOf(error).toEqualTypeOf<DefaultError | null>()\n        expectTypeOf(variables).toEqualTypeOf<void>()\n        expectTypeOf(context).toEqualTypeOf<unknown>()\n      },\n    })\n\n    const queryDefaults = queryClient.getQueryDefaults(queryKey)\n    expectTypeOf(queryDefaults).toEqualTypeOf<\n      OmitKeyof<QueryObserverOptions<any, any, any, any, any>, 'queryKey'>\n    >()\n\n    // Voids and Untyped returns\n    queryClient.invalidateQueries(queryFilters)\n    queryClient.isFetching(queryFilters)\n    queryClient.isMutating(mutationFilters)\n    queryClient.removeQueries(queryFilters)\n    queryClient.resetQueries(queryFilters)\n    queryClient.cancelQueries(queryFilters)\n    queryClient.invalidateQueries(queryFilters)\n    queryClient.refetchQueries(queryFilters)\n    queryClient.prefetchInfiniteQuery(fetchInfiniteQueryOptions)\n    queryClient.setQueryDefaults(queryKey, {} as any)\n    queryClient.getMutationDefaults(mutationKey)\n  })\n})\n\ndescribe('invalidateQueries', () => {\n  it('shows type error when queryKey is a wrong type in invalidateQueries', () => {\n    assertType<Parameters<QueryClient['invalidateQueries']>>([])\n    assertType<Parameters<QueryClient['invalidateQueries']>>([\n      { queryKey: ['1'] },\n    ])\n    assertType<Parameters<QueryClient['invalidateQueries']>>([\n      // @ts-expect-error\n      { queryKey: '1' },\n    ])\n  })\n  it('needs queryKey to be an array (#8684)', () => {\n    assertType<Parameters<QueryClient['invalidateQueries']>>({\n      // @ts-expect-error key is not an array\n      queryKey: { foo: true },\n    })\n  })\n  it('predicate should be typed if key is tagged', () => {\n    const queryKey = ['key'] as DataTag<Array<string>, number>\n    const queryClient = new QueryClient()\n    queryClient.invalidateQueries({\n      queryKey,\n      predicate: (query) => {\n        expectTypeOf(query.state.data).toEqualTypeOf<unknown>()\n        expectTypeOf(query.queryKey).toEqualTypeOf<QueryKey>()\n        return true\n      },\n    })\n  })\n})\n\ndescribe('cancelQueries', () => {\n  it('predicate should be typed if key is tagged', () => {\n    const queryKey = ['key'] as DataTag<Array<string>, number>\n    const queryClient = new QueryClient()\n    queryClient.cancelQueries({\n      queryKey,\n      predicate: (query) => {\n        expectTypeOf(query.state.data).toEqualTypeOf<unknown>()\n        expectTypeOf(query.queryKey).toEqualTypeOf<QueryKey>()\n        return true\n      },\n    })\n  })\n})\n\ndescribe('removeQueries', () => {\n  it('predicate should be typed if key is tagged', () => {\n    const queryKey = ['key'] as DataTag<Array<string>, number>\n    const queryClient = new QueryClient()\n    queryClient.removeQueries({\n      queryKey,\n      predicate: (query) => {\n        expectTypeOf(query.state.data).toEqualTypeOf<unknown>()\n        expectTypeOf(query.queryKey).toEqualTypeOf<QueryKey>()\n        return true\n      },\n    })\n  })\n})\n\ndescribe('refetchQueries', () => {\n  it('predicate should be typed if key is tagged', () => {\n    const queryKey = ['key'] as DataTag<Array<string>, number>\n    const queryClient = new QueryClient()\n    queryClient.refetchQueries({\n      queryKey,\n      predicate: (query) => {\n        expectTypeOf(query.state.data).toEqualTypeOf<unknown>()\n        expectTypeOf(query.queryKey).toEqualTypeOf<QueryKey>()\n        return true\n      },\n    })\n  })\n})\n\ndescribe('resetQueries', () => {\n  it('predicate should be typed if key is tagged', () => {\n    const queryKey = ['key'] as DataTag<Array<string>, number>\n    const queryClient = new QueryClient()\n    queryClient.resetQueries({\n      queryKey,\n      predicate: (query) => {\n        expectTypeOf(query.state.data).toEqualTypeOf<unknown>()\n        expectTypeOf(query.queryKey).toEqualTypeOf<QueryKey>()\n        return true\n      },\n    })\n  })\n})\ntype SuccessCallback = () => unknown\nit('should infer types correctly with expression body arrow functions', () => {\n  const queryKey = ['key'] as DataTag<Array<string>, number>\n  const queryClient = new QueryClient()\n\n  // @ts-expect-error\n  const callbackTest: SuccessCallback = () =>\n    queryClient.setQueryData(queryKey, (data) => {\n      expectTypeOf(data).toEqualTypeOf<number | undefined>()\n      return data\n    })\n})\n\nit('should infer types correctly with block body arrow functions', () => {\n  const queryKey = ['key'] as DataTag<Array<string>, number>\n  const queryClient = new QueryClient()\n\n  // @ts-expect-error\n  const callbackTest2: SuccessCallback = () => {\n    queryClient.setQueryData(queryKey, (data) => {\n      expectTypeOf(data).toEqualTypeOf<number | undefined>()\n      return data\n    })\n  }\n})\n"
  },
  {
    "path": "packages/query-core/src/__tests__/queryClient.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport {\n  CancelledError,\n  MutationObserver,\n  QueryClient,\n  QueryObserver,\n  dehydrate,\n  focusManager,\n  hydrate,\n  onlineManager,\n  skipToken,\n} from '..'\nimport { mockOnlineManagerIsOnline } from './utils'\nimport type { QueryCache, QueryFunction, QueryObserverOptions } from '..'\n\ndescribe('queryClient', () => {\n  let queryClient: QueryClient\n  let queryCache: QueryCache\n\n  beforeEach(() => {\n    vi.useFakeTimers()\n    queryClient = new QueryClient()\n    queryCache = queryClient.getQueryCache()\n    queryClient.mount()\n  })\n\n  afterEach(() => {\n    queryClient.clear()\n    queryClient.unmount()\n    vi.useRealTimers()\n  })\n\n  describe('defaultOptions', () => {\n    test('should merge defaultOptions', () => {\n      const key = queryKey()\n\n      const queryFn = () => 'data'\n      const testClient = new QueryClient({\n        defaultOptions: { queries: { queryFn } },\n      })\n\n      expect(() => testClient.prefetchQuery({ queryKey: key })).not.toThrow()\n    })\n\n    test('should merge defaultOptions when query is added to cache', async () => {\n      const key = queryKey()\n\n      const testClient = new QueryClient({\n        defaultOptions: {\n          queries: { gcTime: Infinity },\n        },\n      })\n\n      const fetchData = () => Promise.resolve('data')\n      await testClient.prefetchQuery({ queryKey: key, queryFn: fetchData })\n      const newQuery = testClient.getQueryCache().find({ queryKey: key })\n      expect(newQuery?.options.gcTime).toBe(Infinity)\n    })\n\n    test('should get defaultOptions', () => {\n      const queryFn = () => 'data'\n      const defaultOptions = { queries: { queryFn } }\n      const testClient = new QueryClient({\n        defaultOptions,\n      })\n      expect(testClient.getDefaultOptions()).toMatchObject(defaultOptions)\n    })\n  })\n\n  describe('setQueryDefaults', () => {\n    test('should not trigger a fetch', () => {\n      const key = queryKey()\n      queryClient.setQueryDefaults(key, { queryFn: () => 'data' })\n      const data = queryClient.getQueryData(key)\n      expect(data).toBeUndefined()\n    })\n\n    test('should be able to override defaults', async () => {\n      const key = queryKey()\n      queryClient.setQueryDefaults(key, { queryFn: () => 'data' })\n      const observer = new QueryObserver(queryClient, { queryKey: key })\n      const { data } = await observer.refetch()\n      expect(data).toBe('data')\n    })\n\n    test('should match the query key partially', async () => {\n      const key = queryKey()\n      queryClient.setQueryDefaults([key], { queryFn: () => 'data' })\n      const observer = new QueryObserver(queryClient, {\n        queryKey: [key, 'a'],\n      })\n      const { data } = await observer.refetch()\n      expect(data).toBe('data')\n    })\n\n    test('should not match if the query key is a subset', async () => {\n      const key = queryKey()\n      queryClient.setQueryDefaults([key, 'a'], {\n        queryFn: () => 'data',\n      })\n      const observer = new QueryObserver(queryClient, {\n        queryKey: [key],\n        retry: false,\n        enabled: false,\n      })\n      const { status } = await observer.refetch()\n      expect(status).toBe('error')\n    })\n\n    test('should also set defaults for observers', () => {\n      const key = queryKey()\n      queryClient.setQueryDefaults(key, {\n        queryFn: () => 'data',\n        enabled: false,\n      })\n      const observer = new QueryObserver(queryClient, {\n        queryKey: [key],\n      })\n      expect(observer.getCurrentResult().status).toBe('pending')\n      expect(observer.getCurrentResult().fetchStatus).toBe('idle')\n    })\n\n    test('should update existing query defaults', () => {\n      const key = queryKey()\n      const queryOptions1 = { queryFn: () => 'data' }\n      const queryOptions2 = { retry: false }\n      queryClient.setQueryDefaults(key, { ...queryOptions1 })\n      queryClient.setQueryDefaults(key, { ...queryOptions2 })\n      expect(queryClient.getQueryDefaults(key)).toMatchObject(queryOptions2)\n    })\n\n    test('should merge defaultOptions', () => {\n      const key = queryKey()\n\n      queryClient.setQueryDefaults([...key, 'todo'], { suspense: true })\n      queryClient.setQueryDefaults([...key, 'todo', 'detail'], {\n        staleTime: 5000,\n      })\n\n      expect(\n        queryClient.getQueryDefaults([...key, 'todo', 'detail']),\n      ).toMatchObject({ suspense: true, staleTime: 5000 })\n    })\n  })\n\n  describe('defaultQueryOptions', () => {\n    test('should default networkMode when persister is present', () => {\n      expect(\n        new QueryClient({\n          defaultOptions: {\n            queries: {\n              persister: 'ignore' as any,\n            },\n          },\n        }).defaultQueryOptions({ queryKey: queryKey() }).networkMode,\n      ).toBe('offlineFirst')\n    })\n\n    test('should not default networkMode without persister', () => {\n      expect(\n        new QueryClient({\n          defaultOptions: {\n            queries: {\n              staleTime: 1000,\n            },\n          },\n        }).defaultQueryOptions({ queryKey: queryKey() }).networkMode,\n      ).toBe(undefined)\n    })\n\n    test('should not default networkMode when already present', () => {\n      expect(\n        new QueryClient({\n          defaultOptions: {\n            queries: {\n              persister: 'ignore' as any,\n              networkMode: 'always',\n            },\n          },\n        }).defaultQueryOptions({ queryKey: queryKey() }).networkMode,\n      ).toBe('always')\n    })\n  })\n\n  describe('setQueryData', () => {\n    test('should not crash if query could not be found', () => {\n      const key = queryKey()\n      const user = { userId: 1 }\n      expect(() => {\n        queryClient.setQueryData([key, user], (prevUser?: typeof user) => ({\n          ...prevUser!,\n          name: 'James',\n        }))\n      }).not.toThrow()\n    })\n\n    test('should not crash when variable is null', () => {\n      const key = queryKey()\n      queryClient.setQueryData([key, { userId: null }], 'Old Data')\n      expect(() => {\n        queryClient.setQueryData([key, { userId: null }], 'New Data')\n      }).not.toThrow()\n    })\n\n    test('should use default options', () => {\n      const key = queryKey()\n      const testClient = new QueryClient({\n        defaultOptions: { queries: { queryKeyHashFn: () => 'someKey' } },\n      })\n      const testCache = testClient.getQueryCache()\n      testClient.setQueryData(key, 'data')\n      expect(testClient.getQueryData(key)).toBe('data')\n      expect(testCache.find({ queryKey: key })).toBe(testCache.get('someKey'))\n    })\n\n    test('should create a new query if query was not found 1', () => {\n      const key = queryKey()\n      queryClient.setQueryData(key, 'bar')\n      expect(queryClient.getQueryData(key)).toBe('bar')\n    })\n\n    test('should create a new query if query was not found 2', () => {\n      const key = queryKey()\n      queryClient.setQueryData(key, 'qux')\n      expect(queryClient.getQueryData(key)).toBe('qux')\n    })\n\n    test('should not create a new query if query was not found and data is undefined', () => {\n      const key = queryKey()\n      expect(queryClient.getQueryCache().find({ queryKey: key })).toBe(\n        undefined,\n      )\n      queryClient.setQueryData(key, undefined)\n      expect(queryClient.getQueryCache().find({ queryKey: key })).toBe(\n        undefined,\n      )\n    })\n\n    test('should not create a new query if query was not found and updater returns undefined', () => {\n      const key = queryKey()\n      expect(queryClient.getQueryCache().find({ queryKey: key })).toBe(\n        undefined,\n      )\n      queryClient.setQueryData(key, () => undefined)\n      expect(queryClient.getQueryCache().find({ queryKey: key })).toBe(\n        undefined,\n      )\n    })\n\n    test('should not update query data if data is undefined', () => {\n      const key = queryKey()\n      queryClient.setQueryData(key, 'qux')\n      queryClient.setQueryData(key, undefined)\n      expect(queryClient.getQueryData(key)).toBe('qux')\n    })\n\n    test('should not update query data if updater returns undefined', () => {\n      const key = queryKey()\n      queryClient.setQueryData<string>(key, 'qux')\n      queryClient.setQueryData<string>(key, () => undefined)\n      expect(queryClient.getQueryData(key)).toBe('qux')\n    })\n\n    test('should accept an update function', () => {\n      const key = queryKey()\n\n      const updater = vi.fn((oldData) => `new data + ${oldData}`)\n\n      queryClient.setQueryData(key, 'test data')\n      queryClient.setQueryData(key, updater)\n\n      expect(updater).toHaveBeenCalled()\n      expect(queryCache.find({ queryKey: key })!.state.data).toEqual(\n        'new data + test data',\n      )\n    })\n\n    test('should set the new data without comparison if structuralSharing is set to false', () => {\n      const key = queryKey()\n\n      queryClient.setDefaultOptions({\n        queries: {\n          structuralSharing: false,\n        },\n      })\n\n      const oldData = { value: true }\n      const newData = { value: true }\n      queryClient.setQueryData(key, oldData)\n      queryClient.setQueryData(key, newData)\n\n      expect(queryCache.find({ queryKey: key })!.state.data).toBe(newData)\n    })\n\n    test('should apply a custom structuralSharing function when provided', () => {\n      const key = queryKey()\n\n      const queryObserverOptions = {\n        structuralSharing: (\n          prevData: { value: Date } | undefined,\n          newData: { value: Date },\n        ) => {\n          if (!prevData) {\n            return newData\n          }\n          return newData.value.getTime() === prevData.value.getTime()\n            ? prevData\n            : newData\n        },\n      } as QueryObserverOptions\n\n      queryClient.setDefaultOptions({ queries: queryObserverOptions })\n\n      const oldData = { value: new Date(2022, 6, 19) }\n      const newData = { value: new Date(2022, 6, 19) }\n      queryClient.setQueryData(key, oldData)\n      queryClient.setQueryData(key, newData)\n\n      expect(queryCache.find({ queryKey: key })!.state.data).toBe(oldData)\n\n      const distinctData = { value: new Date(2021, 11, 25) }\n      queryClient.setQueryData(key, distinctData)\n\n      expect(queryCache.find({ queryKey: key })!.state.data).toBe(distinctData)\n    })\n\n    test('should not set isFetching to false', async () => {\n      const key = queryKey()\n      queryClient.prefetchQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 23),\n      })\n      expect(queryClient.getQueryState(key)).toMatchObject({\n        data: undefined,\n        fetchStatus: 'fetching',\n      })\n      queryClient.setQueryData(key, 42)\n      expect(queryClient.getQueryState(key)).toMatchObject({\n        data: 42,\n        fetchStatus: 'fetching',\n      })\n      await vi.advanceTimersByTimeAsync(10)\n      expect(queryClient.getQueryState(key)).toMatchObject({\n        data: 23,\n        fetchStatus: 'idle',\n      })\n    })\n  })\n\n  describe('setQueriesData', () => {\n    test('should update all existing, matching queries', () => {\n      queryClient.setQueryData(['key', 1], 1)\n      queryClient.setQueryData(['key', 2], 2)\n\n      const result = queryClient.setQueriesData<number>(\n        { queryKey: ['key'] },\n        (old) => (old ? old + 5 : undefined),\n      )\n\n      expect(result).toEqual([\n        [['key', 1], 6],\n        [['key', 2], 7],\n      ])\n      expect(queryClient.getQueryData(['key', 1])).toBe(6)\n      expect(queryClient.getQueryData(['key', 2])).toBe(7)\n    })\n\n    test('should accept queryFilters', () => {\n      queryClient.setQueryData(['key', 1], 1)\n      queryClient.setQueryData(['key', 2], 2)\n      const query1 = queryCache.find({ queryKey: ['key', 1] })!\n\n      const result = queryClient.setQueriesData<number>(\n        { predicate: (query) => query === query1 },\n        (old) => old! + 5,\n      )\n\n      expect(result).toEqual([[['key', 1], 6]])\n      expect(queryClient.getQueryData(['key', 1])).toBe(6)\n      expect(queryClient.getQueryData(['key', 2])).toBe(2)\n    })\n\n    test('should not update non existing queries', () => {\n      const result = queryClient.setQueriesData<string>(\n        { queryKey: ['key'] },\n        'data',\n      )\n\n      expect(result).toEqual([])\n      expect(queryClient.getQueryData(['key'])).toBe(undefined)\n    })\n  })\n\n  describe('isFetching', () => {\n    test('should return length of fetching queries', async () => {\n      expect(queryClient.isFetching()).toBe(0)\n      queryClient.prefetchQuery({\n        queryKey: queryKey(),\n        queryFn: () => sleep(10).then(() => 'data'),\n      })\n      expect(queryClient.isFetching()).toBe(1)\n      queryClient.prefetchQuery({\n        queryKey: queryKey(),\n        queryFn: () => sleep(5).then(() => 'data'),\n      })\n      expect(queryClient.isFetching()).toBe(2)\n      await vi.advanceTimersByTimeAsync(5)\n      expect(queryClient.isFetching()).toEqual(1)\n      await vi.advanceTimersByTimeAsync(5)\n      expect(queryClient.isFetching()).toEqual(0)\n    })\n  })\n\n  describe('isMutating', () => {\n    test('should return length of mutating', async () => {\n      expect(queryClient.isMutating()).toBe(0)\n      new MutationObserver(queryClient, {\n        mutationFn: () => sleep(10).then(() => 'data'),\n      }).mutate()\n      expect(queryClient.isMutating()).toBe(1)\n      new MutationObserver(queryClient, {\n        mutationFn: () => sleep(5).then(() => 'data'),\n      }).mutate()\n      expect(queryClient.isMutating()).toBe(2)\n      await vi.advanceTimersByTimeAsync(5)\n      expect(queryClient.isMutating()).toEqual(1)\n      await vi.advanceTimersByTimeAsync(5)\n      expect(queryClient.isMutating()).toEqual(0)\n    })\n  })\n\n  describe('getQueryData', () => {\n    test('should return the query data if the query is found', () => {\n      const key = queryKey()\n      queryClient.setQueryData([key, 'id'], 'bar')\n      expect(queryClient.getQueryData([key, 'id'])).toBe('bar')\n    })\n\n    test('should return undefined if the query is not found', () => {\n      const key = queryKey()\n      expect(queryClient.getQueryData(key)).toBeUndefined()\n    })\n\n    test('should match exact by default', () => {\n      const key = queryKey()\n      queryClient.setQueryData([key, 'id'], 'bar')\n      expect(queryClient.getQueryData([key])).toBeUndefined()\n    })\n  })\n\n  describe('ensureQueryData', () => {\n    test('should return the cached query data if the query is found', async () => {\n      const key = queryKey()\n      const queryFn = () => Promise.resolve('data')\n\n      queryClient.setQueryData([key, 'id'], 'bar')\n\n      await expect(\n        queryClient.ensureQueryData({ queryKey: [key, 'id'], queryFn }),\n      ).resolves.toEqual('bar')\n    })\n\n    test('should return the cached query data if the query is found and cached query data is falsy', async () => {\n      const key = queryKey()\n      const queryFn = () => Promise.resolve(0)\n\n      queryClient.setQueryData([key, 'id'], null)\n\n      await expect(\n        queryClient.ensureQueryData({ queryKey: [key, 'id'], queryFn }),\n      ).resolves.toEqual(null)\n    })\n\n    test('should call fetchQuery and return its results if the query is not found', async () => {\n      const key = queryKey()\n      const queryFn = () => Promise.resolve('data')\n\n      await expect(\n        queryClient.ensureQueryData({ queryKey: [key], queryFn }),\n      ).resolves.toEqual('data')\n    })\n\n    test('should return the cached query data if the query is found and preFetchQuery in the background when revalidateIfStale is set', async () => {\n      const TIMEOUT = 10\n      const key = queryKey()\n      queryClient.setQueryData([key, 'id'], 'old')\n\n      const queryFn = () =>\n        new Promise((resolve) => {\n          setTimeout(() => resolve('new'), TIMEOUT)\n        })\n\n      await expect(\n        queryClient.ensureQueryData({\n          queryKey: [key, 'id'],\n          queryFn,\n          revalidateIfStale: true,\n        }),\n      ).resolves.toEqual('old')\n      await vi.advanceTimersByTimeAsync(TIMEOUT + 10)\n      await expect(\n        queryClient.ensureQueryData({\n          queryKey: [key, 'id'],\n          queryFn,\n          revalidateIfStale: true,\n        }),\n      ).resolves.toEqual('new')\n    })\n\n    test('should not fetch with initialDat', async () => {\n      const key = queryKey()\n      const queryFn = vi.fn().mockImplementation(() => Promise.resolve('data'))\n\n      await expect(\n        queryClient.ensureQueryData({\n          queryKey: [key, 'id'],\n          queryFn,\n          initialData: 'initial',\n        }),\n      ).resolves.toEqual('initial')\n\n      expect(queryFn).toHaveBeenCalledTimes(0)\n    })\n  })\n\n  describe('ensureInfiniteQueryData', () => {\n    test('should return the cached query data if the query is found', async () => {\n      const key = queryKey()\n      const queryFn = () => Promise.resolve('data')\n\n      queryClient.setQueryData([key, 'id'], { pages: ['bar'], pageParams: [0] })\n\n      await expect(\n        queryClient.ensureInfiniteQueryData({\n          queryKey: [key, 'id'],\n          queryFn,\n          initialPageParam: 1,\n          getNextPageParam: () => undefined,\n        }),\n      ).resolves.toEqual({ pages: ['bar'], pageParams: [0] })\n    })\n\n    test('should fetch the query and return its results if the query is not found', async () => {\n      const key = queryKey()\n      const queryFn = () => Promise.resolve('data')\n\n      await expect(\n        queryClient.ensureInfiniteQueryData({\n          queryKey: [key, 'id'],\n          queryFn,\n          initialPageParam: 1,\n          getNextPageParam: () => undefined,\n        }),\n      ).resolves.toEqual({ pages: ['data'], pageParams: [1] })\n    })\n\n    test('should return the cached query data if the query is found and preFetchQuery in the background when revalidateIfStale is set', async () => {\n      const TIMEOUT = 10\n      const key = queryKey()\n      queryClient.setQueryData([key, 'id'], { pages: ['old'], pageParams: [0] })\n\n      const queryFn = () => sleep(TIMEOUT).then(() => 'new')\n\n      await expect(\n        queryClient.ensureInfiniteQueryData({\n          queryKey: [key, 'id'],\n          queryFn,\n          initialPageParam: 1,\n          getNextPageParam: () => undefined,\n          revalidateIfStale: true,\n        }),\n      ).resolves.toEqual({ pages: ['old'], pageParams: [0] })\n      await vi.advanceTimersByTimeAsync(TIMEOUT + 10)\n      await expect(\n        queryClient.ensureInfiniteQueryData({\n          queryKey: [key, 'id'],\n          queryFn,\n          initialPageParam: 1,\n          getNextPageParam: () => undefined,\n          revalidateIfStale: true,\n        }),\n      ).resolves.toEqual({ pages: ['new'], pageParams: [0] })\n    })\n  })\n\n  describe('getQueriesData', () => {\n    test('should return the query data for all matched queries', () => {\n      const key1 = queryKey()\n      const key2 = queryKey()\n      queryClient.setQueryData([key1, 1], 1)\n      queryClient.setQueryData([key1, 2], 2)\n      queryClient.setQueryData([key2, 2], 2)\n      expect(queryClient.getQueriesData({ queryKey: [key1] })).toEqual([\n        [[key1, 1], 1],\n        [[key1, 2], 2],\n      ])\n    })\n\n    test('should return empty array if queries are not found', () => {\n      const key = queryKey()\n      expect(queryClient.getQueriesData({ queryKey: key })).toEqual([])\n    })\n\n    test('should accept query filters', () => {\n      queryClient.setQueryData(['key', 1], 1)\n      queryClient.setQueryData(['key', 2], 2)\n      const query1 = queryCache.find({ queryKey: ['key', 1] })!\n\n      const result = queryClient.getQueriesData({\n        predicate: (query) => query === query1,\n      })\n\n      expect(result).toEqual([[['key', 1], 1]])\n    })\n  })\n\n  describe('fetchQuery', () => {\n    test('should not type-error with strict query key', async () => {\n      type StrictData = 'data'\n      type StrictQueryKey = ['strict', ...ReturnType<typeof queryKey>]\n      const key: StrictQueryKey = ['strict', ...queryKey()]\n\n      const fetchFn: QueryFunction<StrictData, StrictQueryKey> = () =>\n        Promise.resolve('data')\n\n      await expect(\n        queryClient.fetchQuery<StrictData, any, StrictData, StrictQueryKey>({\n          queryKey: key,\n          queryFn: fetchFn,\n        }),\n      ).resolves.toEqual('data')\n    })\n\n    // https://github.com/tannerlinsley/react-query/issues/652\n    test('should not retry by default', async () => {\n      const key = queryKey()\n\n      await expect(\n        queryClient.fetchQuery({\n          queryKey: key,\n          queryFn: (): Promise<unknown> => {\n            throw new Error('error')\n          },\n        }),\n      ).rejects.toEqual(new Error('error'))\n    })\n\n    test('should return the cached data on cache hit', async () => {\n      const key = queryKey()\n\n      const fetchFn = () => Promise.resolve('data')\n      const first = await queryClient.fetchQuery({\n        queryKey: key,\n        queryFn: fetchFn,\n      })\n      const second = await queryClient.fetchQuery({\n        queryKey: key,\n        queryFn: fetchFn,\n      })\n\n      expect(second).toBe(first)\n    })\n\n    test('should read from cache with static staleTime even if invalidated', async () => {\n      const key = queryKey()\n\n      const fetchFn = vi.fn(() => Promise.resolve({ data: 'data' }))\n      const first = await queryClient.fetchQuery({\n        queryKey: key,\n        queryFn: fetchFn,\n        staleTime: 'static',\n      })\n\n      expect(first.data).toBe('data')\n      expect(fetchFn).toHaveBeenCalledTimes(1)\n\n      await queryClient.invalidateQueries({\n        queryKey: key,\n        refetchType: 'none',\n      })\n\n      const second = await queryClient.fetchQuery({\n        queryKey: key,\n        queryFn: fetchFn,\n        staleTime: 'static',\n      })\n\n      expect(fetchFn).toHaveBeenCalledTimes(1)\n\n      expect(second).toBe(first)\n    })\n\n    test('should be able to fetch when garbage collection time is set to 0 and then be removed', async () => {\n      const key1 = queryKey()\n      const promise = queryClient.fetchQuery({\n        queryKey: key1,\n        queryFn: () => sleep(10).then(() => 1),\n        gcTime: 0,\n      })\n      await vi.advanceTimersByTimeAsync(10)\n      await expect(promise).resolves.toEqual(1)\n      await vi.advanceTimersByTimeAsync(1)\n      expect(queryClient.getQueryData(key1)).toEqual(undefined)\n    })\n\n    test('should keep a query in cache if garbage collection time is Infinity', async () => {\n      const key1 = queryKey()\n      const promise = queryClient.fetchQuery({\n        queryKey: key1,\n        queryFn: () => sleep(10).then(() => 1),\n        gcTime: Infinity,\n      })\n      await vi.advanceTimersByTimeAsync(10)\n      const result2 = queryClient.getQueryData(key1)\n      await expect(promise).resolves.toEqual(1)\n      expect(result2).toEqual(1)\n    })\n\n    test('should not force fetch', async () => {\n      const key = queryKey()\n\n      queryClient.setQueryData(key, 'og')\n      const fetchFn = () => Promise.resolve('new')\n      const first = await queryClient.fetchQuery({\n        queryKey: key,\n        queryFn: fetchFn,\n        initialData: 'initial',\n        staleTime: 100,\n      })\n      expect(first).toBe('og')\n    })\n\n    test('should only fetch if the data is older then the given stale time', async () => {\n      const key = queryKey()\n\n      let count = 0\n      const queryFn = () => ++count\n\n      queryClient.setQueryData(key, count)\n      const firstPromise = queryClient.fetchQuery({\n        queryKey: key,\n        queryFn,\n        staleTime: 100,\n      })\n      await expect(firstPromise).resolves.toBe(0)\n      await vi.advanceTimersByTimeAsync(10)\n      const secondPromise = queryClient.fetchQuery({\n        queryKey: key,\n        queryFn,\n        staleTime: 10,\n      })\n      await expect(secondPromise).resolves.toBe(1)\n      const thirdPromise = queryClient.fetchQuery({\n        queryKey: key,\n        queryFn,\n        staleTime: 10,\n      })\n      await expect(thirdPromise).resolves.toBe(1)\n      await vi.advanceTimersByTimeAsync(10)\n      const fourthPromise = queryClient.fetchQuery({\n        queryKey: key,\n        queryFn,\n        staleTime: 10,\n      })\n      await expect(fourthPromise).resolves.toBe(2)\n    })\n\n    test('should allow new meta', async () => {\n      const key = queryKey()\n\n      const first = await queryClient.fetchQuery({\n        queryKey: key,\n        queryFn: ({ meta }) => Promise.resolve(meta),\n        meta: {\n          foo: true,\n        },\n      })\n      expect(first).toStrictEqual({ foo: true })\n\n      const second = await queryClient.fetchQuery({\n        queryKey: key,\n        queryFn: ({ meta }) => Promise.resolve(meta),\n        meta: {\n          foo: false,\n        },\n      })\n      expect(second).toStrictEqual({ foo: false })\n    })\n  })\n\n  describe('fetchInfiniteQuery', () => {\n    test('should not type-error with strict query key', async () => {\n      type StrictData = string\n      type StrictQueryKey = ['strict', ...ReturnType<typeof queryKey>]\n      const key: StrictQueryKey = ['strict', ...queryKey()]\n\n      const data = {\n        pages: ['data'],\n        pageParams: [0],\n      } as const\n\n      const fetchFn: QueryFunction<StrictData, StrictQueryKey, number> = () =>\n        Promise.resolve(data.pages[0])\n\n      await expect(\n        queryClient.fetchInfiniteQuery<\n          StrictData,\n          any,\n          StrictData,\n          StrictQueryKey,\n          number\n        >({ queryKey: key, queryFn: fetchFn, initialPageParam: 0 }),\n      ).resolves.toEqual(data)\n    })\n\n    test('should return infinite query data', async () => {\n      const key = queryKey()\n      const result = await queryClient.fetchInfiniteQuery({\n        queryKey: key,\n        initialPageParam: 10,\n        queryFn: ({ pageParam }) => Number(pageParam),\n      })\n      const result2 = queryClient.getQueryData(key)\n\n      const expected = {\n        pages: [10],\n        pageParams: [10],\n      }\n\n      expect(result).toEqual(expected)\n      expect(result2).toEqual(expected)\n    })\n  })\n\n  describe('prefetchInfiniteQuery', () => {\n    test('should not type-error with strict query key', async () => {\n      type StrictData = 'data'\n      type StrictQueryKey = ['strict', ...ReturnType<typeof queryKey>]\n      const key: StrictQueryKey = ['strict', ...queryKey()]\n\n      const fetchFn: QueryFunction<StrictData, StrictQueryKey, number> = () =>\n        Promise.resolve('data')\n\n      await queryClient.prefetchInfiniteQuery<\n        StrictData,\n        any,\n        StrictData,\n        StrictQueryKey,\n        number\n      >({ queryKey: key, queryFn: fetchFn, initialPageParam: 0 })\n\n      const result = queryClient.getQueryData(key)\n\n      expect(result).toEqual({\n        pages: ['data'],\n        pageParams: [0],\n      })\n    })\n\n    test('should return infinite query data', async () => {\n      const key = queryKey()\n\n      await queryClient.prefetchInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) => Number(pageParam),\n        initialPageParam: 10,\n      })\n\n      const result = queryClient.getQueryData(key)\n\n      expect(result).toEqual({\n        pages: [10],\n        pageParams: [10],\n      })\n    })\n\n    test('should prefetch multiple pages', async () => {\n      const key = queryKey()\n\n      await queryClient.prefetchInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) => String(pageParam),\n        getNextPageParam: (_lastPage, _pages, lastPageParam) =>\n          lastPageParam + 5,\n        initialPageParam: 10,\n        pages: 3,\n      })\n\n      const result = queryClient.getQueryData(key)\n\n      expect(result).toEqual({\n        pages: ['10', '15', '20'],\n        pageParams: [10, 15, 20],\n      })\n    })\n\n    test('should stop prefetching if getNextPageParam returns undefined', async () => {\n      const key = queryKey()\n      let count = 0\n\n      await queryClient.prefetchInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) => String(pageParam),\n        getNextPageParam: (_lastPage, _pages, lastPageParam) => {\n          count++\n          return lastPageParam >= 20 ? undefined : lastPageParam + 5\n        },\n        initialPageParam: 10,\n        pages: 5,\n      })\n\n      const result = queryClient.getQueryData(key)\n\n      expect(result).toEqual({\n        pages: ['10', '15', '20'],\n        pageParams: [10, 15, 20],\n      })\n\n      // this check ensures we're exiting the fetch loop early\n      expect(count).toBe(3)\n    })\n  })\n\n  describe('prefetchQuery', () => {\n    test('should not type-error with strict query key', async () => {\n      type StrictData = 'data'\n      type StrictQueryKey = ['strict', ...ReturnType<typeof queryKey>]\n      const key: StrictQueryKey = ['strict', ...queryKey()]\n\n      const fetchFn: QueryFunction<StrictData, StrictQueryKey> = () =>\n        Promise.resolve('data')\n\n      await queryClient.prefetchQuery<\n        StrictData,\n        any,\n        StrictData,\n        StrictQueryKey\n      >({ queryKey: key, queryFn: fetchFn })\n\n      const result = queryClient.getQueryData(key)\n\n      expect(result).toEqual('data')\n    })\n\n    test('should return undefined when an error is thrown', async () => {\n      const key = queryKey()\n\n      const result = await queryClient.prefetchQuery({\n        queryKey: key,\n        queryFn: (): Promise<unknown> => {\n          throw new Error('error')\n        },\n        retry: false,\n      })\n\n      expect(result).toBeUndefined()\n    })\n\n    test('should be garbage collected after gcTime if unused', async () => {\n      const key = queryKey()\n\n      await queryClient.prefetchQuery({\n        queryKey: key,\n        queryFn: () => 'data',\n        gcTime: 10,\n      })\n      expect(queryCache.find({ queryKey: key })).toBeDefined()\n      await vi.advanceTimersByTimeAsync(15)\n      expect(queryCache.find({ queryKey: key })).not.toBeDefined()\n    })\n  })\n\n  describe('removeQueries', () => {\n    test('should not crash when exact is provided', async () => {\n      const key = queryKey()\n\n      const fetchFn = () => Promise.resolve('data')\n\n      // check the query was added to the cache\n      await queryClient.prefetchQuery({ queryKey: key, queryFn: fetchFn })\n      expect(queryCache.find({ queryKey: key })).toBeTruthy()\n\n      // check the error doesn't occur\n      expect(() =>\n        queryClient.removeQueries({ queryKey: key, exact: true }),\n      ).not.toThrow()\n\n      // check query was successful removed\n      expect(queryCache.find({ queryKey: key })).toBeFalsy()\n    })\n  })\n\n  describe('cancelQueries', () => {\n    test('should revert queries to their previous state', async () => {\n      const key1 = queryKey()\n      queryClient.setQueryData(key1, 'data')\n\n      const pending = queryClient.fetchQuery({\n        queryKey: key1,\n        queryFn: () => sleep(1000).then(() => 'data2'),\n      })\n\n      await vi.advanceTimersByTimeAsync(10)\n\n      await queryClient.cancelQueries()\n\n      // with previous data present, imperative fetch should resolve to that data after cancel\n      await expect(pending).resolves.toBe('data')\n\n      const state1 = queryClient.getQueryState(key1)\n      expect(state1).toMatchObject({\n        data: 'data',\n        status: 'success',\n      })\n    })\n\n    test('should not revert if revert option is set to false', async () => {\n      const key1 = queryKey()\n      await queryClient.fetchQuery({\n        queryKey: key1,\n        queryFn: () => 'data',\n      })\n      queryClient.prefetchQuery({\n        queryKey: key1,\n        queryFn: () => sleep(1000).then(() => 'data2'),\n      })\n      await vi.advanceTimersByTimeAsync(10)\n      await queryClient.cancelQueries({ queryKey: key1 }, { revert: false })\n      const state1 = queryClient.getQueryState(key1)\n      expect(state1).toMatchObject({\n        status: 'error',\n      })\n    })\n\n    test('should throw CancelledError for imperative methods when initial fetch is cancelled', async () => {\n      const key = queryKey()\n\n      const promise = queryClient.fetchQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(50)\n          return 25\n        },\n      })\n\n      await vi.advanceTimersByTimeAsync(10)\n\n      await queryClient.cancelQueries({ queryKey: key })\n\n      // we have to reject here because we can't resolve with `undefined`\n      // the alternative would be a never-ending promise\n      await expect(promise).rejects.toBeInstanceOf(CancelledError)\n\n      // however, the query was correctly reverted to pending state\n      expect(queryClient.getQueryState(key)).toMatchObject({\n        status: 'pending',\n        fetchStatus: 'idle',\n        data: undefined,\n        error: null,\n      })\n    })\n  })\n\n  describe('refetchQueries', () => {\n    test('should not refetch if all observers are disabled', async () => {\n      const key = queryKey()\n      const queryFn = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data')\n      await queryClient.fetchQuery({ queryKey: key, queryFn })\n      const observer1 = new QueryObserver(queryClient, {\n        queryKey: key,\n        queryFn,\n        enabled: false,\n      })\n      observer1.subscribe(() => undefined)\n      await queryClient.refetchQueries()\n      observer1.destroy()\n      expect(queryFn).toHaveBeenCalledTimes(1)\n    })\n    test('should refetch if at least one observer is enabled', async () => {\n      const key = queryKey()\n      const queryFn = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data')\n      await queryClient.fetchQuery({ queryKey: key, queryFn })\n      const observer1 = new QueryObserver(queryClient, {\n        queryKey: key,\n        queryFn,\n        enabled: false,\n      })\n      const observer2 = new QueryObserver(queryClient, {\n        queryKey: key,\n        queryFn,\n        refetchOnMount: false,\n      })\n      observer1.subscribe(() => undefined)\n      observer2.subscribe(() => undefined)\n      await queryClient.refetchQueries()\n      observer1.destroy()\n      observer2.destroy()\n      expect(queryFn).toHaveBeenCalledTimes(2)\n    })\n    test('should refetch all queries when no arguments are given', async () => {\n      const key1 = queryKey()\n      const key2 = queryKey()\n      const queryFn1 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data1')\n      const queryFn2 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data2')\n      await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })\n      await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })\n      const observer1 = new QueryObserver(queryClient, {\n        queryKey: key1,\n        queryFn: queryFn1,\n        staleTime: Infinity,\n        initialData: 'initial',\n      })\n      const observer2 = new QueryObserver(queryClient, {\n        queryKey: key1,\n        queryFn: queryFn1,\n        staleTime: Infinity,\n        initialData: 'initial',\n      })\n      observer1.subscribe(() => undefined)\n      observer2.subscribe(() => undefined)\n      await queryClient.refetchQueries()\n      observer1.destroy()\n      observer2.destroy()\n      expect(queryFn1).toHaveBeenCalledTimes(2)\n      expect(queryFn2).toHaveBeenCalledTimes(2)\n    })\n\n    test('should be able to refetch all fresh queries', async () => {\n      const key1 = queryKey()\n      const key2 = queryKey()\n      const queryFn1 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data1')\n      const queryFn2 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data2')\n      await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })\n      await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })\n      const observer = new QueryObserver(queryClient, {\n        queryKey: key1,\n        queryFn: queryFn1,\n        staleTime: Infinity,\n      })\n      const unsubscribe = observer.subscribe(() => undefined)\n      await queryClient.refetchQueries({ type: 'active', stale: false })\n      unsubscribe()\n      expect(queryFn1).toHaveBeenCalledTimes(2)\n      expect(queryFn2).toHaveBeenCalledTimes(1)\n    })\n\n    test('should be able to refetch all stale queries', async () => {\n      const key1 = queryKey()\n      const key2 = queryKey()\n      const queryFn1 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data1')\n      const queryFn2 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data2')\n      await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })\n      await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })\n      const observer = new QueryObserver(queryClient, {\n        queryKey: key1,\n        queryFn: queryFn1,\n      })\n      const unsubscribe = observer.subscribe(() => undefined)\n      queryClient.invalidateQueries({ queryKey: key1 })\n      await queryClient.refetchQueries({ stale: true })\n      unsubscribe()\n      // fetchQuery, observer mount, invalidation (cancels observer mount) and refetch\n      expect(queryFn1).toHaveBeenCalledTimes(4)\n      expect(queryFn2).toHaveBeenCalledTimes(1)\n    })\n\n    test('should be able to refetch all stale and active queries', async () => {\n      const key1 = queryKey()\n      const key2 = queryKey()\n      const queryFn1 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data1')\n      const queryFn2 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data2')\n      await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })\n      await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })\n      queryClient.invalidateQueries({ queryKey: key1 })\n      const observer = new QueryObserver(queryClient, {\n        queryKey: key1,\n        queryFn: queryFn1,\n      })\n      const unsubscribe = observer.subscribe(() => undefined)\n      await queryClient.refetchQueries(\n        { type: 'active', stale: true },\n        { cancelRefetch: false },\n      )\n      unsubscribe()\n      expect(queryFn1).toHaveBeenCalledTimes(2)\n      expect(queryFn2).toHaveBeenCalledTimes(1)\n    })\n\n    test('should be able to refetch all active and inactive queries (queryClient.refetchQueries()', async () => {\n      const key1 = queryKey()\n      const key2 = queryKey()\n      const queryFn1 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data1')\n      const queryFn2 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data2')\n      await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })\n      await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })\n      const observer = new QueryObserver(queryClient, {\n        queryKey: key1,\n        queryFn: queryFn1,\n        staleTime: Infinity,\n      })\n      const unsubscribe = observer.subscribe(() => undefined)\n      await queryClient.refetchQueries()\n      unsubscribe()\n      expect(queryFn1).toHaveBeenCalledTimes(2)\n      expect(queryFn2).toHaveBeenCalledTimes(2)\n    })\n\n    test('should be able to refetch all active and inactive queries (queryClient.refetchQueries({ type: \"all\" }))', async () => {\n      const key1 = queryKey()\n      const key2 = queryKey()\n      const queryFn1 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data1')\n      const queryFn2 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data2')\n      await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })\n      await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })\n      const observer = new QueryObserver(queryClient, {\n        queryKey: key1,\n        queryFn: queryFn1,\n        staleTime: Infinity,\n      })\n      const unsubscribe = observer.subscribe(() => undefined)\n      await queryClient.refetchQueries({ type: 'all' })\n      unsubscribe()\n      expect(queryFn1).toHaveBeenCalledTimes(2)\n      expect(queryFn2).toHaveBeenCalledTimes(2)\n    })\n\n    test('should be able to refetch only active queries', async () => {\n      const key1 = queryKey()\n      const key2 = queryKey()\n      const queryFn1 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data1')\n      const queryFn2 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data2')\n      await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })\n      await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })\n      const observer = new QueryObserver(queryClient, {\n        queryKey: key1,\n        queryFn: queryFn1,\n        staleTime: Infinity,\n      })\n      const unsubscribe = observer.subscribe(() => undefined)\n      await queryClient.refetchQueries({ type: 'active' })\n      unsubscribe()\n      expect(queryFn1).toHaveBeenCalledTimes(2)\n      expect(queryFn2).toHaveBeenCalledTimes(1)\n    })\n\n    test('should be able to refetch only inactive queries', async () => {\n      const key1 = queryKey()\n      const key2 = queryKey()\n      const queryFn1 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data1')\n      const queryFn2 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data2')\n      await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })\n      await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })\n      const observer = new QueryObserver(queryClient, {\n        queryKey: key1,\n        queryFn: queryFn1,\n        staleTime: Infinity,\n      })\n      const unsubscribe = observer.subscribe(() => undefined)\n      await queryClient.refetchQueries({ type: 'inactive' })\n      unsubscribe()\n      expect(queryFn1).toHaveBeenCalledTimes(1)\n      expect(queryFn2).toHaveBeenCalledTimes(2)\n    })\n\n    test('should throw an error if throwOnError option is set to true', async () => {\n      const key1 = queryKey()\n      const queryFnError = () => Promise.reject<unknown>('error')\n      try {\n        await queryClient.fetchQuery({\n          queryKey: key1,\n          queryFn: queryFnError,\n          retry: false,\n        })\n      } catch {}\n      let error: any\n      try {\n        await queryClient.refetchQueries(\n          { queryKey: key1 },\n          { throwOnError: true },\n        )\n      } catch (err) {\n        error = err\n      }\n      expect(error).toEqual('error')\n    })\n\n    test('should resolve Promise immediately if query is paused', async () => {\n      const key1 = queryKey()\n      const queryFn1 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data1')\n      await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      await queryClient.refetchQueries({ queryKey: key1 })\n\n      // if we reach this point, the test succeeds because the Promise was resolved immediately\n      expect(queryFn1).toHaveBeenCalledTimes(1)\n      onlineMock.mockRestore()\n    })\n\n    test('should refetch if query we are offline but query networkMode is always', async () => {\n      const key1 = queryKey()\n      queryClient.setQueryDefaults(key1, { networkMode: 'always' })\n      const queryFn1 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data1')\n      await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      await queryClient.refetchQueries({ queryKey: key1 })\n\n      // initial fetch + refetch (even though we are offline)\n      expect(queryFn1).toHaveBeenCalledTimes(2)\n      onlineMock.mockRestore()\n    })\n\n    test('should not refetch static queries', async () => {\n      const key = queryKey()\n      const queryFn = vi.fn(() => 'data1')\n      await queryClient.fetchQuery({ queryKey: key, queryFn: queryFn })\n\n      expect(queryFn).toHaveBeenCalledTimes(1)\n\n      const observer = new QueryObserver(queryClient, {\n        queryKey: key,\n        queryFn,\n        staleTime: 'static',\n      })\n      const unsubscribe = observer.subscribe(() => undefined)\n      await queryClient.refetchQueries()\n\n      expect(queryFn).toHaveBeenCalledTimes(1)\n      unsubscribe()\n    })\n  })\n\n  describe('invalidateQueries', () => {\n    test('should refetch active queries by default', async () => {\n      const key1 = queryKey()\n      const key2 = queryKey()\n      const queryFn1 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data1')\n      const queryFn2 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data2')\n      await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })\n      await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })\n      const observer = new QueryObserver(queryClient, {\n        queryKey: key1,\n        queryFn: queryFn1,\n        staleTime: Infinity,\n      })\n      const unsubscribe = observer.subscribe(() => undefined)\n      queryClient.invalidateQueries({ queryKey: key1 })\n      unsubscribe()\n      expect(queryFn1).toHaveBeenCalledTimes(2)\n      expect(queryFn2).toHaveBeenCalledTimes(1)\n    })\n\n    test('should not refetch inactive queries by default', async () => {\n      const key1 = queryKey()\n      const key2 = queryKey()\n      const queryFn1 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data1')\n      const queryFn2 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data2')\n      await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })\n      await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })\n      const observer = new QueryObserver(queryClient, {\n        queryKey: key1,\n        enabled: false,\n        staleTime: Infinity,\n      })\n      const unsubscribe = observer.subscribe(() => undefined)\n      queryClient.invalidateQueries({ queryKey: key1 })\n      unsubscribe()\n      expect(queryFn1).toHaveBeenCalledTimes(1)\n      expect(queryFn2).toHaveBeenCalledTimes(1)\n    })\n\n    test('should not refetch active queries when \"refetch\" is \"none\"', async () => {\n      const key1 = queryKey()\n      const key2 = queryKey()\n      const queryFn1 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data1')\n      const queryFn2 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data2')\n      await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })\n      await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })\n      const observer = new QueryObserver(queryClient, {\n        queryKey: key1,\n        queryFn: queryFn1,\n        staleTime: Infinity,\n      })\n      const unsubscribe = observer.subscribe(() => undefined)\n      queryClient.invalidateQueries({\n        queryKey: key1,\n        refetchType: 'none',\n      })\n      unsubscribe()\n      expect(queryFn1).toHaveBeenCalledTimes(1)\n      expect(queryFn2).toHaveBeenCalledTimes(1)\n    })\n\n    test('should refetch inactive queries when \"refetch\" is \"inactive\"', async () => {\n      const key1 = queryKey()\n      const key2 = queryKey()\n      const queryFn1 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data1')\n      const queryFn2 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data2')\n      await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })\n      await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })\n      const observer = new QueryObserver(queryClient, {\n        queryKey: key1,\n        queryFn: queryFn1,\n        staleTime: Infinity,\n        refetchOnMount: false,\n      })\n      const unsubscribe = observer.subscribe(() => undefined)\n      unsubscribe()\n\n      await queryClient.invalidateQueries({\n        queryKey: key1,\n        refetchType: 'inactive',\n      })\n      expect(queryFn1).toHaveBeenCalledTimes(2)\n      expect(queryFn2).toHaveBeenCalledTimes(1)\n    })\n\n    test('should refetch active and inactive queries when \"refetch\" is \"all\"', async () => {\n      const key1 = queryKey()\n      const key2 = queryKey()\n      const queryFn1 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data1')\n      const queryFn2 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data2')\n      await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })\n      await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })\n      const observer = new QueryObserver(queryClient, {\n        queryKey: key1,\n        queryFn: queryFn1,\n        staleTime: Infinity,\n      })\n      const unsubscribe = observer.subscribe(() => undefined)\n      queryClient.invalidateQueries({\n        refetchType: 'all',\n      })\n      unsubscribe()\n      expect(queryFn1).toHaveBeenCalledTimes(2)\n      expect(queryFn2).toHaveBeenCalledTimes(2)\n    })\n\n    test('should not refetch disabled inactive queries even if \"refetchType\" is \"all', async () => {\n      const queryFn = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data1')\n      const observer = new QueryObserver(queryClient, {\n        queryKey: queryKey(),\n        queryFn: queryFn,\n        staleTime: Infinity,\n        enabled: false,\n      })\n      const unsubscribe = observer.subscribe(() => undefined)\n      unsubscribe()\n      await queryClient.invalidateQueries({\n        refetchType: 'all',\n      })\n      expect(queryFn).toHaveBeenCalledTimes(0)\n    })\n\n    test('should not refetch inactive queries that have a skipToken queryFn even if \"refetchType\" is \"all', async () => {\n      const key = queryKey()\n      const observer = new QueryObserver(queryClient, {\n        queryKey: key,\n        queryFn: skipToken,\n        staleTime: Infinity,\n      })\n\n      queryClient.setQueryData(key, 'data1')\n\n      const unsubscribe = observer.subscribe(() => undefined)\n      unsubscribe()\n\n      expect(queryClient.getQueryState(key)?.dataUpdateCount).toBe(1)\n\n      await queryClient.invalidateQueries({\n        refetchType: 'all',\n      })\n\n      expect(queryClient.getQueryState(key)?.dataUpdateCount).toBe(1)\n    })\n\n    test('should cancel ongoing fetches if cancelRefetch option is set (default value)', async () => {\n      const key = queryKey()\n      const abortFn = vi.fn()\n      let fetchCount = 0\n      const observer = new QueryObserver(queryClient, {\n        queryKey: key,\n        queryFn: ({ signal }) =>\n          new Promise((resolve) => {\n            fetchCount++\n            setTimeout(() => resolve(5), 10)\n            signal.addEventListener('abort', abortFn)\n          }),\n        initialData: 1,\n      })\n      observer.subscribe(() => undefined)\n\n      queryClient.refetchQueries()\n      await vi.advanceTimersByTimeAsync(10)\n      observer.destroy()\n      expect(abortFn).toHaveBeenCalledTimes(1)\n      expect(fetchCount).toBe(2)\n    })\n\n    test('should not cancel ongoing fetches if cancelRefetch option is set to false', async () => {\n      const key = queryKey()\n      const abortFn = vi.fn()\n      let fetchCount = 0\n      const observer = new QueryObserver(queryClient, {\n        queryKey: key,\n        queryFn: ({ signal }) => {\n          return new Promise((resolve) => {\n            fetchCount++\n            setTimeout(() => resolve(5), 10)\n            signal.addEventListener('abort', abortFn)\n          })\n        },\n        initialData: 1,\n      })\n      observer.subscribe(() => undefined)\n\n      queryClient.refetchQueries(undefined, { cancelRefetch: false })\n      await vi.advanceTimersByTimeAsync(10)\n      observer.destroy()\n      expect(abortFn).toHaveBeenCalledTimes(0)\n      expect(fetchCount).toBe(1)\n    })\n\n    test('should not refetch static queries after invalidation', async () => {\n      const key = queryKey()\n      const queryFn = vi.fn(() => 'data1')\n      await queryClient.fetchQuery({ queryKey: key, queryFn: queryFn })\n\n      expect(queryFn).toHaveBeenCalledTimes(1)\n\n      const observer = new QueryObserver(queryClient, {\n        queryKey: key,\n        queryFn,\n        staleTime: 'static',\n      })\n      const unsubscribe = observer.subscribe(() => undefined)\n      await queryClient.invalidateQueries()\n\n      expect(queryFn).toHaveBeenCalledTimes(1)\n      unsubscribe()\n    })\n  })\n\n  describe('resetQueries', () => {\n    test('should notify listeners when a query is reset', async () => {\n      const key = queryKey()\n\n      const callback = vi.fn()\n\n      await queryClient.prefetchQuery({ queryKey: key, queryFn: () => 'data' })\n\n      queryCache.subscribe(callback)\n\n      queryClient.resetQueries({ queryKey: key })\n\n      expect(callback).toHaveBeenCalled()\n    })\n\n    test('should reset query', async () => {\n      const key = queryKey()\n\n      await queryClient.prefetchQuery({ queryKey: key, queryFn: () => 'data' })\n\n      let state = queryClient.getQueryState(key)\n      expect(state?.data).toEqual('data')\n      expect(state?.status).toEqual('success')\n\n      queryClient.resetQueries({ queryKey: key })\n\n      state = queryClient.getQueryState(key)\n\n      expect(state).toBeTruthy()\n      expect(state?.data).toBeUndefined()\n      expect(state?.status).toEqual('pending')\n      expect(state?.fetchStatus).toEqual('idle')\n    })\n\n    test('should reset query data to initial data if set', async () => {\n      const key = queryKey()\n\n      await queryClient.prefetchQuery({\n        queryKey: key,\n        queryFn: () => 'data',\n        initialData: 'initial',\n      })\n\n      let state = queryClient.getQueryState(key)\n      expect(state?.data).toEqual('data')\n\n      queryClient.resetQueries({ queryKey: key })\n\n      state = queryClient.getQueryState(key)\n\n      expect(state).toBeTruthy()\n      expect(state?.data).toEqual('initial')\n    })\n\n    test('should refetch all active queries', async () => {\n      const key1 = queryKey()\n      const key2 = queryKey()\n      const key3 = queryKey()\n      const queryFn1 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data1')\n      const queryFn2 = vi\n        .fn<(...args: Array<unknown>) => string>()\n        .mockReturnValue('data2')\n      const observer1 = new QueryObserver(queryClient, {\n        queryKey: key1,\n        queryFn: queryFn1,\n        enabled: true,\n      })\n      const observer2 = new QueryObserver(queryClient, {\n        queryKey: key2,\n        queryFn: queryFn2,\n        enabled: false,\n      })\n      const observer3 = new QueryObserver(queryClient, {\n        queryKey: key3,\n        queryFn: skipToken,\n      })\n      let didSkipTokenRun = false\n      observer1.subscribe(() => undefined)\n      observer2.subscribe(() => undefined)\n      observer3.subscribe(() => (didSkipTokenRun = true))\n      await queryClient.resetQueries()\n      observer3.destroy()\n      observer2.destroy()\n      observer1.destroy()\n      expect(queryFn1).toHaveBeenCalledTimes(2)\n      expect(queryFn2).toHaveBeenCalledTimes(0)\n      expect(didSkipTokenRun).toBe(false)\n    })\n  })\n\n  describe('focusManager and onlineManager', () => {\n    afterEach(() => {\n      onlineManager.setOnline(true)\n      focusManager.setFocused(undefined)\n    })\n    test('should notify queryCache and mutationCache if focused', async () => {\n      const testClient = new QueryClient()\n      testClient.mount()\n\n      const queryCacheOnFocusSpy = vi.spyOn(\n        testClient.getQueryCache(),\n        'onFocus',\n      )\n      const queryCacheOnOnlineSpy = vi.spyOn(\n        testClient.getQueryCache(),\n        'onOnline',\n      )\n      const mutationCacheResumePausedMutationsSpy = vi.spyOn(\n        testClient.getMutationCache(),\n        'resumePausedMutations',\n      )\n\n      focusManager.setFocused(false)\n      expect(queryCacheOnFocusSpy).not.toHaveBeenCalled()\n      expect(mutationCacheResumePausedMutationsSpy).not.toHaveBeenCalled()\n\n      focusManager.setFocused(true)\n      await vi.advanceTimersByTimeAsync(0)\n      expect(queryCacheOnFocusSpy).toHaveBeenCalledTimes(1)\n      expect(mutationCacheResumePausedMutationsSpy).toHaveBeenCalledTimes(1)\n\n      expect(queryCacheOnOnlineSpy).not.toHaveBeenCalled()\n\n      queryCacheOnFocusSpy.mockRestore()\n      mutationCacheResumePausedMutationsSpy.mockRestore()\n      queryCacheOnOnlineSpy.mockRestore()\n    })\n\n    test('should notify queryCache and mutationCache if online', async () => {\n      const testClient = new QueryClient()\n      testClient.mount()\n\n      const queryCacheOnFocusSpy = vi.spyOn(\n        testClient.getQueryCache(),\n        'onFocus',\n      )\n      const queryCacheOnOnlineSpy = vi.spyOn(\n        testClient.getQueryCache(),\n        'onOnline',\n      )\n      const mutationCacheResumePausedMutationsSpy = vi.spyOn(\n        testClient.getMutationCache(),\n        'resumePausedMutations',\n      )\n\n      onlineManager.setOnline(false)\n      expect(queryCacheOnOnlineSpy).not.toHaveBeenCalled()\n      expect(mutationCacheResumePausedMutationsSpy).not.toHaveBeenCalled()\n\n      onlineManager.setOnline(true)\n      await vi.advanceTimersByTimeAsync(0)\n      expect(queryCacheOnOnlineSpy).toHaveBeenCalledTimes(1)\n\n      expect(mutationCacheResumePausedMutationsSpy).toHaveBeenCalledTimes(1)\n\n      expect(queryCacheOnFocusSpy).not.toHaveBeenCalled()\n\n      queryCacheOnFocusSpy.mockRestore()\n      queryCacheOnOnlineSpy.mockRestore()\n      mutationCacheResumePausedMutationsSpy.mockRestore()\n    })\n\n    test('should resume paused mutations when coming online', async () => {\n      const consoleMock = vi.spyOn(console, 'error')\n      consoleMock.mockImplementation(() => undefined)\n      onlineManager.setOnline(false)\n\n      const observer1 = new MutationObserver(queryClient, {\n        mutationFn: () => Promise.resolve(1),\n      })\n\n      const observer2 = new MutationObserver(queryClient, {\n        mutationFn: () => Promise.resolve(2),\n      })\n      void observer1.mutate()\n      void observer2.mutate()\n\n      expect(observer1.getCurrentResult().isPaused).toBeTruthy()\n      expect(observer2.getCurrentResult().isPaused).toBeTruthy()\n\n      onlineManager.setOnline(true)\n\n      await vi.advanceTimersByTimeAsync(0)\n      expect(observer1.getCurrentResult().status).toBe('success')\n      expect(observer2.getCurrentResult().status).toBe('success')\n    })\n\n    test('should resume paused mutations in parallel', async () => {\n      onlineManager.setOnline(false)\n\n      const orders: Array<string> = []\n\n      const observer1 = new MutationObserver(queryClient, {\n        mutationFn: async () => {\n          orders.push('1start')\n          await sleep(50)\n          orders.push('1end')\n          return 1\n        },\n      })\n\n      const observer2 = new MutationObserver(queryClient, {\n        mutationFn: async () => {\n          orders.push('2start')\n          await sleep(20)\n          orders.push('2end')\n          return 2\n        },\n      })\n      void observer1.mutate()\n      void observer2.mutate()\n\n      expect(observer1.getCurrentResult().isPaused).toBeTruthy()\n      expect(observer2.getCurrentResult().isPaused).toBeTruthy()\n\n      onlineManager.setOnline(true)\n\n      await vi.advanceTimersByTimeAsync(50)\n      expect(observer1.getCurrentResult().status).toBe('success')\n      expect(observer2.getCurrentResult().status).toBe('success')\n\n      expect(orders).toEqual(['1start', '2start', '2end', '1end'])\n    })\n\n    test('should resume paused mutations one after the other when in the same scope when invoked manually at the same time', async () => {\n      const consoleMock = vi.spyOn(console, 'error')\n      consoleMock.mockImplementation(() => undefined)\n      onlineManager.setOnline(false)\n\n      const orders: Array<string> = []\n\n      const observer1 = new MutationObserver(queryClient, {\n        scope: {\n          id: 'scope',\n        },\n        mutationFn: async () => {\n          orders.push('1start')\n          await sleep(50)\n          orders.push('1end')\n          return 1\n        },\n      })\n\n      const observer2 = new MutationObserver(queryClient, {\n        scope: {\n          id: 'scope',\n        },\n        mutationFn: async () => {\n          orders.push('2start')\n          await sleep(20)\n          orders.push('2end')\n          return 2\n        },\n      })\n      void observer1.mutate()\n      void observer2.mutate()\n\n      expect(observer1.getCurrentResult().isPaused).toBeTruthy()\n      expect(observer2.getCurrentResult().isPaused).toBeTruthy()\n\n      onlineManager.setOnline(true)\n      void queryClient.resumePausedMutations()\n\n      await vi.advanceTimersByTimeAsync(70)\n      expect(observer1.getCurrentResult().status).toBe('success')\n      expect(observer2.getCurrentResult().status).toBe('success')\n\n      expect(orders).toEqual(['1start', '1end', '2start', '2end'])\n    })\n\n    test('should resumePausedMutations when coming online after having called resumePausedMutations while offline', async () => {\n      const consoleMock = vi.spyOn(console, 'error')\n      consoleMock.mockImplementation(() => undefined)\n      onlineManager.setOnline(false)\n\n      const observer = new MutationObserver(queryClient, {\n        mutationFn: () => Promise.resolve(1),\n      })\n\n      void observer.mutate()\n\n      expect(observer.getCurrentResult().isPaused).toBeTruthy()\n\n      await queryClient.resumePausedMutations()\n\n      // still paused because we are still offline\n      expect(observer.getCurrentResult().isPaused).toBeTruthy()\n\n      onlineManager.setOnline(true)\n\n      await vi.advanceTimersByTimeAsync(0)\n      expect(observer.getCurrentResult().status).toBe('success')\n    })\n\n    test('should resumePausedMutations when coming online after having restored cache (and resumed) while offline', async () => {\n      const consoleMock = vi.spyOn(console, 'error')\n      consoleMock.mockImplementation(() => undefined)\n      onlineManager.setOnline(false)\n\n      const observer = new MutationObserver(queryClient, {\n        mutationFn: () => Promise.resolve(1),\n      })\n\n      void observer.mutate()\n\n      expect(observer.getCurrentResult().isPaused).toBeTruthy()\n\n      const state = dehydrate(queryClient)\n\n      const newQueryClient = new QueryClient({\n        defaultOptions: {\n          mutations: {\n            mutationFn: () => Promise.resolve(1),\n          },\n        },\n      })\n\n      newQueryClient.mount()\n\n      hydrate(newQueryClient, state)\n\n      // still paused because we are still offline\n      expect(\n        newQueryClient.getMutationCache().getAll()[0]?.state.isPaused,\n      ).toBeTruthy()\n\n      await newQueryClient.resumePausedMutations()\n\n      onlineManager.setOnline(true)\n\n      await vi.advanceTimersByTimeAsync(0)\n      expect(newQueryClient.getMutationCache().getAll()[0]?.state.status).toBe(\n        'success',\n      )\n\n      newQueryClient.unmount()\n    })\n\n    test('should notify queryCache after resumePausedMutations has finished when coming online', async () => {\n      const key = queryKey()\n\n      let count = 0\n      const results: Array<string> = []\n\n      const queryObserver = new QueryObserver(queryClient, {\n        queryKey: key,\n        queryFn: async () => {\n          count++\n          results.push('data' + count)\n          await sleep(10)\n          return 'data' + count\n        },\n      })\n\n      const unsubscribe = queryObserver.subscribe(() => undefined)\n\n      await vi.advanceTimersByTimeAsync(10)\n      expect(queryClient.getQueryData(key)).toBe('data1')\n\n      onlineManager.setOnline(false)\n\n      const observer = new MutationObserver(queryClient, {\n        mutationFn: async () => {\n          results.push('mutation1-start')\n          await sleep(50)\n          results.push('mutation1-end')\n          return 1\n        },\n      })\n\n      void observer.mutate()\n\n      const observer2 = new MutationObserver(queryClient, {\n        scope: {\n          id: 'scope',\n        },\n        mutationFn: async () => {\n          results.push('mutation2-start')\n          await sleep(50)\n          results.push('mutation2-end')\n          return 2\n        },\n      })\n\n      void observer2.mutate()\n\n      const observer3 = new MutationObserver(queryClient, {\n        scope: {\n          id: 'scope',\n        },\n        mutationFn: async () => {\n          results.push('mutation3-start')\n          await sleep(50)\n          results.push('mutation3-end')\n          return 3\n        },\n      })\n\n      void observer3.mutate()\n\n      expect(observer.getCurrentResult().isPaused).toBeTruthy()\n      expect(observer2.getCurrentResult().isPaused).toBeTruthy()\n      expect(observer3.getCurrentResult().isPaused).toBeTruthy()\n      onlineManager.setOnline(true)\n\n      await vi.advanceTimersByTimeAsync(110)\n      expect(queryClient.getQueryData(key)).toBe('data2')\n\n      // refetch from coming online should happen after mutations have finished\n      expect(results).toStrictEqual([\n        'data1',\n        'mutation1-start',\n        'mutation2-start',\n        'mutation1-end',\n        'mutation2-end',\n        'mutation3-start', // 3 starts after 2 because they are in the same scope\n        'mutation3-end',\n        'data2',\n      ])\n\n      unsubscribe()\n    })\n\n    test('should notify queryCache and mutationCache after multiple mounts and single unmount', async () => {\n      const testClient = new QueryClient()\n      testClient.mount()\n      testClient.mount()\n      testClient.unmount()\n\n      const queryCacheOnFocusSpy = vi.spyOn(\n        testClient.getQueryCache(),\n        'onFocus',\n      )\n      const queryCacheOnOnlineSpy = vi.spyOn(\n        testClient.getQueryCache(),\n        'onOnline',\n      )\n      const mutationCacheResumePausedMutationsSpy = vi.spyOn(\n        testClient.getMutationCache(),\n        'resumePausedMutations',\n      )\n\n      onlineManager.setOnline(false)\n      onlineManager.setOnline(true)\n      await vi.advanceTimersByTimeAsync(0)\n      expect(queryCacheOnOnlineSpy).toHaveBeenCalledTimes(1)\n      expect(mutationCacheResumePausedMutationsSpy).toHaveBeenCalledTimes(1)\n\n      focusManager.setFocused(true)\n      await vi.advanceTimersByTimeAsync(0)\n      expect(queryCacheOnFocusSpy).toHaveBeenCalledTimes(1)\n      expect(mutationCacheResumePausedMutationsSpy).toHaveBeenCalledTimes(2)\n\n      queryCacheOnFocusSpy.mockRestore()\n      queryCacheOnOnlineSpy.mockRestore()\n      mutationCacheResumePausedMutationsSpy.mockRestore()\n      focusManager.setFocused(undefined)\n      onlineManager.setOnline(true)\n    })\n\n    test('should not notify queryCache and mutationCache after multiple mounts/unmounts', () => {\n      const testClient = new QueryClient()\n      testClient.mount()\n      testClient.mount()\n      testClient.unmount()\n      testClient.unmount()\n\n      const queryCacheOnFocusSpy = vi.spyOn(\n        testClient.getQueryCache(),\n        'onFocus',\n      )\n      const queryCacheOnOnlineSpy = vi.spyOn(\n        testClient.getQueryCache(),\n        'onOnline',\n      )\n      const mutationCacheResumePausedMutationsSpy = vi.spyOn(\n        testClient.getMutationCache(),\n        'resumePausedMutations',\n      )\n\n      onlineManager.setOnline(true)\n      expect(queryCacheOnOnlineSpy).not.toHaveBeenCalled()\n      expect(mutationCacheResumePausedMutationsSpy).not.toHaveBeenCalled()\n\n      focusManager.setFocused(true)\n      expect(queryCacheOnFocusSpy).not.toHaveBeenCalled()\n      expect(mutationCacheResumePausedMutationsSpy).not.toHaveBeenCalled()\n\n      queryCacheOnFocusSpy.mockRestore()\n      queryCacheOnOnlineSpy.mockRestore()\n      mutationCacheResumePausedMutationsSpy.mockRestore()\n      focusManager.setFocused(undefined)\n      onlineManager.setOnline(true)\n    })\n  })\n\n  describe('setMutationDefaults', () => {\n    test('should update existing mutation defaults', () => {\n      const key = queryKey()\n      const mutationOptions1 = { mutationFn: () => Promise.resolve('data') }\n      const mutationOptions2 = { retry: false }\n      queryClient.setMutationDefaults(key, mutationOptions1)\n      queryClient.setMutationDefaults(key, mutationOptions2)\n      expect(queryClient.getMutationDefaults(key)).toMatchObject(\n        mutationOptions2,\n      )\n    })\n\n    test('should return only matching defaults when multiple mutation defaults are set', () => {\n      const key1 = queryKey()\n      const key2 = queryKey()\n      const mutationOptions1 = { retry: 1 }\n      const mutationOptions2 = { retry: 2 }\n      queryClient.setMutationDefaults(key1, mutationOptions1)\n      queryClient.setMutationDefaults(key2, mutationOptions2)\n\n      expect(queryClient.getMutationDefaults(key1)).toMatchObject(\n        mutationOptions1,\n      )\n      expect(queryClient.getMutationDefaults(key2)).toMatchObject(\n        mutationOptions2,\n      )\n    })\n  })\n})\n"
  },
  {
    "path": "packages/query-core/src/__tests__/queryObserver.test-d.tsx",
    "content": "import { afterEach, beforeEach, describe, expectTypeOf, it } from 'vitest'\nimport { queryKey } from '@tanstack/query-test-utils'\nimport { QueryClient, QueryObserver } from '..'\nimport type { DefaultError } from '..'\n\ndescribe('queryObserver', () => {\n  let queryClient: QueryClient\n\n  beforeEach(() => {\n    queryClient = new QueryClient()\n    queryClient.mount()\n  })\n\n  afterEach(() => {\n    queryClient.clear()\n  })\n\n  it('should be inferred as a correct result type', () => {\n    const observer = new QueryObserver(queryClient, {\n      queryKey: queryKey(),\n      queryFn: () => Promise.resolve({ value: 'data' }),\n    })\n\n    const result = observer.getCurrentResult()\n\n    if (result.isPending) {\n      expectTypeOf(result.data).toEqualTypeOf<undefined>()\n      expectTypeOf(result.error).toEqualTypeOf<null>()\n      expectTypeOf(result.isError).toEqualTypeOf<false>()\n      expectTypeOf(result.isPending).toEqualTypeOf<true>()\n      expectTypeOf(result.isLoading).toEqualTypeOf<boolean>()\n      expectTypeOf(result.isLoadingError).toEqualTypeOf<false>()\n      expectTypeOf(result.isRefetchError).toEqualTypeOf<false>()\n      expectTypeOf(result.status).toEqualTypeOf<'pending'>()\n      expectTypeOf(result.isPlaceholderData).toEqualTypeOf<false>()\n    }\n    if (result.isLoading) {\n      expectTypeOf(result.data).toEqualTypeOf<undefined>()\n      expectTypeOf(result.error).toEqualTypeOf<null>()\n      expectTypeOf(result.isError).toEqualTypeOf<false>()\n      expectTypeOf(result.isPending).toEqualTypeOf<true>()\n      expectTypeOf(result.isLoading).toEqualTypeOf<true>()\n      expectTypeOf(result.isLoadingError).toEqualTypeOf<false>()\n      expectTypeOf(result.isRefetchError).toEqualTypeOf<false>()\n      expectTypeOf(result.isSuccess).toEqualTypeOf<false>()\n      expectTypeOf(result.status).toEqualTypeOf<'pending'>()\n      expectTypeOf(result.isPlaceholderData).toEqualTypeOf<false>()\n    }\n\n    if (result.isLoadingError) {\n      expectTypeOf(result.data).toEqualTypeOf<undefined>()\n      expectTypeOf(result.error).toEqualTypeOf<DefaultError>()\n      expectTypeOf(result.isError).toEqualTypeOf<true>()\n      expectTypeOf(result.isPending).toEqualTypeOf<false>()\n      expectTypeOf(result.isLoading).toEqualTypeOf<false>()\n      expectTypeOf(result.isLoadingError).toEqualTypeOf<true>()\n      expectTypeOf(result.isRefetchError).toEqualTypeOf<false>()\n      expectTypeOf(result.isSuccess).toEqualTypeOf<false>()\n      expectTypeOf(result.status).toEqualTypeOf<'error'>()\n      expectTypeOf(result.isPlaceholderData).toEqualTypeOf<false>()\n    }\n\n    if (result.isRefetchError) {\n      expectTypeOf(result.data).toEqualTypeOf<{ value: string }>()\n      expectTypeOf(result.error).toEqualTypeOf<DefaultError>()\n      expectTypeOf(result.isError).toEqualTypeOf<true>()\n      expectTypeOf(result.isPending).toEqualTypeOf<false>()\n      expectTypeOf(result.isLoading).toEqualTypeOf<false>()\n      expectTypeOf(result.isLoadingError).toEqualTypeOf<false>()\n      expectTypeOf(result.isRefetchError).toEqualTypeOf<true>()\n      expectTypeOf(result.isSuccess).toEqualTypeOf<false>()\n      expectTypeOf(result.status).toEqualTypeOf<'error'>()\n      expectTypeOf(result.isPlaceholderData).toEqualTypeOf<false>()\n    }\n\n    if (result.isSuccess) {\n      expectTypeOf(result.data).toEqualTypeOf<{ value: string }>()\n      expectTypeOf(result.error).toEqualTypeOf<null>()\n      expectTypeOf(result.isError).toEqualTypeOf<false>()\n      expectTypeOf(result.isPending).toEqualTypeOf<false>()\n      expectTypeOf(result.isLoading).toEqualTypeOf<false>()\n      expectTypeOf(result.isLoadingError).toEqualTypeOf<false>()\n      expectTypeOf(result.isRefetchError).toEqualTypeOf<false>()\n      expectTypeOf(result.isSuccess).toEqualTypeOf<true>()\n      expectTypeOf(result.status).toEqualTypeOf<'success'>()\n      expectTypeOf(result.isPlaceholderData).toEqualTypeOf<boolean>()\n    }\n\n    if (result.isPlaceholderData) {\n      expectTypeOf(result.data).toEqualTypeOf<{ value: string }>()\n      expectTypeOf(result.error).toEqualTypeOf<null>()\n      expectTypeOf(result.isError).toEqualTypeOf<false>()\n      expectTypeOf(result.isPending).toEqualTypeOf<false>()\n      expectTypeOf(result.isLoading).toEqualTypeOf<false>()\n      expectTypeOf(result.isLoadingError).toEqualTypeOf<false>()\n      expectTypeOf(result.isRefetchError).toEqualTypeOf<false>()\n      expectTypeOf(result.isSuccess).toEqualTypeOf<true>()\n      expectTypeOf(result.status).toEqualTypeOf<'success'>()\n      expectTypeOf(result.isPlaceholderData).toEqualTypeOf<true>()\n    }\n  })\n\n  describe('placeholderData', () => {\n    it('previousQuery should have typed queryKey', () => {\n      const testQueryKey = ['SomeQuery', 42, { foo: 'bar' }] as const\n\n      new QueryObserver(new QueryClient(), {\n        queryKey: testQueryKey,\n        placeholderData: (_, previousQuery) => {\n          if (previousQuery) {\n            expectTypeOf(previousQuery.queryKey).toEqualTypeOf<\n              typeof testQueryKey\n            >()\n          }\n        },\n      })\n    })\n\n    it('previousQuery should have typed error', () => {\n      class CustomError extends Error {\n        name = 'CustomError' as const\n      }\n\n      new QueryObserver<boolean, CustomError>(new QueryClient(), {\n        queryKey: ['key'],\n        placeholderData: (_, previousQuery) => {\n          if (previousQuery) {\n            expectTypeOf(\n              previousQuery.state.error,\n            ).toEqualTypeOf<CustomError | null>()\n          }\n          return undefined\n        },\n      })\n    })\n\n    it('previousData should have the same type as query data', () => {\n      const queryData = { foo: 'bar' } as const\n\n      new QueryObserver(new QueryClient(), {\n        queryKey: ['key'],\n        queryFn: () => queryData,\n        select: (data) => data.foo,\n        placeholderData: (previousData) => {\n          expectTypeOf(previousData).toEqualTypeOf<\n            typeof queryData | undefined\n          >()\n          return undefined\n        },\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/query-core/src/__tests__/queryObserver.test.tsx",
    "content": "import {\n  afterEach,\n  beforeEach,\n  describe,\n  expect,\n  expectTypeOf,\n  it,\n  test,\n  vi,\n} from 'vitest'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { QueryClient, QueryObserver, focusManager } from '..'\nimport type { QueryObserverResult } from '..'\n\ndescribe('queryObserver', () => {\n  let queryClient: QueryClient\n\n  beforeEach(() => {\n    vi.useFakeTimers()\n    queryClient = new QueryClient({\n      defaultOptions: {\n        queries: {\n          experimental_prefetchInRender: true,\n        },\n      },\n    })\n    queryClient.mount()\n  })\n\n  afterEach(() => {\n    queryClient.clear()\n    vi.useRealTimers()\n  })\n\n  test('should trigger a fetch when subscribed', () => {\n    const key = queryKey()\n    const queryFn = vi\n      .fn<(...args: Array<unknown>) => string>()\n      .mockReturnValue('data')\n    const observer = new QueryObserver(queryClient, { queryKey: key, queryFn })\n    const unsubscribe = observer.subscribe(() => undefined)\n    unsubscribe()\n    expect(queryFn).toHaveBeenCalledTimes(1)\n  })\n\n  test('should be able to read latest data after subscribing', () => {\n    const key = queryKey()\n    queryClient.setQueryData(key, 'data')\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      enabled: false,\n    })\n\n    const unsubscribe = observer.subscribe(vi.fn())\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      data: 'data',\n    })\n\n    unsubscribe()\n  })\n\n  describe('enabled is a callback that initially returns false', () => {\n    let observer: QueryObserver<string, Error, string, string, Array<string>>\n    let enabled: boolean\n    let count: number\n    let key: Array<string>\n\n    beforeEach(() => {\n      key = queryKey()\n      count = 0\n      enabled = false\n\n      observer = new QueryObserver(queryClient, {\n        queryKey: key,\n        staleTime: Infinity,\n        enabled: () => enabled,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          return 'data'\n        },\n      })\n    })\n\n    test('should not fetch on mount', () => {\n      const unsubscribe = observer.subscribe(vi.fn())\n\n      // Has not fetched and is not fetching since its disabled\n      expect(count).toBe(0)\n      expect(observer.getCurrentResult()).toMatchObject({\n        status: 'pending',\n        fetchStatus: 'idle',\n        data: undefined,\n      })\n\n      unsubscribe()\n    })\n\n    test('should not be re-fetched when invalidated with refetchType: all', async () => {\n      const unsubscribe = observer.subscribe(vi.fn())\n\n      queryClient.invalidateQueries({ queryKey: key, refetchType: 'all' })\n\n      // So we still expect it to not have fetched and not be fetching\n      expect(count).toBe(0)\n      expect(observer.getCurrentResult()).toMatchObject({\n        status: 'pending',\n        fetchStatus: 'idle',\n        data: undefined,\n      })\n      await vi.advanceTimersByTimeAsync(10)\n      expect(count).toBe(0)\n\n      unsubscribe()\n    })\n\n    test('should still trigger a fetch when refetch is called', async () => {\n      const unsubscribe = observer.subscribe(vi.fn())\n\n      expect(enabled).toBe(false)\n\n      // Not the same with explicit refetch, this will override enabled and trigger a fetch anyway\n      observer.refetch()\n\n      expect(observer.getCurrentResult()).toMatchObject({\n        status: 'pending',\n        fetchStatus: 'fetching',\n        data: undefined,\n      })\n\n      await vi.advanceTimersByTimeAsync(10)\n      expect(count).toBe(1)\n      expect(observer.getCurrentResult()).toMatchObject({\n        status: 'success',\n        fetchStatus: 'idle',\n        data: 'data',\n      })\n\n      unsubscribe()\n    })\n\n    test('should fetch if unsubscribed, then enabled returns true, and then re-subscribed', async () => {\n      let unsubscribe = observer.subscribe(vi.fn())\n      expect(observer.getCurrentResult()).toMatchObject({\n        status: 'pending',\n        fetchStatus: 'idle',\n        data: undefined,\n      })\n\n      unsubscribe()\n\n      enabled = true\n\n      unsubscribe = observer.subscribe(vi.fn())\n\n      expect(observer.getCurrentResult()).toMatchObject({\n        status: 'pending',\n        fetchStatus: 'fetching',\n        data: undefined,\n      })\n      await vi.advanceTimersByTimeAsync(10)\n      expect(count).toBe(1)\n\n      unsubscribe()\n    })\n\n    test('should not be re-fetched if not subscribed to after enabled was toggled to true (fetchStatus: \"idle\")', () => {\n      const unsubscribe = observer.subscribe(vi.fn())\n\n      // Toggle enabled\n      enabled = true\n\n      unsubscribe()\n\n      queryClient.invalidateQueries({ queryKey: key, refetchType: 'active' })\n\n      expect(observer.getCurrentResult()).toMatchObject({\n        status: 'pending',\n        fetchStatus: 'idle',\n        data: undefined,\n      })\n      expect(count).toBe(0)\n    })\n\n    test('should not be re-fetched if not subscribed to after enabled was toggled to true (fetchStatus: \"fetching\")', async () => {\n      const unsubscribe = observer.subscribe(vi.fn())\n\n      // Toggle enabled\n      enabled = true\n\n      queryClient.invalidateQueries({ queryKey: key, refetchType: 'active' })\n\n      expect(observer.getCurrentResult()).toMatchObject({\n        status: 'pending',\n        fetchStatus: 'fetching',\n        data: undefined,\n      })\n      await vi.advanceTimersByTimeAsync(10)\n      expect(count).toBe(1)\n\n      unsubscribe()\n    })\n\n    test('should handle that the enabled callback updates the return value', async () => {\n      const unsubscribe = observer.subscribe(vi.fn())\n\n      // Toggle enabled\n      enabled = true\n\n      queryClient.invalidateQueries({ queryKey: key, refetchType: 'inactive' })\n\n      // should not refetch since it was active and we only refetch inactive\n      await vi.advanceTimersByTimeAsync(10)\n      expect(count).toBe(0)\n\n      queryClient.invalidateQueries({ queryKey: key, refetchType: 'active' })\n\n      // should refetch since it was active and we refetch active\n      await vi.advanceTimersByTimeAsync(10)\n      expect(count).toBe(1)\n\n      // Toggle enabled\n      enabled = false\n\n      // should not refetch since it is not active and we only refetch active\n      queryClient.invalidateQueries({ queryKey: key, refetchType: 'active' })\n\n      await vi.advanceTimersByTimeAsync(10)\n      expect(count).toBe(1)\n\n      unsubscribe()\n    })\n  })\n\n  test('should be able to read latest data when re-subscribing (but not re-fetching)', async () => {\n    const key = queryKey()\n    let count = 0\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      staleTime: Infinity,\n      queryFn: async () => {\n        await sleep(10)\n        count++\n        return 'data'\n      },\n    })\n\n    let unsubscribe = observer.subscribe(vi.fn())\n\n    // unsubscribe before data comes in\n    unsubscribe()\n    expect(count).toBe(0)\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'fetching',\n      data: undefined,\n    })\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(count).toBe(1)\n\n    // re-subscribe after data comes in\n    unsubscribe = observer.subscribe(vi.fn())\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      data: 'data',\n    })\n\n    unsubscribe()\n  })\n\n  test('should notify when switching query', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const results: Array<QueryObserverResult> = []\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key1,\n      queryFn: () => 1,\n    })\n    const unsubscribe = observer.subscribe((result) => {\n      results.push(result)\n    })\n    await vi.advanceTimersByTimeAsync(0)\n    observer.setOptions({ queryKey: key2, queryFn: () => 2 })\n    await vi.advanceTimersByTimeAsync(0)\n    unsubscribe()\n    expect(results.length).toBe(4)\n    expect(results[0]).toMatchObject({ data: undefined, status: 'pending' })\n    expect(results[1]).toMatchObject({ data: 1, status: 'success' })\n    expect(results[2]).toMatchObject({ data: undefined, status: 'pending' })\n    expect(results[3]).toMatchObject({ data: 2, status: 'success' })\n  })\n\n  test('should be able to fetch with a selector', async () => {\n    const key = queryKey()\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => ({ count: 1 }),\n      select: (data) => ({ myCount: data.count }),\n    })\n    let observerResult\n    const unsubscribe = observer.subscribe((result) => {\n      expectTypeOf(result).toEqualTypeOf<\n        QueryObserverResult<{ myCount: number }>\n      >()\n      observerResult = result\n    })\n    await vi.advanceTimersByTimeAsync(0)\n    unsubscribe()\n    expect(observerResult).toMatchObject({ data: { myCount: 1 } })\n  })\n\n  test('should be able to fetch with a selector using the fetch method', async () => {\n    const key = queryKey()\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => ({ count: 1 }),\n      select: (data) => ({ myCount: data.count }),\n    })\n    const observerResult = await observer.refetch()\n    expectTypeOf(observerResult.data).toEqualTypeOf<\n      { myCount: number } | undefined\n    >()\n    expect(observerResult.data).toMatchObject({ myCount: 1 })\n  })\n\n  test('should be able to fetch with a selector and object syntax', async () => {\n    const key = queryKey()\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => ({ count: 1 }),\n      select: (data) => ({ myCount: data.count }),\n    })\n    let observerResult\n    const unsubscribe = observer.subscribe((result) => {\n      observerResult = result\n    })\n    await vi.advanceTimersByTimeAsync(0)\n    unsubscribe()\n    expect(observerResult).toMatchObject({ data: { myCount: 1 } })\n  })\n\n  test('should run the selector again if the data changed', async () => {\n    const key = queryKey()\n    let count = 0\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => ({ count }),\n      select: (data) => {\n        count++\n        return { myCount: data.count }\n      },\n    })\n    const observerResult1 = await observer.refetch()\n    const observerResult2 = await observer.refetch()\n    expect(count).toBe(2)\n    expect(observerResult1.data).toMatchObject({ myCount: 0 })\n    expect(observerResult2.data).toMatchObject({ myCount: 1 })\n  })\n\n  test('should run the selector again if the selector changed', async () => {\n    const key = queryKey()\n    let count = 0\n    const results: Array<QueryObserverResult> = []\n    const queryFn = () => ({ count: 1 })\n    const select1 = (data: ReturnType<typeof queryFn>) => {\n      count++\n      return { myCount: data.count }\n    }\n    const select2 = (_data: ReturnType<typeof queryFn>) => {\n      count++\n      return { myCount: 99 }\n    }\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn,\n      select: select1,\n    })\n    const unsubscribe = observer.subscribe((result) => {\n      results.push(result)\n    })\n    await vi.advanceTimersByTimeAsync(0)\n    observer.setOptions({\n      queryKey: key,\n      queryFn,\n      select: select2,\n    })\n    await observer.refetch()\n    unsubscribe()\n    expect(count).toBe(2)\n    expect(results.length).toBe(5)\n    expect(results[0]).toMatchObject({\n      status: 'pending',\n      isFetching: true,\n      data: undefined,\n    })\n    expect(results[1]).toMatchObject({\n      status: 'success',\n      isFetching: false,\n      data: { myCount: 1 },\n    })\n    expect(results[2]).toMatchObject({\n      status: 'success',\n      isFetching: false,\n      data: { myCount: 99 },\n    })\n    expect(results[3]).toMatchObject({\n      status: 'success',\n      isFetching: true,\n      data: { myCount: 99 },\n    })\n    expect(results[4]).toMatchObject({\n      status: 'success',\n      isFetching: false,\n      data: { myCount: 99 },\n    })\n  })\n\n  test('should not run the selector again if the data and selector did not change', async () => {\n    const key = queryKey()\n    let count = 0\n    const results: Array<QueryObserverResult> = []\n    const queryFn = () => ({ count: 1 })\n    const select = (data: ReturnType<typeof queryFn>) => {\n      count++\n      return { myCount: data.count }\n    }\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn,\n      select,\n    })\n    const unsubscribe = observer.subscribe((result) => {\n      results.push(result)\n    })\n    await vi.advanceTimersByTimeAsync(0)\n    observer.setOptions({\n      queryKey: key,\n      queryFn,\n      select,\n    })\n    await observer.refetch()\n    unsubscribe()\n    expect(count).toBe(1)\n    expect(results.length).toBe(4)\n    expect(results[0]).toMatchObject({\n      status: 'pending',\n      isFetching: true,\n      data: undefined,\n    })\n    expect(results[1]).toMatchObject({\n      status: 'success',\n      isFetching: false,\n      data: { myCount: 1 },\n    })\n    expect(results[2]).toMatchObject({\n      status: 'success',\n      isFetching: true,\n      data: { myCount: 1 },\n    })\n    expect(results[3]).toMatchObject({\n      status: 'success',\n      isFetching: false,\n      data: { myCount: 1 },\n    })\n  })\n\n  test('should not run the selector again if the data did not change', async () => {\n    const key = queryKey()\n    let count = 0\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => ({ count: 1 }),\n      select: (data) => {\n        count++\n        return { myCount: data.count }\n      },\n    })\n    const observerResult1 = await observer.refetch()\n    const observerResult2 = await observer.refetch()\n    expect(count).toBe(1)\n    expect(observerResult1.data).toMatchObject({ myCount: 1 })\n    expect(observerResult2.data).toMatchObject({ myCount: 1 })\n  })\n\n  test('should always run the selector again if selector throws an error and selector is not referentially stable', async () => {\n    const key = queryKey()\n    const results: Array<QueryObserverResult> = []\n    const queryFn = async () => {\n      await sleep(10)\n      return { count: 1 }\n    }\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn,\n      select: () => {\n        throw new Error('selector error')\n      },\n    })\n    const unsubscribe = observer.subscribe((result) => {\n      results.push(result)\n    })\n    await vi.advanceTimersByTimeAsync(10)\n    observer.refetch()\n    await vi.advanceTimersByTimeAsync(10)\n    unsubscribe()\n    expect(results[0]).toMatchObject({\n      status: 'pending',\n      isFetching: true,\n      data: undefined,\n    })\n    expect(results[1]).toMatchObject({\n      status: 'error',\n      isFetching: false,\n      data: undefined,\n    })\n    expect(results[2]).toMatchObject({\n      status: 'error',\n      isFetching: true,\n      data: undefined,\n    })\n    expect(results[3]).toMatchObject({\n      status: 'error',\n      isFetching: false,\n      data: undefined,\n    })\n  })\n\n  test('should return stale data if selector throws an error', async () => {\n    const key = queryKey()\n    const results: Array<QueryObserverResult> = []\n    let shouldError = false\n    const error = new Error('select error')\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      retry: 0,\n      queryFn: async () => {\n        await sleep(10)\n        return shouldError ? 2 : 1\n      },\n      select: (num) => {\n        if (shouldError) {\n          throw error\n        }\n        shouldError = true\n        return String(num)\n      },\n    })\n\n    const unsubscribe = observer.subscribe((result) => {\n      results.push(result)\n    })\n    await vi.advanceTimersByTimeAsync(10)\n    observer.refetch()\n    await vi.advanceTimersByTimeAsync(10)\n    unsubscribe()\n\n    expect(results[0]).toMatchObject({\n      status: 'pending',\n      isFetching: true,\n      data: undefined,\n      error: null,\n    })\n    expect(results[1]).toMatchObject({\n      status: 'success',\n      isFetching: false,\n      data: '1',\n      error: null,\n    })\n    expect(results[2]).toMatchObject({\n      status: 'success',\n      isFetching: true,\n      data: '1',\n      error: null,\n    })\n    expect(results[3]).toMatchObject({\n      status: 'error',\n      isFetching: false,\n      data: '1',\n      error,\n    })\n  })\n\n  test('should structurally share the selector', async () => {\n    const key = queryKey()\n    let count = 0\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => ({ count: ++count }),\n      select: () => ({ myCount: 1 }),\n    })\n    const observerResult1 = await observer.refetch()\n    const observerResult2 = await observer.refetch()\n    expect(count).toBe(2)\n    expect(observerResult1.data).toBe(observerResult2.data)\n  })\n\n  test('should not trigger a fetch when subscribed and disabled', async () => {\n    const key = queryKey()\n    const queryFn = vi\n      .fn<(...args: Array<unknown>) => string>()\n      .mockReturnValue('data')\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn,\n      enabled: false,\n    })\n    const unsubscribe = observer.subscribe(() => undefined)\n    await vi.advanceTimersByTimeAsync(0)\n    unsubscribe()\n    expect(queryFn).toHaveBeenCalledTimes(0)\n  })\n\n  test('should not trigger a fetch when subscribed and disabled by callback', async () => {\n    const key = queryKey()\n    const queryFn = vi\n      .fn<(...args: Array<unknown>) => string>()\n      .mockReturnValue('data')\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn,\n      enabled: () => false,\n    })\n    const unsubscribe = observer.subscribe(() => undefined)\n    await vi.advanceTimersByTimeAsync(0)\n    unsubscribe()\n    expect(queryFn).toHaveBeenCalledTimes(0)\n  })\n\n  test('should not trigger a fetch when not subscribed', async () => {\n    const key = queryKey()\n    const queryFn = vi\n      .fn<(...args: Array<unknown>) => string>()\n      .mockReturnValue('data')\n    new QueryObserver(queryClient, { queryKey: key, queryFn })\n    await vi.advanceTimersByTimeAsync(0)\n    expect(queryFn).toHaveBeenCalledTimes(0)\n  })\n\n  test('should be able to watch a query without defining a query function', async () => {\n    const key = queryKey()\n    const queryFn = vi\n      .fn<(...args: Array<unknown>) => string>()\n      .mockReturnValue('data')\n    const callback = vi.fn()\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      enabled: false,\n    })\n    const unsubscribe = observer.subscribe(callback)\n    await queryClient.fetchQuery({ queryKey: key, queryFn })\n    await vi.advanceTimersByTimeAsync(0)\n    unsubscribe()\n    expect(queryFn).toHaveBeenCalledTimes(1)\n    expect(callback).toHaveBeenCalledTimes(2)\n  })\n\n  test('should accept unresolved query config in update function', async () => {\n    const key = queryKey()\n    const queryFn = vi\n      .fn<(...args: Array<unknown>) => string>()\n      .mockReturnValue('data')\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      enabled: false,\n    })\n    const results: Array<QueryObserverResult<unknown>> = []\n    const unsubscribe = observer.subscribe((x) => {\n      results.push(x)\n    })\n    observer.setOptions({ queryKey: key, enabled: false, staleTime: 10 })\n    await queryClient.fetchQuery({ queryKey: key, queryFn })\n    await vi.advanceTimersByTimeAsync(0)\n    unsubscribe()\n    expect(queryFn).toHaveBeenCalledTimes(1)\n    expect(results.length).toBe(2)\n    expect(results[0]).toMatchObject({ isStale: false, data: undefined })\n    expect(results[1]).toMatchObject({ isStale: false, data: 'data' })\n  })\n\n  test('should be able to handle multiple subscribers', async () => {\n    const key = queryKey()\n    const queryFn = vi\n      .fn<(...args: Array<unknown>) => string>()\n      .mockReturnValue('data')\n    const observer = new QueryObserver<string>(queryClient, {\n      queryKey: key,\n      enabled: false,\n    })\n    const results1: Array<QueryObserverResult<string>> = []\n    const results2: Array<QueryObserverResult<string>> = []\n    const unsubscribe1 = observer.subscribe((x) => {\n      results1.push(x)\n    })\n    const unsubscribe2 = observer.subscribe((x) => {\n      results2.push(x)\n    })\n    await queryClient.fetchQuery({ queryKey: key, queryFn })\n    await vi.advanceTimersByTimeAsync(0)\n    unsubscribe1()\n    unsubscribe2()\n    expect(queryFn).toHaveBeenCalledTimes(1)\n    expect(results1.length).toBe(2)\n    expect(results2.length).toBe(2)\n    expect(results1[0]).toMatchObject({ data: undefined })\n    expect(results1[1]).toMatchObject({ data: 'data' })\n    expect(results2[0]).toMatchObject({ data: undefined })\n    expect(results2[1]).toMatchObject({ data: 'data' })\n  })\n\n  test('should stop retry when unsubscribing', async () => {\n    const key = queryKey()\n    let count = 0\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => {\n        count++\n        return Promise.reject<unknown>('reject')\n      },\n      retry: 10,\n      retryDelay: 50,\n    })\n    const unsubscribe = observer.subscribe(() => undefined)\n    await vi.advanceTimersByTimeAsync(50)\n    unsubscribe()\n    await vi.advanceTimersByTimeAsync(50)\n    expect(count).toBe(2)\n  })\n\n  test('should clear interval when unsubscribing to a refetchInterval query', async () => {\n    const key = queryKey()\n    let count = 0\n\n    const fetchData = () => {\n      count++\n      return Promise.resolve('data')\n    }\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: fetchData,\n      gcTime: 0,\n      refetchInterval: 10,\n    })\n    const unsubscribe = observer.subscribe(() => undefined)\n    expect(count).toBe(1)\n    await vi.advanceTimersByTimeAsync(10)\n    expect(count).toBe(2)\n    unsubscribe()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(queryClient.getQueryCache().find({ queryKey: key })).toBeUndefined()\n    expect(count).toBe(2)\n  })\n\n  test('uses placeholderData as non-cache data when pending a query with no data', async () => {\n    const key = queryKey()\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => 'data',\n      placeholderData: 'placeholder',\n    })\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      data: 'placeholder',\n    })\n\n    const results: Array<QueryObserverResult<unknown>> = []\n\n    const unsubscribe = observer.subscribe((x) => {\n      results.push(x)\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n    unsubscribe()\n\n    expect(results.length).toBe(2)\n    expect(results[0]).toMatchObject({ status: 'success', data: 'placeholder' })\n    expect(results[1]).toMatchObject({ status: 'success', data: 'data' })\n  })\n\n  test('should structurally share placeholder data', () => {\n    const key = queryKey()\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      enabled: false,\n      queryFn: () => 'data',\n      placeholderData: {},\n    })\n\n    const firstData = observer.getCurrentResult().data\n\n    observer.setOptions({ queryKey: key, placeholderData: {} })\n\n    const secondData = observer.getCurrentResult().data\n\n    expect(firstData).toBe(secondData)\n  })\n\n  test('should throw an error if enabled option type is not valid', () => {\n    const key = queryKey()\n\n    expect(\n      () =>\n        new QueryObserver(queryClient, {\n          queryKey: key,\n          queryFn: () => 'data',\n          // @ts-expect-error\n          enabled: null,\n        }),\n    ).toThrowError('Expected enabled to be a boolean')\n  })\n\n  test('getCurrentQuery should return the current query', () => {\n    const key = queryKey()\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => 'data',\n    })\n\n    expect(observer.getCurrentQuery().queryKey).toEqual(key)\n  })\n\n  test('should throw an error if throwOnError option is true', async () => {\n    const key = queryKey()\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => Promise.reject<unknown>('error'),\n      retry: false,\n    })\n\n    let error: string | null = null\n    try {\n      await observer.refetch({ throwOnError: true })\n    } catch (err) {\n      error = err as string\n    }\n\n    expect(error).toEqual('error')\n  })\n\n  test('should not refetch in background if refetchIntervalInBackground is false', async () => {\n    const key = queryKey()\n    const queryFn = vi\n      .fn<(...args: Array<unknown>) => string>()\n      .mockReturnValue('data')\n\n    focusManager.setFocused(false)\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn,\n      refetchIntervalInBackground: false,\n      refetchInterval: 10,\n    })\n\n    const unsubscribe = observer.subscribe(() => undefined)\n    await vi.advanceTimersByTimeAsync(30)\n\n    expect(queryFn).toHaveBeenCalledTimes(1)\n\n    // Clean-up\n    unsubscribe()\n    focusManager.setFocused(true)\n  })\n\n  test('should not use replaceEqualDeep for select value when structuralSharing option is true', async () => {\n    const key = queryKey()\n\n    const data = { value: 'data' }\n    const selectedData = { value: 'data' }\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => data,\n      select: () => data,\n    })\n\n    const unsubscribe = observer.subscribe(() => undefined)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(observer.getCurrentResult().data).toBe(data)\n\n    observer.setOptions({\n      queryKey: key,\n      queryFn: () => data,\n      structuralSharing: false,\n      select: () => selectedData,\n    })\n\n    await observer.refetch()\n    expect(observer.getCurrentResult().data).toBe(selectedData)\n\n    unsubscribe()\n  })\n\n  test('should not use replaceEqualDeep for select value when structuralSharing option is true and placeholderData is defined', () => {\n    const key = queryKey()\n\n    const data = { value: 'data' }\n    const selectedData1 = { value: 'data' }\n    const selectedData2 = { value: 'data' }\n    const placeholderData1 = { value: 'data' }\n    const placeholderData2 = { value: 'data' }\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => data,\n      select: () => data,\n    })\n\n    observer.setOptions({\n      queryKey: key,\n      queryFn: () => data,\n      select: () => {\n        return selectedData1\n      },\n      placeholderData: placeholderData1,\n    })\n\n    observer.setOptions({\n      queryKey: key,\n      queryFn: () => data,\n      select: () => {\n        return selectedData2\n      },\n      placeholderData: placeholderData2,\n      structuralSharing: false,\n    })\n\n    expect(observer.getCurrentResult().data).toBe(selectedData2)\n  })\n\n  test('should pass the correct previous queryKey (from prevQuery) to placeholderData function params with select', async () => {\n    const results: Array<QueryObserverResult> = []\n    const keys: Array<ReadonlyArray<unknown> | null> = []\n\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    const data1 = { value: 'data1' }\n    const data2 = { value: 'data2' }\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key1,\n      queryFn: () => data1,\n      placeholderData: (prev, prevQuery) => {\n        keys.push(prevQuery?.queryKey || null)\n        return prev\n      },\n      select: (data) => data.value,\n    })\n\n    const unsubscribe = observer.subscribe((result) => {\n      results.push(result)\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    observer.setOptions({\n      queryKey: key2,\n      queryFn: () => data2,\n      placeholderData: (prev, prevQuery) => {\n        keys.push(prevQuery?.queryKey || null)\n        return prev\n      },\n      select: (data) => data.value,\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n    unsubscribe()\n    expect(results.length).toBe(4)\n    expect(keys.length).toBe(3)\n    expect(keys[0]).toBe(null) // First Query - status: 'pending', fetchStatus: 'idle'\n    expect(keys[1]).toBe(null) // First Query - status: 'pending', fetchStatus: 'fetching'\n    expect(keys[2]).toBe(key1) // Second Query - status: 'pending', fetchStatus: 'fetching'\n\n    expect(results[0]).toMatchObject({\n      data: undefined,\n      status: 'pending',\n      fetchStatus: 'fetching',\n    }) // Initial fetch\n    expect(results[1]).toMatchObject({\n      data: 'data1',\n      status: 'success',\n      fetchStatus: 'idle',\n    }) // Successful fetch\n    expect(results[2]).toMatchObject({\n      data: 'data1',\n      status: 'success',\n      fetchStatus: 'fetching',\n    }) // Fetch for new key, but using previous data as placeholder\n    expect(results[3]).toMatchObject({\n      data: 'data2',\n      status: 'success',\n      fetchStatus: 'idle',\n    }) // Successful fetch for new key\n  })\n\n  test('should pass the correct previous data to placeholderData function params when select function is used in conjunction', async () => {\n    const results: Array<QueryObserverResult> = []\n\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    const data1 = { value: 'data1' }\n    const data2 = { value: 'data2' }\n\n    let selectCount = 0\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key1,\n      queryFn: () => data1,\n      placeholderData: (prev) => prev,\n      select: (data) => {\n        selectCount++\n        return data.value\n      },\n    })\n\n    const unsubscribe = observer.subscribe((result) => {\n      results.push(result)\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    observer.setOptions({\n      queryKey: key2,\n      queryFn: () => data2,\n      placeholderData: (prev) => prev,\n      select: (data) => {\n        selectCount++\n        return data.value\n      },\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n    unsubscribe()\n\n    expect(results.length).toBe(4)\n    expect(results[0]).toMatchObject({\n      data: undefined,\n      status: 'pending',\n      fetchStatus: 'fetching',\n    }) // Initial fetch\n    expect(results[1]).toMatchObject({\n      data: 'data1',\n      status: 'success',\n      fetchStatus: 'idle',\n    }) // Successful fetch\n    expect(results[2]).toMatchObject({\n      data: 'data1',\n      status: 'success',\n      fetchStatus: 'fetching',\n    }) // Fetch for new key, but using previous data as placeholder\n    expect(results[3]).toMatchObject({\n      data: 'data2',\n      status: 'success',\n      fetchStatus: 'idle',\n    }) // Successful fetch for new key\n\n    // it's 3 because select is an inline function\n    expect(selectCount).toBe(3)\n  })\n\n  test('should use cached selectResult when switching between queries and placeholderData returns previousData', async () => {\n    const results: Array<QueryObserverResult> = []\n\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    const data1 = { value: 'data1' }\n    const data2 = { value: 'data2' }\n\n    const stableSelect = vi.fn((data: { value: string }) => data.value)\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key1,\n      queryFn: () => data1,\n      placeholderData: (prev) => prev,\n      select: stableSelect,\n    })\n\n    const unsubscribe = observer.subscribe((result) => {\n      results.push(result)\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    observer.setOptions({\n      queryKey: key2,\n      queryFn: () => data2,\n      placeholderData: (prev) => prev,\n      select: stableSelect,\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n    unsubscribe()\n\n    expect(results.length).toBe(4)\n    expect(results[0]).toMatchObject({\n      data: undefined,\n      status: 'pending',\n      fetchStatus: 'fetching',\n    }) // Initial fetch\n    expect(results[1]).toMatchObject({\n      data: 'data1',\n      status: 'success',\n      fetchStatus: 'idle',\n    }) // Successful fetch\n    expect(results[2]).toMatchObject({\n      data: 'data1',\n      status: 'success',\n      fetchStatus: 'fetching',\n    }) // Fetch for new key, but using previous data as placeholder\n    expect(results[3]).toMatchObject({\n      data: 'data2',\n      status: 'success',\n      fetchStatus: 'idle',\n    }) // Successful fetch for new key\n\n    expect(stableSelect).toHaveBeenCalledTimes(2)\n    expect(stableSelect.mock.calls[0]![0]).toEqual(data1)\n    expect(stableSelect.mock.calls[1]![0]).toEqual(data2)\n  })\n\n  test('setOptions should notify cache listeners', () => {\n    const key = queryKey()\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      enabled: false,\n    })\n\n    const spy = vi.fn()\n    const unsubscribe = queryClient.getQueryCache().subscribe(spy)\n    observer.setOptions({ queryKey: key, enabled: false, refetchInterval: 10 })\n\n    expect(spy).toHaveBeenCalledTimes(1)\n    expect(spy).toHaveBeenCalledWith(\n      expect.objectContaining({ type: 'observerOptionsUpdated' }),\n    )\n\n    unsubscribe()\n  })\n\n  test('disabled observers should not be stale', () => {\n    const key = queryKey()\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      enabled: false,\n    })\n\n    const result = observer.getCurrentResult()\n    expect(result.isStale).toBe(false)\n  })\n\n  test('should allow staleTime as a function', async () => {\n    const key = queryKey()\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: async () => {\n        await sleep(5)\n        return {\n          data: 'data',\n          staleTime: 20,\n        }\n      },\n      staleTime: (query) => query.state.data?.staleTime ?? 0,\n    })\n    const results: Array<QueryObserverResult<unknown>> = []\n    const unsubscribe = observer.subscribe((x) => {\n      if (x.data) {\n        results.push(x)\n      }\n    })\n\n    await vi.advanceTimersByTimeAsync(25)\n    expect(results[0]?.isStale).toBe(false)\n    await vi.advanceTimersByTimeAsync(1)\n    expect(results[1]?.isStale).toBe(true)\n\n    unsubscribe()\n  })\n\n  test('should not see queries as stale is staleTime is Static', async () => {\n    const key = queryKey()\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: async () => {\n        await sleep(5)\n        return {\n          data: 'data',\n        }\n      },\n      staleTime: 'static',\n    })\n    const result = observer.getCurrentResult()\n    expect(result.isStale).toBe(true) // no data = stale\n\n    const results: Array<QueryObserverResult<unknown>> = []\n    const unsubscribe = observer.subscribe((x) => {\n      if (x.data) {\n        results.push(x)\n      }\n    })\n\n    await vi.advanceTimersByTimeAsync(5)\n    expect(results[0]?.isStale).toBe(false)\n\n    unsubscribe()\n  })\n\n  test('should return a promise that resolves when data is present', async () => {\n    const results: Array<QueryObserverResult> = []\n    const key = queryKey()\n    let count = 0\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => {\n        if (++count > 9) {\n          return Promise.resolve('data')\n        }\n        throw new Error('rejected')\n      },\n      retry: 10,\n      retryDelay: 0,\n    })\n    const unsubscribe = observer.subscribe(() => {\n      results.push(observer.getCurrentResult())\n    })\n\n    await vi.advanceTimersByTimeAsync(8)\n    expect(results.at(-1)?.data).toBe('data')\n\n    const numberOfUniquePromises = new Set(\n      results.map((result) => result.promise),\n    ).size\n    expect(numberOfUniquePromises).toBe(1)\n\n    unsubscribe()\n  })\n\n  test('should return a new promise after recovering from an error', async () => {\n    const results: Array<QueryObserverResult> = []\n    const key = queryKey()\n\n    let succeeds = false\n    let idx = 0\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => {\n        if (succeeds) {\n          return Promise.resolve('data')\n        }\n        throw new Error(`rejected #${++idx}`)\n      },\n      retry: 5,\n      retryDelay: 0,\n    })\n    const unsubscribe = observer.subscribe(() => {\n      results.push(observer.getCurrentResult())\n    })\n\n    await vi.advanceTimersByTimeAsync(4)\n    expect(results.at(-1)?.status).toBe('error')\n\n    expect(\n      results.every((result) => result.promise === results[0]!.promise),\n    ).toBe(true)\n\n    {\n      // fail again\n      const lengthBefore = results.length\n      observer.refetch()\n      await vi.advanceTimersByTimeAsync(4)\n      expect(results.length).toBeGreaterThan(lengthBefore)\n      expect(results.at(-1)?.status).toBe('error')\n\n      const numberOfUniquePromises = new Set(\n        results.map((result) => result.promise),\n      ).size\n\n      expect(numberOfUniquePromises).toBe(2)\n    }\n    {\n      // succeed\n      succeeds = true\n      observer.refetch()\n\n      await vi.advanceTimersByTimeAsync(0)\n      results.at(-1)?.status === 'success'\n\n      const numberOfUniquePromises = new Set(\n        results.map((result) => result.promise),\n      ).size\n\n      expect(numberOfUniquePromises).toBe(3)\n    }\n\n    unsubscribe()\n  })\n\n  test('shouldFetchOnWindowFocus should respect refetchOnWindowFocus option', () => {\n    const key = queryKey()\n\n    const observer1 = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => 'data',\n      refetchOnWindowFocus: true,\n    })\n    expect(observer1.shouldFetchOnWindowFocus()).toBe(true)\n\n    const observer2 = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => 'data',\n      refetchOnWindowFocus: false,\n    })\n    expect(observer2.shouldFetchOnWindowFocus()).toBe(false)\n  })\n\n  test('fetchOptimistic should fetch and return optimistic result', async () => {\n    const key = queryKey()\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => 'data',\n    })\n\n    const result = await observer.fetchOptimistic({\n      queryKey: key,\n      queryFn: () => 'data',\n    })\n\n    expect(result.status).toBe('success')\n    expect(result.data).toBe('data')\n  })\n\n  test('should track error prop when throwOnError is true', async () => {\n    const key = queryKey()\n    const results: Array<QueryObserverResult> = []\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => Promise.reject('error'),\n      retry: false,\n      throwOnError: true,\n    })\n\n    const trackedResult = observer.trackResult(\n      observer.getCurrentResult(),\n      (prop) => {\n        if (prop === 'data' || prop === 'status') {\n          observer.trackProp(prop)\n        }\n      },\n    )\n\n    trackedResult.data\n    trackedResult.status\n\n    const unsubscribe = observer.subscribe((result) => {\n      results.push(result)\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n    const lastResult = results[results.length - 1]\n    expect(lastResult?.status).toBe('error')\n\n    expect(results.length).toBe(1)\n    expect(results[0]).toMatchObject({\n      status: 'error',\n      error: 'error',\n    })\n\n    unsubscribe()\n  })\n\n  test('should reject promise when experimental_prefetchInRender is disabled and thenable is pending', async () => {\n    const key = queryKey()\n    const queryClient2 = new QueryClient({\n      defaultOptions: {\n        queries: {\n          experimental_prefetchInRender: false,\n        },\n      },\n    })\n    const observer = new QueryObserver(queryClient2, {\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'data'),\n      enabled: false,\n    })\n\n    const result = observer.getCurrentResult()\n    const tracked = observer.trackResult(result)\n\n    await expect(tracked.promise).rejects.toThrow(\n      'experimental_prefetchInRender feature flag is not enabled',\n    )\n\n    queryClient2.clear()\n  })\n\n  test('should not refetchOnMount when set to \"always\" when staleTime is Static', async () => {\n    const key = queryKey()\n    const queryFn = vi.fn(() => 'data')\n    queryClient.setQueryData(key, 'initial')\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn,\n      staleTime: 'static',\n      refetchOnMount: 'always',\n    })\n    const unsubscribe = observer.subscribe(() => undefined)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(queryFn).toHaveBeenCalledTimes(0)\n    unsubscribe()\n  })\n\n  test('should not refetchOnWindowFocus when staleTime is static and query has background error', async () => {\n    const key = queryKey()\n    let callCount = 0\n    const queryFn = vi.fn(async () => {\n      callCount++\n      if (callCount === 1) {\n        return 'data'\n      }\n      throw new Error('background error')\n    })\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn,\n      staleTime: 'static',\n      refetchOnWindowFocus: true,\n      retry: false,\n    })\n\n    const unsubscribe = observer.subscribe(() => undefined)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(queryFn).toHaveBeenCalledTimes(1)\n    expect(observer.getCurrentResult().data).toBe('data')\n    expect(observer.getCurrentResult().status).toBe('success')\n\n    await observer.refetch()\n    await vi.advanceTimersByTimeAsync(0)\n    expect(queryFn).toHaveBeenCalledTimes(2)\n    expect(observer.getCurrentResult().status).toBe('error')\n    expect(observer.getCurrentResult().data).toBe('data')\n\n    focusManager.setFocused(false)\n    focusManager.setFocused(true)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(queryFn).toHaveBeenCalledTimes(2)\n\n    unsubscribe()\n  })\n\n  test('should refetchOnWindowFocus when query has background error and staleTime is not static', async () => {\n    const key = queryKey()\n    let callCount = 0\n    const queryFn = vi.fn(async () => {\n      callCount++\n      if (callCount === 1) {\n        return 'data'\n      }\n      if (callCount === 2) {\n        throw new Error('background error')\n      }\n      return 'new data'\n    })\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn,\n      staleTime: 1000,\n      refetchOnWindowFocus: true,\n      retry: false,\n    })\n\n    const unsubscribe = observer.subscribe(() => undefined)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(queryFn).toHaveBeenCalledTimes(1)\n    expect(observer.getCurrentResult().data).toBe('data')\n    expect(observer.getCurrentResult().status).toBe('success')\n\n    await observer.refetch()\n    await vi.advanceTimersByTimeAsync(0)\n    expect(queryFn).toHaveBeenCalledTimes(2)\n    expect(observer.getCurrentResult().status).toBe('error')\n    expect(observer.getCurrentResult().data).toBe('data')\n\n    focusManager.setFocused(false)\n    focusManager.setFocused(true)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(queryFn).toHaveBeenCalledTimes(3)\n\n    unsubscribe()\n  })\n\n  test('should set fetchStatus to idle when _optimisticResults is isRestoring', () => {\n    const key = queryKey()\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => 'data',\n      _optimisticResults: 'isRestoring',\n    })\n\n    const result = observer.getCurrentResult()\n    expect(result.fetchStatus).toBe('idle')\n  })\n\n  test('should return isEnabled depending on enabled being resolved', () => {\n    const key = queryKey()\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => 'data',\n      enabled: () => false,\n    })\n\n    const result = observer.getCurrentResult()\n    expect(result.isEnabled).toBe(false)\n  })\n\n  test('should return isEnabled as true per default', () => {\n    const key = queryKey()\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => 'data',\n    })\n\n    const result = observer.getCurrentResult()\n    expect(result.isEnabled).toBe(true)\n  })\n\n  test('should update currentResult when getOptimisticResult is called with changed data', () => {\n    const key = queryKey()\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: () => 'data',\n    })\n\n    const defaultedOptions = queryClient.defaultQueryOptions({\n      queryKey: key,\n      queryFn: () => 'data',\n    })\n\n    // First render: no data yet\n    const initialResult = observer.getOptimisticResult(defaultedOptions)\n    expect(initialResult.data).toBeUndefined()\n\n    // Another component sets data (e.g., dependent query resolved)\n    queryClient.setQueryData(key, 'updated')\n\n    // Re-render: getOptimisticResult should pick up the new data and update currentResult\n    const updatedResult = observer.getOptimisticResult(defaultedOptions)\n    expect(updatedResult.data).toBe('updated')\n    expect(observer.getCurrentResult().data).toBe('updated')\n  })\n\n  describe('StrictMode behavior', () => {\n    it('should deduplicate calls to queryFn', async () => {\n      const key = queryKey()\n      const queryFn = vi.fn(async () => {\n        await sleep(50)\n        return 'data'\n      })\n      const observer = new QueryObserver(queryClient, {\n        queryKey: key,\n        queryFn,\n      })\n\n      const unsubscribe1 = observer.subscribe(vi.fn())\n\n      await vi.advanceTimersByTimeAsync(5)\n      unsubscribe1()\n\n      // replicate strict mode behavior\n      await vi.advanceTimersByTimeAsync(5)\n      const unsubscribe2 = observer.subscribe(vi.fn())\n\n      await vi.advanceTimersByTimeAsync(40)\n\n      expect(queryClient.getQueryState(key)).toMatchObject({\n        status: 'success',\n        data: 'data',\n      })\n\n      expect(queryFn).toHaveBeenCalledTimes(1)\n\n      unsubscribe2()\n    })\n\n    it('should resolve with data when signal was consumed', async () => {\n      const key = queryKey()\n      const queryFn = vi.fn(async ({ signal }) => {\n        await sleep(50)\n        return 'data' + String(signal)\n      })\n      const observer = new QueryObserver(queryClient, {\n        queryKey: key,\n        queryFn,\n      })\n\n      const unsubscribe1 = observer.subscribe(vi.fn())\n\n      await vi.advanceTimersByTimeAsync(5)\n      unsubscribe1()\n\n      // replicate strict mode behavior\n      await vi.advanceTimersByTimeAsync(5)\n      const unsubscribe2 = observer.subscribe(vi.fn())\n\n      await vi.advanceTimersByTimeAsync(50)\n\n      expect(queryClient.getQueryState(key)).toMatchObject({\n        status: 'success',\n        data: 'data[object AbortSignal]',\n      })\n\n      expect(queryFn).toHaveBeenCalledTimes(2)\n\n      unsubscribe2()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/query-core/src/__tests__/streamedQuery.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { streamedQuery } from '../streamedQuery'\nimport { QueryClient, QueryObserver } from '..'\n\ndescribe('streamedQuery', () => {\n  let queryClient: QueryClient\n\n  beforeEach(() => {\n    vi.useFakeTimers()\n    queryClient = new QueryClient()\n    queryClient.mount()\n  })\n\n  afterEach(() => {\n    queryClient.clear()\n    vi.useRealTimers()\n  })\n\n  function createAsyncNumberGenerator(amount: number, start = 0) {\n    return {\n      async *[Symbol.asyncIterator]() {\n        let num = start\n        while (num < amount + start) {\n          await sleep(50)\n          yield num++\n        }\n      },\n    }\n  }\n\n  test('should stream data from an AsyncIterable', async () => {\n    const key = queryKey()\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: streamedQuery({\n        streamFn: () => createAsyncNumberGenerator(3),\n      }),\n    })\n\n    const unsubscribe = observer.subscribe(vi.fn())\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'fetching',\n      data: undefined,\n    })\n\n    await vi.advanceTimersByTimeAsync(50)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: [0],\n    })\n\n    await vi.advanceTimersByTimeAsync(50)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: [0, 1],\n    })\n\n    await vi.advanceTimersByTimeAsync(50)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: [0, 1, 2],\n    })\n\n    unsubscribe()\n  })\n\n  test('should allow Arrays to be returned from the stream', async () => {\n    const key = queryKey()\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: streamedQuery({\n        streamFn: async function* () {\n          for await (const num of createAsyncNumberGenerator(3)) {\n            yield [num, num] as const\n          }\n        },\n      }),\n    })\n\n    const unsubscribe = observer.subscribe(vi.fn())\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'fetching',\n      data: undefined,\n    })\n\n    await vi.advanceTimersByTimeAsync(50)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: [[0, 0]],\n    })\n\n    await vi.advanceTimersByTimeAsync(50)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: [\n        [0, 0],\n        [1, 1],\n      ],\n    })\n\n    await vi.advanceTimersByTimeAsync(50)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: [\n        [0, 0],\n        [1, 1],\n        [2, 2],\n      ],\n    })\n\n    unsubscribe()\n  })\n\n  test('should handle empty streams', async () => {\n    const key = queryKey()\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: streamedQuery({\n        streamFn: async function* () {},\n      }),\n    })\n\n    const unsubscribe = observer.subscribe(vi.fn())\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'fetching',\n      data: undefined,\n    })\n\n    await vi.advanceTimersByTimeAsync(50)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: [],\n    })\n\n    unsubscribe()\n  })\n\n  test('should replace on refetch', async () => {\n    const key = queryKey()\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: streamedQuery({\n        streamFn: () => createAsyncNumberGenerator(2),\n      }),\n    })\n\n    const unsubscribe = observer.subscribe(vi.fn())\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'fetching',\n      data: undefined,\n    })\n\n    await vi.advanceTimersByTimeAsync(100)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: [0, 1],\n    })\n\n    void observer.refetch()\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'fetching',\n      data: undefined,\n    })\n\n    await vi.advanceTimersByTimeAsync(40)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: [0],\n    })\n\n    await vi.advanceTimersByTimeAsync(50)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: [0, 1],\n    })\n\n    unsubscribe()\n  })\n\n  test('should support refetchMode append', async () => {\n    const key = queryKey()\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: streamedQuery({\n        streamFn: () => createAsyncNumberGenerator(2),\n        refetchMode: 'append',\n      }),\n    })\n\n    const unsubscribe = observer.subscribe(vi.fn())\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'fetching',\n      data: undefined,\n    })\n\n    await vi.advanceTimersByTimeAsync(100)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: [0, 1],\n    })\n\n    void observer.refetch()\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: [0, 1],\n    })\n\n    await vi.advanceTimersByTimeAsync(40)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: [0, 1, 0],\n    })\n\n    await vi.advanceTimersByTimeAsync(50)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: [0, 1, 0, 1],\n    })\n\n    unsubscribe()\n  })\n\n  test('should support refetchMode replace', async () => {\n    const key = queryKey()\n    let offset = 0\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: streamedQuery({\n        streamFn: () => createAsyncNumberGenerator(2, offset),\n        refetchMode: 'replace',\n      }),\n    })\n\n    const unsubscribe = observer.subscribe(vi.fn())\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'fetching',\n      data: undefined,\n    })\n\n    await vi.advanceTimersByTimeAsync(100)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: [0, 1],\n    })\n\n    offset = 100\n\n    void observer.refetch()\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: [0, 1],\n    })\n\n    await vi.advanceTimersByTimeAsync(40)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: [0, 1],\n    })\n\n    await vi.advanceTimersByTimeAsync(50)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: [100, 101],\n    })\n\n    unsubscribe()\n  })\n\n  test('should abort ongoing stream when refetch happens', async () => {\n    const key = queryKey()\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: streamedQuery({\n        streamFn: (context) => {\n          // just consume the signal\n          // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n          const numbers = context.signal ? 3 : 0\n          return createAsyncNumberGenerator(numbers)\n        },\n        refetchMode: 'append',\n      }),\n    })\n\n    const unsubscribe = observer.subscribe(vi.fn())\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'fetching',\n      data: undefined,\n    })\n\n    await vi.advanceTimersByTimeAsync(100)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: [0, 1],\n    })\n\n    void observer.refetch()\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: [0, 1],\n    })\n\n    await vi.advanceTimersByTimeAsync(40)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: [0, 1, 0],\n    })\n\n    await vi.advanceTimersByTimeAsync(100)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: [0, 1, 0, 1, 2],\n    })\n\n    unsubscribe()\n  })\n\n  test('should abort when unsubscribed', async () => {\n    const key = queryKey()\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: streamedQuery({\n        streamFn: (context) => {\n          // just consume the signal\n          // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n          const numbers = context.signal ? 3 : 0\n          return createAsyncNumberGenerator(numbers)\n        },\n      }),\n    })\n\n    const unsubscribe = observer.subscribe(vi.fn())\n\n    expect(queryClient.getQueryState(key)).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'fetching',\n      data: undefined,\n    })\n\n    await vi.advanceTimersByTimeAsync(60)\n\n    expect(queryClient.getQueryState(key)).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: [0],\n    })\n\n    unsubscribe()\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(queryClient.getQueryState(key)).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: [0],\n    })\n  })\n\n  test('should not abort when signal not consumed', async () => {\n    const key = queryKey()\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: streamedQuery({\n        streamFn: () => createAsyncNumberGenerator(3),\n      }),\n    })\n\n    const unsubscribe = observer.subscribe(vi.fn())\n\n    expect(queryClient.getQueryState(key)).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'fetching',\n      data: undefined,\n    })\n\n    await vi.advanceTimersByTimeAsync(60)\n\n    expect(queryClient.getQueryState(key)).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: [0],\n    })\n\n    unsubscribe()\n\n    await vi.advanceTimersByTimeAsync(50)\n\n    expect(queryClient.getQueryState(key)).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: [0, 1],\n    })\n  })\n\n  test('should support custom reducer', async () => {\n    const key = queryKey()\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: streamedQuery({\n        streamFn: () => createAsyncNumberGenerator(2),\n        reducer: (acc, chunk) => ({\n          ...acc,\n          [chunk]: true,\n        }),\n        initialValue: {} as Record<number, boolean>,\n      }),\n    })\n\n    const unsubscribe = observer.subscribe(vi.fn())\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'fetching',\n      data: undefined,\n    })\n\n    await vi.advanceTimersByTimeAsync(100)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: {\n        0: true,\n        1: true,\n      },\n    })\n\n    unsubscribe()\n  })\n\n  test('should support custom reducer with initialValue', async () => {\n    const key = queryKey()\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: streamedQuery({\n        streamFn: () => createAsyncNumberGenerator(2),\n        reducer: (acc, chunk) => ({\n          ...acc,\n          [chunk]: true,\n        }),\n        initialValue: {\n          10: true,\n          11: true,\n        } as Record<number, boolean>,\n      }),\n    })\n\n    const unsubscribe = observer.subscribe(vi.fn())\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'fetching',\n      data: undefined,\n    })\n\n    await vi.advanceTimersByTimeAsync(100)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: {\n        10: true,\n        11: true,\n        0: true,\n        1: true,\n      },\n    })\n\n    unsubscribe()\n  })\n\n  test('should keep error state on reset refetch when initialData is defined', async () => {\n    const key = queryKey()\n    let shouldError = false\n    const error = new Error('stream failed')\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      initialData: ['initial'],\n      retry: false,\n      queryFn: streamedQuery({\n        refetchMode: 'reset',\n        streamFn: async function* () {\n          if (shouldError) {\n            throw error\n          }\n\n          yield 0\n        },\n      }),\n    })\n\n    const unsubscribe = observer.subscribe(vi.fn())\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: ['initial', 0],\n    })\n\n    shouldError = true\n\n    const refetchPromise = observer.refetch()\n\n    await vi.advanceTimersByTimeAsync(0)\n    await expect(refetchPromise).resolves.toMatchObject({\n      status: 'error',\n      error,\n      data: ['initial'],\n    })\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'error',\n      fetchStatus: 'idle',\n      data: ['initial'],\n      error,\n    })\n\n    unsubscribe()\n  })\n\n  test('should treat a fetch after an initial error as a refetch for reset mode', async () => {\n    const key = queryKey()\n    let shouldError = true\n    const error = new Error('stream failed')\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      retry: false,\n      queryFn: streamedQuery({\n        refetchMode: 'reset',\n        streamFn: async function* () {\n          if (shouldError) {\n            throw error\n          }\n\n          yield* createAsyncNumberGenerator(1)\n        },\n      }),\n    })\n\n    const unsubscribe = observer.subscribe(vi.fn())\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'error',\n      fetchStatus: 'idle',\n      data: undefined,\n      error,\n    })\n\n    shouldError = false\n\n    void observer.refetch()\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'fetching',\n      data: undefined,\n      error: null,\n    })\n\n    await vi.advanceTimersByTimeAsync(50)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: [0],\n      error: null,\n    })\n\n    unsubscribe()\n  })\n\n  test('should reset to initialData on refetch after an initial error', async () => {\n    const key = queryKey()\n    let shouldError = true\n    const error = new Error('stream failed')\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      initialData: ['initial'],\n      retry: false,\n      queryFn: streamedQuery({\n        refetchMode: 'reset',\n        streamFn: async function* () {\n          if (shouldError) {\n            throw error\n          }\n\n          yield* createAsyncNumberGenerator(1)\n        },\n      }),\n    })\n\n    const unsubscribe = observer.subscribe(vi.fn())\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'error',\n      fetchStatus: 'idle',\n      data: ['initial'],\n      error,\n    })\n\n    shouldError = false\n\n    void observer.refetch()\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: ['initial'],\n      error: null,\n    })\n\n    await vi.advanceTimersByTimeAsync(50)\n\n    expect(observer.getCurrentResult()).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: ['initial', 0],\n      error: null,\n    })\n\n    unsubscribe()\n  })\n\n  test('should not call reducer twice when refetchMode is replace', async () => {\n    const key = queryKey()\n    const arr: Array<number> = []\n\n    const observer = new QueryObserver(queryClient, {\n      queryKey: key,\n      queryFn: streamedQuery({\n        streamFn: async function* () {\n          const v = [1, 2, 3]\n          yield* v\n        },\n        reducer: (oldStream, newChunk) => {\n          arr.push(newChunk)\n          return [...oldStream, newChunk]\n        },\n        initialValue: [] as Array<number>,\n        refetchMode: 'replace',\n      }),\n    })\n\n    const unsubscribe = observer.subscribe(vi.fn())\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(arr).toEqual([1, 2, 3])\n    expect(observer.getCurrentResult().data).toEqual([1, 2, 3])\n\n    void observer.refetch()\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(arr).toEqual([1, 2, 3, 1, 2, 3])\n    expect(observer.getCurrentResult().data).toEqual([1, 2, 3])\n\n    unsubscribe()\n  })\n})\n"
  },
  {
    "path": "packages/query-core/src/__tests__/timeoutManager.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport {\n  TimeoutManager,\n  defaultTimeoutProvider,\n  systemSetTimeoutZero,\n  timeoutManager,\n} from '../timeoutManager'\nimport type { MockInstance } from 'vitest'\n\ndescribe('timeoutManager', () => {\n  function createMockProvider(name: string = 'custom') {\n    return {\n      __TEST_ONLY__name: name,\n      setTimeout: vi.fn(() => 123),\n      clearTimeout: vi.fn(),\n      setInterval: vi.fn(() => 456),\n      clearInterval: vi.fn(),\n    }\n  }\n\n  let consoleErrorSpy: MockInstance<typeof console.error>\n\n  beforeEach(() => {\n    consoleErrorSpy = vi.spyOn(console, 'error')\n  })\n\n  afterEach(() => {\n    vi.restoreAllMocks()\n  })\n\n  describe('TimeoutManager', () => {\n    let manager: TimeoutManager\n\n    beforeEach(() => {\n      manager = new TimeoutManager()\n    })\n\n    it('by default proxies calls to globalThis setTimeout/clearTimeout', () => {\n      const setTimeoutSpy = vi.spyOn(globalThis, 'setTimeout')\n      const clearTimeoutSpy = vi.spyOn(globalThis, 'clearTimeout')\n      const setIntervalSpy = vi.spyOn(globalThis, 'setInterval')\n      const clearIntervalSpy = vi.spyOn(globalThis, 'clearInterval')\n\n      const callback = vi.fn()\n      const timeoutId = manager.setTimeout(callback, 100)\n      expect(setTimeoutSpy).toHaveBeenCalledWith(callback, 100)\n      clearTimeout(Number(timeoutId))\n\n      manager.clearTimeout(200)\n      expect(clearTimeoutSpy).toHaveBeenCalledWith(200)\n\n      const intervalId = manager.setInterval(callback, 300)\n      expect(setIntervalSpy).toHaveBeenCalledWith(callback, 300)\n      clearInterval(Number(intervalId))\n\n      manager.clearInterval(400)\n      expect(clearIntervalSpy).toHaveBeenCalledWith(400)\n    })\n\n    describe('setTimeoutProvider', () => {\n      it('proxies calls to the configured timeout provider', () => {\n        const customProvider = createMockProvider()\n        manager.setTimeoutProvider(customProvider)\n\n        const callback = vi.fn()\n\n        manager.setTimeout(callback, 100)\n        expect(customProvider.setTimeout).toHaveBeenCalledWith(callback, 100)\n\n        manager.clearTimeout(999)\n        expect(customProvider.clearTimeout).toHaveBeenCalledWith(999)\n\n        manager.setInterval(callback, 200)\n        expect(customProvider.setInterval).toHaveBeenCalledWith(callback, 200)\n\n        manager.clearInterval(888)\n        expect(customProvider.clearInterval).toHaveBeenCalledWith(888)\n      })\n\n      it('warns when switching providers after making call', () => {\n        // 1. switching before making any calls does not warn\n        const customProvider = createMockProvider()\n        manager.setTimeoutProvider(customProvider)\n        expect(consoleErrorSpy).not.toHaveBeenCalled()\n\n        // Make a call. The next switch should warn\n        manager.setTimeout(vi.fn(), 100)\n\n        // 2. switching after making a call should warn\n        const customProvider2 = createMockProvider('custom2')\n        manager.setTimeoutProvider(customProvider2)\n        expect(consoleErrorSpy).toHaveBeenCalledWith(\n          expect.stringMatching(\n            /\\[timeoutManager\\]: Switching .* might result in unexpected behavior\\..*/,\n          ),\n          expect.anything(),\n        )\n\n        // 3. Switching again with no intermediate calls should not warn\n        vi.mocked(consoleErrorSpy).mockClear()\n        const customProvider3 = createMockProvider('custom3')\n        manager.setTimeoutProvider(customProvider3)\n        expect(consoleErrorSpy).not.toHaveBeenCalled()\n      })\n    })\n  })\n\n  describe('globalThis timeoutManager instance', () => {\n    it('should be an instance of TimeoutManager', () => {\n      expect(timeoutManager).toBeInstanceOf(TimeoutManager)\n    })\n  })\n\n  describe('exported functions', () => {\n    let provider: ReturnType<typeof createMockProvider>\n    beforeEach(() => {\n      provider = createMockProvider()\n      timeoutManager.setTimeoutProvider(provider)\n    })\n    afterEach(() => {\n      timeoutManager.setTimeoutProvider(defaultTimeoutProvider)\n    })\n\n    describe('systemSetTimeoutZero', () => {\n      it('should use globalThis setTimeout with 0 delay', () => {\n        const spy = vi.spyOn(globalThis, 'setTimeout')\n\n        const callback = vi.fn()\n        systemSetTimeoutZero(callback)\n\n        expect(spy).toHaveBeenCalledWith(callback, 0)\n        clearTimeout(spy.mock.results[0]?.value)\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/query-core/src/__tests__/utils.test-d.tsx",
    "content": "import { assertType, describe, expectTypeOf, it } from 'vitest'\nimport { QueryClient } from '../queryClient'\nimport type { QueryFilters } from '../utils'\nimport type { DataTag, QueryKey } from '../types'\n\ndescribe('QueryFilters', () => {\n  it('should be typed unknown even if tagged generics are passed', () => {\n    type TData = { a: number; b: string }\n    type TError = Error & { message: string }\n\n    const filters: QueryFilters<DataTag<QueryKey, TData, TError>> = {\n      predicate(query) {\n        expectTypeOf(query.setData({ a: 1, b: '1' })).toEqualTypeOf<unknown>()\n        return true\n      },\n      queryKey: ['key'] as DataTag<undefined, TData, TError>,\n    }\n\n    const queryClient = new QueryClient()\n\n    const data = queryClient.getQueryData(filters.queryKey!)\n    expectTypeOf(data).toEqualTypeOf<TData | undefined>()\n\n    const error = queryClient.getQueryState(filters.queryKey!)?.error\n    expectTypeOf(error).toEqualTypeOf<TError | null | undefined>()\n  })\n\n  it('should be loose typed if generics are defaults', () => {\n    const a: QueryFilters = {\n      predicate(query) {\n        expectTypeOf(query.setData({ a: 1, b: '1' })).toEqualTypeOf<unknown>()\n        return true\n      },\n      queryKey: ['key'],\n    }\n\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryData(a.queryKey!)\n    expectTypeOf(data).toEqualTypeOf<unknown>()\n\n    const error = queryClient.getQueryState(a.queryKey!)?.error\n    expectTypeOf(error).toEqualTypeOf<Error | null | undefined>()\n  })\n\n  it('should allow a partial query key to be passed', () => {\n    const filters: QueryFilters<readonly ['key', { a: number; b: string }]> = {\n      queryKey: ['key'],\n    }\n\n    expectTypeOf(filters.queryKey).toEqualTypeOf<\n      | undefined\n      | readonly []\n      | readonly ['key']\n      | readonly [\n          'key',\n          {\n            a: number\n            b: string\n          },\n        ]\n    >()\n  })\n\n  it('should work with readonly union types', () => {\n    const filters: QueryFilters<\n      readonly ['key'] | readonly ['key', 'something']\n    > = {\n      queryKey: ['key'],\n    }\n\n    expectTypeOf(filters.queryKey).toEqualTypeOf<\n      undefined | readonly [] | readonly ['key'] | readonly ['key', 'something']\n    >()\n  })\n\n  // we test that there are not type errors here\n  // eslint-disable-next-line vitest/expect-expect\n  it('should work with unions of different lengths', () => {\n    type Key =\n      | readonly ['foo']\n      | readonly ['foo', 'bar']\n      | readonly ['foo', 'bar', 'baz']\n\n    const queryKey: Key = ['foo', 'bar'] as any as Key\n\n    new QueryClient().invalidateQueries({ queryKey })\n  })\n\n  it('should error on invalid query keys', () => {\n    assertType<QueryFilters<readonly ['key', { a: number; b: string }]>>({\n      // @ts-expect-error cannot pass invalid query key\n      queryKey: ['invalid', { a: 1, b: '1' }],\n    })\n  })\n})\n"
  },
  {
    "path": "packages/query-core/src/__tests__/utils.test.tsx",
    "content": "import { describe, expect, it, vi } from 'vitest'\nimport { QueryClient } from '..'\nimport {\n  addToEnd,\n  addToStart,\n  hashKey,\n  hashQueryKeyByOptions,\n  isPlainArray,\n  isPlainObject,\n  keepPreviousData,\n  matchMutation,\n  partialMatchKey,\n  replaceEqualDeep,\n  shallowEqualObjects,\n  shouldThrowError,\n} from '../utils'\nimport { Mutation } from '../mutation'\n\ndescribe('core/utils', () => {\n  describe('hashQueryKeyByOptions', () => {\n    it('should use custom hash function when provided in options', () => {\n      const queryKey = ['test', { a: 1, b: 2 }]\n      const customHashFn = vi.fn(() => 'custom-hash')\n\n      const result = hashQueryKeyByOptions(queryKey, {\n        queryKeyHashFn: customHashFn,\n      })\n\n      expect(customHashFn).toHaveBeenCalledWith(queryKey)\n      expect(result).toEqual('custom-hash')\n    })\n\n    it('should use default hash function when no options provided', () => {\n      const queryKey = ['test', { a: 1, b: 2 }]\n      const defaultResult = hashKey(queryKey)\n      const result = hashQueryKeyByOptions(queryKey)\n\n      expect(result).toEqual(defaultResult)\n    })\n  })\n\n  describe('shallowEqualObjects', () => {\n    it('should return `true` for shallow equal objects', () => {\n      expect(shallowEqualObjects({ a: 1 }, { a: 1 })).toEqual(true)\n    })\n\n    it('should return `false` for non shallow equal objects', () => {\n      expect(shallowEqualObjects({ a: 1 }, { a: 2 })).toEqual(false)\n    })\n\n    it('should return `false` if lengths are not equal', () => {\n      expect(shallowEqualObjects({ a: 1 }, { a: 1, b: 2 })).toEqual(false)\n    })\n\n    it('should return false if b is undefined', () => {\n      expect(shallowEqualObjects({ a: 1 }, undefined)).toEqual(false)\n    })\n  })\n  describe('isPlainObject', () => {\n    it('should return `true` for a plain object', () => {\n      expect(isPlainObject({})).toEqual(true)\n    })\n\n    it('should return `false` for an array', () => {\n      expect(isPlainObject([])).toEqual(false)\n    })\n\n    it('should return `false` for null', () => {\n      expect(isPlainObject(null)).toEqual(false)\n    })\n\n    it('should return `false` for undefined', () => {\n      expect(isPlainObject(undefined)).toEqual(false)\n    })\n\n    it('should return `true` for object with an undefined constructor', () => {\n      expect(isPlainObject(Object.create(null))).toBeTruthy()\n    })\n\n    it('should return `false` if constructor does not have an Object-specific method', () => {\n      class Foo {\n        abc: any\n        constructor() {\n          this.abc = {}\n        }\n      }\n      expect(isPlainObject(new Foo())).toBeFalsy()\n    })\n\n    it('should return `false` if the object has a modified prototype', () => {\n      function Graph(this: any) {\n        this.vertices = []\n        this.edges = []\n      }\n\n      Graph.prototype.addVertex = function (v: any) {\n        this.vertices.push(v)\n      }\n\n      expect(isPlainObject(Object.create(Graph))).toBeFalsy()\n    })\n\n    it('should return `false` for object with custom prototype', () => {\n      const CustomProto = Object.create({ a: 1 })\n      const obj = Object.create(CustomProto)\n      obj.b = 2\n\n      expect(isPlainObject(obj)).toBeFalsy()\n    })\n  })\n\n  describe('isPlainArray', () => {\n    it('should return `true` for plain arrays', () => {\n      expect(isPlainArray([1, 2])).toEqual(true)\n    })\n\n    it('should return `false` for non plain arrays', () => {\n      expect(isPlainArray(Object.assign([1, 2], { a: 'b' }))).toEqual(false)\n    })\n  })\n\n  describe('partialMatchKey', () => {\n    it('should return `true` if a includes b', () => {\n      const a = [{ a: { b: 'b' }, c: 'c', d: [{ d: 'd ' }] }]\n      const b = [{ a: { b: 'b' }, c: 'c', d: [] }]\n      expect(partialMatchKey(a, b)).toEqual(true)\n    })\n\n    it('should return `false` if a does not include b', () => {\n      const a = [{ a: { b: 'b' }, c: 'c', d: [] }]\n      const b = [{ a: { b: 'b' }, c: 'c', d: [{ d: 'd ' }] }]\n      expect(partialMatchKey(a, b)).toEqual(false)\n    })\n\n    it('should return `true` if array a includes array b', () => {\n      const a = [1, 2, 3]\n      const b = [1, 2]\n      expect(partialMatchKey(a, b)).toEqual(true)\n    })\n\n    it('should return `false` if a is null and b is not', () => {\n      const a = [null]\n      const b = [{ a: { b: 'b' }, c: 'c', d: [{ d: 'd ' }] }]\n      expect(partialMatchKey(a, b)).toEqual(false)\n    })\n\n    it('should return `false` if a contains null and b is not', () => {\n      const a = [{ a: null, c: 'c', d: [] }]\n      const b = [{ a: { b: 'b' }, c: 'c', d: [{ d: 'd ' }] }]\n      expect(partialMatchKey(a, b)).toEqual(false)\n    })\n\n    it('should return `false` if b is null and a is not', () => {\n      const a = [{ a: { b: 'b' }, c: 'c', d: [] }]\n      const b = [null]\n      expect(partialMatchKey(a, b)).toEqual(false)\n    })\n\n    it('should return `false` if b contains null and a is not', () => {\n      const a = [{ a: { b: 'b' }, c: 'c', d: [] }]\n      const b = [{ a: null, c: 'c', d: [{ d: 'd ' }] }]\n      expect(partialMatchKey(a, b)).toEqual(false)\n    })\n  })\n\n  describe('replaceEqualDeep', () => {\n    it('should return the previous value when the next value is an equal primitive', () => {\n      expect(replaceEqualDeep(1, 1)).toBe(1)\n      expect(replaceEqualDeep('1', '1')).toBe('1')\n      expect(replaceEqualDeep(true, true)).toBe(true)\n      expect(replaceEqualDeep(false, false)).toBe(false)\n      expect(replaceEqualDeep(null, null)).toBe(null)\n      expect(replaceEqualDeep(undefined, undefined)).toBe(undefined)\n    })\n    it('should return the next value when the previous value is a different value', () => {\n      const date1 = new Date()\n      const date2 = new Date()\n      expect(replaceEqualDeep(1, 0)).toBe(0)\n      expect(replaceEqualDeep(1, 2)).toBe(2)\n      expect(replaceEqualDeep('1', '2')).toBe('2')\n      expect(replaceEqualDeep(true, false)).toBe(false)\n      expect(replaceEqualDeep(false, true)).toBe(true)\n      expect(replaceEqualDeep(date1, date2)).toBe(date2)\n    })\n\n    it('should return the next value when the previous value is a different type', () => {\n      const array = [1]\n      const object = { a: 'a' }\n      expect(replaceEqualDeep(0, undefined)).toBe(undefined)\n      expect(replaceEqualDeep(undefined, 0)).toBe(0)\n      expect(replaceEqualDeep(2, undefined)).toBe(undefined)\n      expect(replaceEqualDeep(undefined, 2)).toBe(2)\n      expect(replaceEqualDeep(undefined, null)).toBe(null)\n      expect(replaceEqualDeep(null, undefined)).toBe(undefined)\n      expect(replaceEqualDeep({}, undefined)).toBe(undefined)\n      expect(replaceEqualDeep([], undefined)).toBe(undefined)\n      expect(replaceEqualDeep(array, object)).toBe(object)\n      expect(replaceEqualDeep(object, array)).toBe(array)\n    })\n\n    it('should return the previous value when the next value is an equal array', () => {\n      const prev = [1, 2]\n      const next = [1, 2]\n      expect(replaceEqualDeep(prev, next)).toBe(prev)\n    })\n\n    it('should return a copy when the previous value is a different array subset', () => {\n      const prev = [1, 2]\n      const next = [1, 2, 3]\n      const result = replaceEqualDeep(prev, next)\n      expect(result).toEqual(next)\n      expect(result).not.toBe(prev)\n      expect(result).not.toBe(next)\n    })\n\n    it('should return a copy when the previous value is a different array superset', () => {\n      const prev = [1, 2, 3]\n      const next = [1, 2]\n      const result = replaceEqualDeep(prev, next)\n      expect(result).toEqual(next)\n      expect(result).not.toBe(prev)\n      expect(result).not.toBe(next)\n    })\n\n    it('should return the previous value when the next value is an equal empty array', () => {\n      const prev: Array<any> = []\n      const next: Array<any> = []\n      expect(replaceEqualDeep(prev, next)).toBe(prev)\n    })\n\n    it('should return the previous value when the next value is an equal empty object', () => {\n      const prev = {}\n      const next = {}\n      expect(replaceEqualDeep(prev, next)).toBe(prev)\n    })\n\n    it('should return the previous value when the next value is an equal object', () => {\n      const prev = { a: 'a' }\n      const next = { a: 'a' }\n      expect(replaceEqualDeep(prev, next)).toBe(prev)\n    })\n\n    it('should replace different values in objects', () => {\n      const prev = { a: { b: 'b' }, c: 'c' }\n      const next = { a: { b: 'b' }, c: 'd' }\n      const result = replaceEqualDeep(prev, next)\n      expect(result).toEqual(next)\n      expect(result).not.toBe(prev)\n      expect(result).not.toBe(next)\n      expect(result.a).toBe(prev.a)\n      expect(result.c).toBe(next.c)\n    })\n\n    it('should replace different values in arrays', () => {\n      const prev = [1, { a: 'a' }, { b: { b: 'b' } }, [1]] as const\n      const next = [1, { a: 'a' }, { b: { b: 'c' } }, [1]] as const\n      const result = replaceEqualDeep(prev, next)\n      expect(result).toEqual(next)\n      expect(result).not.toBe(prev)\n      expect(result).not.toBe(next)\n      expect(result[0]).toBe(prev[0])\n      expect(result[1]).toBe(prev[1])\n      expect(result[2]).not.toBe(next[2])\n      expect(result[2].b.b).toBe(next[2].b.b)\n      expect(result[3]).toBe(prev[3])\n    })\n\n    it('should replace different values in arrays when the next value is a subset', () => {\n      const prev = [{ a: 'a' }, { b: 'b' }, { c: 'c' }]\n      const next = [{ a: 'a' }, { b: 'b' }]\n      const result = replaceEqualDeep(prev, next)\n      expect(result).toEqual(next)\n      expect(result).not.toBe(prev)\n      expect(result).not.toBe(next)\n      expect(result[0]).toBe(prev[0])\n      expect(result[1]).toBe(prev[1])\n      expect(result[2]).toBeUndefined()\n    })\n\n    it('should replace different values in arrays when the next value is a superset', () => {\n      const prev = [{ a: 'a' }, { b: 'b' }]\n      const next = [{ a: 'a' }, { b: 'b' }, { c: 'c' }]\n      const result = replaceEqualDeep(prev, next)\n      expect(result).toEqual(next)\n      expect(result).not.toBe(prev)\n      expect(result).not.toBe(next)\n      expect(result[0]).toBe(prev[0])\n      expect(result[1]).toBe(prev[1])\n      expect(result[2]).toBe(next[2])\n    })\n\n    it('should copy objects which are not arrays or objects', () => {\n      const prev = [{ a: 'a' }, { b: 'b' }, { c: 'c' }, 1]\n      const next = [{ a: 'a' }, new Map(), { c: 'c' }, 2]\n      const result = replaceEqualDeep(prev, next)\n      expect(result).not.toBe(prev)\n      expect(result).not.toBe(next)\n      expect(result[0]).toBe(prev[0])\n      expect(result[1]).toBe(next[1])\n      expect(result[2]).toBe(prev[2])\n      expect(result[3]).toBe(next[3])\n    })\n\n    it('should support equal objects which are not arrays or objects', () => {\n      const map = new Map()\n      const prev = [map, [1]]\n      const next = [map, [1]]\n      const result = replaceEqualDeep(prev, next)\n      expect(result).toBe(prev)\n    })\n\n    it('should support non equal objects which are not arrays or objects', () => {\n      const map1 = new Map()\n      const map2 = new Map()\n      const prev = [map1, [1]]\n      const next = [map2, [1]]\n      const result = replaceEqualDeep(prev, next)\n      expect(result).not.toBe(prev)\n      expect(result).not.toBe(next)\n      expect(result[0]).toBe(next[0])\n      expect(result[1]).toBe(prev[1])\n    })\n\n    it('should support objects which are not plain arrays', () => {\n      const prev = Object.assign([1, 2], { a: { b: 'b' }, c: 'c' })\n      const next = Object.assign([1, 2], { a: { b: 'b' }, c: 'c' })\n      const result = replaceEqualDeep(prev, next)\n      expect(result).toBe(next)\n    })\n\n    it('should replace all parent objects if some nested value changes', () => {\n      const prev = {\n        todo: { id: '1', meta: { createdAt: 0 }, state: { done: false } },\n        otherTodo: { id: '2', meta: { createdAt: 0 }, state: { done: true } },\n      }\n      const next = {\n        todo: { id: '1', meta: { createdAt: 0 }, state: { done: true } },\n        otherTodo: { id: '2', meta: { createdAt: 0 }, state: { done: true } },\n      }\n      const result = replaceEqualDeep(prev, next)\n      expect(result).toEqual(next)\n      expect(result).not.toBe(prev)\n      expect(result).not.toBe(next)\n      expect(result.todo).not.toBe(prev.todo)\n      expect(result.todo).not.toBe(next.todo)\n      expect(result.todo.id).toBe(next.todo.id)\n      expect(result.todo.meta).toBe(prev.todo.meta)\n      expect(result.todo.state).not.toBe(next.todo.state)\n      expect(result.todo.state.done).toBe(next.todo.state.done)\n      expect(result.otherTodo).toBe(prev.otherTodo)\n    })\n\n    it('should replace all parent arrays if some nested value changes', () => {\n      const prev = {\n        todos: [\n          { id: '1', meta: { createdAt: 0 }, state: { done: false } },\n          { id: '2', meta: { createdAt: 0 }, state: { done: true } },\n        ],\n      }\n      const next = {\n        todos: [\n          { id: '1', meta: { createdAt: 0 }, state: { done: true } },\n          { id: '2', meta: { createdAt: 0 }, state: { done: true } },\n        ],\n      }\n      const result = replaceEqualDeep(prev, next)\n      expect(result).toEqual(next)\n      expect(result).not.toBe(prev)\n      expect(result).not.toBe(next)\n      expect(result.todos).not.toBe(prev.todos)\n      expect(result.todos).not.toBe(next.todos)\n      expect(result.todos[0]).not.toBe(prev.todos[0])\n      expect(result.todos[0]).not.toBe(next.todos[0])\n      expect(result.todos[0]?.id).toBe(next.todos[0]?.id)\n      expect(result.todos[0]?.meta).toBe(prev.todos[0]?.meta)\n      expect(result.todos[0]?.state).not.toBe(next.todos[0]?.state)\n      expect(result.todos[0]?.state.done).toBe(next.todos[0]?.state.done)\n      expect(result.todos[1]).toBe(prev.todos[1])\n    })\n\n    it('should correctly handle objects with the same number of properties and one property being undefined', () => {\n      const obj1 = { a: 2, c: 123 }\n      const obj2 = { a: 2, b: undefined }\n      const result = replaceEqualDeep(obj1, obj2)\n      expect(result).toStrictEqual(obj2)\n    })\n\n    it('should be able to share values that contain undefined', () => {\n      const current = [\n        {\n          data: undefined,\n          foo: true,\n        },\n      ]\n\n      const next = replaceEqualDeep(current, [\n        {\n          data: undefined,\n          foo: true,\n        },\n      ])\n\n      expect(current).toBe(next)\n    })\n\n    it('should return the previous value when both values are an array of undefined', () => {\n      const current = [undefined]\n      const next = replaceEqualDeep(current, [undefined])\n\n      expect(next).toBe(current)\n    })\n\n    it('should return the previous value when both values are an array that contains undefined', () => {\n      const current = [{ foo: 1 }, undefined]\n      const next = replaceEqualDeep(current, [{ foo: 1 }, undefined])\n\n      expect(next).toBe(current)\n    })\n  })\n\n  describe('matchMutation', () => {\n    it('should return false if mutationKey options is undefined', () => {\n      const filters = { mutationKey: ['key1'] }\n      const queryClient = new QueryClient()\n      const mutation = new Mutation({\n        client: queryClient,\n        mutationId: 1,\n        mutationCache: queryClient.getMutationCache(),\n        options: {},\n      })\n      expect(matchMutation(filters, mutation)).toBeFalsy()\n    })\n  })\n\n  describe('keepPreviousData', () => {\n    it('should return the parameter as is', () => {\n      const x = { a: 1, b: 2 }\n      expect(keepPreviousData(x)).toEqual(x)\n    })\n  })\n\n  describe('addToEnd', () => {\n    it('should add item to the end of the array', () => {\n      const items = [1, 2, 3]\n      const newItems = addToEnd(items, 4)\n      expect(newItems).toEqual([1, 2, 3, 4])\n    })\n\n    it('should not exceed max if provided', () => {\n      const items = [1, 2, 3]\n      const newItems = addToEnd(items, 4, 3)\n      expect(newItems).toEqual([2, 3, 4])\n    })\n\n    it('should add item to the end of the array when max = 0', () => {\n      const items = [1, 2, 3]\n      const item = 4\n      const max = 0\n      expect(addToEnd(items, item, max)).toEqual([1, 2, 3, 4])\n    })\n\n    it('should add item to the end of the array when max is undefined', () => {\n      const items = [1, 2, 3]\n      const item = 4\n      const max = undefined\n      expect(addToEnd(items, item, max)).toEqual([1, 2, 3, 4])\n    })\n  })\n\n  describe('addToStart', () => {\n    it('should add an item to the start of the array', () => {\n      const items = [1, 2, 3]\n      const item = 4\n      const newItems = addToStart(items, item)\n      expect(newItems).toEqual([4, 1, 2, 3])\n    })\n\n    it('should respect the max argument', () => {\n      const items = [1, 2, 3]\n      const item = 4\n      const max = 2\n      const newItems = addToStart(items, item, max)\n      expect(newItems).toEqual([4, 1, 2])\n    })\n\n    it('should not remove any items if max = 0', () => {\n      const items = [1, 2, 3]\n      const item = 4\n      const max = 0\n      const newItems = addToStart(items, item, max)\n      expect(newItems).toEqual([4, 1, 2, 3])\n    })\n\n    it('should not remove any items if max is undefined', () => {\n      const items = [1, 2, 3]\n      const item = 4\n      const max = 0\n      const newItems = addToStart(items, item, max)\n      expect(newItems).toEqual([4, 1, 2, 3])\n    })\n  })\n\n  describe('hashKey', () => {\n    it('should hash primitives correctly', () => {\n      expect(hashKey(['test'])).toEqual(JSON.stringify(['test']))\n      expect(hashKey([123])).toEqual(JSON.stringify([123]))\n      expect(hashKey([null])).toEqual(JSON.stringify([null]))\n    })\n\n    it('should hash objects with sorted keys consistently', () => {\n      const key1 = [{ b: 2, a: 1 }]\n      const key2 = [{ a: 1, b: 2 }]\n\n      const hash1 = hashKey(key1)\n      const hash2 = hashKey(key2)\n\n      expect(hash1).toEqual(hash2)\n      expect(hash1).toEqual(JSON.stringify([{ a: 1, b: 2 }]))\n    })\n\n    it('should hash arrays consistently', () => {\n      const arr1 = [{ b: 2, a: 1 }, 'test', 123]\n      const arr2 = [{ a: 1, b: 2 }, 'test', 123]\n\n      expect(hashKey(arr1)).toEqual(hashKey(arr2))\n    })\n\n    it('should handle nested objects with sorted keys', () => {\n      const nested1 = [{ a: { d: 4, c: 3 }, b: 2 }]\n      const nested2 = [{ b: 2, a: { c: 3, d: 4 } }]\n\n      expect(hashKey(nested1)).toEqual(hashKey(nested2))\n    })\n  })\n\n  describe('shouldThrowError', () => {\n    it('should return the result of executing throwOnError if throwOnError parameter is a function', () => {\n      const throwOnError = (error: Error) => error.message === 'test error'\n      expect(shouldThrowError(throwOnError, [new Error('test error')])).toBe(\n        true,\n      )\n      expect(shouldThrowError(throwOnError, [new Error('other error')])).toBe(\n        false,\n      )\n    })\n\n    it('should return throwOnError parameter itself if throwOnError is not a function', () => {\n      expect(shouldThrowError(true, [new Error('test error')])).toBe(true)\n      expect(shouldThrowError(false, [new Error('test error')])).toBe(false)\n      expect(shouldThrowError(undefined, [new Error('test error')])).toBe(false)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/query-core/src/__tests__/utils.ts",
    "content": "import { vi } from 'vitest'\nimport { environmentManager, isServer, onlineManager } from '..'\nimport type { MockInstance } from 'vitest'\nimport type { MutationOptions, QueryClient } from '..'\n\nexport function mockOnlineManagerIsOnline(\n  value: boolean,\n): MockInstance<() => boolean> {\n  return vi.spyOn(onlineManager, 'isOnline').mockReturnValue(value)\n}\n\nexport function executeMutation<TVariables>(\n  queryClient: QueryClient,\n  options: MutationOptions<any, any, TVariables, any>,\n  variables: TVariables,\n) {\n  return queryClient\n    .getMutationCache()\n    .build(queryClient, options)\n    .execute(variables)\n}\n\nexport function setIsServer(value: boolean) {\n  environmentManager.setIsServer(() => value)\n  return () => {\n    environmentManager.setIsServer(() => isServer)\n  }\n}\n"
  },
  {
    "path": "packages/query-core/src/environmentManager.ts",
    "content": "import { isServer } from './utils'\n\nexport type IsServerValue = () => boolean\n\n/**\n * Manages environment detection used by TanStack Query internals.\n */\nexport const environmentManager = (() => {\n  let isServerFn: IsServerValue = () => isServer\n\n  return {\n    /**\n     * Returns whether the current runtime should be treated as a server environment.\n     */\n    isServer(): boolean {\n      return isServerFn()\n    },\n    /**\n     * Overrides the server check globally.\n     */\n    setIsServer(isServerValue: IsServerValue): void {\n      isServerFn = isServerValue\n    },\n  }\n})()\n"
  },
  {
    "path": "packages/query-core/src/focusManager.ts",
    "content": "import { Subscribable } from './subscribable'\n\ntype Listener = (focused: boolean) => void\n\ntype SetupFn = (\n  setFocused: (focused?: boolean) => void,\n) => (() => void) | undefined\n\nexport class FocusManager extends Subscribable<Listener> {\n  #focused?: boolean\n  #cleanup?: () => void\n\n  #setup: SetupFn\n\n  constructor() {\n    super()\n    this.#setup = (onFocus) => {\n      // addEventListener does not exist in React Native, but window does\n      // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n      if (typeof window !== 'undefined' && window.addEventListener) {\n        const listener = () => onFocus()\n        // Listen to visibilitychange\n        window.addEventListener('visibilitychange', listener, false)\n\n        return () => {\n          // Be sure to unsubscribe if a new handler is set\n          window.removeEventListener('visibilitychange', listener)\n        }\n      }\n      return\n    }\n  }\n\n  protected onSubscribe(): void {\n    if (!this.#cleanup) {\n      this.setEventListener(this.#setup)\n    }\n  }\n\n  protected onUnsubscribe() {\n    if (!this.hasListeners()) {\n      this.#cleanup?.()\n      this.#cleanup = undefined\n    }\n  }\n\n  setEventListener(setup: SetupFn): void {\n    this.#setup = setup\n    this.#cleanup?.()\n    this.#cleanup = setup((focused) => {\n      if (typeof focused === 'boolean') {\n        this.setFocused(focused)\n      } else {\n        this.onFocus()\n      }\n    })\n  }\n\n  setFocused(focused?: boolean): void {\n    const changed = this.#focused !== focused\n    if (changed) {\n      this.#focused = focused\n      this.onFocus()\n    }\n  }\n\n  onFocus(): void {\n    const isFocused = this.isFocused()\n    this.listeners.forEach((listener) => {\n      listener(isFocused)\n    })\n  }\n\n  isFocused(): boolean {\n    if (typeof this.#focused === 'boolean') {\n      return this.#focused\n    }\n\n    // document global can be unavailable in react native\n    // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n    return globalThis.document?.visibilityState !== 'hidden'\n  }\n}\n\nexport const focusManager = new FocusManager()\n"
  },
  {
    "path": "packages/query-core/src/hydration.ts",
    "content": "import { tryResolveSync } from './thenable'\nimport { noop } from './utils'\nimport type {\n  DefaultError,\n  MutationKey,\n  MutationMeta,\n  MutationOptions,\n  MutationScope,\n  QueryKey,\n  QueryMeta,\n  QueryOptions,\n} from './types'\nimport type { QueryClient } from './queryClient'\nimport type { Query, QueryState } from './query'\nimport type { Mutation, MutationState } from './mutation'\n\n// TYPES\ntype TransformerFn = (data: any) => any\nfunction defaultTransformerFn(data: any): any {\n  return data\n}\n\nexport interface DehydrateOptions {\n  serializeData?: TransformerFn\n  shouldDehydrateMutation?: (mutation: Mutation) => boolean\n  shouldDehydrateQuery?: (query: Query) => boolean\n  shouldRedactErrors?: (error: unknown) => boolean\n}\n\nexport interface HydrateOptions {\n  defaultOptions?: {\n    deserializeData?: TransformerFn\n    queries?: QueryOptions\n    mutations?: MutationOptions<unknown, DefaultError, unknown, unknown>\n  }\n}\n\ninterface DehydratedMutation {\n  mutationKey?: MutationKey\n  state: MutationState\n  meta?: MutationMeta\n  scope?: MutationScope\n}\n\ninterface DehydratedQuery {\n  queryHash: string\n  queryKey: QueryKey\n  state: QueryState\n  promise?: Promise<unknown>\n  meta?: QueryMeta\n  // This is only optional because older versions of Query might have dehydrated\n  // without it which we need to handle for backwards compatibility.\n  // This should be changed to required in the future.\n  dehydratedAt?: number\n}\n\nexport interface DehydratedState {\n  mutations: Array<DehydratedMutation>\n  queries: Array<DehydratedQuery>\n}\n\n// FUNCTIONS\n\nfunction dehydrateMutation(mutation: Mutation): DehydratedMutation {\n  return {\n    mutationKey: mutation.options.mutationKey,\n    state: mutation.state,\n    ...(mutation.options.scope && { scope: mutation.options.scope }),\n    ...(mutation.meta && { meta: mutation.meta }),\n  }\n}\n\n// Most config is not dehydrated but instead meant to configure again when\n// consuming the de/rehydrated data, typically with useQuery on the client.\n// Sometimes it might make sense to prefetch data on the server and include\n// in the html-payload, but not consume it on the initial render.\nfunction dehydrateQuery(\n  query: Query,\n  serializeData: TransformerFn,\n  shouldRedactErrors: (error: unknown) => boolean,\n): DehydratedQuery {\n  const dehydratePromise = () => {\n    const promise = query.promise?.then(serializeData).catch((error) => {\n      if (!shouldRedactErrors(error)) {\n        // Reject original error if it should not be redacted\n        return Promise.reject(error)\n      }\n      // If not in production, log original error before rejecting redacted error\n      if (process.env.NODE_ENV !== 'production') {\n        console.error(\n          `A query that was dehydrated as pending ended up rejecting. [${query.queryHash}]: ${error}; The error will be redacted in production builds`,\n        )\n      }\n      return Promise.reject(new Error('redacted'))\n    })\n\n    // Avoid unhandled promise rejections\n    // We need the promise we dehydrate to reject to get the correct result into\n    // the query cache, but we also want to avoid unhandled promise rejections\n    // in whatever environment the prefetches are happening in.\n    promise?.catch(noop)\n\n    return promise\n  }\n\n  return {\n    dehydratedAt: Date.now(),\n    state: {\n      ...query.state,\n      ...(query.state.data !== undefined && {\n        data: serializeData(query.state.data),\n      }),\n    },\n    queryKey: query.queryKey,\n    queryHash: query.queryHash,\n    ...(query.state.status === 'pending' && {\n      promise: dehydratePromise(),\n    }),\n    ...(query.meta && { meta: query.meta }),\n  }\n}\n\nexport function defaultShouldDehydrateMutation(mutation: Mutation) {\n  return mutation.state.isPaused\n}\n\nexport function defaultShouldDehydrateQuery(query: Query) {\n  return query.state.status === 'success'\n}\n\nfunction defaultShouldRedactErrors(_: unknown) {\n  return true\n}\n\nexport function dehydrate(\n  client: QueryClient,\n  options: DehydrateOptions = {},\n): DehydratedState {\n  const filterMutation =\n    options.shouldDehydrateMutation ??\n    client.getDefaultOptions().dehydrate?.shouldDehydrateMutation ??\n    defaultShouldDehydrateMutation\n\n  const mutations = client\n    .getMutationCache()\n    .getAll()\n    .flatMap((mutation) =>\n      filterMutation(mutation) ? [dehydrateMutation(mutation)] : [],\n    )\n\n  const filterQuery =\n    options.shouldDehydrateQuery ??\n    client.getDefaultOptions().dehydrate?.shouldDehydrateQuery ??\n    defaultShouldDehydrateQuery\n\n  const shouldRedactErrors =\n    options.shouldRedactErrors ??\n    client.getDefaultOptions().dehydrate?.shouldRedactErrors ??\n    defaultShouldRedactErrors\n\n  const serializeData =\n    options.serializeData ??\n    client.getDefaultOptions().dehydrate?.serializeData ??\n    defaultTransformerFn\n\n  const queries = client\n    .getQueryCache()\n    .getAll()\n    .flatMap((query) =>\n      filterQuery(query)\n        ? [dehydrateQuery(query, serializeData, shouldRedactErrors)]\n        : [],\n    )\n\n  return { mutations, queries }\n}\n\nexport function hydrate(\n  client: QueryClient,\n  dehydratedState: unknown,\n  options?: HydrateOptions,\n): void {\n  if (typeof dehydratedState !== 'object' || dehydratedState === null) {\n    return\n  }\n\n  const mutationCache = client.getMutationCache()\n  const queryCache = client.getQueryCache()\n  const deserializeData =\n    options?.defaultOptions?.deserializeData ??\n    client.getDefaultOptions().hydrate?.deserializeData ??\n    defaultTransformerFn\n\n  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n  const mutations = (dehydratedState as DehydratedState).mutations || []\n  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n  const queries = (dehydratedState as DehydratedState).queries || []\n\n  mutations.forEach(({ state, ...mutationOptions }) => {\n    mutationCache.build(\n      client,\n      {\n        ...client.getDefaultOptions().hydrate?.mutations,\n        ...options?.defaultOptions?.mutations,\n        ...mutationOptions,\n      },\n      state,\n    )\n  })\n\n  queries.forEach(\n    ({ queryKey, state, queryHash, meta, promise, dehydratedAt }) => {\n      const syncData = promise ? tryResolveSync(promise) : undefined\n      const rawData = state.data === undefined ? syncData?.data : state.data\n      const data = rawData === undefined ? rawData : deserializeData(rawData)\n\n      let query = queryCache.get(queryHash)\n      const existingQueryIsPending = query?.state.status === 'pending'\n      const existingQueryIsFetching = query?.state.fetchStatus === 'fetching'\n\n      // Do not hydrate if an existing query exists with newer data\n      if (query) {\n        const hasNewerSyncData =\n          syncData &&\n          // We only need this undefined check to handle older dehydration\n          // payloads that might not have dehydratedAt\n          dehydratedAt !== undefined &&\n          dehydratedAt > query.state.dataUpdatedAt\n        if (\n          state.dataUpdatedAt > query.state.dataUpdatedAt ||\n          hasNewerSyncData\n        ) {\n          // omit fetchStatus from dehydrated state\n          // so that query stays in its current fetchStatus\n          const { fetchStatus: _ignored, ...serializedState } = state\n          query.setState({\n            ...serializedState,\n            data,\n          })\n        }\n      } else {\n        // Restore query\n        query = queryCache.build(\n          client,\n          {\n            ...client.getDefaultOptions().hydrate?.queries,\n            ...options?.defaultOptions?.queries,\n            queryKey,\n            queryHash,\n            meta,\n          },\n          // Reset fetch status to idle to avoid\n          // query being stuck in fetching state upon hydration\n          {\n            ...state,\n            data,\n            fetchStatus: 'idle',\n            status: data !== undefined ? 'success' : state.status,\n          },\n        )\n      }\n\n      if (\n        promise &&\n        !existingQueryIsPending &&\n        !existingQueryIsFetching &&\n        // Only hydrate if dehydration is newer than any existing data,\n        // this is always true for new queries\n        (dehydratedAt === undefined || dehydratedAt > query.state.dataUpdatedAt)\n      ) {\n        // This doesn't actually fetch - it just creates a retryer\n        // which will re-use the passed `initialPromise`\n        // Note that we need to call these even when data was synchronously\n        // available, as we still need to set up the retryer\n        query\n          .fetch(undefined, {\n            // RSC transformed promises are not thenable\n            initialPromise: Promise.resolve(promise).then(deserializeData),\n          })\n          // Avoid unhandled promise rejections\n          .catch(noop)\n      }\n    },\n  )\n}\n"
  },
  {
    "path": "packages/query-core/src/index.ts",
    "content": "/* istanbul ignore file */\n\nexport { focusManager } from './focusManager'\nexport { environmentManager } from './environmentManager'\nexport {\n  defaultShouldDehydrateMutation,\n  defaultShouldDehydrateQuery,\n  dehydrate,\n  hydrate,\n} from './hydration'\nexport { InfiniteQueryObserver } from './infiniteQueryObserver'\nexport { MutationCache } from './mutationCache'\nexport type { MutationCacheNotifyEvent } from './mutationCache'\nexport { MutationObserver } from './mutationObserver'\nexport { defaultScheduler, notifyManager } from './notifyManager'\nexport { onlineManager } from './onlineManager'\nexport { QueriesObserver } from './queriesObserver'\nexport { QueryCache } from './queryCache'\nexport type { QueryCacheNotifyEvent } from './queryCache'\nexport { QueryClient } from './queryClient'\nexport { QueryObserver } from './queryObserver'\nexport { CancelledError, isCancelledError } from './retryer'\nexport {\n  timeoutManager,\n  type ManagedTimerId,\n  type TimeoutCallback,\n  type TimeoutProvider,\n} from './timeoutManager'\nexport {\n  hashKey,\n  isServer,\n  keepPreviousData,\n  matchMutation,\n  matchQuery,\n  noop,\n  partialMatchKey,\n  replaceEqualDeep,\n  shouldThrowError,\n  skipToken,\n} from './utils'\nexport type { MutationFilters, QueryFilters, SkipToken, Updater } from './utils'\n\nexport { streamedQuery as experimental_streamedQuery } from './streamedQuery'\n\n// Types\nexport type {\n  DehydratedState,\n  DehydrateOptions,\n  HydrateOptions,\n} from './hydration'\nexport { Mutation } from './mutation'\nexport type { MutationState } from './mutation'\nexport type { QueriesObserverOptions } from './queriesObserver'\nexport { Query } from './query'\nexport type { QueryState } from './query'\nexport * from './types'\n"
  },
  {
    "path": "packages/query-core/src/infiniteQueryBehavior.ts",
    "content": "import {\n  addConsumeAwareSignal,\n  addToEnd,\n  addToStart,\n  ensureQueryFn,\n} from './utils'\nimport type { QueryBehavior } from './query'\nimport type {\n  InfiniteData,\n  InfiniteQueryPageParamsOptions,\n  OmitKeyof,\n  QueryFunctionContext,\n  QueryKey,\n} from './types'\n\nexport function infiniteQueryBehavior<TQueryFnData, TError, TData, TPageParam>(\n  pages?: number,\n): QueryBehavior<TQueryFnData, TError, InfiniteData<TData, TPageParam>> {\n  return {\n    onFetch: (context, query) => {\n      const options = context.options as InfiniteQueryPageParamsOptions<TData>\n      const direction = context.fetchOptions?.meta?.fetchMore?.direction\n      const oldPages = context.state.data?.pages || []\n      const oldPageParams = context.state.data?.pageParams || []\n      let result: InfiniteData<unknown> = { pages: [], pageParams: [] }\n      let currentPage = 0\n\n      const fetchFn = async () => {\n        let cancelled = false\n        const addSignalProperty = (object: unknown) => {\n          addConsumeAwareSignal(\n            object,\n            () => context.signal,\n            () => (cancelled = true),\n          )\n        }\n\n        const queryFn = ensureQueryFn(context.options, context.fetchOptions)\n\n        // Create function to fetch a page\n        const fetchPage = async (\n          data: InfiniteData<unknown>,\n          param: unknown,\n          previous?: boolean,\n        ): Promise<InfiniteData<unknown>> => {\n          if (cancelled) {\n            return Promise.reject()\n          }\n\n          if (param == null && data.pages.length) {\n            return Promise.resolve(data)\n          }\n\n          const createQueryFnContext = () => {\n            const queryFnContext: OmitKeyof<\n              QueryFunctionContext<QueryKey, unknown>,\n              'signal'\n            > = {\n              client: context.client,\n              queryKey: context.queryKey,\n              pageParam: param,\n              direction: previous ? 'backward' : 'forward',\n              meta: context.options.meta,\n            }\n            addSignalProperty(queryFnContext)\n            return queryFnContext as QueryFunctionContext<QueryKey, unknown>\n          }\n\n          const queryFnContext = createQueryFnContext()\n\n          const page = await queryFn(queryFnContext)\n\n          const { maxPages } = context.options\n          const addTo = previous ? addToStart : addToEnd\n\n          return {\n            pages: addTo(data.pages, page, maxPages),\n            pageParams: addTo(data.pageParams, param, maxPages),\n          }\n        }\n\n        // fetch next / previous page?\n        if (direction && oldPages.length) {\n          const previous = direction === 'backward'\n          const pageParamFn = previous ? getPreviousPageParam : getNextPageParam\n          const oldData = {\n            pages: oldPages,\n            pageParams: oldPageParams,\n          }\n          const param = pageParamFn(options, oldData)\n\n          result = await fetchPage(oldData, param, previous)\n        } else {\n          const remainingPages = pages ?? oldPages.length\n\n          // Fetch all pages\n          do {\n            const param =\n              currentPage === 0\n                ? (oldPageParams[0] ?? options.initialPageParam)\n                : getNextPageParam(options, result)\n            if (currentPage > 0 && param == null) {\n              break\n            }\n            result = await fetchPage(result, param)\n            currentPage++\n          } while (currentPage < remainingPages)\n        }\n\n        return result\n      }\n      if (context.options.persister) {\n        context.fetchFn = () => {\n          return context.options.persister?.(\n            fetchFn as any,\n            {\n              client: context.client,\n              queryKey: context.queryKey,\n              meta: context.options.meta,\n              signal: context.signal,\n            },\n            query,\n          )\n        }\n      } else {\n        context.fetchFn = fetchFn\n      }\n    },\n  }\n}\n\nfunction getNextPageParam(\n  options: InfiniteQueryPageParamsOptions<any>,\n  { pages, pageParams }: InfiniteData<unknown>,\n): unknown | undefined {\n  const lastIndex = pages.length - 1\n  return pages.length > 0\n    ? options.getNextPageParam(\n        pages[lastIndex],\n        pages,\n        pageParams[lastIndex],\n        pageParams,\n      )\n    : undefined\n}\n\nfunction getPreviousPageParam(\n  options: InfiniteQueryPageParamsOptions<any>,\n  { pages, pageParams }: InfiniteData<unknown>,\n): unknown | undefined {\n  return pages.length > 0\n    ? options.getPreviousPageParam?.(pages[0], pages, pageParams[0], pageParams)\n    : undefined\n}\n\n/**\n * Checks if there is a next page.\n */\nexport function hasNextPage(\n  options: InfiniteQueryPageParamsOptions<any, any>,\n  data?: InfiniteData<unknown>,\n): boolean {\n  if (!data) return false\n  return getNextPageParam(options, data) != null\n}\n\n/**\n * Checks if there is a previous page.\n */\nexport function hasPreviousPage(\n  options: InfiniteQueryPageParamsOptions<any, any>,\n  data?: InfiniteData<unknown>,\n): boolean {\n  if (!data || !options.getPreviousPageParam) return false\n  return getPreviousPageParam(options, data) != null\n}\n"
  },
  {
    "path": "packages/query-core/src/infiniteQueryObserver.ts",
    "content": "import { QueryObserver } from './queryObserver'\nimport {\n  hasNextPage,\n  hasPreviousPage,\n  infiniteQueryBehavior,\n} from './infiniteQueryBehavior'\nimport type { Subscribable } from './subscribable'\nimport type {\n  DefaultError,\n  DefaultedInfiniteQueryObserverOptions,\n  FetchNextPageOptions,\n  FetchPreviousPageOptions,\n  InfiniteData,\n  InfiniteQueryObserverBaseResult,\n  InfiniteQueryObserverOptions,\n  InfiniteQueryObserverResult,\n  QueryKey,\n} from './types'\nimport type { QueryClient } from './queryClient'\nimport type { Query } from './query'\n\ntype InfiniteQueryObserverListener<TData, TError> = (\n  result: InfiniteQueryObserverResult<TData, TError>,\n) => void\n\nexport class InfiniteQueryObserver<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> extends QueryObserver<\n  TQueryFnData,\n  TError,\n  TData,\n  InfiniteData<TQueryFnData, TPageParam>,\n  TQueryKey\n> {\n  // Type override\n  subscribe!: Subscribable<\n    InfiniteQueryObserverListener<TData, TError>\n  >['subscribe']\n\n  // Type override\n  getCurrentResult!: ReplaceReturnType<\n    QueryObserver<\n      TQueryFnData,\n      TError,\n      TData,\n      InfiniteData<TQueryFnData, TPageParam>,\n      TQueryKey\n    >['getCurrentResult'],\n    InfiniteQueryObserverResult<TData, TError>\n  >\n\n  // Type override\n  protected fetch!: ReplaceReturnType<\n    QueryObserver<\n      TQueryFnData,\n      TError,\n      TData,\n      InfiniteData<TQueryFnData, TPageParam>,\n      TQueryKey\n    >['fetch'],\n    Promise<InfiniteQueryObserverResult<TData, TError>>\n  >\n\n  constructor(\n    client: QueryClient,\n    options: InfiniteQueryObserverOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey,\n      TPageParam\n    >,\n  ) {\n    super(client, options)\n  }\n\n  protected bindMethods(): void {\n    super.bindMethods()\n    this.fetchNextPage = this.fetchNextPage.bind(this)\n    this.fetchPreviousPage = this.fetchPreviousPage.bind(this)\n  }\n\n  setOptions(\n    options: InfiniteQueryObserverOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey,\n      TPageParam\n    >,\n  ): void {\n    super.setOptions({\n      ...options,\n      behavior: infiniteQueryBehavior(),\n    })\n  }\n\n  getOptimisticResult(\n    options: DefaultedInfiniteQueryObserverOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey,\n      TPageParam\n    >,\n  ): InfiniteQueryObserverResult<TData, TError> {\n    options.behavior = infiniteQueryBehavior()\n    return super.getOptimisticResult(options) as InfiniteQueryObserverResult<\n      TData,\n      TError\n    >\n  }\n\n  fetchNextPage(\n    options?: FetchNextPageOptions,\n  ): Promise<InfiniteQueryObserverResult<TData, TError>> {\n    return this.fetch({\n      ...options,\n      meta: {\n        fetchMore: { direction: 'forward' },\n      },\n    })\n  }\n\n  fetchPreviousPage(\n    options?: FetchPreviousPageOptions,\n  ): Promise<InfiniteQueryObserverResult<TData, TError>> {\n    return this.fetch({\n      ...options,\n      meta: {\n        fetchMore: { direction: 'backward' },\n      },\n    })\n  }\n\n  protected createResult(\n    query: Query<\n      TQueryFnData,\n      TError,\n      InfiniteData<TQueryFnData, TPageParam>,\n      TQueryKey\n    >,\n    options: InfiniteQueryObserverOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey,\n      TPageParam\n    >,\n  ): InfiniteQueryObserverResult<TData, TError> {\n    const { state } = query\n    const parentResult = super.createResult(query, options)\n\n    const { isFetching, isRefetching, isError, isRefetchError } = parentResult\n    const fetchDirection = state.fetchMeta?.fetchMore?.direction\n\n    const isFetchNextPageError = isError && fetchDirection === 'forward'\n    const isFetchingNextPage = isFetching && fetchDirection === 'forward'\n\n    const isFetchPreviousPageError = isError && fetchDirection === 'backward'\n    const isFetchingPreviousPage = isFetching && fetchDirection === 'backward'\n\n    const result: InfiniteQueryObserverBaseResult<TData, TError> = {\n      ...parentResult,\n      fetchNextPage: this.fetchNextPage,\n      fetchPreviousPage: this.fetchPreviousPage,\n      hasNextPage: hasNextPage(options, state.data),\n      hasPreviousPage: hasPreviousPage(options, state.data),\n      isFetchNextPageError,\n      isFetchingNextPage,\n      isFetchPreviousPageError,\n      isFetchingPreviousPage,\n      isRefetchError:\n        isRefetchError && !isFetchNextPageError && !isFetchPreviousPageError,\n      isRefetching:\n        isRefetching && !isFetchingNextPage && !isFetchingPreviousPage,\n    }\n\n    return result as InfiniteQueryObserverResult<TData, TError>\n  }\n}\n\ntype ReplaceReturnType<\n  TFunction extends (...args: Array<any>) => unknown,\n  TReturn,\n> = (...args: Parameters<TFunction>) => TReturn\n"
  },
  {
    "path": "packages/query-core/src/mutation.ts",
    "content": "import { notifyManager } from './notifyManager'\nimport { Removable } from './removable'\nimport { createRetryer } from './retryer'\nimport type {\n  DefaultError,\n  MutationFunctionContext,\n  MutationMeta,\n  MutationOptions,\n  MutationStatus,\n} from './types'\nimport type { MutationCache } from './mutationCache'\nimport type { MutationObserver } from './mutationObserver'\nimport type { Retryer } from './retryer'\nimport type { QueryClient } from './queryClient'\n\n// TYPES\n\ninterface MutationConfig<TData, TError, TVariables, TOnMutateResult> {\n  client: QueryClient\n  mutationId: number\n  mutationCache: MutationCache\n  options: MutationOptions<TData, TError, TVariables, TOnMutateResult>\n  state?: MutationState<TData, TError, TVariables, TOnMutateResult>\n}\n\nexport interface MutationState<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = unknown,\n  TOnMutateResult = unknown,\n> {\n  context: TOnMutateResult | undefined\n  data: TData | undefined\n  error: TError | null\n  failureCount: number\n  failureReason: TError | null\n  isPaused: boolean\n  status: MutationStatus\n  variables: TVariables | undefined\n  submittedAt: number\n}\n\ninterface FailedAction<TError> {\n  type: 'failed'\n  failureCount: number\n  error: TError | null\n}\n\ninterface PendingAction<TVariables, TOnMutateResult> {\n  type: 'pending'\n  isPaused: boolean\n  variables?: TVariables\n  context?: TOnMutateResult\n}\n\ninterface SuccessAction<TData> {\n  type: 'success'\n  data: TData\n}\n\ninterface ErrorAction<TError> {\n  type: 'error'\n  error: TError\n}\n\ninterface PauseAction {\n  type: 'pause'\n}\n\ninterface ContinueAction {\n  type: 'continue'\n}\n\nexport type Action<TData, TError, TVariables, TOnMutateResult> =\n  | ContinueAction\n  | ErrorAction<TError>\n  | FailedAction<TError>\n  | PendingAction<TVariables, TOnMutateResult>\n  | PauseAction\n  | SuccessAction<TData>\n\n// CLASS\n\nexport class Mutation<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = unknown,\n  TOnMutateResult = unknown,\n> extends Removable {\n  state: MutationState<TData, TError, TVariables, TOnMutateResult>\n  options!: MutationOptions<TData, TError, TVariables, TOnMutateResult>\n  readonly mutationId: number\n\n  #client: QueryClient\n  #observers: Array<\n    MutationObserver<TData, TError, TVariables, TOnMutateResult>\n  >\n  #mutationCache: MutationCache\n  #retryer?: Retryer<TData>\n\n  constructor(\n    config: MutationConfig<TData, TError, TVariables, TOnMutateResult>,\n  ) {\n    super()\n\n    this.#client = config.client\n    this.mutationId = config.mutationId\n    this.#mutationCache = config.mutationCache\n    this.#observers = []\n    this.state = config.state || getDefaultState()\n\n    this.setOptions(config.options)\n    this.scheduleGc()\n  }\n\n  setOptions(\n    options: MutationOptions<TData, TError, TVariables, TOnMutateResult>,\n  ): void {\n    this.options = options\n\n    this.updateGcTime(this.options.gcTime)\n  }\n\n  get meta(): MutationMeta | undefined {\n    return this.options.meta\n  }\n\n  addObserver(observer: MutationObserver<any, any, any, any>): void {\n    if (!this.#observers.includes(observer)) {\n      this.#observers.push(observer)\n\n      // Stop the mutation from being garbage collected\n      this.clearGcTimeout()\n\n      this.#mutationCache.notify({\n        type: 'observerAdded',\n        mutation: this,\n        observer,\n      })\n    }\n  }\n\n  removeObserver(observer: MutationObserver<any, any, any, any>): void {\n    this.#observers = this.#observers.filter((x) => x !== observer)\n\n    this.scheduleGc()\n\n    this.#mutationCache.notify({\n      type: 'observerRemoved',\n      mutation: this,\n      observer,\n    })\n  }\n\n  protected optionalRemove() {\n    if (!this.#observers.length) {\n      if (this.state.status === 'pending') {\n        this.scheduleGc()\n      } else {\n        this.#mutationCache.remove(this)\n      }\n    }\n  }\n\n  continue(): Promise<unknown> {\n    return (\n      this.#retryer?.continue() ??\n      // continuing a mutation assumes that variables are set, mutation must have been dehydrated before\n      this.execute(this.state.variables!)\n    )\n  }\n\n  async execute(variables: TVariables): Promise<TData> {\n    const onContinue = () => {\n      this.#dispatch({ type: 'continue' })\n    }\n\n    const mutationFnContext = {\n      client: this.#client,\n      meta: this.options.meta,\n      mutationKey: this.options.mutationKey,\n    } satisfies MutationFunctionContext\n\n    this.#retryer = createRetryer({\n      fn: () => {\n        if (!this.options.mutationFn) {\n          return Promise.reject(new Error('No mutationFn found'))\n        }\n\n        return this.options.mutationFn(variables, mutationFnContext)\n      },\n      onFail: (failureCount, error) => {\n        this.#dispatch({ type: 'failed', failureCount, error })\n      },\n      onPause: () => {\n        this.#dispatch({ type: 'pause' })\n      },\n      onContinue,\n      retry: this.options.retry ?? 0,\n      retryDelay: this.options.retryDelay,\n      networkMode: this.options.networkMode,\n      canRun: () => this.#mutationCache.canRun(this),\n    })\n\n    const restored = this.state.status === 'pending'\n    const isPaused = !this.#retryer.canStart()\n\n    try {\n      if (restored) {\n        // Dispatch continue action to unpause restored mutation\n        onContinue()\n      } else {\n        this.#dispatch({ type: 'pending', variables, isPaused })\n        // Notify cache callback\n        if (this.#mutationCache.config.onMutate) {\n          await this.#mutationCache.config.onMutate(\n            variables,\n            this as Mutation<unknown, unknown, unknown, unknown>,\n            mutationFnContext,\n          )\n        }\n        const context = await this.options.onMutate?.(\n          variables,\n          mutationFnContext,\n        )\n        if (context !== this.state.context) {\n          this.#dispatch({\n            type: 'pending',\n            context,\n            variables,\n            isPaused,\n          })\n        }\n      }\n      const data = await this.#retryer.start()\n\n      // Notify cache callback\n      await this.#mutationCache.config.onSuccess?.(\n        data,\n        variables,\n        this.state.context,\n        this as Mutation<unknown, unknown, unknown, unknown>,\n        mutationFnContext,\n      )\n\n      await this.options.onSuccess?.(\n        data,\n        variables,\n        this.state.context!,\n        mutationFnContext,\n      )\n\n      // Notify cache callback\n      await this.#mutationCache.config.onSettled?.(\n        data,\n        null,\n        this.state.variables,\n        this.state.context,\n        this as Mutation<unknown, unknown, unknown, unknown>,\n        mutationFnContext,\n      )\n\n      await this.options.onSettled?.(\n        data,\n        null,\n        variables,\n        this.state.context,\n        mutationFnContext,\n      )\n\n      this.#dispatch({ type: 'success', data })\n      return data\n    } catch (error) {\n      try {\n        // Notify cache callback\n        await this.#mutationCache.config.onError?.(\n          error as any,\n          variables,\n          this.state.context,\n          this as Mutation<unknown, unknown, unknown, unknown>,\n          mutationFnContext,\n        )\n      } catch (e) {\n        void Promise.reject(e)\n      }\n\n      try {\n        await this.options.onError?.(\n          error as TError,\n          variables,\n          this.state.context,\n          mutationFnContext,\n        )\n      } catch (e) {\n        void Promise.reject(e)\n      }\n\n      try {\n        // Notify cache callback\n        await this.#mutationCache.config.onSettled?.(\n          undefined,\n          error as any,\n          this.state.variables,\n          this.state.context,\n          this as Mutation<unknown, unknown, unknown, unknown>,\n          mutationFnContext,\n        )\n      } catch (e) {\n        void Promise.reject(e)\n      }\n\n      try {\n        await this.options.onSettled?.(\n          undefined,\n          error as TError,\n          variables,\n          this.state.context,\n          mutationFnContext,\n        )\n      } catch (e) {\n        void Promise.reject(e)\n      }\n\n      this.#dispatch({ type: 'error', error: error as TError })\n      throw error\n    } finally {\n      this.#mutationCache.runNext(this)\n    }\n  }\n\n  #dispatch(action: Action<TData, TError, TVariables, TOnMutateResult>): void {\n    const reducer = (\n      state: MutationState<TData, TError, TVariables, TOnMutateResult>,\n    ): MutationState<TData, TError, TVariables, TOnMutateResult> => {\n      switch (action.type) {\n        case 'failed':\n          return {\n            ...state,\n            failureCount: action.failureCount,\n            failureReason: action.error,\n          }\n        case 'pause':\n          return {\n            ...state,\n            isPaused: true,\n          }\n        case 'continue':\n          return {\n            ...state,\n            isPaused: false,\n          }\n        case 'pending':\n          return {\n            ...state,\n            context: action.context,\n            data: undefined,\n            failureCount: 0,\n            failureReason: null,\n            error: null,\n            isPaused: action.isPaused,\n            status: 'pending',\n            variables: action.variables,\n            submittedAt: Date.now(),\n          }\n        case 'success':\n          return {\n            ...state,\n            data: action.data,\n            failureCount: 0,\n            failureReason: null,\n            error: null,\n            status: 'success',\n            isPaused: false,\n          }\n        case 'error':\n          return {\n            ...state,\n            data: undefined,\n            error: action.error,\n            failureCount: state.failureCount + 1,\n            failureReason: action.error,\n            isPaused: false,\n            status: 'error',\n          }\n      }\n    }\n    this.state = reducer(this.state)\n\n    notifyManager.batch(() => {\n      this.#observers.forEach((observer) => {\n        observer.onMutationUpdate(action)\n      })\n      this.#mutationCache.notify({\n        mutation: this,\n        type: 'updated',\n        action,\n      })\n    })\n  }\n}\n\nexport function getDefaultState<\n  TData,\n  TError,\n  TVariables,\n  TOnMutateResult,\n>(): MutationState<TData, TError, TVariables, TOnMutateResult> {\n  return {\n    context: undefined,\n    data: undefined,\n    error: null,\n    failureCount: 0,\n    failureReason: null,\n    isPaused: false,\n    status: 'idle',\n    variables: undefined,\n    submittedAt: 0,\n  }\n}\n"
  },
  {
    "path": "packages/query-core/src/mutationCache.ts",
    "content": "import { notifyManager } from './notifyManager'\nimport { Mutation } from './mutation'\nimport { matchMutation, noop } from './utils'\nimport { Subscribable } from './subscribable'\nimport type { MutationObserver } from './mutationObserver'\nimport type {\n  DefaultError,\n  MutationFunctionContext,\n  MutationOptions,\n  NotifyEvent,\n} from './types'\nimport type { QueryClient } from './queryClient'\nimport type { Action, MutationState } from './mutation'\nimport type { MutationFilters } from './utils'\n\n// TYPES\n\ninterface MutationCacheConfig {\n  onError?: (\n    error: DefaultError,\n    variables: unknown,\n    onMutateResult: unknown,\n    mutation: Mutation<unknown, unknown, unknown>,\n    context: MutationFunctionContext,\n  ) => Promise<unknown> | unknown\n  onSuccess?: (\n    data: unknown,\n    variables: unknown,\n    onMutateResult: unknown,\n    mutation: Mutation<unknown, unknown, unknown>,\n    context: MutationFunctionContext,\n  ) => Promise<unknown> | unknown\n  onMutate?: (\n    variables: unknown,\n    mutation: Mutation<unknown, unknown, unknown>,\n    context: MutationFunctionContext,\n  ) => Promise<unknown> | unknown\n  onSettled?: (\n    data: unknown | undefined,\n    error: DefaultError | null,\n    variables: unknown,\n    onMutateResult: unknown,\n    mutation: Mutation<unknown, unknown, unknown>,\n    context: MutationFunctionContext,\n  ) => Promise<unknown> | unknown\n}\n\ninterface NotifyEventMutationAdded extends NotifyEvent {\n  type: 'added'\n  mutation: Mutation<any, any, any, any>\n}\ninterface NotifyEventMutationRemoved extends NotifyEvent {\n  type: 'removed'\n  mutation: Mutation<any, any, any, any>\n}\n\ninterface NotifyEventMutationObserverAdded extends NotifyEvent {\n  type: 'observerAdded'\n  mutation: Mutation<any, any, any, any>\n  observer: MutationObserver<any, any, any>\n}\n\ninterface NotifyEventMutationObserverRemoved extends NotifyEvent {\n  type: 'observerRemoved'\n  mutation: Mutation<any, any, any, any>\n  observer: MutationObserver<any, any, any>\n}\n\ninterface NotifyEventMutationObserverOptionsUpdated extends NotifyEvent {\n  type: 'observerOptionsUpdated'\n  mutation?: Mutation<any, any, any, any>\n  observer: MutationObserver<any, any, any, any>\n}\n\ninterface NotifyEventMutationUpdated extends NotifyEvent {\n  type: 'updated'\n  mutation: Mutation<any, any, any, any>\n  action: Action<any, any, any, any>\n}\n\nexport type MutationCacheNotifyEvent =\n  | NotifyEventMutationAdded\n  | NotifyEventMutationRemoved\n  | NotifyEventMutationObserverAdded\n  | NotifyEventMutationObserverRemoved\n  | NotifyEventMutationObserverOptionsUpdated\n  | NotifyEventMutationUpdated\n\ntype MutationCacheListener = (event: MutationCacheNotifyEvent) => void\n\n// CLASS\n\nexport class MutationCache extends Subscribable<MutationCacheListener> {\n  #mutations: Set<Mutation<any, any, any, any>>\n  #scopes: Map<string, Array<Mutation<any, any, any, any>>>\n  #mutationId: number\n\n  constructor(public config: MutationCacheConfig = {}) {\n    super()\n    this.#mutations = new Set()\n    this.#scopes = new Map()\n    this.#mutationId = 0\n  }\n\n  build<TData, TError, TVariables, TOnMutateResult>(\n    client: QueryClient,\n    options: MutationOptions<TData, TError, TVariables, TOnMutateResult>,\n    state?: MutationState<TData, TError, TVariables, TOnMutateResult>,\n  ): Mutation<TData, TError, TVariables, TOnMutateResult> {\n    const mutation = new Mutation({\n      client,\n      mutationCache: this,\n      mutationId: ++this.#mutationId,\n      options: client.defaultMutationOptions(options),\n      state,\n    })\n\n    this.add(mutation)\n\n    return mutation\n  }\n\n  add(mutation: Mutation<any, any, any, any>): void {\n    this.#mutations.add(mutation)\n    const scope = scopeFor(mutation)\n    if (typeof scope === 'string') {\n      const scopedMutations = this.#scopes.get(scope)\n      if (scopedMutations) {\n        scopedMutations.push(mutation)\n      } else {\n        this.#scopes.set(scope, [mutation])\n      }\n    }\n    this.notify({ type: 'added', mutation })\n  }\n\n  remove(mutation: Mutation<any, any, any, any>): void {\n    if (this.#mutations.delete(mutation)) {\n      const scope = scopeFor(mutation)\n      if (typeof scope === 'string') {\n        const scopedMutations = this.#scopes.get(scope)\n        if (scopedMutations) {\n          if (scopedMutations.length > 1) {\n            const index = scopedMutations.indexOf(mutation)\n            if (index !== -1) {\n              scopedMutations.splice(index, 1)\n            }\n          } else if (scopedMutations[0] === mutation) {\n            this.#scopes.delete(scope)\n          }\n        }\n      }\n    }\n\n    // Currently we notify the removal even if the mutation was already removed.\n    // Consider making this an error or not notifying of the removal depending on the desired semantics.\n    this.notify({ type: 'removed', mutation })\n  }\n\n  canRun(mutation: Mutation<any, any, any, any>): boolean {\n    const scope = scopeFor(mutation)\n    if (typeof scope === 'string') {\n      const mutationsWithSameScope = this.#scopes.get(scope)\n      const firstPendingMutation = mutationsWithSameScope?.find(\n        (m) => m.state.status === 'pending',\n      )\n      // we can run if there is no current pending mutation (start use-case)\n      // or if WE are the first pending mutation (continue use-case)\n      return !firstPendingMutation || firstPendingMutation === mutation\n    } else {\n      // For unscoped mutations there are never any pending mutations in front of the\n      // current mutation\n      return true\n    }\n  }\n\n  runNext(mutation: Mutation<any, any, any, any>): Promise<unknown> {\n    const scope = scopeFor(mutation)\n    if (typeof scope === 'string') {\n      const foundMutation = this.#scopes\n        .get(scope)\n        ?.find((m) => m !== mutation && m.state.isPaused)\n\n      return foundMutation?.continue() ?? Promise.resolve()\n    } else {\n      return Promise.resolve()\n    }\n  }\n\n  clear(): void {\n    notifyManager.batch(() => {\n      this.#mutations.forEach((mutation) => {\n        this.notify({ type: 'removed', mutation })\n      })\n      this.#mutations.clear()\n      this.#scopes.clear()\n    })\n  }\n\n  getAll(): Array<Mutation> {\n    return Array.from(this.#mutations)\n  }\n\n  find<\n    TData = unknown,\n    TError = DefaultError,\n    TVariables = any,\n    TOnMutateResult = unknown,\n  >(\n    filters: MutationFilters,\n  ): Mutation<TData, TError, TVariables, TOnMutateResult> | undefined {\n    const defaultedFilters = { exact: true, ...filters }\n\n    return this.getAll().find((mutation) =>\n      matchMutation(defaultedFilters, mutation),\n    ) as Mutation<TData, TError, TVariables, TOnMutateResult> | undefined\n  }\n\n  findAll(filters: MutationFilters = {}): Array<Mutation> {\n    return this.getAll().filter((mutation) => matchMutation(filters, mutation))\n  }\n\n  notify(event: MutationCacheNotifyEvent) {\n    notifyManager.batch(() => {\n      this.listeners.forEach((listener) => {\n        listener(event)\n      })\n    })\n  }\n\n  resumePausedMutations(): Promise<unknown> {\n    const pausedMutations = this.getAll().filter((x) => x.state.isPaused)\n\n    return notifyManager.batch(() =>\n      Promise.all(\n        pausedMutations.map((mutation) => mutation.continue().catch(noop)),\n      ),\n    )\n  }\n}\n\nfunction scopeFor(mutation: Mutation<any, any, any, any>) {\n  return mutation.options.scope?.id\n}\n"
  },
  {
    "path": "packages/query-core/src/mutationObserver.ts",
    "content": "import { getDefaultState } from './mutation'\nimport { notifyManager } from './notifyManager'\nimport { Subscribable } from './subscribable'\nimport { hashKey, shallowEqualObjects } from './utils'\nimport type { QueryClient } from './queryClient'\nimport type {\n  DefaultError,\n  MutateOptions,\n  MutationFunctionContext,\n  MutationObserverOptions,\n  MutationObserverResult,\n} from './types'\nimport type { Action, Mutation } from './mutation'\n\n// TYPES\n\ntype MutationObserverListener<TData, TError, TVariables, TOnMutateResult> = (\n  result: MutationObserverResult<TData, TError, TVariables, TOnMutateResult>,\n) => void\n\n// CLASS\n\nexport class MutationObserver<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> extends Subscribable<\n  MutationObserverListener<TData, TError, TVariables, TOnMutateResult>\n> {\n  options!: MutationObserverOptions<TData, TError, TVariables, TOnMutateResult>\n\n  #client: QueryClient\n  #currentResult: MutationObserverResult<\n    TData,\n    TError,\n    TVariables,\n    TOnMutateResult\n  > = undefined!\n  #currentMutation?: Mutation<TData, TError, TVariables, TOnMutateResult>\n  #mutateOptions?: MutateOptions<TData, TError, TVariables, TOnMutateResult>\n\n  constructor(\n    client: QueryClient,\n    options: MutationObserverOptions<\n      TData,\n      TError,\n      TVariables,\n      TOnMutateResult\n    >,\n  ) {\n    super()\n\n    this.#client = client\n    this.setOptions(options)\n    this.bindMethods()\n    this.#updateResult()\n  }\n\n  protected bindMethods(): void {\n    this.mutate = this.mutate.bind(this)\n    this.reset = this.reset.bind(this)\n  }\n\n  setOptions(\n    options: MutationObserverOptions<\n      TData,\n      TError,\n      TVariables,\n      TOnMutateResult\n    >,\n  ) {\n    const prevOptions = this.options as\n      | MutationObserverOptions<TData, TError, TVariables, TOnMutateResult>\n      | undefined\n    this.options = this.#client.defaultMutationOptions(options)\n    if (!shallowEqualObjects(this.options, prevOptions)) {\n      this.#client.getMutationCache().notify({\n        type: 'observerOptionsUpdated',\n        mutation: this.#currentMutation,\n        observer: this,\n      })\n    }\n\n    if (\n      prevOptions?.mutationKey &&\n      this.options.mutationKey &&\n      hashKey(prevOptions.mutationKey) !== hashKey(this.options.mutationKey)\n    ) {\n      this.reset()\n    } else if (this.#currentMutation?.state.status === 'pending') {\n      this.#currentMutation.setOptions(this.options)\n    }\n  }\n\n  protected onUnsubscribe(): void {\n    if (!this.hasListeners()) {\n      this.#currentMutation?.removeObserver(this)\n    }\n  }\n\n  onMutationUpdate(\n    action: Action<TData, TError, TVariables, TOnMutateResult>,\n  ): void {\n    this.#updateResult()\n\n    this.#notify(action)\n  }\n\n  getCurrentResult(): MutationObserverResult<\n    TData,\n    TError,\n    TVariables,\n    TOnMutateResult\n  > {\n    return this.#currentResult\n  }\n\n  reset(): void {\n    // reset needs to remove the observer from the mutation because there is no way to \"get it back\"\n    // another mutate call will yield a new mutation!\n    this.#currentMutation?.removeObserver(this)\n    this.#currentMutation = undefined\n    this.#updateResult()\n    this.#notify()\n  }\n\n  mutate(\n    variables: TVariables,\n    options?: MutateOptions<TData, TError, TVariables, TOnMutateResult>,\n  ): Promise<TData> {\n    this.#mutateOptions = options\n\n    this.#currentMutation?.removeObserver(this)\n\n    this.#currentMutation = this.#client\n      .getMutationCache()\n      .build(this.#client, this.options)\n\n    this.#currentMutation.addObserver(this)\n\n    return this.#currentMutation.execute(variables)\n  }\n\n  #updateResult(): void {\n    const state =\n      this.#currentMutation?.state ??\n      getDefaultState<TData, TError, TVariables, TOnMutateResult>()\n\n    this.#currentResult = {\n      ...state,\n      isPending: state.status === 'pending',\n      isSuccess: state.status === 'success',\n      isError: state.status === 'error',\n      isIdle: state.status === 'idle',\n      mutate: this.mutate,\n      reset: this.reset,\n    } as MutationObserverResult<TData, TError, TVariables, TOnMutateResult>\n  }\n\n  #notify(action?: Action<TData, TError, TVariables, TOnMutateResult>): void {\n    notifyManager.batch(() => {\n      // First trigger the mutate callbacks\n      if (this.#mutateOptions && this.hasListeners()) {\n        const variables = this.#currentResult.variables!\n        const onMutateResult = this.#currentResult.context\n\n        const context = {\n          client: this.#client,\n          meta: this.options.meta,\n          mutationKey: this.options.mutationKey,\n        } satisfies MutationFunctionContext\n\n        if (action?.type === 'success') {\n          try {\n            this.#mutateOptions.onSuccess?.(\n              action.data,\n              variables,\n              onMutateResult,\n              context,\n            )\n          } catch (e) {\n            void Promise.reject(e)\n          }\n          try {\n            this.#mutateOptions.onSettled?.(\n              action.data,\n              null,\n              variables,\n              onMutateResult,\n              context,\n            )\n          } catch (e) {\n            void Promise.reject(e)\n          }\n        } else if (action?.type === 'error') {\n          try {\n            this.#mutateOptions.onError?.(\n              action.error,\n              variables,\n              onMutateResult,\n              context,\n            )\n          } catch (e) {\n            void Promise.reject(e)\n          }\n          try {\n            this.#mutateOptions.onSettled?.(\n              undefined,\n              action.error,\n              variables,\n              onMutateResult,\n              context,\n            )\n          } catch (e) {\n            void Promise.reject(e)\n          }\n        }\n      }\n\n      // Then trigger the listeners\n      this.listeners.forEach((listener) => {\n        listener(this.#currentResult)\n      })\n    })\n  }\n}\n"
  },
  {
    "path": "packages/query-core/src/notifyManager.ts",
    "content": "// TYPES\n\nimport { systemSetTimeoutZero } from './timeoutManager'\n\ntype NotifyCallback = () => void\n\ntype NotifyFunction = (callback: () => void) => void\n\ntype BatchNotifyFunction = (callback: () => void) => void\n\ntype BatchCallsCallback<T extends Array<unknown>> = (...args: T) => void\n\ntype ScheduleFunction = (callback: () => void) => void\n\nexport const defaultScheduler: ScheduleFunction = systemSetTimeoutZero\n\nexport function createNotifyManager() {\n  let queue: Array<NotifyCallback> = []\n  let transactions = 0\n  let notifyFn: NotifyFunction = (callback) => {\n    callback()\n  }\n  let batchNotifyFn: BatchNotifyFunction = (callback: () => void) => {\n    callback()\n  }\n  let scheduleFn = defaultScheduler\n\n  const schedule = (callback: NotifyCallback): void => {\n    if (transactions) {\n      queue.push(callback)\n    } else {\n      scheduleFn(() => {\n        notifyFn(callback)\n      })\n    }\n  }\n  const flush = (): void => {\n    const originalQueue = queue\n    queue = []\n    if (originalQueue.length) {\n      scheduleFn(() => {\n        batchNotifyFn(() => {\n          originalQueue.forEach((callback) => {\n            notifyFn(callback)\n          })\n        })\n      })\n    }\n  }\n\n  return {\n    batch: <T>(callback: () => T): T => {\n      let result\n      transactions++\n      try {\n        result = callback()\n      } finally {\n        transactions--\n        if (!transactions) {\n          flush()\n        }\n      }\n      return result\n    },\n    /**\n     * All calls to the wrapped function will be batched.\n     */\n    batchCalls: <T extends Array<unknown>>(\n      callback: BatchCallsCallback<T>,\n    ): BatchCallsCallback<T> => {\n      return (...args) => {\n        schedule(() => {\n          callback(...args)\n        })\n      }\n    },\n    schedule,\n    /**\n     * Use this method to set a custom notify function.\n     * This can be used to for example wrap notifications with `React.act` while running tests.\n     */\n    setNotifyFunction: (fn: NotifyFunction) => {\n      notifyFn = fn\n    },\n    /**\n     * Use this method to set a custom function to batch notifications together into a single tick.\n     * By default React Query will use the batch function provided by ReactDOM or React Native.\n     */\n    setBatchNotifyFunction: (fn: BatchNotifyFunction) => {\n      batchNotifyFn = fn\n    },\n    setScheduler: (fn: ScheduleFunction) => {\n      scheduleFn = fn\n    },\n  } as const\n}\n\n// SINGLETON\nexport const notifyManager = createNotifyManager()\n"
  },
  {
    "path": "packages/query-core/src/onlineManager.ts",
    "content": "import { Subscribable } from './subscribable'\n\ntype Listener = (online: boolean) => void\ntype SetupFn = (setOnline: Listener) => (() => void) | undefined\n\nexport class OnlineManager extends Subscribable<Listener> {\n  #online = true\n  #cleanup?: () => void\n\n  #setup: SetupFn\n\n  constructor() {\n    super()\n    this.#setup = (onOnline) => {\n      // addEventListener does not exist in React Native, but window does\n      // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n      if (typeof window !== 'undefined' && window.addEventListener) {\n        const onlineListener = () => onOnline(true)\n        const offlineListener = () => onOnline(false)\n        // Listen to online\n        window.addEventListener('online', onlineListener, false)\n        window.addEventListener('offline', offlineListener, false)\n\n        return () => {\n          // Be sure to unsubscribe if a new handler is set\n          window.removeEventListener('online', onlineListener)\n          window.removeEventListener('offline', offlineListener)\n        }\n      }\n\n      return\n    }\n  }\n\n  protected onSubscribe(): void {\n    if (!this.#cleanup) {\n      this.setEventListener(this.#setup)\n    }\n  }\n\n  protected onUnsubscribe() {\n    if (!this.hasListeners()) {\n      this.#cleanup?.()\n      this.#cleanup = undefined\n    }\n  }\n\n  setEventListener(setup: SetupFn): void {\n    this.#setup = setup\n    this.#cleanup?.()\n    this.#cleanup = setup(this.setOnline.bind(this))\n  }\n\n  setOnline(online: boolean): void {\n    const changed = this.#online !== online\n\n    if (changed) {\n      this.#online = online\n      this.listeners.forEach((listener) => {\n        listener(online)\n      })\n    }\n  }\n\n  isOnline(): boolean {\n    return this.#online\n  }\n}\n\nexport const onlineManager = new OnlineManager()\n"
  },
  {
    "path": "packages/query-core/src/queriesObserver.ts",
    "content": "import { notifyManager } from './notifyManager'\nimport { QueryObserver } from './queryObserver'\nimport { Subscribable } from './subscribable'\nimport { replaceEqualDeep, shallowEqualObjects } from './utils'\nimport type {\n  DefaultedQueryObserverOptions,\n  QueryObserverOptions,\n  QueryObserverResult,\n} from './types'\nimport type { QueryClient } from './queryClient'\n\nfunction difference<T>(array1: Array<T>, array2: Array<T>): Array<T> {\n  const excludeSet = new Set(array2)\n  return array1.filter((x) => !excludeSet.has(x))\n}\n\nfunction replaceAt<T>(array: Array<T>, index: number, value: T): Array<T> {\n  const copy = array.slice(0)\n  copy[index] = value\n  return copy\n}\n\ntype QueriesObserverListener = (result: Array<QueryObserverResult>) => void\n\ntype CombineFn<TCombinedResult> = (\n  result: Array<QueryObserverResult>,\n) => TCombinedResult\n\nexport interface QueriesObserverOptions<\n  TCombinedResult = Array<QueryObserverResult>,\n> {\n  combine?: CombineFn<TCombinedResult>\n}\n\nexport class QueriesObserver<\n  TCombinedResult = Array<QueryObserverResult>,\n> extends Subscribable<QueriesObserverListener> {\n  #client: QueryClient\n  #result!: Array<QueryObserverResult>\n  #queries: Array<QueryObserverOptions>\n  #options?: QueriesObserverOptions<TCombinedResult>\n  #observers: Array<QueryObserver>\n  #combinedResult?: TCombinedResult\n  #lastCombine?: CombineFn<TCombinedResult>\n  #lastResult?: Array<QueryObserverResult>\n  #lastQueryHashes?: Array<string>\n  #observerMatches: Array<QueryObserverMatch> = []\n\n  constructor(\n    client: QueryClient,\n    queries: Array<QueryObserverOptions<any, any, any, any, any>>,\n    options?: QueriesObserverOptions<TCombinedResult>,\n  ) {\n    super()\n\n    this.#client = client\n    this.#options = options\n    this.#queries = []\n    this.#observers = []\n    this.#result = []\n\n    this.setQueries(queries)\n  }\n\n  protected onSubscribe(): void {\n    if (this.listeners.size === 1) {\n      this.#observers.forEach((observer) => {\n        observer.subscribe((result) => {\n          this.#onUpdate(observer, result)\n        })\n      })\n    }\n  }\n\n  protected onUnsubscribe(): void {\n    if (!this.listeners.size) {\n      this.destroy()\n    }\n  }\n\n  destroy(): void {\n    this.listeners = new Set()\n    this.#observers.forEach((observer) => {\n      observer.destroy()\n    })\n  }\n\n  setQueries(\n    queries: Array<QueryObserverOptions>,\n    options?: QueriesObserverOptions<TCombinedResult>,\n  ): void {\n    this.#queries = queries\n    this.#options = options\n\n    if (process.env.NODE_ENV !== 'production') {\n      const queryHashes = queries.map(\n        (query) => this.#client.defaultQueryOptions(query).queryHash,\n      )\n      if (new Set(queryHashes).size !== queryHashes.length) {\n        console.warn(\n          '[QueriesObserver]: Duplicate Queries found. This might result in unexpected behavior.',\n        )\n      }\n    }\n\n    notifyManager.batch(() => {\n      const prevObservers = this.#observers\n\n      const newObserverMatches = this.#findMatchingObservers(this.#queries)\n\n      // set options for the new observers to notify of changes\n      newObserverMatches.forEach((match) =>\n        match.observer.setOptions(match.defaultedQueryOptions),\n      )\n\n      const newObservers = newObserverMatches.map((match) => match.observer)\n      const newResult = newObservers.map((observer) =>\n        observer.getCurrentResult(),\n      )\n\n      const hasLengthChange = prevObservers.length !== newObservers.length\n      const hasIndexChange = newObservers.some(\n        (observer, index) => observer !== prevObservers[index],\n      )\n      const hasStructuralChange = hasLengthChange || hasIndexChange\n\n      const hasResultChange = hasStructuralChange\n        ? true\n        : newResult.some((result, index) => {\n            const prev = this.#result[index]\n            return !prev || !shallowEqualObjects(result, prev)\n          })\n\n      if (!hasStructuralChange && !hasResultChange) return\n\n      if (hasStructuralChange) {\n        this.#observerMatches = newObserverMatches\n        this.#observers = newObservers\n      }\n\n      this.#result = newResult\n\n      if (!this.hasListeners()) return\n\n      if (hasStructuralChange) {\n        difference(prevObservers, newObservers).forEach((observer) => {\n          observer.destroy()\n        })\n        difference(newObservers, prevObservers).forEach((observer) => {\n          observer.subscribe((result) => {\n            this.#onUpdate(observer, result)\n          })\n        })\n      }\n\n      this.#notify()\n    })\n  }\n\n  getCurrentResult(): Array<QueryObserverResult> {\n    return this.#result\n  }\n\n  getQueries() {\n    return this.#observers.map((observer) => observer.getCurrentQuery())\n  }\n\n  getObservers() {\n    return this.#observers\n  }\n\n  getOptimisticResult(\n    queries: Array<QueryObserverOptions>,\n    combine: CombineFn<TCombinedResult> | undefined,\n  ): [\n    rawResult: Array<QueryObserverResult>,\n    combineResult: (r?: Array<QueryObserverResult>) => TCombinedResult,\n    trackResult: () => Array<QueryObserverResult>,\n  ] {\n    const matches = this.#findMatchingObservers(queries)\n    const result = matches.map((match) =>\n      match.observer.getOptimisticResult(match.defaultedQueryOptions),\n    )\n    const queryHashes = matches.map(\n      (match) => match.defaultedQueryOptions.queryHash,\n    )\n\n    return [\n      result,\n      (r?: Array<QueryObserverResult>) => {\n        return this.#combineResult(r ?? result, combine, queryHashes)\n      },\n      () => {\n        return this.#trackResult(result, matches)\n      },\n    ]\n  }\n\n  #trackResult(\n    result: Array<QueryObserverResult>,\n    matches: Array<QueryObserverMatch>,\n  ) {\n    return matches.map((match, index) => {\n      const observerResult = result[index]!\n      return !match.defaultedQueryOptions.notifyOnChangeProps\n        ? match.observer.trackResult(observerResult, (accessedProp) => {\n            // track property on all observers to ensure proper (synchronized) tracking (#7000)\n            matches.forEach((m) => {\n              m.observer.trackProp(accessedProp)\n            })\n          })\n        : observerResult\n    })\n  }\n\n  #combineResult(\n    input: Array<QueryObserverResult>,\n    combine: CombineFn<TCombinedResult> | undefined,\n    queryHashes?: Array<string>,\n  ): TCombinedResult {\n    if (combine) {\n      const lastHashes = this.#lastQueryHashes\n      const queryHashesChanged =\n        queryHashes !== undefined &&\n        lastHashes !== undefined &&\n        (lastHashes.length !== queryHashes.length ||\n          queryHashes.some((hash, i) => hash !== lastHashes[i]))\n\n      if (\n        !this.#combinedResult ||\n        this.#result !== this.#lastResult ||\n        queryHashesChanged ||\n        combine !== this.#lastCombine\n      ) {\n        this.#lastCombine = combine\n        this.#lastResult = this.#result\n\n        if (queryHashes !== undefined) {\n          this.#lastQueryHashes = queryHashes\n        }\n        this.#combinedResult = replaceEqualDeep(\n          this.#combinedResult,\n          combine(input),\n        )\n      }\n\n      return this.#combinedResult\n    }\n    return input as any\n  }\n\n  #findMatchingObservers(\n    queries: Array<QueryObserverOptions>,\n  ): Array<QueryObserverMatch> {\n    const prevObserversMap = new Map<string, Array<QueryObserver>>()\n\n    this.#observers.forEach((observer) => {\n      const key = observer.options.queryHash\n      if (!key) return\n\n      const previousObservers = prevObserversMap.get(key)\n\n      if (previousObservers) {\n        previousObservers.push(observer)\n      } else {\n        prevObserversMap.set(key, [observer])\n      }\n    })\n\n    const observers: Array<QueryObserverMatch> = []\n\n    queries.forEach((options) => {\n      const defaultedOptions = this.#client.defaultQueryOptions(options)\n      const match = prevObserversMap.get(defaultedOptions.queryHash)?.shift()\n      const observer =\n        match ?? new QueryObserver(this.#client, defaultedOptions)\n\n      observers.push({\n        defaultedQueryOptions: defaultedOptions,\n        observer,\n      })\n    })\n\n    return observers\n  }\n\n  #onUpdate(observer: QueryObserver, result: QueryObserverResult): void {\n    const index = this.#observers.indexOf(observer)\n    if (index !== -1) {\n      this.#result = replaceAt(this.#result, index, result)\n      this.#notify()\n    }\n  }\n\n  #notify(): void {\n    if (this.hasListeners()) {\n      const previousResult = this.#combinedResult\n      const newTracked = this.#trackResult(this.#result, this.#observerMatches)\n      const newResult = this.#combineResult(newTracked, this.#options?.combine)\n\n      if (previousResult !== newResult) {\n        notifyManager.batch(() => {\n          this.listeners.forEach((listener) => {\n            listener(this.#result)\n          })\n        })\n      }\n    }\n  }\n}\n\ntype QueryObserverMatch = {\n  defaultedQueryOptions: DefaultedQueryObserverOptions\n  observer: QueryObserver\n}\n"
  },
  {
    "path": "packages/query-core/src/query.ts",
    "content": "import {\n  ensureQueryFn,\n  noop,\n  replaceData,\n  resolveEnabled,\n  resolveStaleTime,\n  skipToken,\n  timeUntilStale,\n} from './utils'\nimport { notifyManager } from './notifyManager'\nimport { CancelledError, canFetch, createRetryer } from './retryer'\nimport { Removable } from './removable'\nimport type { QueryCache } from './queryCache'\nimport type { QueryClient } from './queryClient'\nimport type {\n  CancelOptions,\n  DefaultError,\n  FetchStatus,\n  InitialDataFunction,\n  OmitKeyof,\n  QueryFunctionContext,\n  QueryKey,\n  QueryMeta,\n  QueryOptions,\n  QueryStatus,\n  SetDataOptions,\n  StaleTime,\n} from './types'\nimport type { QueryObserver } from './queryObserver'\nimport type { Retryer } from './retryer'\n\n// TYPES\n\ninterface QueryConfig<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey extends QueryKey = QueryKey,\n> {\n  client: QueryClient\n  queryKey: TQueryKey\n  queryHash: string\n  options?: QueryOptions<TQueryFnData, TError, TData, TQueryKey>\n  defaultOptions?: QueryOptions<TQueryFnData, TError, TData, TQueryKey>\n  state?: QueryState<TData, TError>\n}\n\nexport interface QueryState<TData = unknown, TError = DefaultError> {\n  data: TData | undefined\n  dataUpdateCount: number\n  dataUpdatedAt: number\n  error: TError | null\n  errorUpdateCount: number\n  errorUpdatedAt: number\n  fetchFailureCount: number\n  fetchFailureReason: TError | null\n  fetchMeta: FetchMeta | null\n  isInvalidated: boolean\n  status: QueryStatus\n  fetchStatus: FetchStatus\n}\n\nexport interface FetchContext<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey extends QueryKey = QueryKey,\n> {\n  fetchFn: () => unknown | Promise<unknown>\n  fetchOptions?: FetchOptions\n  signal: AbortSignal\n  options: QueryOptions<TQueryFnData, TError, TData, any>\n  client: QueryClient\n  queryKey: TQueryKey\n  state: QueryState<TData, TError>\n}\n\nexport interface QueryBehavior<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> {\n  onFetch: (\n    context: FetchContext<TQueryFnData, TError, TData, TQueryKey>,\n    query: Query,\n  ) => void\n}\n\nexport type FetchDirection = 'forward' | 'backward'\n\nexport interface FetchMeta {\n  fetchMore?: { direction: FetchDirection }\n}\n\nexport interface FetchOptions<TData = unknown> {\n  cancelRefetch?: boolean\n  meta?: FetchMeta\n  initialPromise?: Promise<TData>\n}\n\ninterface FailedAction<TError> {\n  type: 'failed'\n  failureCount: number\n  error: TError\n}\n\ninterface FetchAction {\n  type: 'fetch'\n  meta?: FetchMeta\n}\n\ninterface SuccessAction<TData> {\n  data: TData | undefined\n  type: 'success'\n  dataUpdatedAt?: number\n  manual?: boolean\n}\n\ninterface ErrorAction<TError> {\n  type: 'error'\n  error: TError\n}\n\ninterface InvalidateAction {\n  type: 'invalidate'\n}\n\ninterface PauseAction {\n  type: 'pause'\n}\n\ninterface ContinueAction {\n  type: 'continue'\n}\n\ninterface SetStateAction<TData, TError> {\n  type: 'setState'\n  state: Partial<QueryState<TData, TError>>\n  setStateOptions?: SetStateOptions\n}\n\nexport type Action<TData, TError> =\n  | ContinueAction\n  | ErrorAction<TError>\n  | FailedAction<TError>\n  | FetchAction\n  | InvalidateAction\n  | PauseAction\n  | SetStateAction<TData, TError>\n  | SuccessAction<TData>\n\nexport interface SetStateOptions {\n  meta?: any\n}\n\n// CLASS\n\nexport class Query<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> extends Removable {\n  queryKey: TQueryKey\n  queryHash: string\n  options!: QueryOptions<TQueryFnData, TError, TData, TQueryKey>\n  state: QueryState<TData, TError>\n\n  #initialState: QueryState<TData, TError>\n  #revertState?: QueryState<TData, TError>\n  #cache: QueryCache\n  #client: QueryClient\n  #retryer?: Retryer<TData>\n  observers: Array<QueryObserver<any, any, any, any, any>>\n  #defaultOptions?: QueryOptions<TQueryFnData, TError, TData, TQueryKey>\n  #abortSignalConsumed: boolean\n\n  constructor(config: QueryConfig<TQueryFnData, TError, TData, TQueryKey>) {\n    super()\n\n    this.#abortSignalConsumed = false\n    this.#defaultOptions = config.defaultOptions\n    this.setOptions(config.options)\n    this.observers = []\n    this.#client = config.client\n    this.#cache = this.#client.getQueryCache()\n    this.queryKey = config.queryKey\n    this.queryHash = config.queryHash\n    this.#initialState = getDefaultState(this.options)\n    this.state = config.state ?? this.#initialState\n    this.scheduleGc()\n  }\n  get meta(): QueryMeta | undefined {\n    return this.options.meta\n  }\n\n  get promise(): Promise<TData> | undefined {\n    return this.#retryer?.promise\n  }\n\n  setOptions(\n    options?: QueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  ): void {\n    this.options = { ...this.#defaultOptions, ...options }\n\n    this.updateGcTime(this.options.gcTime)\n\n    // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n    if (this.state && this.state.data === undefined) {\n      const defaultState = getDefaultState(this.options)\n      if (defaultState.data !== undefined) {\n        this.setState(\n          successState(defaultState.data, defaultState.dataUpdatedAt),\n        )\n        this.#initialState = defaultState\n      }\n    }\n  }\n\n  protected optionalRemove() {\n    if (!this.observers.length && this.state.fetchStatus === 'idle') {\n      this.#cache.remove(this)\n    }\n  }\n\n  setData(\n    newData: TData,\n    options?: SetDataOptions & { manual: boolean },\n  ): TData {\n    const data = replaceData(this.state.data, newData, this.options)\n\n    // Set data and mark it as cached\n    this.#dispatch({\n      data,\n      type: 'success',\n      dataUpdatedAt: options?.updatedAt,\n      manual: options?.manual,\n    })\n\n    return data\n  }\n\n  setState(\n    state: Partial<QueryState<TData, TError>>,\n    setStateOptions?: SetStateOptions,\n  ): void {\n    this.#dispatch({ type: 'setState', state, setStateOptions })\n  }\n\n  cancel(options?: CancelOptions): Promise<void> {\n    const promise = this.#retryer?.promise\n    this.#retryer?.cancel(options)\n    return promise ? promise.then(noop).catch(noop) : Promise.resolve()\n  }\n\n  destroy(): void {\n    super.destroy()\n\n    this.cancel({ silent: true })\n  }\n\n  get resetState(): QueryState<TData, TError> {\n    return this.#initialState\n  }\n\n  reset(): void {\n    this.destroy()\n    this.setState(this.resetState)\n  }\n\n  isActive(): boolean {\n    return this.observers.some(\n      (observer) => resolveEnabled(observer.options.enabled, this) !== false,\n    )\n  }\n\n  isDisabled(): boolean {\n    if (this.getObserversCount() > 0) {\n      return !this.isActive()\n    }\n    // if a query has no observers, it should still be considered disabled if it never attempted a fetch\n    return this.options.queryFn === skipToken || !this.isFetched()\n  }\n\n  isFetched() {\n    return this.state.dataUpdateCount + this.state.errorUpdateCount > 0\n  }\n\n  isStatic(): boolean {\n    if (this.getObserversCount() > 0) {\n      return this.observers.some(\n        (observer) =>\n          resolveStaleTime(observer.options.staleTime, this) === 'static',\n      )\n    }\n\n    return false\n  }\n\n  isStale(): boolean {\n    // check observers first, their `isStale` has the source of truth\n    // calculated with `isStaleByTime` and it takes `enabled` into account\n    if (this.getObserversCount() > 0) {\n      return this.observers.some(\n        (observer) => observer.getCurrentResult().isStale,\n      )\n    }\n\n    return this.state.data === undefined || this.state.isInvalidated\n  }\n\n  isStaleByTime(staleTime: StaleTime = 0): boolean {\n    // no data is always stale\n    if (this.state.data === undefined) {\n      return true\n    }\n    // static is never stale\n    if (staleTime === 'static') {\n      return false\n    }\n    // if the query is invalidated, it is stale\n    if (this.state.isInvalidated) {\n      return true\n    }\n\n    return !timeUntilStale(this.state.dataUpdatedAt, staleTime)\n  }\n\n  onFocus(): void {\n    const observer = this.observers.find((x) => x.shouldFetchOnWindowFocus())\n\n    observer?.refetch({ cancelRefetch: false })\n\n    // Continue fetch if currently paused\n    this.#retryer?.continue()\n  }\n\n  onOnline(): void {\n    const observer = this.observers.find((x) => x.shouldFetchOnReconnect())\n\n    observer?.refetch({ cancelRefetch: false })\n\n    // Continue fetch if currently paused\n    this.#retryer?.continue()\n  }\n\n  addObserver(observer: QueryObserver<any, any, any, any, any>): void {\n    if (!this.observers.includes(observer)) {\n      this.observers.push(observer)\n\n      // Stop the query from being garbage collected\n      this.clearGcTimeout()\n\n      this.#cache.notify({ type: 'observerAdded', query: this, observer })\n    }\n  }\n\n  removeObserver(observer: QueryObserver<any, any, any, any, any>): void {\n    if (this.observers.includes(observer)) {\n      this.observers = this.observers.filter((x) => x !== observer)\n\n      if (!this.observers.length) {\n        // If the transport layer does not support cancellation\n        // we'll let the query continue so the result can be cached\n        if (this.#retryer) {\n          if (this.#abortSignalConsumed || this.#isInitialPausedFetch()) {\n            this.#retryer.cancel({ revert: true })\n          } else {\n            this.#retryer.cancelRetry()\n          }\n        }\n\n        this.scheduleGc()\n      }\n\n      this.#cache.notify({ type: 'observerRemoved', query: this, observer })\n    }\n  }\n\n  getObserversCount(): number {\n    return this.observers.length\n  }\n\n  #isInitialPausedFetch(): boolean {\n    return (\n      this.state.fetchStatus === 'paused' && this.state.status === 'pending'\n    )\n  }\n\n  invalidate(): void {\n    if (!this.state.isInvalidated) {\n      this.#dispatch({ type: 'invalidate' })\n    }\n  }\n\n  async fetch(\n    options?: QueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n    fetchOptions?: FetchOptions<TQueryFnData>,\n  ): Promise<TData> {\n    if (\n      this.state.fetchStatus !== 'idle' &&\n      // If the promise in the retryer is already rejected, we have to definitely\n      // re-start the fetch; there is a chance that the query is still in a\n      // pending state when that happens\n      this.#retryer?.status() !== 'rejected'\n    ) {\n      if (this.state.data !== undefined && fetchOptions?.cancelRefetch) {\n        // Silently cancel current fetch if the user wants to cancel refetch\n        this.cancel({ silent: true })\n      } else if (this.#retryer) {\n        // make sure that retries that were potentially cancelled due to unmounts can continue\n        this.#retryer.continueRetry()\n        // Return current promise if we are already fetching\n        return this.#retryer.promise\n      }\n    }\n\n    // Update config if passed, otherwise the config from the last execution is used\n    if (options) {\n      this.setOptions(options)\n    }\n\n    // Use the options from the first observer with a query function if no function is found.\n    // This can happen when the query is hydrated or created with setQueryData.\n    if (!this.options.queryFn) {\n      const observer = this.observers.find((x) => x.options.queryFn)\n      if (observer) {\n        this.setOptions(observer.options)\n      }\n    }\n\n    if (process.env.NODE_ENV !== 'production') {\n      if (!Array.isArray(this.options.queryKey)) {\n        console.error(\n          `As of v4, queryKey needs to be an Array. If you are using a string like 'repoData', please change it to an Array, e.g. ['repoData']`,\n        )\n      }\n    }\n\n    const abortController = new AbortController()\n\n    // Adds an enumerable signal property to the object that\n    // which sets abortSignalConsumed to true when the signal\n    // is read.\n    const addSignalProperty = (object: unknown) => {\n      Object.defineProperty(object, 'signal', {\n        enumerable: true,\n        get: () => {\n          this.#abortSignalConsumed = true\n          return abortController.signal\n        },\n      })\n    }\n\n    // Create fetch function\n    const fetchFn = () => {\n      const queryFn = ensureQueryFn(this.options, fetchOptions)\n\n      // Create query function context\n      const createQueryFnContext = (): QueryFunctionContext<TQueryKey> => {\n        const queryFnContext: OmitKeyof<\n          QueryFunctionContext<TQueryKey>,\n          'signal'\n        > = {\n          client: this.#client,\n          queryKey: this.queryKey,\n          meta: this.meta,\n        }\n        addSignalProperty(queryFnContext)\n        return queryFnContext as QueryFunctionContext<TQueryKey>\n      }\n\n      const queryFnContext = createQueryFnContext()\n\n      this.#abortSignalConsumed = false\n      if (this.options.persister) {\n        return this.options.persister(\n          queryFn,\n          queryFnContext,\n          this as unknown as Query,\n        )\n      }\n\n      return queryFn(queryFnContext)\n    }\n\n    // Trigger behavior hook\n    const createFetchContext = (): FetchContext<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey\n    > => {\n      const context: OmitKeyof<\n        FetchContext<TQueryFnData, TError, TData, TQueryKey>,\n        'signal'\n      > = {\n        fetchOptions,\n        options: this.options,\n        queryKey: this.queryKey,\n        client: this.#client,\n        state: this.state,\n        fetchFn,\n      }\n\n      addSignalProperty(context)\n      return context as FetchContext<TQueryFnData, TError, TData, TQueryKey>\n    }\n\n    const context = createFetchContext()\n\n    this.options.behavior?.onFetch(context, this as unknown as Query)\n\n    // Store state in case the current fetch needs to be reverted\n    this.#revertState = this.state\n\n    // Set to fetching state if not already in it\n    if (\n      this.state.fetchStatus === 'idle' ||\n      this.state.fetchMeta !== context.fetchOptions?.meta\n    ) {\n      this.#dispatch({ type: 'fetch', meta: context.fetchOptions?.meta })\n    }\n\n    // Try to fetch the data\n    this.#retryer = createRetryer({\n      initialPromise: fetchOptions?.initialPromise as\n        | Promise<TData>\n        | undefined,\n      fn: context.fetchFn as () => Promise<TData>,\n      onCancel: (error) => {\n        if (error instanceof CancelledError && error.revert) {\n          this.setState({\n            ...this.#revertState,\n            fetchStatus: 'idle' as const,\n          })\n        }\n        abortController.abort()\n      },\n      onFail: (failureCount, error) => {\n        this.#dispatch({ type: 'failed', failureCount, error })\n      },\n      onPause: () => {\n        this.#dispatch({ type: 'pause' })\n      },\n      onContinue: () => {\n        this.#dispatch({ type: 'continue' })\n      },\n      retry: context.options.retry,\n      retryDelay: context.options.retryDelay,\n      networkMode: context.options.networkMode,\n      canRun: () => true,\n    })\n\n    try {\n      const data = await this.#retryer.start()\n      // this is more of a runtime guard\n      // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n      if (data === undefined) {\n        if (process.env.NODE_ENV !== 'production') {\n          console.error(\n            `Query data cannot be undefined. Please make sure to return a value other than undefined from your query function. Affected query key: ${this.queryHash}`,\n          )\n        }\n        throw new Error(`${this.queryHash} data is undefined`)\n      }\n\n      this.setData(data)\n\n      // Notify cache callback\n      this.#cache.config.onSuccess?.(data, this as Query<any, any, any, any>)\n      this.#cache.config.onSettled?.(\n        data,\n        this.state.error as any,\n        this as Query<any, any, any, any>,\n      )\n      return data\n    } catch (error) {\n      if (error instanceof CancelledError) {\n        if (error.silent) {\n          // silent cancellation implies a new fetch is going to be started,\n          // so we piggyback onto that promise\n          return this.#retryer.promise\n        } else if (error.revert) {\n          // transform error into reverted state data\n          // if the initial fetch was cancelled, we have no data, so we have\n          // to get reject with a CancelledError\n          if (this.state.data === undefined) {\n            throw error\n          }\n          return this.state.data\n        }\n      }\n      this.#dispatch({\n        type: 'error',\n        error: error as TError,\n      })\n\n      // Notify cache callback\n      this.#cache.config.onError?.(\n        error as any,\n        this as Query<any, any, any, any>,\n      )\n      this.#cache.config.onSettled?.(\n        this.state.data,\n        error as any,\n        this as Query<any, any, any, any>,\n      )\n\n      throw error // rethrow the error for further handling\n    } finally {\n      // Schedule query gc after fetching\n      this.scheduleGc()\n    }\n  }\n\n  #dispatch(action: Action<TData, TError>): void {\n    const reducer = (\n      state: QueryState<TData, TError>,\n    ): QueryState<TData, TError> => {\n      switch (action.type) {\n        case 'failed':\n          return {\n            ...state,\n            fetchFailureCount: action.failureCount,\n            fetchFailureReason: action.error,\n          }\n        case 'pause':\n          return {\n            ...state,\n            fetchStatus: 'paused',\n          }\n        case 'continue':\n          return {\n            ...state,\n            fetchStatus: 'fetching',\n          }\n        case 'fetch':\n          return {\n            ...state,\n            ...fetchState(state.data, this.options),\n            fetchMeta: action.meta ?? null,\n          }\n        case 'success':\n          const newState = {\n            ...state,\n            ...successState(action.data, action.dataUpdatedAt),\n            dataUpdateCount: state.dataUpdateCount + 1,\n            ...(!action.manual && {\n              fetchStatus: 'idle' as const,\n              fetchFailureCount: 0,\n              fetchFailureReason: null,\n            }),\n          }\n          // If fetching ends successfully, we don't need revertState as a fallback anymore.\n          // For manual updates, capture the state to revert to it in case of a cancellation.\n          this.#revertState = action.manual ? newState : undefined\n\n          return newState\n        case 'error':\n          const error = action.error\n          return {\n            ...state,\n            error,\n            errorUpdateCount: state.errorUpdateCount + 1,\n            errorUpdatedAt: Date.now(),\n            fetchFailureCount: state.fetchFailureCount + 1,\n            fetchFailureReason: error,\n            fetchStatus: 'idle',\n            status: 'error',\n            // flag existing data as invalidated if we get a background error\n            // note that \"no data\" always means stale so we can set unconditionally here\n            isInvalidated: true,\n          }\n        case 'invalidate':\n          return {\n            ...state,\n            isInvalidated: true,\n          }\n        case 'setState':\n          return {\n            ...state,\n            ...action.state,\n          }\n      }\n    }\n\n    this.state = reducer(this.state)\n\n    notifyManager.batch(() => {\n      this.observers.forEach((observer) => {\n        observer.onQueryUpdate()\n      })\n\n      this.#cache.notify({ query: this, type: 'updated', action })\n    })\n  }\n}\n\nexport function fetchState<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey extends QueryKey,\n>(\n  data: TData | undefined,\n  options: QueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n) {\n  return {\n    fetchFailureCount: 0,\n    fetchFailureReason: null,\n    fetchStatus: canFetch(options.networkMode) ? 'fetching' : 'paused',\n    ...(data === undefined &&\n      ({\n        error: null,\n        status: 'pending',\n      } as const)),\n  } as const\n}\n\nfunction successState<TData>(data: TData | undefined, dataUpdatedAt?: number) {\n  return {\n    data,\n    dataUpdatedAt: dataUpdatedAt ?? Date.now(),\n    error: null,\n    isInvalidated: false,\n    status: 'success' as const,\n  }\n}\n\nfunction getDefaultState<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey extends QueryKey,\n>(\n  options: QueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n): QueryState<TData, TError> {\n  const data =\n    typeof options.initialData === 'function'\n      ? (options.initialData as InitialDataFunction<TData>)()\n      : options.initialData\n\n  const hasData = data !== undefined\n\n  const initialDataUpdatedAt = hasData\n    ? typeof options.initialDataUpdatedAt === 'function'\n      ? options.initialDataUpdatedAt()\n      : options.initialDataUpdatedAt\n    : 0\n\n  return {\n    data,\n    dataUpdateCount: 0,\n    dataUpdatedAt: hasData ? (initialDataUpdatedAt ?? Date.now()) : 0,\n    error: null,\n    errorUpdateCount: 0,\n    errorUpdatedAt: 0,\n    fetchFailureCount: 0,\n    fetchFailureReason: null,\n    fetchMeta: null,\n    isInvalidated: false,\n    status: hasData ? 'success' : 'pending',\n    fetchStatus: 'idle',\n  }\n}\n"
  },
  {
    "path": "packages/query-core/src/queryCache.ts",
    "content": "import { hashQueryKeyByOptions, matchQuery } from './utils'\nimport { Query } from './query'\nimport { notifyManager } from './notifyManager'\nimport { Subscribable } from './subscribable'\nimport type { QueryFilters } from './utils'\nimport type { Action, QueryState } from './query'\nimport type {\n  DefaultError,\n  NotifyEvent,\n  QueryKey,\n  QueryOptions,\n  WithRequired,\n} from './types'\nimport type { QueryClient } from './queryClient'\nimport type { QueryObserver } from './queryObserver'\n\n// TYPES\n\ninterface QueryCacheConfig {\n  onError?: (\n    error: DefaultError,\n    query: Query<unknown, unknown, unknown>,\n  ) => void\n  onSuccess?: (data: unknown, query: Query<unknown, unknown, unknown>) => void\n  onSettled?: (\n    data: unknown | undefined,\n    error: DefaultError | null,\n    query: Query<unknown, unknown, unknown>,\n  ) => void\n}\n\ninterface NotifyEventQueryAdded extends NotifyEvent {\n  type: 'added'\n  query: Query<any, any, any, any>\n}\n\ninterface NotifyEventQueryRemoved extends NotifyEvent {\n  type: 'removed'\n  query: Query<any, any, any, any>\n}\n\ninterface NotifyEventQueryUpdated extends NotifyEvent {\n  type: 'updated'\n  query: Query<any, any, any, any>\n  action: Action<any, any>\n}\n\ninterface NotifyEventQueryObserverAdded extends NotifyEvent {\n  type: 'observerAdded'\n  query: Query<any, any, any, any>\n  observer: QueryObserver<any, any, any, any, any>\n}\n\ninterface NotifyEventQueryObserverRemoved extends NotifyEvent {\n  type: 'observerRemoved'\n  query: Query<any, any, any, any>\n  observer: QueryObserver<any, any, any, any, any>\n}\n\ninterface NotifyEventQueryObserverResultsUpdated extends NotifyEvent {\n  type: 'observerResultsUpdated'\n  query: Query<any, any, any, any>\n}\n\ninterface NotifyEventQueryObserverOptionsUpdated extends NotifyEvent {\n  type: 'observerOptionsUpdated'\n  query: Query<any, any, any, any>\n  observer: QueryObserver<any, any, any, any, any>\n}\n\nexport type QueryCacheNotifyEvent =\n  | NotifyEventQueryAdded\n  | NotifyEventQueryRemoved\n  | NotifyEventQueryUpdated\n  | NotifyEventQueryObserverAdded\n  | NotifyEventQueryObserverRemoved\n  | NotifyEventQueryObserverResultsUpdated\n  | NotifyEventQueryObserverOptionsUpdated\n\ntype QueryCacheListener = (event: QueryCacheNotifyEvent) => void\n\nexport interface QueryStore {\n  has: (queryHash: string) => boolean\n  set: (queryHash: string, query: Query) => void\n  get: (queryHash: string) => Query | undefined\n  delete: (queryHash: string) => void\n  values: () => IterableIterator<Query>\n}\n\n// CLASS\n\nexport class QueryCache extends Subscribable<QueryCacheListener> {\n  #queries: QueryStore\n\n  constructor(public config: QueryCacheConfig = {}) {\n    super()\n    this.#queries = new Map<string, Query>()\n  }\n\n  build<\n    TQueryFnData = unknown,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryKey extends QueryKey = QueryKey,\n  >(\n    client: QueryClient,\n    options: WithRequired<\n      QueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n      'queryKey'\n    >,\n    state?: QueryState<TData, TError>,\n  ): Query<TQueryFnData, TError, TData, TQueryKey> {\n    const queryKey = options.queryKey\n    const queryHash =\n      options.queryHash ?? hashQueryKeyByOptions(queryKey, options)\n    let query = this.get<TQueryFnData, TError, TData, TQueryKey>(queryHash)\n\n    if (!query) {\n      query = new Query({\n        client,\n        queryKey,\n        queryHash,\n        options: client.defaultQueryOptions(options),\n        state,\n        defaultOptions: client.getQueryDefaults(queryKey),\n      })\n      this.add(query)\n    }\n\n    return query\n  }\n\n  add(query: Query<any, any, any, any>): void {\n    if (!this.#queries.has(query.queryHash)) {\n      this.#queries.set(query.queryHash, query)\n\n      this.notify({\n        type: 'added',\n        query,\n      })\n    }\n  }\n\n  remove(query: Query<any, any, any, any>): void {\n    const queryInMap = this.#queries.get(query.queryHash)\n\n    if (queryInMap) {\n      query.destroy()\n\n      if (queryInMap === query) {\n        this.#queries.delete(query.queryHash)\n      }\n\n      this.notify({ type: 'removed', query })\n    }\n  }\n\n  clear(): void {\n    notifyManager.batch(() => {\n      this.getAll().forEach((query) => {\n        this.remove(query)\n      })\n    })\n  }\n\n  get<\n    TQueryFnData = unknown,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryKey extends QueryKey = QueryKey,\n  >(\n    queryHash: string,\n  ): Query<TQueryFnData, TError, TData, TQueryKey> | undefined {\n    return this.#queries.get(queryHash) as\n      | Query<TQueryFnData, TError, TData, TQueryKey>\n      | undefined\n  }\n\n  getAll(): Array<Query> {\n    return [...this.#queries.values()]\n  }\n\n  find<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData>(\n    filters: WithRequired<QueryFilters, 'queryKey'>,\n  ): Query<TQueryFnData, TError, TData> | undefined {\n    const defaultedFilters = { exact: true, ...filters }\n\n    return this.getAll().find((query) =>\n      matchQuery(defaultedFilters, query),\n    ) as Query<TQueryFnData, TError, TData> | undefined\n  }\n\n  findAll(filters: QueryFilters<any> = {}): Array<Query> {\n    const queries = this.getAll()\n    return Object.keys(filters).length > 0\n      ? queries.filter((query) => matchQuery(filters, query))\n      : queries\n  }\n\n  notify(event: QueryCacheNotifyEvent): void {\n    notifyManager.batch(() => {\n      this.listeners.forEach((listener) => {\n        listener(event)\n      })\n    })\n  }\n\n  onFocus(): void {\n    notifyManager.batch(() => {\n      this.getAll().forEach((query) => {\n        query.onFocus()\n      })\n    })\n  }\n\n  onOnline(): void {\n    notifyManager.batch(() => {\n      this.getAll().forEach((query) => {\n        query.onOnline()\n      })\n    })\n  }\n}\n"
  },
  {
    "path": "packages/query-core/src/queryClient.ts",
    "content": "import {\n  functionalUpdate,\n  hashKey,\n  hashQueryKeyByOptions,\n  noop,\n  partialMatchKey,\n  resolveStaleTime,\n  skipToken,\n} from './utils'\nimport { QueryCache } from './queryCache'\nimport { MutationCache } from './mutationCache'\nimport { focusManager } from './focusManager'\nimport { onlineManager } from './onlineManager'\nimport { notifyManager } from './notifyManager'\nimport { infiniteQueryBehavior } from './infiniteQueryBehavior'\nimport type {\n  CancelOptions,\n  DefaultError,\n  DefaultOptions,\n  DefaultedQueryObserverOptions,\n  EnsureInfiniteQueryDataOptions,\n  EnsureQueryDataOptions,\n  FetchInfiniteQueryOptions,\n  FetchQueryOptions,\n  InferDataFromTag,\n  InferErrorFromTag,\n  InfiniteData,\n  InvalidateOptions,\n  InvalidateQueryFilters,\n  MutationKey,\n  MutationObserverOptions,\n  MutationOptions,\n  NoInfer,\n  OmitKeyof,\n  QueryClientConfig,\n  QueryKey,\n  QueryObserverOptions,\n  QueryOptions,\n  RefetchOptions,\n  RefetchQueryFilters,\n  ResetOptions,\n  SetDataOptions,\n} from './types'\nimport type { QueryState } from './query'\nimport type { MutationFilters, QueryFilters, Updater } from './utils'\n\n// TYPES\n\ninterface QueryDefaults {\n  queryKey: QueryKey\n  defaultOptions: OmitKeyof<QueryOptions<any, any, any>, 'queryKey'>\n}\n\ninterface MutationDefaults {\n  mutationKey: MutationKey\n  defaultOptions: MutationOptions<any, any, any, any>\n}\n\n// CLASS\n\nexport class QueryClient {\n  #queryCache: QueryCache\n  #mutationCache: MutationCache\n  #defaultOptions: DefaultOptions\n  #queryDefaults: Map<string, QueryDefaults>\n  #mutationDefaults: Map<string, MutationDefaults>\n  #mountCount: number\n  #unsubscribeFocus?: () => void\n  #unsubscribeOnline?: () => void\n\n  constructor(config: QueryClientConfig = {}) {\n    this.#queryCache = config.queryCache || new QueryCache()\n    this.#mutationCache = config.mutationCache || new MutationCache()\n    this.#defaultOptions = config.defaultOptions || {}\n    this.#queryDefaults = new Map()\n    this.#mutationDefaults = new Map()\n    this.#mountCount = 0\n  }\n\n  mount(): void {\n    this.#mountCount++\n    if (this.#mountCount !== 1) return\n\n    this.#unsubscribeFocus = focusManager.subscribe(async (focused) => {\n      if (focused) {\n        await this.resumePausedMutations()\n        this.#queryCache.onFocus()\n      }\n    })\n    this.#unsubscribeOnline = onlineManager.subscribe(async (online) => {\n      if (online) {\n        await this.resumePausedMutations()\n        this.#queryCache.onOnline()\n      }\n    })\n  }\n\n  unmount(): void {\n    this.#mountCount--\n    if (this.#mountCount !== 0) return\n\n    this.#unsubscribeFocus?.()\n    this.#unsubscribeFocus = undefined\n\n    this.#unsubscribeOnline?.()\n    this.#unsubscribeOnline = undefined\n  }\n\n  isFetching<TQueryFilters extends QueryFilters<any> = QueryFilters>(\n    filters?: TQueryFilters,\n  ): number {\n    return this.#queryCache.findAll({ ...filters, fetchStatus: 'fetching' })\n      .length\n  }\n\n  isMutating<\n    TMutationFilters extends MutationFilters<any, any> = MutationFilters,\n  >(filters?: TMutationFilters): number {\n    return this.#mutationCache.findAll({ ...filters, status: 'pending' }).length\n  }\n\n  /**\n   * Imperative (non-reactive) way to retrieve data for a QueryKey.\n   * Should only be used in callbacks or functions where reading the latest data is necessary, e.g. for optimistic updates.\n   *\n   * Hint: Do not use this function inside a component, because it won't receive updates.\n   * Use `useQuery` to create a `QueryObserver` that subscribes to changes.\n   */\n  getQueryData<\n    TQueryFnData = unknown,\n    TTaggedQueryKey extends QueryKey = QueryKey,\n    TInferredQueryFnData = InferDataFromTag<TQueryFnData, TTaggedQueryKey>,\n  >(queryKey: TTaggedQueryKey): TInferredQueryFnData | undefined {\n    const options = this.defaultQueryOptions({ queryKey })\n\n    return this.#queryCache.get<TInferredQueryFnData>(options.queryHash)?.state\n      .data\n  }\n\n  ensureQueryData<\n    TQueryFnData,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryKey extends QueryKey = QueryKey,\n  >(\n    options: EnsureQueryDataOptions<TQueryFnData, TError, TData, TQueryKey>,\n  ): Promise<TData> {\n    const defaultedOptions = this.defaultQueryOptions(options)\n    const query = this.#queryCache.build(this, defaultedOptions)\n    const cachedData = query.state.data\n\n    if (cachedData === undefined) {\n      return this.fetchQuery(options)\n    }\n\n    if (\n      options.revalidateIfStale &&\n      query.isStaleByTime(resolveStaleTime(defaultedOptions.staleTime, query))\n    ) {\n      void this.prefetchQuery(defaultedOptions)\n    }\n\n    return Promise.resolve(cachedData)\n  }\n\n  getQueriesData<\n    TQueryFnData = unknown,\n    TQueryFilters extends QueryFilters<any> = QueryFilters,\n  >(filters: TQueryFilters): Array<[QueryKey, TQueryFnData | undefined]> {\n    return this.#queryCache.findAll(filters).map(({ queryKey, state }) => {\n      const data = state.data as TQueryFnData | undefined\n      return [queryKey, data]\n    })\n  }\n\n  setQueryData<\n    TQueryFnData = unknown,\n    TTaggedQueryKey extends QueryKey = QueryKey,\n    TInferredQueryFnData = InferDataFromTag<TQueryFnData, TTaggedQueryKey>,\n  >(\n    queryKey: TTaggedQueryKey,\n    updater: Updater<\n      NoInfer<TInferredQueryFnData> | undefined,\n      NoInfer<TInferredQueryFnData> | undefined\n    >,\n    options?: SetDataOptions,\n  ): NoInfer<TInferredQueryFnData> | undefined {\n    const defaultedOptions = this.defaultQueryOptions<\n      any,\n      any,\n      unknown,\n      any,\n      QueryKey\n    >({ queryKey })\n\n    const query = this.#queryCache.get<TInferredQueryFnData>(\n      defaultedOptions.queryHash,\n    )\n    const prevData = query?.state.data\n    const data = functionalUpdate(updater, prevData)\n\n    if (data === undefined) {\n      return undefined\n    }\n\n    return this.#queryCache\n      .build(this, defaultedOptions)\n      .setData(data, { ...options, manual: true })\n  }\n\n  setQueriesData<\n    TQueryFnData,\n    TQueryFilters extends QueryFilters<any> = QueryFilters,\n  >(\n    filters: TQueryFilters,\n    updater: Updater<\n      NoInfer<TQueryFnData> | undefined,\n      NoInfer<TQueryFnData> | undefined\n    >,\n    options?: SetDataOptions,\n  ): Array<[QueryKey, TQueryFnData | undefined]> {\n    return notifyManager.batch(() =>\n      this.#queryCache\n        .findAll(filters)\n        .map(({ queryKey }) => [\n          queryKey,\n          this.setQueryData<TQueryFnData>(queryKey, updater, options),\n        ]),\n    )\n  }\n\n  getQueryState<\n    TQueryFnData = unknown,\n    TError = DefaultError,\n    TTaggedQueryKey extends QueryKey = QueryKey,\n    TInferredQueryFnData = InferDataFromTag<TQueryFnData, TTaggedQueryKey>,\n    TInferredError = InferErrorFromTag<TError, TTaggedQueryKey>,\n  >(\n    queryKey: TTaggedQueryKey,\n  ): QueryState<TInferredQueryFnData, TInferredError> | undefined {\n    const options = this.defaultQueryOptions({ queryKey })\n    return this.#queryCache.get<TInferredQueryFnData, TInferredError>(\n      options.queryHash,\n    )?.state\n  }\n\n  removeQueries<TTaggedQueryKey extends QueryKey = QueryKey>(\n    filters?: QueryFilters<TTaggedQueryKey>,\n  ): void {\n    const queryCache = this.#queryCache\n    notifyManager.batch(() => {\n      queryCache.findAll(filters).forEach((query) => {\n        queryCache.remove(query)\n      })\n    })\n  }\n\n  resetQueries<TTaggedQueryKey extends QueryKey = QueryKey>(\n    filters?: QueryFilters<TTaggedQueryKey>,\n    options?: ResetOptions,\n  ): Promise<void> {\n    const queryCache = this.#queryCache\n\n    return notifyManager.batch(() => {\n      queryCache.findAll(filters).forEach((query) => {\n        query.reset()\n      })\n      return this.refetchQueries(\n        {\n          type: 'active',\n          ...filters,\n        },\n        options,\n      )\n    })\n  }\n\n  cancelQueries<TTaggedQueryKey extends QueryKey = QueryKey>(\n    filters?: QueryFilters<TTaggedQueryKey>,\n    cancelOptions: CancelOptions = {},\n  ): Promise<void> {\n    const defaultedCancelOptions = { revert: true, ...cancelOptions }\n\n    const promises = notifyManager.batch(() =>\n      this.#queryCache\n        .findAll(filters)\n        .map((query) => query.cancel(defaultedCancelOptions)),\n    )\n\n    return Promise.all(promises).then(noop).catch(noop)\n  }\n\n  invalidateQueries<TTaggedQueryKey extends QueryKey = QueryKey>(\n    filters?: InvalidateQueryFilters<TTaggedQueryKey>,\n    options: InvalidateOptions = {},\n  ): Promise<void> {\n    return notifyManager.batch(() => {\n      this.#queryCache.findAll(filters).forEach((query) => {\n        query.invalidate()\n      })\n\n      if (filters?.refetchType === 'none') {\n        return Promise.resolve()\n      }\n      return this.refetchQueries(\n        {\n          ...filters,\n          type: filters?.refetchType ?? filters?.type ?? 'active',\n        },\n        options,\n      )\n    })\n  }\n\n  refetchQueries<TTaggedQueryKey extends QueryKey = QueryKey>(\n    filters?: RefetchQueryFilters<TTaggedQueryKey>,\n    options: RefetchOptions = {},\n  ): Promise<void> {\n    const fetchOptions = {\n      ...options,\n      cancelRefetch: options.cancelRefetch ?? true,\n    }\n    const promises = notifyManager.batch(() =>\n      this.#queryCache\n        .findAll(filters)\n        .filter((query) => !query.isDisabled() && !query.isStatic())\n        .map((query) => {\n          let promise = query.fetch(undefined, fetchOptions)\n          if (!fetchOptions.throwOnError) {\n            promise = promise.catch(noop)\n          }\n          return query.state.fetchStatus === 'paused'\n            ? Promise.resolve()\n            : promise\n        }),\n    )\n\n    return Promise.all(promises).then(noop)\n  }\n\n  fetchQuery<\n    TQueryFnData,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryKey extends QueryKey = QueryKey,\n    TPageParam = never,\n  >(\n    options: FetchQueryOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey,\n      TPageParam\n    >,\n  ): Promise<TData> {\n    const defaultedOptions = this.defaultQueryOptions(options)\n\n    // https://github.com/tannerlinsley/react-query/issues/652\n    if (defaultedOptions.retry === undefined) {\n      defaultedOptions.retry = false\n    }\n\n    const query = this.#queryCache.build(this, defaultedOptions)\n\n    return query.isStaleByTime(\n      resolveStaleTime(defaultedOptions.staleTime, query),\n    )\n      ? query.fetch(defaultedOptions)\n      : Promise.resolve(query.state.data as TData)\n  }\n\n  prefetchQuery<\n    TQueryFnData = unknown,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryKey extends QueryKey = QueryKey,\n  >(\n    options: FetchQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  ): Promise<void> {\n    return this.fetchQuery(options).then(noop).catch(noop)\n  }\n\n  fetchInfiniteQuery<\n    TQueryFnData,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryKey extends QueryKey = QueryKey,\n    TPageParam = unknown,\n  >(\n    options: FetchInfiniteQueryOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey,\n      TPageParam\n    >,\n  ): Promise<InfiniteData<TData, TPageParam>> {\n    options.behavior = infiniteQueryBehavior<\n      TQueryFnData,\n      TError,\n      TData,\n      TPageParam\n    >(options.pages)\n    return this.fetchQuery(options as any)\n  }\n\n  prefetchInfiniteQuery<\n    TQueryFnData,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryKey extends QueryKey = QueryKey,\n    TPageParam = unknown,\n  >(\n    options: FetchInfiniteQueryOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey,\n      TPageParam\n    >,\n  ): Promise<void> {\n    return this.fetchInfiniteQuery(options).then(noop).catch(noop)\n  }\n\n  ensureInfiniteQueryData<\n    TQueryFnData,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryKey extends QueryKey = QueryKey,\n    TPageParam = unknown,\n  >(\n    options: EnsureInfiniteQueryDataOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey,\n      TPageParam\n    >,\n  ): Promise<InfiniteData<TData, TPageParam>> {\n    options.behavior = infiniteQueryBehavior<\n      TQueryFnData,\n      TError,\n      TData,\n      TPageParam\n    >(options.pages)\n\n    return this.ensureQueryData(options as any)\n  }\n\n  resumePausedMutations(): Promise<unknown> {\n    if (onlineManager.isOnline()) {\n      return this.#mutationCache.resumePausedMutations()\n    }\n    return Promise.resolve()\n  }\n\n  getQueryCache(): QueryCache {\n    return this.#queryCache\n  }\n\n  getMutationCache(): MutationCache {\n    return this.#mutationCache\n  }\n\n  getDefaultOptions(): DefaultOptions {\n    return this.#defaultOptions\n  }\n\n  setDefaultOptions(options: DefaultOptions): void {\n    this.#defaultOptions = options\n  }\n\n  setQueryDefaults<\n    TQueryFnData = unknown,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryData = TQueryFnData,\n  >(\n    queryKey: QueryKey,\n    options: Partial<\n      OmitKeyof<\n        QueryObserverOptions<TQueryFnData, TError, TData, TQueryData>,\n        'queryKey'\n      >\n    >,\n  ): void {\n    this.#queryDefaults.set(hashKey(queryKey), {\n      queryKey,\n      defaultOptions: options,\n    })\n  }\n\n  getQueryDefaults(\n    queryKey: QueryKey,\n  ): OmitKeyof<QueryObserverOptions<any, any, any, any, any>, 'queryKey'> {\n    const defaults = [...this.#queryDefaults.values()]\n\n    const result: OmitKeyof<\n      QueryObserverOptions<any, any, any, any, any>,\n      'queryKey'\n    > = {}\n\n    defaults.forEach((queryDefault) => {\n      if (partialMatchKey(queryKey, queryDefault.queryKey)) {\n        Object.assign(result, queryDefault.defaultOptions)\n      }\n    })\n    return result\n  }\n\n  setMutationDefaults<\n    TData = unknown,\n    TError = DefaultError,\n    TVariables = void,\n    TOnMutateResult = unknown,\n  >(\n    mutationKey: MutationKey,\n    options: OmitKeyof<\n      MutationObserverOptions<TData, TError, TVariables, TOnMutateResult>,\n      'mutationKey'\n    >,\n  ): void {\n    this.#mutationDefaults.set(hashKey(mutationKey), {\n      mutationKey,\n      defaultOptions: options,\n    })\n  }\n\n  getMutationDefaults(\n    mutationKey: MutationKey,\n  ): OmitKeyof<MutationObserverOptions<any, any, any, any>, 'mutationKey'> {\n    const defaults = [...this.#mutationDefaults.values()]\n\n    const result: OmitKeyof<\n      MutationObserverOptions<any, any, any, any>,\n      'mutationKey'\n    > = {}\n\n    defaults.forEach((queryDefault) => {\n      if (partialMatchKey(mutationKey, queryDefault.mutationKey)) {\n        Object.assign(result, queryDefault.defaultOptions)\n      }\n    })\n\n    return result\n  }\n\n  defaultQueryOptions<\n    TQueryFnData = unknown,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryData = TQueryFnData,\n    TQueryKey extends QueryKey = QueryKey,\n    TPageParam = never,\n  >(\n    options:\n      | QueryObserverOptions<\n          TQueryFnData,\n          TError,\n          TData,\n          TQueryData,\n          TQueryKey,\n          TPageParam\n        >\n      | DefaultedQueryObserverOptions<\n          TQueryFnData,\n          TError,\n          TData,\n          TQueryData,\n          TQueryKey\n        >,\n  ): DefaultedQueryObserverOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryData,\n    TQueryKey\n  > {\n    if (options._defaulted) {\n      return options as DefaultedQueryObserverOptions<\n        TQueryFnData,\n        TError,\n        TData,\n        TQueryData,\n        TQueryKey\n      >\n    }\n\n    const defaultedOptions = {\n      ...this.#defaultOptions.queries,\n      ...this.getQueryDefaults(options.queryKey),\n      ...options,\n      _defaulted: true,\n    }\n\n    if (!defaultedOptions.queryHash) {\n      defaultedOptions.queryHash = hashQueryKeyByOptions(\n        defaultedOptions.queryKey,\n        defaultedOptions,\n      )\n    }\n\n    // dependent default values\n    if (defaultedOptions.refetchOnReconnect === undefined) {\n      defaultedOptions.refetchOnReconnect =\n        defaultedOptions.networkMode !== 'always'\n    }\n    if (defaultedOptions.throwOnError === undefined) {\n      defaultedOptions.throwOnError = !!defaultedOptions.suspense\n    }\n\n    if (!defaultedOptions.networkMode && defaultedOptions.persister) {\n      defaultedOptions.networkMode = 'offlineFirst'\n    }\n\n    if (defaultedOptions.queryFn === skipToken) {\n      defaultedOptions.enabled = false\n    }\n\n    return defaultedOptions as DefaultedQueryObserverOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryData,\n      TQueryKey\n    >\n  }\n\n  defaultMutationOptions<T extends MutationOptions<any, any, any, any>>(\n    options?: T,\n  ): T {\n    if (options?._defaulted) {\n      return options\n    }\n    return {\n      ...this.#defaultOptions.mutations,\n      ...(options?.mutationKey &&\n        this.getMutationDefaults(options.mutationKey)),\n      ...options,\n      _defaulted: true,\n    } as T\n  }\n\n  clear(): void {\n    this.#queryCache.clear()\n    this.#mutationCache.clear()\n  }\n}\n"
  },
  {
    "path": "packages/query-core/src/queryObserver.ts",
    "content": "import { focusManager } from './focusManager'\nimport { environmentManager } from './environmentManager'\nimport { notifyManager } from './notifyManager'\nimport { fetchState } from './query'\nimport { Subscribable } from './subscribable'\nimport { pendingThenable } from './thenable'\nimport {\n  isValidTimeout,\n  noop,\n  replaceData,\n  resolveEnabled,\n  resolveStaleTime,\n  shallowEqualObjects,\n  timeUntilStale,\n} from './utils'\nimport { timeoutManager } from './timeoutManager'\nimport type { ManagedTimerId } from './timeoutManager'\nimport type { FetchOptions, Query, QueryState } from './query'\nimport type { QueryClient } from './queryClient'\nimport type { PendingThenable, Thenable } from './thenable'\nimport type {\n  DefaultError,\n  DefaultedQueryObserverOptions,\n  PlaceholderDataFunction,\n  QueryKey,\n  QueryObserverBaseResult,\n  QueryObserverOptions,\n  QueryObserverResult,\n  RefetchOptions,\n} from './types'\n\ntype QueryObserverListener<TData, TError> = (\n  result: QueryObserverResult<TData, TError>,\n) => void\n\ninterface ObserverFetchOptions extends FetchOptions {\n  throwOnError?: boolean\n}\n\nexport class QueryObserver<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> extends Subscribable<QueryObserverListener<TData, TError>> {\n  #client: QueryClient\n  #currentQuery: Query<TQueryFnData, TError, TQueryData, TQueryKey> = undefined!\n  #currentQueryInitialState: QueryState<TQueryData, TError> = undefined!\n  #currentResult: QueryObserverResult<TData, TError> = undefined!\n  #currentResultState?: QueryState<TQueryData, TError>\n  #currentResultOptions?: QueryObserverOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryData,\n    TQueryKey\n  >\n  #currentThenable: Thenable<TData>\n  #selectError: TError | null\n  #selectFn?: (data: TQueryData) => TData\n  #selectResult?: TData\n  // This property keeps track of the last query with defined data.\n  // It will be used to pass the previous data and query to the placeholder function between renders.\n  #lastQueryWithDefinedData?: Query<TQueryFnData, TError, TQueryData, TQueryKey>\n  #staleTimeoutId?: ManagedTimerId\n  #refetchIntervalId?: ManagedTimerId\n  #currentRefetchInterval?: number | false\n  #trackedProps = new Set<keyof QueryObserverResult>()\n\n  constructor(\n    client: QueryClient,\n    public options: QueryObserverOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryData,\n      TQueryKey\n    >,\n  ) {\n    super()\n\n    this.#client = client\n    this.#selectError = null\n    this.#currentThenable = pendingThenable()\n\n    this.bindMethods()\n    this.setOptions(options)\n  }\n\n  protected bindMethods(): void {\n    this.refetch = this.refetch.bind(this)\n  }\n\n  protected onSubscribe(): void {\n    if (this.listeners.size === 1) {\n      this.#currentQuery.addObserver(this)\n\n      if (shouldFetchOnMount(this.#currentQuery, this.options)) {\n        this.#executeFetch()\n      } else {\n        this.updateResult()\n      }\n\n      this.#updateTimers()\n    }\n  }\n\n  protected onUnsubscribe(): void {\n    if (!this.hasListeners()) {\n      this.destroy()\n    }\n  }\n\n  shouldFetchOnReconnect(): boolean {\n    return shouldFetchOn(\n      this.#currentQuery,\n      this.options,\n      this.options.refetchOnReconnect,\n    )\n  }\n\n  shouldFetchOnWindowFocus(): boolean {\n    return shouldFetchOn(\n      this.#currentQuery,\n      this.options,\n      this.options.refetchOnWindowFocus,\n    )\n  }\n\n  destroy(): void {\n    this.listeners = new Set()\n    this.#clearStaleTimeout()\n    this.#clearRefetchInterval()\n    this.#currentQuery.removeObserver(this)\n  }\n\n  setOptions(\n    options: QueryObserverOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryData,\n      TQueryKey\n    >,\n  ): void {\n    const prevOptions = this.options\n    const prevQuery = this.#currentQuery\n\n    this.options = this.#client.defaultQueryOptions(options)\n\n    if (\n      this.options.enabled !== undefined &&\n      typeof this.options.enabled !== 'boolean' &&\n      typeof this.options.enabled !== 'function' &&\n      typeof resolveEnabled(this.options.enabled, this.#currentQuery) !==\n        'boolean'\n    ) {\n      throw new Error(\n        'Expected enabled to be a boolean or a callback that returns a boolean',\n      )\n    }\n\n    this.#updateQuery()\n    this.#currentQuery.setOptions(this.options)\n\n    if (\n      prevOptions._defaulted &&\n      !shallowEqualObjects(this.options, prevOptions)\n    ) {\n      this.#client.getQueryCache().notify({\n        type: 'observerOptionsUpdated',\n        query: this.#currentQuery,\n        observer: this,\n      })\n    }\n\n    const mounted = this.hasListeners()\n\n    // Fetch if there are subscribers\n    if (\n      mounted &&\n      shouldFetchOptionally(\n        this.#currentQuery,\n        prevQuery,\n        this.options,\n        prevOptions,\n      )\n    ) {\n      this.#executeFetch()\n    }\n\n    // Update result\n    this.updateResult()\n\n    // Update stale interval if needed\n    if (\n      mounted &&\n      (this.#currentQuery !== prevQuery ||\n        resolveEnabled(this.options.enabled, this.#currentQuery) !==\n          resolveEnabled(prevOptions.enabled, this.#currentQuery) ||\n        resolveStaleTime(this.options.staleTime, this.#currentQuery) !==\n          resolveStaleTime(prevOptions.staleTime, this.#currentQuery))\n    ) {\n      this.#updateStaleTimeout()\n    }\n\n    const nextRefetchInterval = this.#computeRefetchInterval()\n\n    // Update refetch interval if needed\n    if (\n      mounted &&\n      (this.#currentQuery !== prevQuery ||\n        resolveEnabled(this.options.enabled, this.#currentQuery) !==\n          resolveEnabled(prevOptions.enabled, this.#currentQuery) ||\n        nextRefetchInterval !== this.#currentRefetchInterval)\n    ) {\n      this.#updateRefetchInterval(nextRefetchInterval)\n    }\n  }\n\n  getOptimisticResult(\n    options: DefaultedQueryObserverOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryData,\n      TQueryKey\n    >,\n  ): QueryObserverResult<TData, TError> {\n    const query = this.#client.getQueryCache().build(this.#client, options)\n\n    const result = this.createResult(query, options)\n\n    if (shouldAssignObserverCurrentProperties(this, result)) {\n      // this assigns the optimistic result to the current Observer\n      // because if the query function changes, useQuery will be performing\n      // an effect where it would fetch again.\n      // When the fetch finishes, we perform a deep data cloning in order\n      // to reuse objects references. This deep data clone is performed against\n      // the `observer.currentResult.data` property\n      // When QueryKey changes, we refresh the query and get new `optimistic`\n      // result, while we leave the `observer.currentResult`, so when new data\n      // arrives, it finds the old `observer.currentResult` which is related\n      // to the old QueryKey. Which means that currentResult and selectData are\n      // out of sync already.\n      // To solve this, we move the cursor of the currentResult every time\n      // an observer reads an optimistic value.\n\n      // When keeping the previous data, the result doesn't change until new\n      // data arrives.\n      this.#currentResult = result\n      this.#currentResultOptions = this.options\n      this.#currentResultState = this.#currentQuery.state\n    }\n    return result\n  }\n\n  getCurrentResult(): QueryObserverResult<TData, TError> {\n    return this.#currentResult\n  }\n\n  trackResult(\n    result: QueryObserverResult<TData, TError>,\n    onPropTracked?: (key: keyof QueryObserverResult) => void,\n  ): QueryObserverResult<TData, TError> {\n    return new Proxy(result, {\n      get: (target, key) => {\n        this.trackProp(key as keyof QueryObserverResult)\n        onPropTracked?.(key as keyof QueryObserverResult)\n        if (key === 'promise') {\n          this.trackProp('data')\n          if (\n            !this.options.experimental_prefetchInRender &&\n            this.#currentThenable.status === 'pending'\n          ) {\n            this.#currentThenable.reject(\n              new Error(\n                'experimental_prefetchInRender feature flag is not enabled',\n              ),\n            )\n          }\n        }\n        return Reflect.get(target, key)\n      },\n    })\n  }\n\n  trackProp(key: keyof QueryObserverResult) {\n    this.#trackedProps.add(key)\n  }\n\n  getCurrentQuery(): Query<TQueryFnData, TError, TQueryData, TQueryKey> {\n    return this.#currentQuery\n  }\n\n  refetch({ ...options }: RefetchOptions = {}): Promise<\n    QueryObserverResult<TData, TError>\n  > {\n    return this.fetch({\n      ...options,\n    })\n  }\n\n  fetchOptimistic(\n    options: QueryObserverOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryData,\n      TQueryKey\n    >,\n  ): Promise<QueryObserverResult<TData, TError>> {\n    const defaultedOptions = this.#client.defaultQueryOptions(options)\n\n    const query = this.#client\n      .getQueryCache()\n      .build(this.#client, defaultedOptions)\n\n    return query.fetch().then(() => this.createResult(query, defaultedOptions))\n  }\n\n  protected fetch(\n    fetchOptions: ObserverFetchOptions,\n  ): Promise<QueryObserverResult<TData, TError>> {\n    return this.#executeFetch({\n      ...fetchOptions,\n      cancelRefetch: fetchOptions.cancelRefetch ?? true,\n    }).then(() => {\n      this.updateResult()\n      return this.#currentResult\n    })\n  }\n\n  #executeFetch(\n    fetchOptions?: Omit<ObserverFetchOptions, 'initialPromise'>,\n  ): Promise<TQueryData | undefined> {\n    // Make sure we reference the latest query as the current one might have been removed\n    this.#updateQuery()\n\n    // Fetch\n    let promise: Promise<TQueryData | undefined> = this.#currentQuery.fetch(\n      this.options,\n      fetchOptions,\n    )\n\n    if (!fetchOptions?.throwOnError) {\n      promise = promise.catch(noop)\n    }\n\n    return promise\n  }\n\n  #updateStaleTimeout(): void {\n    this.#clearStaleTimeout()\n    const staleTime = resolveStaleTime(\n      this.options.staleTime,\n      this.#currentQuery,\n    )\n\n    if (\n      environmentManager.isServer() ||\n      this.#currentResult.isStale ||\n      !isValidTimeout(staleTime)\n    ) {\n      return\n    }\n\n    const time = timeUntilStale(this.#currentResult.dataUpdatedAt, staleTime)\n\n    // The timeout is sometimes triggered 1 ms before the stale time expiration.\n    // To mitigate this issue we always add 1 ms to the timeout.\n    const timeout = time + 1\n\n    this.#staleTimeoutId = timeoutManager.setTimeout(() => {\n      if (!this.#currentResult.isStale) {\n        this.updateResult()\n      }\n    }, timeout)\n  }\n\n  #computeRefetchInterval() {\n    return (\n      (typeof this.options.refetchInterval === 'function'\n        ? this.options.refetchInterval(this.#currentQuery)\n        : this.options.refetchInterval) ?? false\n    )\n  }\n\n  #updateRefetchInterval(nextInterval: number | false): void {\n    this.#clearRefetchInterval()\n\n    this.#currentRefetchInterval = nextInterval\n\n    if (\n      environmentManager.isServer() ||\n      resolveEnabled(this.options.enabled, this.#currentQuery) === false ||\n      !isValidTimeout(this.#currentRefetchInterval) ||\n      this.#currentRefetchInterval === 0\n    ) {\n      return\n    }\n\n    this.#refetchIntervalId = timeoutManager.setInterval(() => {\n      if (\n        this.options.refetchIntervalInBackground ||\n        focusManager.isFocused()\n      ) {\n        this.#executeFetch()\n      }\n    }, this.#currentRefetchInterval)\n  }\n\n  #updateTimers(): void {\n    this.#updateStaleTimeout()\n    this.#updateRefetchInterval(this.#computeRefetchInterval())\n  }\n\n  #clearStaleTimeout(): void {\n    if (this.#staleTimeoutId) {\n      timeoutManager.clearTimeout(this.#staleTimeoutId)\n      this.#staleTimeoutId = undefined\n    }\n  }\n\n  #clearRefetchInterval(): void {\n    if (this.#refetchIntervalId) {\n      timeoutManager.clearInterval(this.#refetchIntervalId)\n      this.#refetchIntervalId = undefined\n    }\n  }\n\n  protected createResult(\n    query: Query<TQueryFnData, TError, TQueryData, TQueryKey>,\n    options: QueryObserverOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryData,\n      TQueryKey\n    >,\n  ): QueryObserverResult<TData, TError> {\n    const prevQuery = this.#currentQuery\n    const prevOptions = this.options\n    const prevResult = this.#currentResult as\n      | QueryObserverResult<TData, TError>\n      | undefined\n    const prevResultState = this.#currentResultState\n    const prevResultOptions = this.#currentResultOptions\n    const queryChange = query !== prevQuery\n    const queryInitialState = queryChange\n      ? query.state\n      : this.#currentQueryInitialState\n\n    const { state } = query\n    let newState = { ...state }\n    let isPlaceholderData = false\n    let data: TData | undefined\n\n    // Optimistically set result in fetching state if needed\n    if (options._optimisticResults) {\n      const mounted = this.hasListeners()\n\n      const fetchOnMount = !mounted && shouldFetchOnMount(query, options)\n\n      const fetchOptionally =\n        mounted && shouldFetchOptionally(query, prevQuery, options, prevOptions)\n\n      if (fetchOnMount || fetchOptionally) {\n        newState = {\n          ...newState,\n          ...fetchState(state.data, query.options),\n        }\n      }\n      if (options._optimisticResults === 'isRestoring') {\n        newState.fetchStatus = 'idle'\n      }\n    }\n\n    let { error, errorUpdatedAt, status } = newState\n\n    // Per default, use query data\n    data = newState.data as unknown as TData\n    let skipSelect = false\n\n    // use placeholderData if needed\n    if (\n      options.placeholderData !== undefined &&\n      data === undefined &&\n      status === 'pending'\n    ) {\n      let placeholderData\n\n      // Memoize placeholder data\n      if (\n        prevResult?.isPlaceholderData &&\n        options.placeholderData === prevResultOptions?.placeholderData\n      ) {\n        placeholderData = prevResult.data\n        // we have to skip select when reading this memoization\n        // because prevResult.data is already \"selected\"\n        skipSelect = true\n      } else {\n        // compute placeholderData\n        placeholderData =\n          typeof options.placeholderData === 'function'\n            ? (\n                options.placeholderData as unknown as PlaceholderDataFunction<TQueryData>\n              )(\n                this.#lastQueryWithDefinedData?.state.data,\n                this.#lastQueryWithDefinedData as any,\n              )\n            : options.placeholderData\n      }\n\n      if (placeholderData !== undefined) {\n        status = 'success'\n        data = replaceData(\n          prevResult?.data,\n          placeholderData as unknown,\n          options,\n        ) as TData\n        isPlaceholderData = true\n      }\n    }\n\n    // Select data if needed\n    // this also runs placeholderData through the select function\n    if (options.select && data !== undefined && !skipSelect) {\n      // Memoize select result\n      if (\n        prevResult &&\n        data === prevResultState?.data &&\n        options.select === this.#selectFn\n      ) {\n        data = this.#selectResult\n      } else {\n        try {\n          this.#selectFn = options.select\n          data = options.select(data as any)\n          data = replaceData(prevResult?.data, data, options)\n          this.#selectResult = data\n          this.#selectError = null\n        } catch (selectError) {\n          this.#selectError = selectError as TError\n        }\n      }\n    }\n\n    if (this.#selectError) {\n      error = this.#selectError\n      data = this.#selectResult\n      errorUpdatedAt = Date.now()\n      status = 'error'\n    }\n\n    const isFetching = newState.fetchStatus === 'fetching'\n    const isPending = status === 'pending'\n    const isError = status === 'error'\n\n    const isLoading = isPending && isFetching\n    const hasData = data !== undefined\n\n    const result: QueryObserverBaseResult<TData, TError> = {\n      status,\n      fetchStatus: newState.fetchStatus,\n      isPending,\n      isSuccess: status === 'success',\n      isError,\n      isInitialLoading: isLoading,\n      isLoading,\n      data,\n      dataUpdatedAt: newState.dataUpdatedAt,\n      error,\n      errorUpdatedAt,\n      failureCount: newState.fetchFailureCount,\n      failureReason: newState.fetchFailureReason,\n      errorUpdateCount: newState.errorUpdateCount,\n      isFetched: query.isFetched(),\n      isFetchedAfterMount:\n        newState.dataUpdateCount > queryInitialState.dataUpdateCount ||\n        newState.errorUpdateCount > queryInitialState.errorUpdateCount,\n      isFetching,\n      isRefetching: isFetching && !isPending,\n      isLoadingError: isError && !hasData,\n      isPaused: newState.fetchStatus === 'paused',\n      isPlaceholderData,\n      isRefetchError: isError && hasData,\n      isStale: isStale(query, options),\n      refetch: this.refetch,\n      promise: this.#currentThenable,\n      isEnabled: resolveEnabled(options.enabled, query) !== false,\n    }\n\n    const nextResult = result as QueryObserverResult<TData, TError>\n\n    if (this.options.experimental_prefetchInRender) {\n      const hasResultData = nextResult.data !== undefined\n      const isErrorWithoutData = nextResult.status === 'error' && !hasResultData\n      const finalizeThenableIfPossible = (thenable: PendingThenable<TData>) => {\n        if (isErrorWithoutData) {\n          thenable.reject(nextResult.error)\n        } else if (hasResultData) {\n          thenable.resolve(nextResult.data as TData)\n        }\n      }\n\n      /**\n       * Create a new thenable and result promise when the results have changed\n       */\n      const recreateThenable = () => {\n        const pending =\n          (this.#currentThenable =\n          nextResult.promise =\n            pendingThenable())\n\n        finalizeThenableIfPossible(pending)\n      }\n\n      const prevThenable = this.#currentThenable\n      switch (prevThenable.status) {\n        case 'pending':\n          // Finalize the previous thenable if it was pending\n          // and we are still observing the same query\n          if (query.queryHash === prevQuery.queryHash) {\n            finalizeThenableIfPossible(prevThenable)\n          }\n          break\n        case 'fulfilled':\n          if (isErrorWithoutData || nextResult.data !== prevThenable.value) {\n            recreateThenable()\n          }\n          break\n        case 'rejected':\n          if (!isErrorWithoutData || nextResult.error !== prevThenable.reason) {\n            recreateThenable()\n          }\n          break\n      }\n    }\n\n    return nextResult\n  }\n\n  updateResult(): void {\n    const prevResult = this.#currentResult as\n      | QueryObserverResult<TData, TError>\n      | undefined\n\n    const nextResult = this.createResult(this.#currentQuery, this.options)\n\n    this.#currentResultState = this.#currentQuery.state\n    this.#currentResultOptions = this.options\n\n    if (this.#currentResultState.data !== undefined) {\n      this.#lastQueryWithDefinedData = this.#currentQuery\n    }\n\n    // Only notify and update result if something has changed\n    if (shallowEqualObjects(nextResult, prevResult)) {\n      return\n    }\n\n    this.#currentResult = nextResult\n\n    const shouldNotifyListeners = (): boolean => {\n      if (!prevResult) {\n        return true\n      }\n\n      const { notifyOnChangeProps } = this.options\n      const notifyOnChangePropsValue =\n        typeof notifyOnChangeProps === 'function'\n          ? notifyOnChangeProps()\n          : notifyOnChangeProps\n\n      if (\n        notifyOnChangePropsValue === 'all' ||\n        (!notifyOnChangePropsValue && !this.#trackedProps.size)\n      ) {\n        return true\n      }\n\n      const includedProps = new Set(\n        notifyOnChangePropsValue ?? this.#trackedProps,\n      )\n\n      if (this.options.throwOnError) {\n        includedProps.add('error')\n      }\n\n      return Object.keys(this.#currentResult).some((key) => {\n        const typedKey = key as keyof QueryObserverResult\n        const changed = this.#currentResult[typedKey] !== prevResult[typedKey]\n\n        return changed && includedProps.has(typedKey)\n      })\n    }\n\n    this.#notify({ listeners: shouldNotifyListeners() })\n  }\n\n  #updateQuery(): void {\n    const query = this.#client.getQueryCache().build(this.#client, this.options)\n\n    if (query === this.#currentQuery) {\n      return\n    }\n\n    const prevQuery = this.#currentQuery as\n      | Query<TQueryFnData, TError, TQueryData, TQueryKey>\n      | undefined\n    this.#currentQuery = query\n    this.#currentQueryInitialState = query.state\n\n    if (this.hasListeners()) {\n      prevQuery?.removeObserver(this)\n      query.addObserver(this)\n    }\n  }\n\n  onQueryUpdate(): void {\n    this.updateResult()\n\n    if (this.hasListeners()) {\n      this.#updateTimers()\n    }\n  }\n\n  #notify(notifyOptions: { listeners: boolean }): void {\n    notifyManager.batch(() => {\n      // First, trigger the listeners\n      if (notifyOptions.listeners) {\n        this.listeners.forEach((listener) => {\n          listener(this.#currentResult)\n        })\n      }\n\n      // Then the cache listeners\n      this.#client.getQueryCache().notify({\n        query: this.#currentQuery,\n        type: 'observerResultsUpdated',\n      })\n    })\n  }\n}\n\nfunction shouldLoadOnMount(\n  query: Query<any, any, any, any>,\n  options: QueryObserverOptions<any, any, any, any>,\n): boolean {\n  return (\n    resolveEnabled(options.enabled, query) !== false &&\n    query.state.data === undefined &&\n    !(query.state.status === 'error' && options.retryOnMount === false)\n  )\n}\n\nfunction shouldFetchOnMount(\n  query: Query<any, any, any, any>,\n  options: QueryObserverOptions<any, any, any, any, any>,\n): boolean {\n  return (\n    shouldLoadOnMount(query, options) ||\n    (query.state.data !== undefined &&\n      shouldFetchOn(query, options, options.refetchOnMount))\n  )\n}\n\nfunction shouldFetchOn(\n  query: Query<any, any, any, any>,\n  options: QueryObserverOptions<any, any, any, any, any>,\n  field: (typeof options)['refetchOnMount'] &\n    (typeof options)['refetchOnWindowFocus'] &\n    (typeof options)['refetchOnReconnect'],\n) {\n  if (\n    resolveEnabled(options.enabled, query) !== false &&\n    resolveStaleTime(options.staleTime, query) !== 'static'\n  ) {\n    const value = typeof field === 'function' ? field(query) : field\n\n    return value === 'always' || (value !== false && isStale(query, options))\n  }\n  return false\n}\n\nfunction shouldFetchOptionally(\n  query: Query<any, any, any, any>,\n  prevQuery: Query<any, any, any, any>,\n  options: QueryObserverOptions<any, any, any, any, any>,\n  prevOptions: QueryObserverOptions<any, any, any, any, any>,\n): boolean {\n  return (\n    (query !== prevQuery ||\n      resolveEnabled(prevOptions.enabled, query) === false) &&\n    (!options.suspense || query.state.status !== 'error') &&\n    isStale(query, options)\n  )\n}\n\nfunction isStale(\n  query: Query<any, any, any, any>,\n  options: QueryObserverOptions<any, any, any, any, any>,\n): boolean {\n  return (\n    resolveEnabled(options.enabled, query) !== false &&\n    query.isStaleByTime(resolveStaleTime(options.staleTime, query))\n  )\n}\n\n// this function would decide if we will update the observer's 'current'\n// properties after an optimistic reading via getOptimisticResult\nfunction shouldAssignObserverCurrentProperties<\n  TQueryFnData = unknown,\n  TError = unknown,\n  TData = TQueryFnData,\n  TQueryData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  observer: QueryObserver<TQueryFnData, TError, TData, TQueryData, TQueryKey>,\n  optimisticResult: QueryObserverResult<TData, TError>,\n) {\n  // if the newly created result isn't what the observer is holding as current,\n  // then we'll need to update the properties as well\n  if (!shallowEqualObjects(observer.getCurrentResult(), optimisticResult)) {\n    return true\n  }\n\n  // basically, just keep previous properties if nothing changed\n  return false\n}\n"
  },
  {
    "path": "packages/query-core/src/removable.ts",
    "content": "import { timeoutManager } from './timeoutManager'\nimport { environmentManager } from './environmentManager'\nimport { isValidTimeout } from './utils'\nimport type { ManagedTimerId } from './timeoutManager'\n\nexport abstract class Removable {\n  gcTime!: number\n  #gcTimeout?: ManagedTimerId\n\n  destroy(): void {\n    this.clearGcTimeout()\n  }\n\n  protected scheduleGc(): void {\n    this.clearGcTimeout()\n\n    if (isValidTimeout(this.gcTime)) {\n      this.#gcTimeout = timeoutManager.setTimeout(() => {\n        this.optionalRemove()\n      }, this.gcTime)\n    }\n  }\n\n  protected updateGcTime(newGcTime: number | undefined): void {\n    // Default to 5 minutes (Infinity for server-side) if no gcTime is set\n    this.gcTime = Math.max(\n      this.gcTime || 0,\n      newGcTime ?? (environmentManager.isServer() ? Infinity : 5 * 60 * 1000),\n    )\n  }\n\n  protected clearGcTimeout() {\n    if (this.#gcTimeout) {\n      timeoutManager.clearTimeout(this.#gcTimeout)\n      this.#gcTimeout = undefined\n    }\n  }\n\n  protected abstract optionalRemove(): void\n}\n"
  },
  {
    "path": "packages/query-core/src/retryer.ts",
    "content": "import { focusManager } from './focusManager'\nimport { onlineManager } from './onlineManager'\nimport { pendingThenable } from './thenable'\nimport { environmentManager } from './environmentManager'\nimport { sleep } from './utils'\nimport type { Thenable } from './thenable'\nimport type { CancelOptions, DefaultError, NetworkMode } from './types'\n\n// TYPES\n\ninterface RetryerConfig<TData = unknown, TError = DefaultError> {\n  fn: () => TData | Promise<TData>\n  initialPromise?: Promise<TData>\n  onCancel?: (error: TError) => void\n  onFail?: (failureCount: number, error: TError) => void\n  onPause?: () => void\n  onContinue?: () => void\n  retry?: RetryValue<TError>\n  retryDelay?: RetryDelayValue<TError>\n  networkMode: NetworkMode | undefined\n  canRun: () => boolean\n}\n\nexport interface Retryer<TData = unknown> {\n  promise: Promise<TData>\n  cancel: (cancelOptions?: CancelOptions) => void\n  continue: () => Promise<unknown>\n  cancelRetry: () => void\n  continueRetry: () => void\n  canStart: () => boolean\n  start: () => Promise<TData>\n  status: () => 'pending' | 'resolved' | 'rejected'\n}\n\nexport type RetryValue<TError> = boolean | number | ShouldRetryFunction<TError>\n\ntype ShouldRetryFunction<TError = DefaultError> = (\n  failureCount: number,\n  error: TError,\n) => boolean\n\nexport type RetryDelayValue<TError> = number | RetryDelayFunction<TError>\n\ntype RetryDelayFunction<TError = DefaultError> = (\n  failureCount: number,\n  error: TError,\n) => number\n\nfunction defaultRetryDelay(failureCount: number) {\n  return Math.min(1000 * 2 ** failureCount, 30000)\n}\n\nexport function canFetch(networkMode: NetworkMode | undefined): boolean {\n  return (networkMode ?? 'online') === 'online'\n    ? onlineManager.isOnline()\n    : true\n}\n\nexport class CancelledError extends Error {\n  revert?: boolean\n  silent?: boolean\n  constructor(options?: CancelOptions) {\n    super('CancelledError')\n    this.revert = options?.revert\n    this.silent = options?.silent\n  }\n}\n\n/**\n * @deprecated Use instanceof `CancelledError` instead.\n */\nexport function isCancelledError(value: any): value is CancelledError {\n  return value instanceof CancelledError\n}\n\nexport function createRetryer<TData = unknown, TError = DefaultError>(\n  config: RetryerConfig<TData, TError>,\n): Retryer<TData> {\n  let isRetryCancelled = false\n  let failureCount = 0\n  let continueFn: ((value?: unknown) => void) | undefined\n\n  const thenable = pendingThenable<TData>()\n\n  const isResolved = () =>\n    (thenable.status as Thenable<TData>['status']) !== 'pending'\n\n  const cancel = (cancelOptions?: CancelOptions): void => {\n    if (!isResolved()) {\n      const error = new CancelledError(cancelOptions) as TError\n      reject(error)\n\n      config.onCancel?.(error)\n    }\n  }\n  const cancelRetry = () => {\n    isRetryCancelled = true\n  }\n\n  const continueRetry = () => {\n    isRetryCancelled = false\n  }\n\n  const canContinue = () =>\n    focusManager.isFocused() &&\n    (config.networkMode === 'always' || onlineManager.isOnline()) &&\n    config.canRun()\n\n  const canStart = () => canFetch(config.networkMode) && config.canRun()\n\n  const resolve = (value: any) => {\n    if (!isResolved()) {\n      continueFn?.()\n      thenable.resolve(value)\n    }\n  }\n\n  const reject = (value: any) => {\n    if (!isResolved()) {\n      continueFn?.()\n      thenable.reject(value)\n    }\n  }\n\n  const pause = () => {\n    return new Promise((continueResolve) => {\n      continueFn = (value) => {\n        if (isResolved() || canContinue()) {\n          continueResolve(value)\n        }\n      }\n      config.onPause?.()\n    }).then(() => {\n      continueFn = undefined\n      if (!isResolved()) {\n        config.onContinue?.()\n      }\n    })\n  }\n\n  // Create loop function\n  const run = () => {\n    // Do nothing if already resolved\n    if (isResolved()) {\n      return\n    }\n\n    let promiseOrValue: any\n\n    // we can re-use config.initialPromise on the first call of run()\n    const initialPromise =\n      failureCount === 0 ? config.initialPromise : undefined\n\n    // Execute query\n    try {\n      promiseOrValue = initialPromise ?? config.fn()\n    } catch (error) {\n      promiseOrValue = Promise.reject(error)\n    }\n\n    Promise.resolve(promiseOrValue)\n      .then(resolve)\n      .catch((error) => {\n        // Stop if the fetch is already resolved\n        if (isResolved()) {\n          return\n        }\n\n        // Do we need to retry the request?\n        const retry = config.retry ?? (environmentManager.isServer() ? 0 : 3)\n        const retryDelay = config.retryDelay ?? defaultRetryDelay\n        const delay =\n          typeof retryDelay === 'function'\n            ? retryDelay(failureCount, error)\n            : retryDelay\n        const shouldRetry =\n          retry === true ||\n          (typeof retry === 'number' && failureCount < retry) ||\n          (typeof retry === 'function' && retry(failureCount, error))\n\n        if (isRetryCancelled || !shouldRetry) {\n          // We are done if the query does not need to be retried\n          reject(error)\n          return\n        }\n\n        failureCount++\n\n        // Notify on fail\n        config.onFail?.(failureCount, error)\n\n        // Delay\n        sleep(delay)\n          // Pause if the document is not visible or when the device is offline\n          .then(() => {\n            return canContinue() ? undefined : pause()\n          })\n          .then(() => {\n            if (isRetryCancelled) {\n              reject(error)\n            } else {\n              run()\n            }\n          })\n      })\n  }\n\n  return {\n    promise: thenable,\n    status: () => thenable.status,\n    cancel,\n    continue: () => {\n      continueFn?.()\n      return thenable\n    },\n    cancelRetry,\n    continueRetry,\n    canStart,\n    start: () => {\n      // Start loop\n      if (canStart()) {\n        run()\n      } else {\n        pause().then(run)\n      }\n      return thenable\n    },\n  }\n}\n"
  },
  {
    "path": "packages/query-core/src/streamedQuery.ts",
    "content": "import { addConsumeAwareSignal, addToEnd } from './utils'\nimport type {\n  OmitKeyof,\n  QueryFunction,\n  QueryFunctionContext,\n  QueryKey,\n} from './types'\n\ntype BaseStreamedQueryParams<TQueryFnData, TQueryKey extends QueryKey> = {\n  streamFn: (\n    context: QueryFunctionContext<TQueryKey>,\n  ) => AsyncIterable<TQueryFnData> | Promise<AsyncIterable<TQueryFnData>>\n  refetchMode?: 'append' | 'reset' | 'replace'\n}\n\ntype SimpleStreamedQueryParams<\n  TQueryFnData,\n  TQueryKey extends QueryKey,\n> = BaseStreamedQueryParams<TQueryFnData, TQueryKey> & {\n  reducer?: never\n  initialValue?: never\n}\n\ntype ReducibleStreamedQueryParams<\n  TQueryFnData,\n  TData,\n  TQueryKey extends QueryKey,\n> = BaseStreamedQueryParams<TQueryFnData, TQueryKey> & {\n  reducer: (acc: TData, chunk: TQueryFnData) => TData\n  initialValue: TData\n}\n\ntype StreamedQueryParams<TQueryFnData, TData, TQueryKey extends QueryKey> =\n  | SimpleStreamedQueryParams<TQueryFnData, TQueryKey>\n  | ReducibleStreamedQueryParams<TQueryFnData, TData, TQueryKey>\n\n/**\n * This is a helper function to create a query function that streams data from an AsyncIterable.\n * Data will be an Array of all the chunks received.\n * The query will be in a 'pending' state until the first chunk of data is received, but will go to 'success' after that.\n * The query will stay in fetchStatus 'fetching' until the stream ends.\n * @param queryFn - The function that returns an AsyncIterable to stream data from.\n * @param refetchMode - Defines how re-fetches are handled.\n * Defaults to `'reset'`, erases all data and puts the query back into `pending` state.\n * Set to `'append'` to append new data to the existing data.\n * Set to `'replace'` to write all data to the cache once the stream ends.\n * @param reducer - A function to reduce the streamed chunks into the final data.\n * Defaults to a function that appends chunks to the end of the array.\n * @param initialValue - Initial value to be used while the first chunk is being fetched, and returned if the stream yields no values.\n */\nexport function streamedQuery<\n  TQueryFnData = unknown,\n  TData = Array<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n>({\n  streamFn,\n  refetchMode = 'reset',\n  reducer = (items, chunk) =>\n    addToEnd(items as Array<TQueryFnData>, chunk) as TData,\n  initialValue = [] as TData,\n}: StreamedQueryParams<TQueryFnData, TData, TQueryKey>): QueryFunction<\n  TData,\n  TQueryKey\n> {\n  return async (context) => {\n    const query = context.client\n      .getQueryCache()\n      .find({ queryKey: context.queryKey, exact: true })\n    const isRefetch = !!query && query.isFetched()\n    if (isRefetch && refetchMode === 'reset') {\n      query.setState({\n        ...query.resetState,\n        fetchStatus: 'fetching',\n      })\n    }\n\n    let result = initialValue\n\n    let cancelled: boolean = false as boolean\n    const streamFnContext = addConsumeAwareSignal<\n      OmitKeyof<typeof context, 'signal'>\n    >(\n      {\n        client: context.client,\n        meta: context.meta,\n        queryKey: context.queryKey,\n        pageParam: context.pageParam,\n        direction: context.direction,\n      },\n      () => context.signal,\n      () => (cancelled = true),\n    )\n\n    const stream = await streamFn(streamFnContext)\n\n    const isReplaceRefetch = isRefetch && refetchMode === 'replace'\n\n    for await (const chunk of stream) {\n      if (cancelled) {\n        break\n      }\n\n      if (isReplaceRefetch) {\n        // don't append to the cache directly when replace-refetching\n        result = reducer(result, chunk)\n      } else {\n        context.client.setQueryData<TData>(context.queryKey, (prev) =>\n          reducer(prev === undefined ? initialValue : prev, chunk),\n        )\n      }\n    }\n\n    // finalize result: replace-refetching needs to write to the cache\n    if (isReplaceRefetch && !cancelled) {\n      context.client.setQueryData<TData>(context.queryKey, result)\n    }\n\n    return context.client.getQueryData(context.queryKey) ?? initialValue\n  }\n}\n"
  },
  {
    "path": "packages/query-core/src/subscribable.ts",
    "content": "export class Subscribable<TListener extends Function> {\n  protected listeners = new Set<TListener>()\n\n  constructor() {\n    this.subscribe = this.subscribe.bind(this)\n  }\n\n  subscribe(listener: TListener): () => void {\n    this.listeners.add(listener)\n\n    this.onSubscribe()\n\n    return () => {\n      this.listeners.delete(listener)\n      this.onUnsubscribe()\n    }\n  }\n\n  hasListeners(): boolean {\n    return this.listeners.size > 0\n  }\n\n  protected onSubscribe(): void {\n    // Do nothing\n  }\n\n  protected onUnsubscribe(): void {\n    // Do nothing\n  }\n}\n"
  },
  {
    "path": "packages/query-core/src/thenable.ts",
    "content": "/**\n * Thenable types which matches React's types for promises\n *\n * React seemingly uses `.status`, `.value` and `.reason` properties on a promises to optimistically unwrap data from promises\n *\n * @see https://github.com/facebook/react/blob/main/packages/shared/ReactTypes.js#L112-L138\n * @see https://github.com/facebook/react/blob/4f604941569d2e8947ce1460a0b2997e835f37b9/packages/react-debug-tools/src/ReactDebugHooks.js#L224-L227\n */\n\nimport { noop } from './utils'\n\ninterface Fulfilled<T> {\n  status: 'fulfilled'\n  value: T\n}\ninterface Rejected {\n  status: 'rejected'\n  reason: unknown\n}\ninterface Pending<T> {\n  status: 'pending'\n\n  /**\n   * Resolve the promise with a value.\n   * Will remove the `resolve` and `reject` properties from the promise.\n   */\n  resolve: (value: T) => void\n  /**\n   * Reject the promise with a reason.\n   * Will remove the `resolve` and `reject` properties from the promise.\n   */\n  reject: (reason: unknown) => void\n}\n\nexport type FulfilledThenable<T> = Promise<T> & Fulfilled<T>\nexport type RejectedThenable<T> = Promise<T> & Rejected\nexport type PendingThenable<T> = Promise<T> & Pending<T>\n\nexport type Thenable<T> =\n  | FulfilledThenable<T>\n  | RejectedThenable<T>\n  | PendingThenable<T>\n\nexport function pendingThenable<T>(): PendingThenable<T> {\n  let resolve: Pending<T>['resolve']\n  let reject: Pending<T>['reject']\n  // this could use `Promise.withResolvers()` in the future\n  const thenable = new Promise((_resolve, _reject) => {\n    resolve = _resolve\n    reject = _reject\n  }) as PendingThenable<T>\n\n  thenable.status = 'pending'\n  thenable.catch(() => {\n    // prevent unhandled rejection errors\n  })\n\n  function finalize(data: Fulfilled<T> | Rejected) {\n    Object.assign(thenable, data)\n\n    // clear pending props to avoid calling them twice\n    delete (thenable as Partial<PendingThenable<T>>).resolve\n    delete (thenable as Partial<PendingThenable<T>>).reject\n  }\n\n  thenable.resolve = (value) => {\n    finalize({\n      status: 'fulfilled',\n      value,\n    })\n\n    resolve(value)\n  }\n  thenable.reject = (reason) => {\n    finalize({\n      status: 'rejected',\n      reason,\n    })\n\n    reject(reason)\n  }\n\n  return thenable\n}\n\n/**\n * This function takes a Promise-like input and detects whether the data\n * is synchronously available or not.\n *\n * It does not inspect .status, .value or .reason properties of the promise,\n * as those are not always available, and the .status of React's promises\n * should not be considered part of the public API.\n */\nexport function tryResolveSync(promise: Promise<unknown> | Thenable<unknown>) {\n  let data: unknown\n\n  promise\n    .then((result) => {\n      data = result\n      return result\n    }, noop)\n    // .catch can be unavailable on certain kinds of thenable's\n    // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n    ?.catch(noop)\n\n  if (data !== undefined) {\n    return { data }\n  }\n\n  return undefined\n}\n"
  },
  {
    "path": "packages/query-core/src/timeoutManager.ts",
    "content": "/**\n * {@link TimeoutManager} does not support passing arguments to the callback.\n *\n * `(_: void)` is the argument type inferred by TypeScript's default typings for\n * `setTimeout(cb, number)`.\n * If we don't accept a single void argument, then\n * `new Promise(resolve => timeoutManager.setTimeout(resolve, N))` is a type error.\n */\nexport type TimeoutCallback = (_: void) => void\n\n/**\n * Wrapping `setTimeout` is awkward from a typing perspective because platform\n * typings may extend the return type of `setTimeout`. For example, NodeJS\n * typings add `NodeJS.Timeout`; but a non-default `timeoutManager` may not be\n * able to return such a type.\n */\nexport type ManagedTimerId = number | { [Symbol.toPrimitive]: () => number }\n\n/**\n * Backend for timer functions.\n */\nexport type TimeoutProvider<TTimerId extends ManagedTimerId = ManagedTimerId> =\n  {\n    readonly setTimeout: (callback: TimeoutCallback, delay: number) => TTimerId\n    readonly clearTimeout: (timeoutId: TTimerId | undefined) => void\n\n    readonly setInterval: (callback: TimeoutCallback, delay: number) => TTimerId\n    readonly clearInterval: (intervalId: TTimerId | undefined) => void\n  }\n\nexport const defaultTimeoutProvider: TimeoutProvider<\n  ReturnType<typeof setTimeout>\n> = {\n  // We need the wrapper function syntax below instead of direct references to\n  // global setTimeout etc.\n  //\n  // BAD: `setTimeout: setTimeout`\n  // GOOD: `setTimeout: (cb, delay) => setTimeout(cb, delay)`\n  //\n  // If we use direct references here, then anything that wants to spy on or\n  // replace the global setTimeout (like tests) won't work since we'll already\n  // have a hard reference to the original implementation at the time when this\n  // file was imported.\n  setTimeout: (callback, delay) => setTimeout(callback, delay),\n  clearTimeout: (timeoutId) => clearTimeout(timeoutId),\n\n  setInterval: (callback, delay) => setInterval(callback, delay),\n  clearInterval: (intervalId) => clearInterval(intervalId),\n}\n\n/**\n * Allows customization of how timeouts are created.\n *\n * @tanstack/query-core makes liberal use of timeouts to implement `staleTime`\n * and `gcTime`. The default TimeoutManager provider uses the platform's global\n * `setTimeout` implementation, which is known to have scalability issues with\n * thousands of timeouts on the event loop.\n *\n * If you hit this limitation, consider providing a custom TimeoutProvider that\n * coalesces timeouts.\n */\nexport class TimeoutManager implements Omit<TimeoutProvider, 'name'> {\n  // We cannot have TimeoutManager<T> as we must instantiate it with a concrete\n  // type at app boot; and if we leave that type, then any new timer provider\n  // would need to support ReturnType<typeof setTimeout>, which is infeasible.\n  //\n  // We settle for type safety for the TimeoutProvider type, and accept that\n  // this class is unsafe internally to allow for extension.\n  #provider: TimeoutProvider<any> = defaultTimeoutProvider\n  #providerCalled = false\n\n  setTimeoutProvider<TTimerId extends ManagedTimerId>(\n    provider: TimeoutProvider<TTimerId>,\n  ): void {\n    if (process.env.NODE_ENV !== 'production') {\n      if (this.#providerCalled && provider !== this.#provider) {\n        // After changing providers, `clearTimeout` will not work as expected for\n        // timeouts from the previous provider.\n        //\n        // Since they may allocate the same timeout ID, clearTimeout may cancel an\n        // arbitrary different timeout, or unexpected no-op.\n        //\n        // We could protect against this by mixing the timeout ID bits\n        // deterministically with some per-provider bits.\n        //\n        // We could internally queue `setTimeout` calls to `TimeoutManager` until\n        // some API call to set the initial provider.\n        console.error(\n          `[timeoutManager]: Switching provider after calls to previous provider might result in unexpected behavior.`,\n          { previous: this.#provider, provider },\n        )\n      }\n    }\n\n    this.#provider = provider\n    if (process.env.NODE_ENV !== 'production') {\n      this.#providerCalled = false\n    }\n  }\n\n  setTimeout(callback: TimeoutCallback, delay: number): ManagedTimerId {\n    if (process.env.NODE_ENV !== 'production') {\n      this.#providerCalled = true\n    }\n    return this.#provider.setTimeout(callback, delay)\n  }\n\n  clearTimeout(timeoutId: ManagedTimerId | undefined): void {\n    this.#provider.clearTimeout(timeoutId)\n  }\n\n  setInterval(callback: TimeoutCallback, delay: number): ManagedTimerId {\n    if (process.env.NODE_ENV !== 'production') {\n      this.#providerCalled = true\n    }\n    return this.#provider.setInterval(callback, delay)\n  }\n\n  clearInterval(intervalId: ManagedTimerId | undefined): void {\n    this.#provider.clearInterval(intervalId)\n  }\n}\n\nexport const timeoutManager = new TimeoutManager()\n\n/**\n * In many cases code wants to delay to the next event loop tick; this is not\n * mediated by {@link timeoutManager}.\n *\n * This function is provided to make auditing the `tanstack/query-core` for\n * incorrect use of system `setTimeout` easier.\n */\nexport function systemSetTimeoutZero(callback: TimeoutCallback): void {\n  setTimeout(callback, 0)\n}\n"
  },
  {
    "path": "packages/query-core/src/types.ts",
    "content": "/* istanbul ignore file */\n\nimport type { QueryClient } from './queryClient'\nimport type { DehydrateOptions, HydrateOptions } from './hydration'\nimport type { MutationState } from './mutation'\nimport type { FetchDirection, Query, QueryBehavior } from './query'\nimport type { RetryDelayValue, RetryValue } from './retryer'\nimport type { QueryFilters, QueryTypeFilter, SkipToken } from './utils'\nimport type { QueryCache } from './queryCache'\nimport type { MutationCache } from './mutationCache'\n\nexport type NonUndefinedGuard<T> = T extends undefined ? never : T\n\nexport type DistributiveOmit<\n  TObject,\n  TKey extends keyof TObject,\n> = TObject extends any ? Omit<TObject, TKey> : never\n\nexport type OmitKeyof<\n  TObject,\n  TKey extends TStrictly extends 'safely'\n    ?\n        | keyof TObject\n        | (string & Record<never, never>)\n        | (number & Record<never, never>)\n        | (symbol & Record<never, never>)\n    : keyof TObject,\n  TStrictly extends 'strictly' | 'safely' = 'strictly',\n> = Omit<TObject, TKey>\n\nexport type Override<TTargetA, TTargetB> = {\n  [AKey in keyof TTargetA]: AKey extends keyof TTargetB\n    ? TTargetB[AKey]\n    : TTargetA[AKey]\n}\n\nexport type NoInfer<T> = [T][T extends any ? 0 : never]\n\nexport interface Register {\n  // defaultError: Error\n  // queryMeta: Record<string, unknown>\n  // mutationMeta: Record<string, unknown>\n  // queryKey: ReadonlyArray<unknown>\n  // mutationKey: ReadonlyArray<unknown>\n}\n\nexport type DefaultError = Register extends {\n  defaultError: infer TError\n}\n  ? TError\n  : Error\n\nexport type QueryKey = Register extends {\n  queryKey: infer TQueryKey\n}\n  ? TQueryKey extends ReadonlyArray<unknown>\n    ? TQueryKey\n    : TQueryKey extends Array<unknown>\n      ? TQueryKey\n      : ReadonlyArray<unknown>\n  : ReadonlyArray<unknown>\n\nexport const dataTagSymbol = Symbol('dataTagSymbol')\nexport type dataTagSymbol = typeof dataTagSymbol\nexport const dataTagErrorSymbol = Symbol('dataTagErrorSymbol')\nexport type dataTagErrorSymbol = typeof dataTagErrorSymbol\nexport const unsetMarker = Symbol('unsetMarker')\nexport type UnsetMarker = typeof unsetMarker\nexport type AnyDataTag = {\n  [dataTagSymbol]: any\n  [dataTagErrorSymbol]: any\n}\nexport type DataTag<\n  TType,\n  TValue,\n  TError = UnsetMarker,\n> = TType extends AnyDataTag\n  ? TType\n  : TType & {\n      [dataTagSymbol]: TValue\n      [dataTagErrorSymbol]: TError\n    }\n\nexport type InferDataFromTag<TQueryFnData, TTaggedQueryKey extends QueryKey> =\n  TTaggedQueryKey extends DataTag<unknown, infer TaggedValue, unknown>\n    ? TaggedValue\n    : TQueryFnData\n\nexport type InferErrorFromTag<TError, TTaggedQueryKey extends QueryKey> =\n  TTaggedQueryKey extends DataTag<unknown, unknown, infer TaggedError>\n    ? TaggedError extends UnsetMarker\n      ? TError\n      : TaggedError\n    : TError\n\nexport type QueryFunction<\n  T = unknown,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = never,\n> = (context: QueryFunctionContext<TQueryKey, TPageParam>) => T | Promise<T>\n\nexport type StaleTime = number | 'static'\n\nexport type StaleTimeFunction<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> =\n  | StaleTime\n  | ((query: Query<TQueryFnData, TError, TData, TQueryKey>) => StaleTime)\n\nexport type Enabled<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> =\n  | boolean\n  | ((query: Query<TQueryFnData, TError, TData, TQueryKey>) => boolean)\n\nexport type QueryPersister<\n  T = unknown,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = never,\n> = [TPageParam] extends [never]\n  ? (\n      queryFn: QueryFunction<T, TQueryKey, never>,\n      context: QueryFunctionContext<TQueryKey>,\n      query: Query,\n    ) => T | Promise<T>\n  : (\n      queryFn: QueryFunction<T, TQueryKey, TPageParam>,\n      context: QueryFunctionContext<TQueryKey>,\n      query: Query,\n    ) => T | Promise<T>\n\nexport type QueryFunctionContext<\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = never,\n> = [TPageParam] extends [never]\n  ? {\n      client: QueryClient\n      queryKey: TQueryKey\n      signal: AbortSignal\n      meta: QueryMeta | undefined\n      pageParam?: unknown\n      /**\n       * @deprecated\n       * if you want access to the direction, you can add it to the pageParam\n       */\n      direction?: unknown\n    }\n  : {\n      client: QueryClient\n      queryKey: TQueryKey\n      signal: AbortSignal\n      pageParam: TPageParam\n      /**\n       * @deprecated\n       * if you want access to the direction, you can add it to the pageParam\n       */\n      direction: FetchDirection\n      meta: QueryMeta | undefined\n    }\n\nexport type InitialDataFunction<T> = () => T | undefined\n\ntype NonFunctionGuard<T> = T extends Function ? never : T\n\nexport type PlaceholderDataFunction<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TQueryData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = (\n  previousData: TQueryData | undefined,\n  previousQuery: Query<TQueryFnData, TError, TQueryData, TQueryKey> | undefined,\n) => TQueryData | undefined\n\nexport type QueriesPlaceholderDataFunction<TQueryData> = (\n  previousData: undefined,\n  previousQuery: undefined,\n) => TQueryData | undefined\n\nexport type QueryKeyHashFunction<TQueryKey extends QueryKey> = (\n  queryKey: TQueryKey,\n) => string\n\nexport type GetPreviousPageParamFunction<TPageParam, TQueryFnData = unknown> = (\n  firstPage: TQueryFnData,\n  allPages: Array<TQueryFnData>,\n  firstPageParam: TPageParam,\n  allPageParams: Array<TPageParam>,\n) => TPageParam | undefined | null\n\nexport type GetNextPageParamFunction<TPageParam, TQueryFnData = unknown> = (\n  lastPage: TQueryFnData,\n  allPages: Array<TQueryFnData>,\n  lastPageParam: TPageParam,\n  allPageParams: Array<TPageParam>,\n) => TPageParam | undefined | null\n\nexport interface InfiniteData<TData, TPageParam = unknown> {\n  pages: Array<TData>\n  pageParams: Array<TPageParam>\n}\n\nexport type QueryMeta = Register extends {\n  queryMeta: infer TQueryMeta\n}\n  ? TQueryMeta extends Record<string, unknown>\n    ? TQueryMeta\n    : Record<string, unknown>\n  : Record<string, unknown>\n\nexport type NetworkMode = 'online' | 'always' | 'offlineFirst'\n\nexport type NotifyOnChangeProps =\n  | Array<keyof InfiniteQueryObserverResult>\n  | 'all'\n  | undefined\n  | (() => Array<keyof InfiniteQueryObserverResult> | 'all' | undefined)\n\nexport interface QueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = never,\n> {\n  /**\n   * If `false`, failed queries will not retry by default.\n   * If `true`, failed queries will retry infinitely., failureCount: num\n   * If set to an integer number, e.g. 3, failed queries will retry until the failed query count meets that number.\n   * If set to a function `(failureCount, error) => boolean` failed queries will retry until the function returns false.\n   */\n  retry?: RetryValue<TError>\n  retryDelay?: RetryDelayValue<TError>\n  networkMode?: NetworkMode\n  /**\n   * The time in milliseconds that unused/inactive cache data remains in memory.\n   * When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration.\n   * When different garbage collection times are specified, the longest one will be used.\n   * Setting it to `Infinity` will disable garbage collection.\n   */\n  gcTime?: number\n  queryFn?: QueryFunction<TQueryFnData, TQueryKey, TPageParam> | SkipToken\n  persister?: QueryPersister<\n    NoInfer<TQueryFnData>,\n    NoInfer<TQueryKey>,\n    NoInfer<TPageParam>\n  >\n  queryHash?: string\n  queryKey?: TQueryKey\n  queryKeyHashFn?: QueryKeyHashFunction<TQueryKey>\n  initialData?: TData | InitialDataFunction<TData>\n  initialDataUpdatedAt?: number | (() => number | undefined)\n  behavior?: QueryBehavior<TQueryFnData, TError, TData, TQueryKey>\n  /**\n   * Set this to `false` to disable structural sharing between query results.\n   * Set this to a function which accepts the old and new data and returns resolved data of the same type to implement custom structural sharing logic.\n   * Defaults to `true`.\n   */\n  structuralSharing?:\n    | boolean\n    | ((oldData: unknown | undefined, newData: unknown) => unknown)\n  _defaulted?: boolean\n  /**\n   * Additional payload to be stored on each query.\n   * Use this property to pass information that can be used in other places.\n   */\n  meta?: QueryMeta\n  /**\n   * Maximum number of pages to store in the data of an infinite query.\n   */\n  maxPages?: number\n}\n\nexport interface InitialPageParam<TPageParam = unknown> {\n  initialPageParam: TPageParam\n}\n\nexport interface InfiniteQueryPageParamsOptions<\n  TQueryFnData = unknown,\n  TPageParam = unknown,\n> extends InitialPageParam<TPageParam> {\n  /**\n   * This function can be set to automatically get the previous cursor for infinite queries.\n   * The result will also be used to determine the value of `hasPreviousPage`.\n   */\n  getPreviousPageParam?: GetPreviousPageParamFunction<TPageParam, TQueryFnData>\n  /**\n   * This function can be set to automatically get the next cursor for infinite queries.\n   * The result will also be used to determine the value of `hasNextPage`.\n   */\n  getNextPageParam: GetNextPageParamFunction<TPageParam, TQueryFnData>\n}\n\nexport type ThrowOnError<\n  TQueryFnData,\n  TError,\n  TQueryData,\n  TQueryKey extends QueryKey,\n> =\n  | boolean\n  | ((\n      error: TError,\n      query: Query<TQueryFnData, TError, TQueryData, TQueryKey>,\n    ) => boolean)\n\nexport interface QueryObserverOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = never,\n> extends WithRequired<\n  QueryOptions<TQueryFnData, TError, TQueryData, TQueryKey, TPageParam>,\n  'queryKey'\n> {\n  /**\n   * Set this to `false` or a function that returns `false` to disable automatic refetching when the query mounts or changes query keys.\n   * To refetch the query, use the `refetch` method returned from the `useQuery` instance.\n   * Accepts a boolean or function that returns a boolean.\n   * Defaults to `true`.\n   */\n  enabled?: Enabled<TQueryFnData, TError, TQueryData, TQueryKey>\n  /**\n   * The time in milliseconds after data is considered stale.\n   * If set to `Infinity`, the data will never be considered stale.\n   * If set to a function, the function will be executed with the query to compute a `staleTime`.\n   * Defaults to `0`.\n   */\n  staleTime?: StaleTimeFunction<TQueryFnData, TError, TQueryData, TQueryKey>\n  /**\n   * If set to a number, the query will continuously refetch at this frequency in milliseconds.\n   * If set to a function, the function will be executed with the latest data and query to compute a frequency\n   * Defaults to `false`.\n   */\n  refetchInterval?:\n    | number\n    | false\n    | ((\n        query: Query<TQueryFnData, TError, TQueryData, TQueryKey>,\n      ) => number | false | undefined)\n  /**\n   * If set to `true`, the query will continue to refetch while their tab/window is in the background.\n   * Defaults to `false`.\n   */\n  refetchIntervalInBackground?: boolean\n  /**\n   * If set to `true`, the query will refetch on window focus if the data is stale.\n   * If set to `false`, the query will not refetch on window focus.\n   * If set to `'always'`, the query will always refetch on window focus.\n   * If set to a function, the function will be executed with the latest data and query to compute the value.\n   * Defaults to `true`.\n   */\n  refetchOnWindowFocus?:\n    | boolean\n    | 'always'\n    | ((\n        query: Query<TQueryFnData, TError, TQueryData, TQueryKey>,\n      ) => boolean | 'always')\n  /**\n   * If set to `true`, the query will refetch on reconnect if the data is stale.\n   * If set to `false`, the query will not refetch on reconnect.\n   * If set to `'always'`, the query will always refetch on reconnect.\n   * If set to a function, the function will be executed with the latest data and query to compute the value.\n   * Defaults to the value of `networkOnline` (`true`)\n   */\n  refetchOnReconnect?:\n    | boolean\n    | 'always'\n    | ((\n        query: Query<TQueryFnData, TError, TQueryData, TQueryKey>,\n      ) => boolean | 'always')\n  /**\n   * If set to `true`, the query will refetch on mount if the data is stale.\n   * If set to `false`, will disable additional instances of a query to trigger background refetch.\n   * If set to `'always'`, the query will always refetch on mount.\n   * If set to a function, the function will be executed with the latest data and query to compute the value\n   * Defaults to `true`.\n   */\n  refetchOnMount?:\n    | boolean\n    | 'always'\n    | ((\n        query: Query<TQueryFnData, TError, TQueryData, TQueryKey>,\n      ) => boolean | 'always')\n  /**\n   * If set to `false`, the query will not be retried on mount if it contains an error.\n   * Defaults to `true`.\n   */\n  retryOnMount?: boolean\n  /**\n   * If set, the component will only re-render if any of the listed properties change.\n   * When set to `['data', 'error']`, the component will only re-render when the `data` or `error` properties change.\n   * When set to `'all'`, the component will re-render whenever a query is updated.\n   * When set to a function, the function will be executed to compute the list of properties.\n   * By default, access to properties will be tracked, and the component will only re-render when one of the tracked properties change.\n   */\n  notifyOnChangeProps?: NotifyOnChangeProps\n  /**\n   * Whether errors should be thrown instead of setting the `error` property.\n   * If set to `true` or `suspense` is `true`, all errors will be thrown to the error boundary.\n   * If set to `false` and `suspense` is `false`, errors are returned as state.\n   * If set to a function, it will be passed the error and the query, and it should return a boolean indicating whether to show the error in an error boundary (`true`) or return the error as state (`false`).\n   * Defaults to `false`.\n   */\n  throwOnError?: ThrowOnError<TQueryFnData, TError, TQueryData, TQueryKey>\n  /**\n   * This option can be used to transform or select a part of the data returned by the query function.\n   */\n  select?: (data: TQueryData) => TData\n  /**\n   * If set to `true`, the query will suspend when `status === 'pending'`\n   * and throw errors when `status === 'error'`.\n   * Defaults to `false`.\n   */\n  suspense?: boolean\n  /**\n   * If set, this value will be used as the placeholder data for this particular query observer while the query is still in the `loading` data and no initialData has been provided.\n   */\n  placeholderData?:\n    | NonFunctionGuard<TQueryData>\n    | PlaceholderDataFunction<\n        NonFunctionGuard<TQueryData>,\n        TError,\n        NonFunctionGuard<TQueryData>,\n        TQueryKey\n      >\n\n  _optimisticResults?: 'optimistic' | 'isRestoring'\n\n  /**\n   * Enable prefetching during rendering\n   */\n  experimental_prefetchInRender?: boolean\n}\n\nexport type WithRequired<TTarget, TKey extends keyof TTarget> = TTarget & {\n  [_ in TKey]: {}\n}\n\nexport type DefaultedQueryObserverOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = WithRequired<\n  QueryObserverOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>,\n  'throwOnError' | 'refetchOnReconnect' | 'queryHash'\n>\n\nexport interface InfiniteQueryObserverOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>\n  extends\n    QueryObserverOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      InfiniteData<TQueryFnData, TPageParam>,\n      TQueryKey,\n      TPageParam\n    >,\n    InfiniteQueryPageParamsOptions<TQueryFnData, TPageParam> {}\n\nexport type DefaultedInfiniteQueryObserverOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> = WithRequired<\n  InfiniteQueryObserverOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n  'throwOnError' | 'refetchOnReconnect' | 'queryHash'\n>\n\nexport interface FetchQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = never,\n> extends WithRequired<\n  QueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>,\n  'queryKey'\n> {\n  initialPageParam?: never\n  /**\n   * The time in milliseconds after data is considered stale.\n   * If the data is fresh it will be returned from the cache.\n   */\n  staleTime?: StaleTimeFunction<TQueryFnData, TError, TData, TQueryKey>\n}\n\nexport interface EnsureQueryDataOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = never,\n> extends FetchQueryOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey,\n  TPageParam\n> {\n  revalidateIfStale?: boolean\n}\n\nexport type EnsureInfiniteQueryDataOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> = FetchInfiniteQueryOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey,\n  TPageParam\n> & {\n  revalidateIfStale?: boolean\n}\n\ntype FetchInfiniteQueryPages<TQueryFnData = unknown, TPageParam = unknown> =\n  | { pages?: never }\n  | {\n      pages: number\n      getNextPageParam: GetNextPageParamFunction<TPageParam, TQueryFnData>\n    }\n\nexport type FetchInfiniteQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> = Omit<\n  FetchQueryOptions<\n    TQueryFnData,\n    TError,\n    InfiniteData<TData, TPageParam>,\n    TQueryKey,\n    TPageParam\n  >,\n  'initialPageParam'\n> &\n  InitialPageParam<TPageParam> &\n  FetchInfiniteQueryPages<TQueryFnData, TPageParam>\n\nexport interface ResultOptions {\n  throwOnError?: boolean\n}\n\nexport interface RefetchOptions extends ResultOptions {\n  /**\n   * If set to `true`, a currently running request will be cancelled before a new request is made\n   *\n   * If set to `false`, no refetch will be made if there is already a request running.\n   *\n   * Defaults to `true`.\n   */\n  cancelRefetch?: boolean\n}\n\nexport interface InvalidateQueryFilters<\n  TQueryKey extends QueryKey = QueryKey,\n> extends QueryFilters<TQueryKey> {\n  refetchType?: QueryTypeFilter | 'none'\n}\n\nexport interface RefetchQueryFilters<\n  TQueryKey extends QueryKey = QueryKey,\n> extends QueryFilters<TQueryKey> {}\n\nexport interface InvalidateOptions extends RefetchOptions {}\nexport interface ResetOptions extends RefetchOptions {}\n\nexport interface FetchNextPageOptions extends ResultOptions {\n  /**\n   * If set to `true`, calling `fetchNextPage` repeatedly will invoke `queryFn` every time,\n   * whether the previous invocation has resolved or not. Also, the result from previous invocations will be ignored.\n   *\n   * If set to `false`, calling `fetchNextPage` repeatedly won't have any effect until the first invocation has resolved.\n   *\n   * Defaults to `true`.\n   */\n  cancelRefetch?: boolean\n}\n\nexport interface FetchPreviousPageOptions extends ResultOptions {\n  /**\n   * If set to `true`, calling `fetchPreviousPage` repeatedly will invoke `queryFn` every time,\n   * whether the previous invocation has resolved or not. Also, the result from previous invocations will be ignored.\n   *\n   * If set to `false`, calling `fetchPreviousPage` repeatedly won't have any effect until the first invocation has resolved.\n   *\n   * Defaults to `true`.\n   */\n  cancelRefetch?: boolean\n}\n\nexport type QueryStatus = 'pending' | 'error' | 'success'\nexport type FetchStatus = 'fetching' | 'paused' | 'idle'\n\nexport interface QueryObserverBaseResult<\n  TData = unknown,\n  TError = DefaultError,\n> {\n  /**\n   * The last successfully resolved data for the query.\n   */\n  data: TData | undefined\n  /**\n   * The timestamp for when the query most recently returned the `status` as `\"success\"`.\n   */\n  dataUpdatedAt: number\n  /**\n   * The error object for the query, if an error was thrown.\n   * - Defaults to `null`.\n   */\n  error: TError | null\n  /**\n   * The timestamp for when the query most recently returned the `status` as `\"error\"`.\n   */\n  errorUpdatedAt: number\n  /**\n   * The failure count for the query.\n   * - Incremented every time the query fails.\n   * - Reset to `0` when the query succeeds.\n   */\n  failureCount: number\n  /**\n   * The failure reason for the query retry.\n   * - Reset to `null` when the query succeeds.\n   */\n  failureReason: TError | null\n  /**\n   * The sum of all errors.\n   */\n  errorUpdateCount: number\n  /**\n   * A derived boolean from the `status` variable, provided for convenience.\n   * - `true` if the query attempt resulted in an error.\n   */\n  isError: boolean\n  /**\n   * Will be `true` if the query has been fetched.\n   */\n  isFetched: boolean\n  /**\n   * Will be `true` if the query has been fetched after the component mounted.\n   * - This property can be used to not show any previously cached data.\n   */\n  isFetchedAfterMount: boolean\n  /**\n   * A derived boolean from the `fetchStatus` variable, provided for convenience.\n   * - `true` whenever the `queryFn` is executing, which includes initial `pending` as well as background refetch.\n   */\n  isFetching: boolean\n  /**\n   * Is `true` whenever the first fetch for a query is in-flight.\n   * - Is the same as `isFetching && isPending`.\n   */\n  isLoading: boolean\n  /**\n   * Will be `pending` if there's no cached data and no query attempt was finished yet.\n   */\n  isPending: boolean\n  /**\n   * Will be `true` if the query failed while fetching for the first time.\n   */\n  isLoadingError: boolean\n  /**\n   * @deprecated `isInitialLoading` is being deprecated in favor of `isLoading`\n   * and will be removed in the next major version.\n   */\n  isInitialLoading: boolean\n  /**\n   * A derived boolean from the `fetchStatus` variable, provided for convenience.\n   * - The query wanted to fetch, but has been `paused`.\n   */\n  isPaused: boolean\n  /**\n   * Will be `true` if the data shown is the placeholder data.\n   */\n  isPlaceholderData: boolean\n  /**\n   * Will be `true` if the query failed while refetching.\n   */\n  isRefetchError: boolean\n  /**\n   * Is `true` whenever a background refetch is in-flight, which _does not_ include initial `pending`.\n   * - Is the same as `isFetching && !isPending`.\n   */\n  isRefetching: boolean\n  /**\n   * Will be `true` if the data in the cache is invalidated or if the data is older than the given `staleTime`.\n   */\n  isStale: boolean\n  /**\n   * A derived boolean from the `status` variable, provided for convenience.\n   * - `true` if the query has received a response with no errors and is ready to display its data.\n   */\n  isSuccess: boolean\n  /**\n   * `true` if this observer is enabled, `false` otherwise.\n   */\n  isEnabled: boolean\n  /**\n   * A function to manually refetch the query.\n   */\n  refetch: (\n    options?: RefetchOptions,\n  ) => Promise<QueryObserverResult<TData, TError>>\n  /**\n   * The status of the query.\n   * - Will be:\n   *   - `pending` if there's no cached data and no query attempt was finished yet.\n   *   - `error` if the query attempt resulted in an error.\n   *   - `success` if the query has received a response with no errors and is ready to display its data.\n   */\n  status: QueryStatus\n  /**\n   * The fetch status of the query.\n   * - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch.\n   * - `paused`: The query wanted to fetch, but has been `paused`.\n   * - `idle`: The query is not fetching.\n   * - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information.\n   */\n  fetchStatus: FetchStatus\n  /**\n   * A stable promise that will be resolved with the data of the query.\n   * Requires the `experimental_prefetchInRender` feature flag to be enabled.\n   * @example\n   *\n   * ### Enabling the feature flag\n   * ```ts\n   * const client = new QueryClient({\n   *   defaultOptions: {\n   *     queries: {\n   *       experimental_prefetchInRender: true,\n   *     },\n   *   },\n   * })\n   * ```\n   *\n   * ### Usage\n   * ```tsx\n   * import { useQuery } from '@tanstack/react-query'\n   * import React from 'react'\n   * import { fetchTodos, type Todo } from './api'\n   *\n   * function TodoList({ query }: { query: UseQueryResult<Todo[], Error> }) {\n   *   const data = React.use(query.promise)\n   *\n   *   return (\n   *     <ul>\n   *       {data.map(todo => (\n   *         <li key={todo.id}>{todo.title}</li>\n   *       ))}\n   *     </ul>\n   *   )\n   * }\n   *\n   * export function App() {\n   *   const query = useQuery({ queryKey: ['todos'], queryFn: fetchTodos })\n   *\n   *   return (\n   *     <>\n   *       <h1>Todos</h1>\n   *       <React.Suspense fallback={<div>Loading...</div>}>\n   *         <TodoList query={query} />\n   *       </React.Suspense>\n   *     </>\n   *   )\n   * }\n   * ```\n   */\n  promise: Promise<TData>\n}\n\nexport interface QueryObserverPendingResult<\n  TData = unknown,\n  TError = DefaultError,\n> extends QueryObserverBaseResult<TData, TError> {\n  data: undefined\n  error: null\n  isError: false\n  isPending: true\n  isLoadingError: false\n  isRefetchError: false\n  isSuccess: false\n  isPlaceholderData: false\n  status: 'pending'\n}\n\nexport interface QueryObserverLoadingResult<\n  TData = unknown,\n  TError = DefaultError,\n> extends QueryObserverBaseResult<TData, TError> {\n  data: undefined\n  error: null\n  isError: false\n  isPending: true\n  isLoading: true\n  isLoadingError: false\n  isRefetchError: false\n  isSuccess: false\n  isPlaceholderData: false\n  status: 'pending'\n}\n\nexport interface QueryObserverLoadingErrorResult<\n  TData = unknown,\n  TError = DefaultError,\n> extends QueryObserverBaseResult<TData, TError> {\n  data: undefined\n  error: TError\n  isError: true\n  isPending: false\n  isLoading: false\n  isLoadingError: true\n  isRefetchError: false\n  isSuccess: false\n  isPlaceholderData: false\n  status: 'error'\n}\n\nexport interface QueryObserverRefetchErrorResult<\n  TData = unknown,\n  TError = DefaultError,\n> extends QueryObserverBaseResult<TData, TError> {\n  data: TData\n  error: TError\n  isError: true\n  isPending: false\n  isLoading: false\n  isLoadingError: false\n  isRefetchError: true\n  isSuccess: false\n  isPlaceholderData: false\n  status: 'error'\n}\n\nexport interface QueryObserverSuccessResult<\n  TData = unknown,\n  TError = DefaultError,\n> extends QueryObserverBaseResult<TData, TError> {\n  data: TData\n  error: null\n  isError: false\n  isPending: false\n  isLoading: false\n  isLoadingError: false\n  isRefetchError: false\n  isSuccess: true\n  isPlaceholderData: false\n  status: 'success'\n}\n\nexport interface QueryObserverPlaceholderResult<\n  TData = unknown,\n  TError = DefaultError,\n> extends QueryObserverBaseResult<TData, TError> {\n  data: TData\n  isError: false\n  error: null\n  isPending: false\n  isLoading: false\n  isLoadingError: false\n  isRefetchError: false\n  isSuccess: true\n  isPlaceholderData: true\n  status: 'success'\n}\n\nexport type DefinedQueryObserverResult<\n  TData = unknown,\n  TError = DefaultError,\n> =\n  | QueryObserverRefetchErrorResult<TData, TError>\n  | QueryObserverSuccessResult<TData, TError>\n\nexport type QueryObserverResult<TData = unknown, TError = DefaultError> =\n  | DefinedQueryObserverResult<TData, TError>\n  | QueryObserverLoadingErrorResult<TData, TError>\n  | QueryObserverLoadingResult<TData, TError>\n  | QueryObserverPendingResult<TData, TError>\n  | QueryObserverPlaceholderResult<TData, TError>\n\nexport interface InfiniteQueryObserverBaseResult<\n  TData = unknown,\n  TError = DefaultError,\n> extends QueryObserverBaseResult<TData, TError> {\n  /**\n   * This function allows you to fetch the next \"page\" of results.\n   */\n  fetchNextPage: (\n    options?: FetchNextPageOptions,\n  ) => Promise<InfiniteQueryObserverResult<TData, TError>>\n  /**\n   * This function allows you to fetch the previous \"page\" of results.\n   */\n  fetchPreviousPage: (\n    options?: FetchPreviousPageOptions,\n  ) => Promise<InfiniteQueryObserverResult<TData, TError>>\n  /**\n   * Will be `true` if there is a next page to be fetched (known via the `getNextPageParam` option).\n   */\n  hasNextPage: boolean\n  /**\n   * Will be `true` if there is a previous page to be fetched (known via the `getPreviousPageParam` option).\n   */\n  hasPreviousPage: boolean\n  /**\n   * Will be `true` if the query failed while fetching the next page.\n   */\n  isFetchNextPageError: boolean\n  /**\n   * Will be `true` while fetching the next page with `fetchNextPage`.\n   */\n  isFetchingNextPage: boolean\n  /**\n   * Will be `true` if the query failed while fetching the previous page.\n   */\n  isFetchPreviousPageError: boolean\n  /**\n   * Will be `true` while fetching the previous page with `fetchPreviousPage`.\n   */\n  isFetchingPreviousPage: boolean\n}\n\nexport interface InfiniteQueryObserverPendingResult<\n  TData = unknown,\n  TError = DefaultError,\n> extends InfiniteQueryObserverBaseResult<TData, TError> {\n  data: undefined\n  error: null\n  isError: false\n  isPending: true\n  isLoadingError: false\n  isRefetchError: false\n  isFetchNextPageError: false\n  isFetchPreviousPageError: false\n  isSuccess: false\n  isPlaceholderData: false\n  status: 'pending'\n}\n\nexport interface InfiniteQueryObserverLoadingResult<\n  TData = unknown,\n  TError = DefaultError,\n> extends InfiniteQueryObserverBaseResult<TData, TError> {\n  data: undefined\n  error: null\n  isError: false\n  isPending: true\n  isLoading: true\n  isLoadingError: false\n  isRefetchError: false\n  isFetchNextPageError: false\n  isFetchPreviousPageError: false\n  isSuccess: false\n  isPlaceholderData: false\n  status: 'pending'\n}\n\nexport interface InfiniteQueryObserverLoadingErrorResult<\n  TData = unknown,\n  TError = DefaultError,\n> extends InfiniteQueryObserverBaseResult<TData, TError> {\n  data: undefined\n  error: TError\n  isError: true\n  isPending: false\n  isLoading: false\n  isLoadingError: true\n  isRefetchError: false\n  isFetchNextPageError: false\n  isFetchPreviousPageError: false\n  isSuccess: false\n  isPlaceholderData: false\n  status: 'error'\n}\n\nexport interface InfiniteQueryObserverRefetchErrorResult<\n  TData = unknown,\n  TError = DefaultError,\n> extends InfiniteQueryObserverBaseResult<TData, TError> {\n  data: TData\n  error: TError\n  isError: true\n  isPending: false\n  isLoading: false\n  isLoadingError: false\n  isRefetchError: true\n  isSuccess: false\n  isPlaceholderData: false\n  status: 'error'\n}\n\nexport interface InfiniteQueryObserverSuccessResult<\n  TData = unknown,\n  TError = DefaultError,\n> extends InfiniteQueryObserverBaseResult<TData, TError> {\n  data: TData\n  error: null\n  isError: false\n  isPending: false\n  isLoading: false\n  isLoadingError: false\n  isRefetchError: false\n  isFetchNextPageError: false\n  isFetchPreviousPageError: false\n  isSuccess: true\n  isPlaceholderData: false\n  status: 'success'\n}\n\nexport interface InfiniteQueryObserverPlaceholderResult<\n  TData = unknown,\n  TError = DefaultError,\n> extends InfiniteQueryObserverBaseResult<TData, TError> {\n  data: TData\n  isError: false\n  error: null\n  isPending: false\n  isLoading: false\n  isLoadingError: false\n  isRefetchError: false\n  isSuccess: true\n  isPlaceholderData: true\n  isFetchNextPageError: false\n  isFetchPreviousPageError: false\n  status: 'success'\n}\n\nexport type DefinedInfiniteQueryObserverResult<\n  TData = unknown,\n  TError = DefaultError,\n> =\n  | InfiniteQueryObserverRefetchErrorResult<TData, TError>\n  | InfiniteQueryObserverSuccessResult<TData, TError>\n\nexport type InfiniteQueryObserverResult<\n  TData = unknown,\n  TError = DefaultError,\n> =\n  | DefinedInfiniteQueryObserverResult<TData, TError>\n  | InfiniteQueryObserverLoadingErrorResult<TData, TError>\n  | InfiniteQueryObserverLoadingResult<TData, TError>\n  | InfiniteQueryObserverPendingResult<TData, TError>\n  | InfiniteQueryObserverPlaceholderResult<TData, TError>\n\nexport type MutationKey = Register extends {\n  mutationKey: infer TMutationKey\n}\n  ? TMutationKey extends ReadonlyArray<unknown>\n    ? TMutationKey\n    : TMutationKey extends Array<unknown>\n      ? TMutationKey\n      : ReadonlyArray<unknown>\n  : ReadonlyArray<unknown>\n\nexport type MutationStatus = 'idle' | 'pending' | 'success' | 'error'\n\nexport type MutationScope = {\n  id: string\n}\n\nexport type MutationMeta = Register extends {\n  mutationMeta: infer TMutationMeta\n}\n  ? TMutationMeta extends Record<string, unknown>\n    ? TMutationMeta\n    : Record<string, unknown>\n  : Record<string, unknown>\n\nexport type MutationFunctionContext = {\n  client: QueryClient\n  meta: MutationMeta | undefined\n  mutationKey?: MutationKey\n}\n\nexport type MutationFunction<TData = unknown, TVariables = unknown> = (\n  variables: TVariables,\n  context: MutationFunctionContext,\n) => Promise<TData>\n\nexport interface MutationOptions<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> {\n  mutationFn?: MutationFunction<TData, TVariables>\n  mutationKey?: MutationKey\n  onMutate?: (\n    variables: TVariables,\n    context: MutationFunctionContext,\n  ) => Promise<TOnMutateResult> | TOnMutateResult\n  onSuccess?: (\n    data: TData,\n    variables: TVariables,\n    onMutateResult: TOnMutateResult,\n    context: MutationFunctionContext,\n  ) => Promise<unknown> | unknown\n  onError?: (\n    error: TError,\n    variables: TVariables,\n    onMutateResult: TOnMutateResult | undefined,\n    context: MutationFunctionContext,\n  ) => Promise<unknown> | unknown\n  onSettled?: (\n    data: TData | undefined,\n    error: TError | null,\n    variables: TVariables,\n    onMutateResult: TOnMutateResult | undefined,\n    context: MutationFunctionContext,\n  ) => Promise<unknown> | unknown\n  retry?: RetryValue<TError>\n  retryDelay?: RetryDelayValue<TError>\n  networkMode?: NetworkMode\n  gcTime?: number\n  _defaulted?: boolean\n  meta?: MutationMeta\n  scope?: MutationScope\n}\n\nexport interface MutationObserverOptions<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> extends MutationOptions<TData, TError, TVariables, TOnMutateResult> {\n  throwOnError?: boolean | ((error: TError) => boolean)\n}\n\nexport interface MutateOptions<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> {\n  onSuccess?: (\n    data: TData,\n    variables: TVariables,\n    onMutateResult: TOnMutateResult | undefined,\n    context: MutationFunctionContext,\n  ) => void\n  onError?: (\n    error: TError,\n    variables: TVariables,\n    onMutateResult: TOnMutateResult | undefined,\n    context: MutationFunctionContext,\n  ) => void\n  onSettled?: (\n    data: TData | undefined,\n    error: TError | null,\n    variables: TVariables,\n    onMutateResult: TOnMutateResult | undefined,\n    context: MutationFunctionContext,\n  ) => void\n}\n\nexport type MutateFunction<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> = (\n  variables: TVariables,\n  options?: MutateOptions<TData, TError, TVariables, TOnMutateResult>,\n) => Promise<TData>\n\nexport interface MutationObserverBaseResult<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> extends MutationState<TData, TError, TVariables, TOnMutateResult> {\n  /**\n   * The last successfully resolved data for the mutation.\n   */\n  data: TData | undefined\n  /**\n   * The variables object passed to the `mutationFn`.\n   */\n  variables: TVariables | undefined\n  /**\n   * The error object for the mutation, if an error was encountered.\n   * - Defaults to `null`.\n   */\n  error: TError | null\n  /**\n   * A boolean variable derived from `status`.\n   * - `true` if the last mutation attempt resulted in an error.\n   */\n  isError: boolean\n  /**\n   * A boolean variable derived from `status`.\n   * - `true` if the mutation is in its initial state prior to executing.\n   */\n  isIdle: boolean\n  /**\n   * A boolean variable derived from `status`.\n   * - `true` if the mutation is currently executing.\n   */\n  isPending: boolean\n  /**\n   * A boolean variable derived from `status`.\n   * - `true` if the last mutation attempt was successful.\n   */\n  isSuccess: boolean\n  /**\n   * The status of the mutation.\n   * - Will be:\n   *   - `idle` initial status prior to the mutation function executing.\n   *   - `pending` if the mutation is currently executing.\n   *   - `error` if the last mutation attempt resulted in an error.\n   *   - `success` if the last mutation attempt was successful.\n   */\n  status: MutationStatus\n  /**\n   * The mutation function you can call with variables to trigger the mutation and optionally hooks on additional callback options.\n   * @param variables - The variables object to pass to the `mutationFn`.\n   * @param options.onSuccess - This function will fire when the mutation is successful and will be passed the mutation's result.\n   * @param options.onError - This function will fire if the mutation encounters an error and will be passed the error.\n   * @param options.onSettled - This function will fire when the mutation is either successfully fetched or encounters an error and be passed either the data or error.\n   * @remarks\n   * - If you make multiple requests, `onSuccess` will fire only after the latest call you've made.\n   * - All the callback functions (`onSuccess`, `onError`, `onSettled`) are void functions, and the returned value will be ignored.\n   */\n  mutate: MutateFunction<TData, TError, TVariables, TOnMutateResult>\n  /**\n   * A function to clean the mutation internal state (i.e., it resets the mutation to its initial state).\n   */\n  reset: () => void\n}\n\nexport interface MutationObserverIdleResult<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> extends MutationObserverBaseResult<\n  TData,\n  TError,\n  TVariables,\n  TOnMutateResult\n> {\n  data: undefined\n  variables: undefined\n  error: null\n  isError: false\n  isIdle: true\n  isPending: false\n  isSuccess: false\n  status: 'idle'\n}\n\nexport interface MutationObserverLoadingResult<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> extends MutationObserverBaseResult<\n  TData,\n  TError,\n  TVariables,\n  TOnMutateResult\n> {\n  data: undefined\n  variables: TVariables\n  error: null\n  isError: false\n  isIdle: false\n  isPending: true\n  isSuccess: false\n  status: 'pending'\n}\n\nexport interface MutationObserverErrorResult<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> extends MutationObserverBaseResult<\n  TData,\n  TError,\n  TVariables,\n  TOnMutateResult\n> {\n  data: undefined\n  error: TError\n  variables: TVariables\n  isError: true\n  isIdle: false\n  isPending: false\n  isSuccess: false\n  status: 'error'\n}\n\nexport interface MutationObserverSuccessResult<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> extends MutationObserverBaseResult<\n  TData,\n  TError,\n  TVariables,\n  TOnMutateResult\n> {\n  data: TData\n  error: null\n  variables: TVariables\n  isError: false\n  isIdle: false\n  isPending: false\n  isSuccess: true\n  status: 'success'\n}\n\nexport type MutationObserverResult<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> =\n  | MutationObserverIdleResult<TData, TError, TVariables, TOnMutateResult>\n  | MutationObserverLoadingResult<TData, TError, TVariables, TOnMutateResult>\n  | MutationObserverErrorResult<TData, TError, TVariables, TOnMutateResult>\n  | MutationObserverSuccessResult<TData, TError, TVariables, TOnMutateResult>\n\nexport interface QueryClientConfig {\n  queryCache?: QueryCache\n  mutationCache?: MutationCache\n  defaultOptions?: DefaultOptions\n}\n\nexport interface DefaultOptions<TError = DefaultError> {\n  queries?: OmitKeyof<\n    QueryObserverOptions<unknown, TError>,\n    'suspense' | 'queryKey'\n  >\n  mutations?: MutationObserverOptions<unknown, TError, unknown, unknown>\n  hydrate?: HydrateOptions['defaultOptions']\n  dehydrate?: DehydrateOptions\n}\n\nexport interface CancelOptions {\n  revert?: boolean\n  silent?: boolean\n}\n\nexport interface SetDataOptions {\n  updatedAt?: number\n}\n\nexport type NotifyEventType =\n  | 'added'\n  | 'removed'\n  | 'updated'\n  | 'observerAdded'\n  | 'observerRemoved'\n  | 'observerResultsUpdated'\n  | 'observerOptionsUpdated'\n\nexport interface NotifyEvent {\n  type: NotifyEventType\n}\n"
  },
  {
    "path": "packages/query-core/src/utils.ts",
    "content": "import { timeoutManager } from './timeoutManager'\nimport type {\n  DefaultError,\n  Enabled,\n  FetchStatus,\n  MutationKey,\n  MutationStatus,\n  QueryFunction,\n  QueryKey,\n  QueryOptions,\n  StaleTime,\n  StaleTimeFunction,\n} from './types'\nimport type { Mutation } from './mutation'\nimport type { FetchOptions, Query } from './query'\n\n// TYPES\n\ntype DropLast<T extends ReadonlyArray<unknown>> = T extends readonly [\n  ...infer R,\n  unknown,\n]\n  ? readonly [...R]\n  : never\n\ntype TuplePrefixes<T extends ReadonlyArray<unknown>> = T extends readonly []\n  ? readonly []\n  : TuplePrefixes<DropLast<T>> | T\n\nexport interface QueryFilters<TQueryKey extends QueryKey = QueryKey> {\n  /**\n   * Filter to active queries, inactive queries or all queries\n   */\n  type?: QueryTypeFilter\n  /**\n   * Match query key exactly\n   */\n  exact?: boolean\n  /**\n   * Include queries matching this predicate function\n   */\n  predicate?: (query: Query) => boolean\n  /**\n   * Include queries matching this query key\n   */\n  queryKey?: TQueryKey | TuplePrefixes<TQueryKey>\n  /**\n   * Include or exclude stale queries\n   */\n  stale?: boolean\n  /**\n   * Include queries matching their fetchStatus\n   */\n  fetchStatus?: FetchStatus\n}\n\nexport interface MutationFilters<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = unknown,\n  TOnMutateResult = unknown,\n> {\n  /**\n   * Match mutation key exactly\n   */\n  exact?: boolean\n  /**\n   * Include mutations matching this predicate function\n   */\n  predicate?: (\n    mutation: Mutation<TData, TError, TVariables, TOnMutateResult>,\n  ) => boolean\n  /**\n   * Include mutations matching this mutation key\n   */\n  mutationKey?: TuplePrefixes<MutationKey>\n  /**\n   * Filter by mutation status\n   */\n  status?: MutationStatus\n}\n\nexport type Updater<TInput, TOutput> = TOutput | ((input: TInput) => TOutput)\n\nexport type QueryTypeFilter = 'all' | 'active' | 'inactive'\n\n// UTILS\n\n/** @deprecated\n * use `environmentManager.isServer()` instead.\n */\nexport const isServer = typeof window === 'undefined' || 'Deno' in globalThis\n\nexport function noop(): void\nexport function noop(): undefined\nexport function noop() {}\n\nexport function functionalUpdate<TInput, TOutput>(\n  updater: Updater<TInput, TOutput>,\n  input: TInput,\n): TOutput {\n  return typeof updater === 'function'\n    ? (updater as (_: TInput) => TOutput)(input)\n    : updater\n}\n\nexport function isValidTimeout(value: unknown): value is number {\n  return typeof value === 'number' && value >= 0 && value !== Infinity\n}\n\nexport function timeUntilStale(updatedAt: number, staleTime?: number): number {\n  return Math.max(updatedAt + (staleTime || 0) - Date.now(), 0)\n}\n\nexport function resolveStaleTime<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  staleTime:\n    | undefined\n    | StaleTimeFunction<TQueryFnData, TError, TData, TQueryKey>,\n  query: Query<TQueryFnData, TError, TData, TQueryKey>,\n): StaleTime | undefined {\n  return typeof staleTime === 'function' ? staleTime(query) : staleTime\n}\n\nexport function resolveEnabled<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  enabled: undefined | Enabled<TQueryFnData, TError, TData, TQueryKey>,\n  query: Query<TQueryFnData, TError, TData, TQueryKey>,\n): boolean | undefined {\n  return typeof enabled === 'function' ? enabled(query) : enabled\n}\n\nexport function matchQuery(\n  filters: QueryFilters,\n  query: Query<any, any, any, any>,\n): boolean {\n  const {\n    type = 'all',\n    exact,\n    fetchStatus,\n    predicate,\n    queryKey,\n    stale,\n  } = filters\n\n  if (queryKey) {\n    if (exact) {\n      if (query.queryHash !== hashQueryKeyByOptions(queryKey, query.options)) {\n        return false\n      }\n    } else if (!partialMatchKey(query.queryKey, queryKey)) {\n      return false\n    }\n  }\n\n  if (type !== 'all') {\n    const isActive = query.isActive()\n    if (type === 'active' && !isActive) {\n      return false\n    }\n    if (type === 'inactive' && isActive) {\n      return false\n    }\n  }\n\n  if (typeof stale === 'boolean' && query.isStale() !== stale) {\n    return false\n  }\n\n  if (fetchStatus && fetchStatus !== query.state.fetchStatus) {\n    return false\n  }\n\n  if (predicate && !predicate(query)) {\n    return false\n  }\n\n  return true\n}\n\nexport function matchMutation(\n  filters: MutationFilters,\n  mutation: Mutation<any, any>,\n): boolean {\n  const { exact, status, predicate, mutationKey } = filters\n  if (mutationKey) {\n    if (!mutation.options.mutationKey) {\n      return false\n    }\n    if (exact) {\n      if (hashKey(mutation.options.mutationKey) !== hashKey(mutationKey)) {\n        return false\n      }\n    } else if (!partialMatchKey(mutation.options.mutationKey, mutationKey)) {\n      return false\n    }\n  }\n\n  if (status && mutation.state.status !== status) {\n    return false\n  }\n\n  if (predicate && !predicate(mutation)) {\n    return false\n  }\n\n  return true\n}\n\nexport function hashQueryKeyByOptions<TQueryKey extends QueryKey = QueryKey>(\n  queryKey: TQueryKey,\n  options?: Pick<QueryOptions<any, any, any, any>, 'queryKeyHashFn'>,\n): string {\n  const hashFn = options?.queryKeyHashFn || hashKey\n  return hashFn(queryKey)\n}\n\n/**\n * Default query & mutation keys hash function.\n * Hashes the value into a stable hash.\n */\nexport function hashKey(queryKey: QueryKey | MutationKey): string {\n  return JSON.stringify(queryKey, (_, val) =>\n    isPlainObject(val)\n      ? Object.keys(val)\n          .sort()\n          .reduce((result, key) => {\n            result[key] = val[key]\n            return result\n          }, {} as any)\n      : val,\n  )\n}\n\n/**\n * Checks if key `b` partially matches with key `a`.\n */\nexport function partialMatchKey(a: QueryKey, b: QueryKey): boolean\nexport function partialMatchKey(a: any, b: any): boolean {\n  if (a === b) {\n    return true\n  }\n\n  if (typeof a !== typeof b) {\n    return false\n  }\n\n  if (a && b && typeof a === 'object' && typeof b === 'object') {\n    return Object.keys(b).every((key) => partialMatchKey(a[key], b[key]))\n  }\n\n  return false\n}\n\nconst hasOwn = Object.prototype.hasOwnProperty\n\n/**\n * This function returns `a` if `b` is deeply equal.\n * If not, it will replace any deeply equal children of `b` with those of `a`.\n * This can be used for structural sharing between JSON values for example.\n */\nexport function replaceEqualDeep<T>(a: unknown, b: T, depth?: number): T\nexport function replaceEqualDeep(a: any, b: any, depth = 0): any {\n  if (a === b) {\n    return a\n  }\n\n  if (depth > 500) return b\n\n  const array = isPlainArray(a) && isPlainArray(b)\n\n  if (!array && !(isPlainObject(a) && isPlainObject(b))) return b\n\n  const aItems = array ? a : Object.keys(a)\n  const aSize = aItems.length\n  const bItems = array ? b : Object.keys(b)\n  const bSize = bItems.length\n  const copy: any = array ? new Array(bSize) : {}\n\n  let equalItems = 0\n\n  for (let i = 0; i < bSize; i++) {\n    const key: any = array ? i : bItems[i]\n    const aItem = a[key]\n    const bItem = b[key]\n\n    if (aItem === bItem) {\n      copy[key] = aItem\n      if (array ? i < aSize : hasOwn.call(a, key)) equalItems++\n      continue\n    }\n\n    if (\n      aItem === null ||\n      bItem === null ||\n      typeof aItem !== 'object' ||\n      typeof bItem !== 'object'\n    ) {\n      copy[key] = bItem\n      continue\n    }\n\n    const v = replaceEqualDeep(aItem, bItem, depth + 1)\n    copy[key] = v\n    if (v === aItem) equalItems++\n  }\n\n  return aSize === bSize && equalItems === aSize ? a : copy\n}\n\n/**\n * Shallow compare objects.\n */\nexport function shallowEqualObjects<T extends Record<string, any>>(\n  a: T,\n  b: T | undefined,\n): boolean {\n  if (!b || Object.keys(a).length !== Object.keys(b).length) {\n    return false\n  }\n\n  for (const key in a) {\n    if (a[key] !== b[key]) {\n      return false\n    }\n  }\n\n  return true\n}\n\nexport function isPlainArray(value: unknown): value is Array<unknown> {\n  return Array.isArray(value) && value.length === Object.keys(value).length\n}\n\n// Copied from: https://github.com/jonschlinkert/is-plain-object\nexport function isPlainObject(o: any): o is Record<PropertyKey, unknown> {\n  if (!hasObjectPrototype(o)) {\n    return false\n  }\n\n  // If has no constructor\n  const ctor = o.constructor\n  if (ctor === undefined) {\n    return true\n  }\n\n  // If has modified prototype\n  const prot = ctor.prototype\n  if (!hasObjectPrototype(prot)) {\n    return false\n  }\n\n  // If constructor does not have an Object-specific method\n  if (!prot.hasOwnProperty('isPrototypeOf')) {\n    return false\n  }\n\n  // Handles Objects created by Object.create(<arbitrary prototype>)\n  if (Object.getPrototypeOf(o) !== Object.prototype) {\n    return false\n  }\n\n  // Most likely a plain Object\n  return true\n}\n\nfunction hasObjectPrototype(o: any): boolean {\n  return Object.prototype.toString.call(o) === '[object Object]'\n}\n\nexport function sleep(timeout: number): Promise<void> {\n  return new Promise((resolve) => {\n    timeoutManager.setTimeout(resolve, timeout)\n  })\n}\n\nexport function replaceData<\n  TData,\n  TOptions extends QueryOptions<any, any, any, any>,\n>(prevData: TData | undefined, data: TData, options: TOptions): TData {\n  if (typeof options.structuralSharing === 'function') {\n    return options.structuralSharing(prevData, data) as TData\n  } else if (options.structuralSharing !== false) {\n    if (process.env.NODE_ENV !== 'production') {\n      try {\n        return replaceEqualDeep(prevData, data)\n      } catch (error) {\n        console.error(\n          `Structural sharing requires data to be JSON serializable. To fix this, turn off structuralSharing or return JSON-serializable data from your queryFn. [${options.queryHash}]: ${error}`,\n        )\n\n        // Prevent the replaceEqualDeep from being called again down below.\n        throw error\n      }\n    }\n    // Structurally share data between prev and new data if needed\n    return replaceEqualDeep(prevData, data)\n  }\n  return data\n}\n\nexport function keepPreviousData<T>(\n  previousData: T | undefined,\n): T | undefined {\n  return previousData\n}\n\nexport function addToEnd<T>(items: Array<T>, item: T, max = 0): Array<T> {\n  const newItems = [...items, item]\n  return max && newItems.length > max ? newItems.slice(1) : newItems\n}\n\nexport function addToStart<T>(items: Array<T>, item: T, max = 0): Array<T> {\n  const newItems = [item, ...items]\n  return max && newItems.length > max ? newItems.slice(0, -1) : newItems\n}\n\nexport const skipToken = Symbol()\nexport type SkipToken = typeof skipToken\n\nexport function ensureQueryFn<\n  TQueryFnData = unknown,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: {\n    queryFn?: QueryFunction<TQueryFnData, TQueryKey> | SkipToken\n    queryHash?: string\n  },\n  fetchOptions?: FetchOptions<TQueryFnData>,\n): QueryFunction<TQueryFnData, TQueryKey> {\n  if (process.env.NODE_ENV !== 'production') {\n    if (options.queryFn === skipToken) {\n      console.error(\n        `Attempted to invoke queryFn when set to skipToken. This is likely a configuration error. Query hash: '${options.queryHash}'`,\n      )\n    }\n  }\n\n  // if we attempt to retry a fetch that was triggered from an initialPromise\n  // when we don't have a queryFn yet, we can't retry, so we just return the already rejected initialPromise\n  // if an observer has already mounted, we will be able to retry with that queryFn\n  if (!options.queryFn && fetchOptions?.initialPromise) {\n    return () => fetchOptions.initialPromise!\n  }\n\n  if (!options.queryFn || options.queryFn === skipToken) {\n    return () =>\n      Promise.reject(new Error(`Missing queryFn: '${options.queryHash}'`))\n  }\n\n  return options.queryFn\n}\n\nexport function shouldThrowError<T extends (...args: Array<any>) => boolean>(\n  throwOnError: boolean | T | undefined,\n  params: Parameters<T>,\n): boolean {\n  // Allow throwOnError function to override throwing behavior on a per-error basis\n  if (typeof throwOnError === 'function') {\n    return throwOnError(...params)\n  }\n\n  return !!throwOnError\n}\n\nexport function addConsumeAwareSignal<T>(\n  object: T,\n  getSignal: () => AbortSignal,\n  onCancelled: VoidFunction,\n): T & { signal: AbortSignal } {\n  let consumed = false\n  let signal: AbortSignal | undefined\n\n  Object.defineProperty(object, 'signal', {\n    enumerable: true,\n    get: () => {\n      signal ??= getSignal()\n      if (consumed) {\n        return signal\n      }\n\n      consumed = true\n      if (signal.aborted) {\n        onCancelled()\n      } else {\n        signal.addEventListener('abort', onCancelled, { once: true })\n      }\n\n      return signal\n    },\n  })\n\n  return object as T & { signal: AbortSignal }\n}\n"
  },
  {
    "path": "packages/query-core/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\"\n  },\n  \"include\": [\"src\", \"*.config.*\", \"package.json\"]\n}\n"
  },
  {
    "path": "packages/query-core/tsconfig.legacy.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts/legacy\"\n  },\n  \"include\": [\"src\"],\n  \"exclude\": [\"src/__tests__\"]\n}\n"
  },
  {
    "path": "packages/query-core/tsconfig.prod.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"incremental\": false,\n    \"composite\": false,\n    \"rootDir\": \"../../\"\n  }\n}\n"
  },
  {
    "path": "packages/query-core/tsup.config.ts",
    "content": "import { defineConfig } from 'tsup'\nimport { legacyConfig, modernConfig } from './root.tsup.config.js'\n\nexport default defineConfig([\n  modernConfig({ entry: ['src/*.ts'] }),\n  legacyConfig({ entry: ['src/*.ts'] }),\n])\n"
  },
  {
    "path": "packages/query-core/vite.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nimport packageJson from './package.json'\n\nexport default defineConfig({\n  // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660\n  resolve: {\n    conditions: ['@tanstack/custom-condition'],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        conditions: ['@tanstack/custom-condition'],\n      },\n    },\n  },\n  test: {\n    name: packageJson.name,\n    dir: './src',\n    watch: false,\n    environment: 'jsdom',\n    coverage: {\n      enabled: true,\n      provider: 'istanbul',\n      include: ['src/**/*'],\n      exclude: ['src/__tests__/**'],\n    },\n    typecheck: { enabled: true },\n    restoreMocks: true,\n  },\n})\n"
  },
  {
    "path": "packages/query-devtools/CHANGELOG.md",
    "content": "# @tanstack/query-devtools\n\n## 5.93.0\n\n### Minor Changes\n\n- Set data to undefined on Trigger Error ([#10072](https://github.com/TanStack/query/pull/10072))\n\n## 5.92.0\n\n### Minor Changes\n\n- improve a11y around screenreader + resizing ([#9961](https://github.com/TanStack/query/pull/9961))\n\n### Patch Changes\n\n- fix(devtools): handle PiP open failures by resetting persisted state ([#9983](https://github.com/TanStack/query/pull/9983))\n\n## 5.91.1\n\n### Patch Changes\n\n- improves accessibility of devtools ([#9806](https://github.com/TanStack/query/pull/9806))\n\n## 5.91.0\n\n### Minor Changes\n\n- feat(devtools): allow passing a theme via prop ([#9887](https://github.com/TanStack/query/pull/9887))\n"
  },
  {
    "path": "packages/query-devtools/eslint.config.js",
    "content": "// @ts-check\n\nimport rootConfig from './root.eslint.config.js'\n\nexport default [...rootConfig]\n"
  },
  {
    "path": "packages/query-devtools/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-devtools\",\n  \"version\": \"5.93.0\",\n  \"description\": \"Developer tools to interact with and visualize the TanStack Query cache\",\n  \"author\": \"tannerlinsley\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/query-devtools\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"scripts\": {\n    \"clean\": \"premove ./build ./coverage ./dist-ts\",\n    \"compile\": \"tsc --build\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:types\": \"npm-run-all --serial test:types:*\",\n    \"test:types:ts54\": \"node ../../node_modules/typescript54/lib/tsc.js --build\",\n    \"test:types:ts55\": \"node ../../node_modules/typescript55/lib/tsc.js --build\",\n    \"test:types:ts56\": \"node ../../node_modules/typescript56/lib/tsc.js --build\",\n    \"test:types:ts57\": \"node ../../node_modules/typescript57/lib/tsc.js --build\",\n    \"test:types:ts58\": \"node ../../node_modules/typescript58/lib/tsc.js --build\",\n    \"test:types:ts59\": \"node ../../node_modules/typescript59/lib/tsc.js --build\",\n    \"test:types:tscurrent\": \"tsc --build\",\n    \"test:types:ts60\": \"node ../../node_modules/typescript60/lib/tsc.js --build\",\n    \"test:lib\": \"vitest\",\n    \"test:lib:dev\": \"pnpm run test:lib --watch\",\n    \"test:build\": \"publint --strict && attw --pack\",\n    \"build\": \"tsup --tsconfig tsconfig.prod.json\",\n    \"build:dev\": \"tsup --watch\"\n  },\n  \"type\": \"module\",\n  \"main\": \"./build/index.cjs\",\n  \"module\": \"./build/index.js\",\n  \"types\": \"./build/index.d.ts\",\n  \"browser\": {},\n  \"exports\": {\n    \"@tanstack/custom-condition\": \"./src/index.ts\",\n    \"solid\": {\n      \"development\": \"./build/index.js\",\n      \"import\": \"./build/index.js\"\n    },\n    \"development\": {\n      \"import\": {\n        \"types\": \"./build/index.d.ts\",\n        \"default\": \"./build/dev.js\"\n      },\n      \"require\": \"./build/dev.cjs\"\n    },\n    \"import\": {\n      \"types\": \"./build/index.d.ts\",\n      \"default\": \"./build/index.js\"\n    },\n    \"require\": \"./build/index.cjs\"\n  },\n  \"files\": [\n    \"build\",\n    \"src\",\n    \"!src/__tests__\"\n  ],\n  \"devDependencies\": {\n    \"@kobalte/core\": \"^0.13.4\",\n    \"@solid-primitives/keyed\": \"^1.2.2\",\n    \"@solid-primitives/resize-observer\": \"^2.0.26\",\n    \"@solid-primitives/storage\": \"^1.3.11\",\n    \"@tanstack/match-sorter-utils\": \"^8.19.4\",\n    \"@tanstack/query-core\": \"workspace:*\",\n    \"clsx\": \"^2.1.1\",\n    \"goober\": \"^2.1.16\",\n    \"npm-run-all2\": \"^5.0.0\",\n    \"solid-js\": \"^1.9.7\",\n    \"solid-transition-group\": \"^0.2.3\",\n    \"superjson\": \"^2.2.2\",\n    \"tsup-preset-solid\": \"^2.2.0\",\n    \"vite-plugin-solid\": \"^2.11.6\"\n  }\n}\n"
  },
  {
    "path": "packages/query-devtools/src/Devtools.tsx",
    "content": "import {\n  For,\n  Show,\n  batch,\n  createEffect,\n  createMemo,\n  createSignal,\n  on,\n  onCleanup,\n  onMount,\n} from 'solid-js'\nimport { rankItem } from '@tanstack/match-sorter-utils'\nimport * as goober from 'goober'\nimport { clsx as cx } from 'clsx'\nimport { TransitionGroup } from 'solid-transition-group'\nimport { Key } from '@solid-primitives/keyed'\nimport { createResizeObserver } from '@solid-primitives/resize-observer'\nimport { DropdownMenu, RadioGroup } from '@kobalte/core'\nimport { Portal } from 'solid-js/web'\nimport { tokens } from './theme'\nimport {\n  convertRemToPixels,\n  displayValue,\n  getMutationStatusColor,\n  getQueryStatusColor,\n  getQueryStatusColorByLabel,\n  getQueryStatusLabel,\n  getSidedProp,\n  mutationSortFns,\n  sortFns,\n} from './utils'\nimport {\n  ArrowDown,\n  ArrowLeft,\n  ArrowRight,\n  ArrowUp,\n  CheckCircle,\n  ChevronDown,\n  LoadingCircle,\n  Monitor,\n  Moon,\n  Offline,\n  PauseCircle,\n  PiPIcon,\n  Search,\n  Settings,\n  Sun,\n  TanstackLogo,\n  Trash,\n  Wifi,\n  XCircle,\n} from './icons'\nimport Explorer from './Explorer'\nimport { usePiPWindow, useQueryDevtoolsContext, useTheme } from './contexts'\nimport {\n  BUTTON_POSITION,\n  DEFAULT_HEIGHT,\n  DEFAULT_MUTATION_SORT_FN_NAME,\n  DEFAULT_SORT_FN_NAME,\n  DEFAULT_SORT_ORDER,\n  DEFAULT_WIDTH,\n  INITIAL_IS_OPEN,\n  POSITION,\n  firstBreakpoint,\n  secondBreakpoint,\n  thirdBreakpoint,\n} from './constants'\nimport type {\n  DevtoolsErrorType,\n  DevtoolsPosition,\n  QueryDevtoolsProps,\n} from './contexts'\nimport type {\n  Mutation,\n  MutationCache,\n  Query,\n  QueryCache,\n  QueryCacheNotifyEvent,\n} from '@tanstack/query-core'\nimport type { StorageObject, StorageSetter } from '@solid-primitives/storage'\nimport type { Accessor, Component, JSX, Setter } from 'solid-js'\n\ninterface DevtoolsPanelProps {\n  localStore: StorageObject<string>\n  setLocalStore: StorageSetter<string, unknown>\n}\n\ninterface ContentViewProps {\n  localStore: StorageObject<string>\n  setLocalStore: StorageSetter<string, unknown>\n  showPanelViewOnly?: boolean\n  onClose?: () => unknown\n}\n\ninterface QueryStatusProps {\n  label: string\n  color: 'green' | 'yellow' | 'gray' | 'blue' | 'purple' | 'red'\n  count: number\n}\n\nconst [selectedQueryHash, setSelectedQueryHash] = createSignal<string | null>(\n  null,\n)\nconst [selectedMutationId, setSelectedMutationId] = createSignal<number | null>(\n  null,\n)\nconst [panelWidth, setPanelWidth] = createSignal(0)\nconst [offline, setOffline] = createSignal(false)\n\nexport type DevtoolsComponentType = Component<QueryDevtoolsProps> & {\n  shadowDOMTarget?: ShadowRoot\n}\n\nexport const Devtools: Component<DevtoolsPanelProps> = (props) => {\n  const theme = useTheme()\n  const css = useQueryDevtoolsContext().shadowDOMTarget\n    ? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })\n    : goober.css\n  const styles = createMemo(() => {\n    return theme() === 'dark' ? darkStyles(css) : lightStyles(css)\n  })\n  const onlineManager = createMemo(\n    () => useQueryDevtoolsContext().onlineManager,\n  )\n  onMount(() => {\n    const unsubscribe = onlineManager().subscribe((online) => {\n      setOffline(!online)\n    })\n\n    onCleanup(() => {\n      unsubscribe()\n    })\n  })\n\n  const pip = usePiPWindow()\n\n  const buttonPosition = createMemo(() => {\n    return useQueryDevtoolsContext().buttonPosition || BUTTON_POSITION\n  })\n\n  const isOpen = createMemo(() => {\n    return props.localStore.open === 'true'\n      ? true\n      : props.localStore.open === 'false'\n        ? false\n        : useQueryDevtoolsContext().initialIsOpen || INITIAL_IS_OPEN\n  })\n\n  const position = createMemo(() => {\n    return (\n      props.localStore.position ||\n      useQueryDevtoolsContext().position ||\n      POSITION\n    )\n  })\n\n  let transitionsContainerRef!: HTMLDivElement\n  createEffect(() => {\n    const root = transitionsContainerRef.parentElement as HTMLElement\n    const height = props.localStore.height || DEFAULT_HEIGHT\n    const width = props.localStore.width || DEFAULT_WIDTH\n    const panelPosition = position()\n    root.style.setProperty(\n      '--tsqd-panel-height',\n      `${panelPosition === 'top' ? '-' : ''}${height}px`,\n    )\n    root.style.setProperty(\n      '--tsqd-panel-width',\n      `${panelPosition === 'left' ? '-' : ''}${width}px`,\n    )\n  })\n\n  // Calculates the inherited font size of the parent and sets it as a CSS variable\n  // All the design tokens are calculated based on this variable\n  onMount(() => {\n    // This is to make sure that the font size is updated when the stylesheet is updated\n    // and the user focuses back on the window\n    const onFocus = () => {\n      const root = transitionsContainerRef.parentElement as HTMLElement\n      const fontSize = getComputedStyle(root).fontSize\n      root.style.setProperty('--tsqd-font-size', fontSize)\n    }\n    onFocus()\n    window.addEventListener('focus', onFocus)\n    onCleanup(() => {\n      window.removeEventListener('focus', onFocus)\n    })\n  })\n\n  const pip_open = createMemo(\n    () => (props.localStore.pip_open ?? 'false') as 'true' | 'false',\n  )\n\n  return (\n    <>\n      <Show when={pip().pipWindow && pip_open() == 'true'}>\n        <Portal mount={pip().pipWindow?.document.body}>\n          <PiPPanel>\n            <ContentView {...props} />\n          </PiPPanel>\n        </Portal>\n      </Show>\n      <div\n        // styles for animating the panel in and out\n        class={cx(\n          css`\n            & .tsqd-panel-transition-exit-active,\n            & .tsqd-panel-transition-enter-active {\n              transition:\n                opacity 0.3s,\n                transform 0.3s;\n            }\n\n            & .tsqd-panel-transition-exit-to,\n            & .tsqd-panel-transition-enter {\n              ${position() === 'top' || position() === 'bottom'\n                ? `transform: translateY(var(--tsqd-panel-height));`\n                : `transform: translateX(var(--tsqd-panel-width));`}\n            }\n\n            & .tsqd-button-transition-exit-active,\n            & .tsqd-button-transition-enter-active {\n              transition:\n                opacity 0.3s,\n                transform 0.3s;\n              opacity: 1;\n            }\n\n            & .tsqd-button-transition-exit-to,\n            & .tsqd-button-transition-enter {\n              transform: ${buttonPosition() === 'relative'\n                ? `none;`\n                : buttonPosition() === 'top-left'\n                  ? `translateX(-72px);`\n                  : buttonPosition() === 'top-right'\n                    ? `translateX(72px);`\n                    : `translateY(72px);`};\n              opacity: 0;\n            }\n          `,\n          'tsqd-transitions-container',\n        )}\n        ref={transitionsContainerRef}\n      >\n        <TransitionGroup name=\"tsqd-panel-transition\">\n          <Show when={isOpen() && !pip().pipWindow && pip_open() == 'false'}>\n            <DraggablePanel\n              localStore={props.localStore}\n              setLocalStore={props.setLocalStore}\n            />\n          </Show>\n        </TransitionGroup>\n        <TransitionGroup name=\"tsqd-button-transition\">\n          <Show when={!isOpen()}>\n            <div\n              class={cx(\n                styles().devtoolsBtn,\n                styles()[`devtoolsBtn-position-${buttonPosition()}`],\n                'tsqd-open-btn-container',\n              )}\n            >\n              <div aria-hidden=\"true\">\n                <TanstackLogo />\n              </div>\n              <button\n                type=\"button\"\n                aria-label=\"Open Tanstack query devtools\"\n                onClick={() => props.setLocalStore('open', 'true')}\n                class=\"tsqd-open-btn\"\n              >\n                <TanstackLogo />\n              </button>\n            </div>\n          </Show>\n        </TransitionGroup>\n      </div>\n    </>\n  )\n}\n\nconst PiPPanel: Component<{\n  children: JSX.Element\n}> = (props) => {\n  const pip = usePiPWindow()\n  const theme = useTheme()\n  const css = useQueryDevtoolsContext().shadowDOMTarget\n    ? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })\n    : goober.css\n  const styles = createMemo(() => {\n    return theme() === 'dark' ? darkStyles(css) : lightStyles(css)\n  })\n\n  const getPanelDynamicStyles = () => {\n    const { colors } = tokens\n    const t = (light: string, dark: string) =>\n      theme() === 'dark' ? dark : light\n    if (panelWidth() < secondBreakpoint) {\n      return css`\n        flex-direction: column;\n        background-color: ${t(colors.gray[300], colors.gray[600])};\n      `\n    }\n    return css`\n      flex-direction: row;\n      background-color: ${t(colors.gray[200], colors.darkGray[900])};\n    `\n  }\n\n  createEffect(() => {\n    const win = pip().pipWindow\n    const resizeCB = () => {\n      if (!win) return\n      setPanelWidth(win.innerWidth)\n    }\n    if (win) {\n      win.addEventListener('resize', resizeCB)\n      resizeCB()\n    }\n\n    onCleanup(() => {\n      if (win) {\n        win.removeEventListener('resize', resizeCB)\n      }\n    })\n  })\n\n  return (\n    <div\n      style={{\n        '--tsqd-font-size': '16px',\n        'max-height': '100vh',\n        height: '100vh',\n        width: '100vw',\n      }}\n      class={cx(\n        styles().panel,\n        getPanelDynamicStyles(),\n        {\n          [css`\n            min-width: min-content;\n          `]: panelWidth() < thirdBreakpoint,\n        },\n        'tsqd-main-panel',\n      )}\n    >\n      {props.children}\n    </div>\n  )\n}\n\nexport const ParentPanel: Component<{\n  children: JSX.Element\n}> = (props) => {\n  const theme = useTheme()\n  const css = useQueryDevtoolsContext().shadowDOMTarget\n    ? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })\n    : goober.css\n  const styles = createMemo(() => {\n    return theme() === 'dark' ? darkStyles(css) : lightStyles(css)\n  })\n\n  let panelRef!: HTMLDivElement\n\n  onMount(() => {\n    createResizeObserver(panelRef, ({ width }, el) => {\n      if (el === panelRef) {\n        setPanelWidth(width)\n      }\n    })\n  })\n\n  const getPanelDynamicStyles = () => {\n    const { colors } = tokens\n    const t = (light: string, dark: string) =>\n      theme() === 'dark' ? dark : light\n    if (panelWidth() < secondBreakpoint) {\n      return css`\n        flex-direction: column;\n        background-color: ${t(colors.gray[300], colors.gray[600])};\n      `\n    }\n    return css`\n      flex-direction: row;\n      background-color: ${t(colors.gray[200], colors.darkGray[900])};\n    `\n  }\n\n  return (\n    <div\n      style={{\n        '--tsqd-font-size': '16px',\n      }}\n      ref={panelRef}\n      class={cx(\n        styles().parentPanel,\n        getPanelDynamicStyles(),\n        {\n          [css`\n            min-width: min-content;\n          `]: panelWidth() < thirdBreakpoint,\n        },\n        'tsqd-main-panel',\n      )}\n    >\n      {props.children}\n    </div>\n  )\n}\n\nconst DraggablePanel: Component<DevtoolsPanelProps> = (props) => {\n  const theme = useTheme()\n  const css = useQueryDevtoolsContext().shadowDOMTarget\n    ? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })\n    : goober.css\n  const styles = createMemo(() => {\n    return theme() === 'dark' ? darkStyles(css) : lightStyles(css)\n  })\n\n  let closeBtnRef!: HTMLButtonElement\n\n  // Focus the close button when the panel opens for screen reader accessibility\n  onMount(() => {\n    closeBtnRef.focus()\n  })\n\n  const [isResizing, setIsResizing] = createSignal(false)\n\n  const position = createMemo(\n    () =>\n      (props.localStore.position ||\n        useQueryDevtoolsContext().position ||\n        POSITION) as DevtoolsPosition,\n  )\n\n  const handleDragStart: JSX.EventHandler<HTMLDivElement, MouseEvent> = (\n    event,\n  ) => {\n    const panelElement = event.currentTarget.parentElement\n    if (!panelElement) return\n    setIsResizing(true)\n    const { height, width } = panelElement.getBoundingClientRect()\n    const startX = event.clientX\n    const startY = event.clientY\n    let newSize = 0\n    const minHeight = convertRemToPixels(3.5)\n    const minWidth = convertRemToPixels(12)\n    const runDrag = (moveEvent: MouseEvent) => {\n      moveEvent.preventDefault()\n\n      if (position() === 'left' || position() === 'right') {\n        const valToAdd =\n          position() === 'right'\n            ? startX - moveEvent.clientX\n            : moveEvent.clientX - startX\n        newSize = Math.round(width + valToAdd)\n        if (newSize < minWidth) {\n          newSize = minWidth\n        }\n        props.setLocalStore('width', String(Math.round(newSize)))\n\n        const newWidth = panelElement.getBoundingClientRect().width\n        // If the panel size didn't decrease, this means we have reached the minimum width\n        // of the panel so we restore the original width in local storage\n        // Restoring the width helps in smooth open/close transitions\n        if (Number(props.localStore.width) < newWidth) {\n          props.setLocalStore('width', String(newWidth))\n        }\n      } else {\n        const valToAdd =\n          position() === 'bottom'\n            ? startY - moveEvent.clientY\n            : moveEvent.clientY - startY\n        newSize = Math.round(height + valToAdd)\n        // If the panel size is less than the minimum height,\n        // we set the size to the minimum height\n        if (newSize < minHeight) {\n          newSize = minHeight\n          setSelectedQueryHash(null)\n        }\n        props.setLocalStore('height', String(Math.round(newSize)))\n      }\n    }\n\n    const unsubscribe = () => {\n      if (isResizing()) {\n        setIsResizing(false)\n      }\n      document.removeEventListener('mousemove', runDrag, false)\n      document.removeEventListener('mouseup', unsubscribe, false)\n    }\n\n    document.addEventListener('mousemove', runDrag, false)\n    document.addEventListener('mouseup', unsubscribe, false)\n  }\n\n  let panelRef!: HTMLDivElement\n\n  onMount(() => {\n    createResizeObserver(panelRef, ({ width }, el) => {\n      if (el === panelRef) {\n        setPanelWidth(width)\n      }\n    })\n  })\n\n  createEffect(() => {\n    const rootContainer = panelRef.parentElement?.parentElement?.parentElement\n    if (!rootContainer) return\n    const currentPosition = (props.localStore.position ||\n      POSITION) as DevtoolsPosition\n    const styleProp = getSidedProp('padding', currentPosition)\n    const isVertical =\n      props.localStore.position === 'left' ||\n      props.localStore.position === 'right'\n    const previousPaddings = (({\n      padding,\n      paddingTop,\n      paddingBottom,\n      paddingLeft,\n      paddingRight,\n    }) => ({\n      padding,\n      paddingTop,\n      paddingBottom,\n      paddingLeft,\n      paddingRight,\n    }))(rootContainer.style)\n\n    rootContainer.style[styleProp] = `${\n      isVertical ? props.localStore.width : props.localStore.height\n    }px`\n\n    onCleanup(() => {\n      Object.entries(previousPaddings).forEach(([property, previousValue]) => {\n        rootContainer.style[property as keyof typeof previousPaddings] =\n          previousValue\n      })\n    })\n  })\n\n  const getPanelDynamicStyles = () => {\n    const { colors } = tokens\n    const t = (light: string, dark: string) =>\n      theme() === 'dark' ? dark : light\n    if (panelWidth() < secondBreakpoint) {\n      return css`\n        flex-direction: column;\n        background-color: ${t(colors.gray[300], colors.gray[600])};\n      `\n    }\n    return css`\n      flex-direction: row;\n      background-color: ${t(colors.gray[200], colors.darkGray[900])};\n    `\n  }\n\n  return (\n    <aside\n      // Some context for styles here\n      // background-color - Changes to a lighter color create a harder contrast\n      // between the queries and query detail panel\n      // -\n      // min-width - When the panel is in the left or right position, the panel\n      // width is set to min-content to allow the panel to shrink to the lowest possible width\n      class={cx(\n        styles().panel,\n        styles()[`panel-position-${position()}`],\n        getPanelDynamicStyles(),\n        {\n          [css`\n            min-width: min-content;\n          `]:\n            panelWidth() < thirdBreakpoint &&\n            (position() === 'right' || position() === 'left'),\n        },\n        'tsqd-main-panel',\n      )}\n      style={{\n        height:\n          position() === 'bottom' || position() === 'top'\n            ? `${props.localStore.height || DEFAULT_HEIGHT}px`\n            : 'auto',\n        width:\n          position() === 'right' || position() === 'left'\n            ? `${props.localStore.width || DEFAULT_WIDTH}px`\n            : 'auto',\n      }}\n      ref={panelRef}\n      aria-label=\"Tanstack query devtools\"\n    >\n      <div\n        role=\"separator\"\n        aria-orientation={\n          position() === 'top' || position() === 'bottom'\n            ? 'horizontal'\n            : 'vertical'\n        }\n        aria-label=\"Resize devtools panel\"\n        aria-valuemin={\n          position() === 'top' || position() === 'bottom'\n            ? convertRemToPixels(3.5)\n            : convertRemToPixels(12)\n        }\n        aria-valuenow={\n          position() === 'top' || position() === 'bottom'\n            ? Number(props.localStore.height || DEFAULT_HEIGHT)\n            : Number(props.localStore.width || DEFAULT_WIDTH)\n        }\n        tabindex=\"0\"\n        class={cx(\n          styles().dragHandle,\n          styles()[`dragHandle-position-${position()}`],\n          'tsqd-drag-handle',\n        )}\n        onMouseDown={handleDragStart}\n        onKeyDown={(e) => {\n          const step = 10\n          const minHeight = convertRemToPixels(3.5)\n          const minWidth = convertRemToPixels(12)\n          if (position() === 'top' || position() === 'bottom') {\n            if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n              e.preventDefault()\n              const currentHeight = Number(\n                props.localStore.height || DEFAULT_HEIGHT,\n              )\n              const delta =\n                position() === 'bottom'\n                  ? e.key === 'ArrowUp'\n                    ? step\n                    : -step\n                  : e.key === 'ArrowDown'\n                    ? step\n                    : -step\n              const newHeight = Math.max(minHeight, currentHeight + delta)\n              props.setLocalStore('height', String(newHeight))\n            }\n          } else {\n            if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {\n              e.preventDefault()\n              const currentWidth = Number(\n                props.localStore.width || DEFAULT_WIDTH,\n              )\n              const delta =\n                position() === 'right'\n                  ? e.key === 'ArrowLeft'\n                    ? step\n                    : -step\n                  : e.key === 'ArrowRight'\n                    ? step\n                    : -step\n              const newWidth = Math.max(minWidth, currentWidth + delta)\n              props.setLocalStore('width', String(newWidth))\n            }\n          }\n        }}\n      ></div>\n      <button\n        ref={closeBtnRef}\n        aria-label=\"Close tanstack query devtools\"\n        class={cx(\n          styles().closeBtn,\n          styles()[`closeBtn-position-${position()}`],\n          'tsqd-minimize-btn',\n        )}\n        onClick={() => props.setLocalStore('open', 'false')}\n      >\n        <ChevronDown />\n      </button>\n      <ContentView {...props} />\n    </aside>\n  )\n}\n\nexport const ContentView: Component<ContentViewProps> = (props) => {\n  setupQueryCacheSubscription()\n  setupMutationCacheSubscription()\n  let containerRef!: HTMLDivElement\n  const theme = useTheme()\n  const css = useQueryDevtoolsContext().shadowDOMTarget\n    ? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })\n    : goober.css\n  const styles = createMemo(() => {\n    return theme() === 'dark' ? darkStyles(css) : lightStyles(css)\n  })\n\n  const pip = usePiPWindow()\n\n  const [selectedView, setSelectedView] = createSignal<'queries' | 'mutations'>(\n    'queries',\n  )\n\n  const sort = createMemo(() => props.localStore.sort || DEFAULT_SORT_FN_NAME)\n  const sortOrder = createMemo(\n    () => Number(props.localStore.sortOrder) || DEFAULT_SORT_ORDER,\n  ) as () => 1 | -1\n\n  const mutationSort = createMemo(\n    () => props.localStore.mutationSort || DEFAULT_MUTATION_SORT_FN_NAME,\n  )\n  const mutationSortOrder = createMemo(\n    () => Number(props.localStore.mutationSortOrder) || DEFAULT_SORT_ORDER,\n  ) as () => 1 | -1\n\n  const sortFn = createMemo(() => sortFns[sort() as string])\n  const mutationSortFn = createMemo(\n    () => mutationSortFns[mutationSort() as string],\n  )\n\n  const onlineManager = createMemo(\n    () => useQueryDevtoolsContext().onlineManager,\n  )\n\n  const query_cache = createMemo(() => {\n    return useQueryDevtoolsContext().client.getQueryCache()\n  })\n\n  const mutation_cache = createMemo(() => {\n    return useQueryDevtoolsContext().client.getMutationCache()\n  })\n\n  const queryCount = createSubscribeToQueryCacheBatcher((queryCache) => {\n    return queryCache().getAll().length\n  }, false)\n\n  const queries = createMemo(\n    on(\n      () => [\n        queryCount(),\n        props.localStore.filter,\n        sort(),\n        sortOrder(),\n        props.localStore.hideDisabledQueries,\n      ],\n      () => {\n        const curr = query_cache().getAll()\n\n        let filtered = props.localStore.filter\n          ? curr.filter(\n              (item) =>\n                rankItem(item.queryHash, props.localStore.filter || '').passed,\n            )\n          : [...curr]\n\n        // Filter out disabled queries if hideDisabledQueries is enabled\n        if (props.localStore.hideDisabledQueries === 'true') {\n          filtered = filtered.filter((item) => !item.isDisabled())\n        }\n\n        const sorted = sortFn()\n          ? filtered.sort((a, b) => sortFn()!(a, b) * sortOrder())\n          : filtered\n        return sorted\n      },\n    ),\n  )\n\n  const mutationCount = createSubscribeToMutationCacheBatcher(\n    (mutationCache) => {\n      return mutationCache().getAll().length\n    },\n    false,\n  )\n\n  const mutations = createMemo(\n    on(\n      () => [\n        mutationCount(),\n        props.localStore.mutationFilter,\n        mutationSort(),\n        mutationSortOrder(),\n      ],\n      () => {\n        const curr = mutation_cache().getAll()\n\n        const filtered = props.localStore.mutationFilter\n          ? curr.filter((item) => {\n              const value = `${\n                item.options.mutationKey\n                  ? JSON.stringify(item.options.mutationKey) + ' - '\n                  : ''\n              }${new Date(item.state.submittedAt).toLocaleString()}`\n              return rankItem(value, props.localStore.mutationFilter || '')\n                .passed\n            })\n          : [...curr]\n\n        const sorted = mutationSortFn()\n          ? filtered.sort(\n              (a, b) => mutationSortFn()!(a, b) * mutationSortOrder(),\n            )\n          : filtered\n        return sorted\n      },\n    ),\n  )\n\n  const setDevtoolsPosition = (pos: DevtoolsPosition) => {\n    props.setLocalStore('position', pos)\n  }\n\n  // Sets the Font Size variable on portal menu elements since they will be outside\n  // the main panel container\n  const setComputedVariables = (el: HTMLDivElement) => {\n    const computedStyle = getComputedStyle(containerRef)\n    const variable = computedStyle.getPropertyValue('--tsqd-font-size')\n    el.style.setProperty('--tsqd-font-size', variable)\n  }\n  return (\n    <>\n      <div\n        // When the panels are stacked we use the height style\n        // to divide the panels into two equal parts\n        class={cx(\n          styles().queriesContainer,\n          panelWidth() < secondBreakpoint &&\n            (selectedQueryHash() || selectedMutationId()) &&\n            css`\n              height: 50%;\n              max-height: 50%;\n            `,\n          panelWidth() < secondBreakpoint &&\n            !(selectedQueryHash() || selectedMutationId()) &&\n            css`\n              height: 100%;\n              max-height: 100%;\n            `,\n          'tsqd-queries-container',\n        )}\n        ref={containerRef}\n      >\n        <div class={cx(styles().row, 'tsqd-header')}>\n          <div class={styles().logoAndToggleContainer}>\n            <button\n              class={cx(styles().logo, 'tsqd-text-logo-container')}\n              onClick={() => {\n                if (!pip().pipWindow && !props.showPanelViewOnly) {\n                  props.setLocalStore('open', 'false')\n                  return\n                }\n                if (props.onClose) {\n                  props.onClose()\n                }\n              }}\n              aria-label=\"Close Tanstack query devtools\"\n            >\n              <span\n                class={cx(styles().tanstackLogo, 'tsqd-text-logo-tanstack')}\n              >\n                TANSTACK\n              </span>\n              <span\n                class={cx(\n                  styles().queryFlavorLogo,\n                  'tsqd-text-logo-query-flavor',\n                )}\n              >\n                {useQueryDevtoolsContext().queryFlavor} v\n                {useQueryDevtoolsContext().version}\n              </span>\n            </button>\n            <RadioGroup.Root\n              class={cx(styles().viewToggle)}\n              value={selectedView()}\n              aria-label=\"Toggle between queries and mutations view\"\n              onChange={(value) => {\n                setSelectedView(value as 'queries' | 'mutations')\n                setSelectedQueryHash(null)\n                setSelectedMutationId(null)\n              }}\n            >\n              <RadioGroup.Item value=\"queries\" class=\"tsqd-radio-toggle\">\n                <RadioGroup.ItemInput />\n                <RadioGroup.ItemControl>\n                  <RadioGroup.ItemIndicator />\n                </RadioGroup.ItemControl>\n                <RadioGroup.ItemLabel title=\"Toggle Queries View\">\n                  Queries\n                </RadioGroup.ItemLabel>\n              </RadioGroup.Item>\n              <RadioGroup.Item value=\"mutations\" class=\"tsqd-radio-toggle\">\n                <RadioGroup.ItemInput />\n                <RadioGroup.ItemControl>\n                  <RadioGroup.ItemIndicator />\n                </RadioGroup.ItemControl>\n                <RadioGroup.ItemLabel title=\"Toggle Mutations View\">\n                  Mutations\n                </RadioGroup.ItemLabel>\n              </RadioGroup.Item>\n            </RadioGroup.Root>\n          </div>\n\n          <Show when={selectedView() === 'queries'}>\n            <QueryStatusCount />\n          </Show>\n          <Show when={selectedView() === 'mutations'}>\n            <MutationStatusCount />\n          </Show>\n        </div>\n        <div class={cx(styles().row, 'tsqd-filters-actions-container')}>\n          <div class={cx(styles().filtersContainer, 'tsqd-filters-container')}>\n            <div\n              class={cx(\n                styles().filterInput,\n                'tsqd-query-filter-textfield-container',\n              )}\n            >\n              <Search />\n              <input\n                aria-label=\"Filter queries by query key\"\n                type=\"text\"\n                placeholder=\"Filter\"\n                onInput={(e) => {\n                  if (selectedView() === 'queries') {\n                    props.setLocalStore('filter', e.currentTarget.value)\n                  } else {\n                    props.setLocalStore('mutationFilter', e.currentTarget.value)\n                  }\n                }}\n                class={cx('tsqd-query-filter-textfield')}\n                name=\"tsqd-query-filter-input\"\n                value={\n                  selectedView() === 'queries'\n                    ? props.localStore.filter || ''\n                    : props.localStore.mutationFilter || ''\n                }\n              />\n            </div>\n            <div\n              class={cx(\n                styles().filterSelect,\n                'tsqd-query-filter-sort-container',\n              )}\n            >\n              <Show when={selectedView() === 'queries'}>\n                <select\n                  value={sort()}\n                  name=\"tsqd-queries-filter-sort\"\n                  aria-label=\"Sort queries by\"\n                  onChange={(e) => {\n                    props.setLocalStore('sort', e.currentTarget.value)\n                  }}\n                >\n                  {Object.keys(sortFns).map((key) => (\n                    <option value={key}>Sort by {key}</option>\n                  ))}\n                </select>\n              </Show>\n              <Show when={selectedView() === 'mutations'}>\n                <select\n                  value={mutationSort()}\n                  name=\"tsqd-mutations-filter-sort\"\n                  aria-label=\"Sort mutations by\"\n                  onChange={(e) => {\n                    props.setLocalStore('mutationSort', e.currentTarget.value)\n                  }}\n                >\n                  {Object.keys(mutationSortFns).map((key) => (\n                    <option value={key}>Sort by {key}</option>\n                  ))}\n                </select>\n              </Show>\n              <ChevronDown />\n            </div>\n            <button\n              onClick={() => {\n                if (selectedView() === 'queries') {\n                  props.setLocalStore('sortOrder', String(sortOrder() * -1))\n                } else {\n                  props.setLocalStore(\n                    'mutationSortOrder',\n                    String(mutationSortOrder() * -1),\n                  )\n                }\n              }}\n              aria-label={`Sort order ${\n                (selectedView() === 'queries'\n                  ? sortOrder()\n                  : mutationSortOrder()) === -1\n                  ? 'descending'\n                  : 'ascending'\n              }`}\n              aria-pressed={\n                (selectedView() === 'queries'\n                  ? sortOrder()\n                  : mutationSortOrder()) === -1\n              }\n              class=\"tsqd-query-filter-sort-order-btn\"\n            >\n              <Show\n                when={\n                  (selectedView() === 'queries'\n                    ? sortOrder()\n                    : mutationSortOrder()) === 1\n                }\n              >\n                <span>Asc</span>\n                <ArrowUp />\n              </Show>\n              <Show\n                when={\n                  (selectedView() === 'queries'\n                    ? sortOrder()\n                    : mutationSortOrder()) === -1\n                }\n              >\n                <span>Desc</span>\n                <ArrowDown />\n              </Show>\n            </button>\n          </div>\n\n          <div class={cx(styles().actionsContainer, 'tsqd-actions-container')}>\n            <button\n              onClick={() => {\n                if (selectedView() === 'queries') {\n                  sendDevToolsEvent({ type: 'CLEAR_QUERY_CACHE' })\n                  query_cache().clear()\n                } else {\n                  sendDevToolsEvent({ type: 'CLEAR_MUTATION_CACHE' })\n                  mutation_cache().clear()\n                }\n              }}\n              class={cx(\n                styles().actionsBtn,\n                'tsqd-actions-btn',\n                'tsqd-action-clear-cache',\n              )}\n              aria-label=\"Clear query cache\"\n              title={`Clear ${selectedView()} cache`}\n            >\n              <Trash />\n            </button>\n            <button\n              onClick={() => {\n                onlineManager().setOnline(!onlineManager().isOnline())\n              }}\n              class={cx(\n                styles().actionsBtn,\n                offline() && styles().actionsBtnOffline,\n                'tsqd-actions-btn',\n                'tsqd-action-mock-offline-behavior',\n              )}\n              aria-label={`${\n                offline()\n                  ? 'Unset offline mocking behavior'\n                  : 'Mock offline behavior'\n              }`}\n              aria-pressed={offline()}\n              title={`${\n                offline()\n                  ? 'Unset offline mocking behavior'\n                  : 'Mock offline behavior'\n              }`}\n            >\n              {offline() ? <Offline /> : <Wifi />}\n            </button>\n            <Show when={!pip().pipWindow && !pip().disabled}>\n              <button\n                onClick={() => {\n                  pip().requestPipWindow(\n                    Number(window.innerWidth),\n                    Number(props.localStore.height ?? 500),\n                  )\n                }}\n                class={cx(\n                  styles().actionsBtn,\n                  'tsqd-actions-btn',\n                  'tsqd-action-open-pip',\n                )}\n                aria-label=\"Open in picture-in-picture mode\"\n                title=\"Open in picture-in-picture mode\"\n              >\n                <PiPIcon />\n              </button>\n            </Show>\n\n            <DropdownMenu.Root gutter={4}>\n              <DropdownMenu.Trigger\n                class={cx(\n                  styles().actionsBtn,\n                  'tsqd-actions-btn',\n                  'tsqd-action-settings',\n                )}\n                aria-label=\"Open settings menu\"\n                title=\"Open settings menu\"\n              >\n                <Settings />\n              </DropdownMenu.Trigger>\n              <DropdownMenu.Portal\n                ref={(el) => setComputedVariables(el as HTMLDivElement)}\n                mount={\n                  pip().pipWindow\n                    ? pip().pipWindow!.document.body\n                    : document.body\n                }\n              >\n                <DropdownMenu.Content\n                  class={cx(styles().settingsMenu, 'tsqd-settings-menu')}\n                >\n                  <div\n                    class={cx(\n                      styles().settingsMenuHeader,\n                      'tsqd-settings-menu-header',\n                    )}\n                  >\n                    Settings\n                  </div>\n                  <Show when={!props.showPanelViewOnly}>\n                    <DropdownMenu.Sub overlap gutter={8} shift={-4}>\n                      <DropdownMenu.SubTrigger\n                        class={cx(\n                          styles().settingsSubTrigger,\n                          'tsqd-settings-menu-sub-trigger',\n                          'tsqd-settings-menu-sub-trigger-position',\n                        )}\n                      >\n                        <span>Position</span>\n                        <ChevronDown />\n                      </DropdownMenu.SubTrigger>\n                      <DropdownMenu.Portal\n                        ref={(el) => setComputedVariables(el as HTMLDivElement)}\n                        mount={\n                          pip().pipWindow\n                            ? pip().pipWindow!.document.body\n                            : document.body\n                        }\n                      >\n                        <DropdownMenu.SubContent\n                          class={cx(\n                            styles().settingsMenu,\n                            'tsqd-settings-submenu',\n                          )}\n                        >\n                          <DropdownMenu.RadioGroup\n                            aria-label=\"Position settings\"\n                            value={props.localStore.position}\n                            onChange={(value) =>\n                              setDevtoolsPosition(value as DevtoolsPosition)\n                            }\n                          >\n                            <DropdownMenu.RadioItem\n                              value=\"top\"\n                              class={cx(\n                                styles().settingsSubButton,\n                                'tsqd-settings-menu-position-btn',\n                                'tsqd-settings-menu-position-btn-top',\n                              )}\n                            >\n                              <span>Top</span>\n                              <ArrowUp />\n                            </DropdownMenu.RadioItem>\n                            <DropdownMenu.RadioItem\n                              value=\"bottom\"\n                              class={cx(\n                                styles().settingsSubButton,\n                                'tsqd-settings-menu-position-btn',\n                                'tsqd-settings-menu-position-btn-bottom',\n                              )}\n                            >\n                              <span>Bottom</span>\n                              <ArrowDown />\n                            </DropdownMenu.RadioItem>\n                            <DropdownMenu.RadioItem\n                              value=\"left\"\n                              class={cx(\n                                styles().settingsSubButton,\n                                'tsqd-settings-menu-position-btn',\n                                'tsqd-settings-menu-position-btn-left',\n                              )}\n                            >\n                              <span>Left</span>\n                              <ArrowLeft />\n                            </DropdownMenu.RadioItem>\n                            <DropdownMenu.RadioItem\n                              value=\"right\"\n                              class={cx(\n                                styles().settingsSubButton,\n                                'tsqd-settings-menu-position-btn',\n                                'tsqd-settings-menu-position-btn-right',\n                              )}\n                            >\n                              <span>Right</span>\n                              <ArrowRight />\n                            </DropdownMenu.RadioItem>\n                          </DropdownMenu.RadioGroup>\n                        </DropdownMenu.SubContent>\n                      </DropdownMenu.Portal>\n                    </DropdownMenu.Sub>\n                  </Show>\n                  <DropdownMenu.Sub overlap gutter={8} shift={-4}>\n                    <DropdownMenu.SubTrigger\n                      class={cx(\n                        styles().settingsSubTrigger,\n                        'tsqd-settings-menu-sub-trigger',\n                        'tsqd-settings-menu-sub-trigger-position',\n                      )}\n                    >\n                      <span>Theme</span>\n                      <ChevronDown />\n                    </DropdownMenu.SubTrigger>\n                    <DropdownMenu.Portal\n                      ref={(el) => setComputedVariables(el as HTMLDivElement)}\n                      mount={\n                        pip().pipWindow\n                          ? pip().pipWindow!.document.body\n                          : document.body\n                      }\n                    >\n                      <DropdownMenu.SubContent\n                        class={cx(\n                          styles().settingsMenu,\n                          'tsqd-settings-submenu',\n                        )}\n                      >\n                        <DropdownMenu.RadioGroup\n                          value={props.localStore.theme_preference}\n                          onChange={(value) => {\n                            props.setLocalStore('theme_preference', value)\n                          }}\n                          aria-label=\"Theme preference\"\n                        >\n                          <DropdownMenu.RadioItem\n                            value=\"light\"\n                            class={cx(\n                              styles().settingsSubButton,\n                              'tsqd-settings-menu-position-btn',\n                              'tsqd-settings-menu-position-btn-top',\n                            )}\n                          >\n                            <span>Light</span>\n                            <Sun />\n                          </DropdownMenu.RadioItem>\n                          <DropdownMenu.RadioItem\n                            value=\"dark\"\n                            class={cx(\n                              styles().settingsSubButton,\n                              'tsqd-settings-menu-position-btn',\n                              'tsqd-settings-menu-position-btn-bottom',\n                            )}\n                          >\n                            <span>Dark</span>\n                            <Moon />\n                          </DropdownMenu.RadioItem>\n                          <DropdownMenu.RadioItem\n                            value=\"system\"\n                            class={cx(\n                              styles().settingsSubButton,\n                              'tsqd-settings-menu-position-btn',\n                              'tsqd-settings-menu-position-btn-left',\n                            )}\n                          >\n                            <span>System</span>\n                            <Monitor />\n                          </DropdownMenu.RadioItem>\n                        </DropdownMenu.RadioGroup>\n                      </DropdownMenu.SubContent>\n                    </DropdownMenu.Portal>\n                  </DropdownMenu.Sub>\n                  <DropdownMenu.Sub overlap gutter={8} shift={-4}>\n                    <DropdownMenu.SubTrigger\n                      class={cx(\n                        styles().settingsSubTrigger,\n                        'tsqd-settings-menu-sub-trigger',\n                        'tsqd-settings-menu-sub-trigger-disabled-queries',\n                      )}\n                    >\n                      <span>Disabled Queries</span>\n                      <ChevronDown />\n                    </DropdownMenu.SubTrigger>\n                    <DropdownMenu.Portal\n                      ref={(el) => setComputedVariables(el as HTMLDivElement)}\n                      mount={\n                        pip().pipWindow\n                          ? pip().pipWindow!.document.body\n                          : document.body\n                      }\n                    >\n                      <DropdownMenu.SubContent\n                        class={cx(\n                          styles().settingsMenu,\n                          'tsqd-settings-submenu',\n                        )}\n                      >\n                        <DropdownMenu.RadioGroup\n                          value={props.localStore.hideDisabledQueries}\n                          aria-label=\"Hide disabled queries setting\"\n                          onChange={(value) =>\n                            props.setLocalStore('hideDisabledQueries', value)\n                          }\n                        >\n                          <DropdownMenu.RadioItem\n                            value=\"false\"\n                            class={cx(\n                              styles().settingsSubButton,\n                              'tsqd-settings-menu-position-btn',\n                              'tsqd-settings-menu-position-btn-show',\n                            )}\n                          >\n                            <span>Show</span>\n                            <Show\n                              when={\n                                props.localStore.hideDisabledQueries !== 'true'\n                              }\n                            >\n                              <CheckCircle />\n                            </Show>\n                          </DropdownMenu.RadioItem>\n                          <DropdownMenu.RadioItem\n                            value=\"true\"\n                            class={cx(\n                              styles().settingsSubButton,\n                              'tsqd-settings-menu-position-btn',\n                              'tsqd-settings-menu-position-btn-hide',\n                            )}\n                          >\n                            <span>Hide</span>\n                            <Show\n                              when={\n                                props.localStore.hideDisabledQueries === 'true'\n                              }\n                            >\n                              <CheckCircle />\n                            </Show>\n                          </DropdownMenu.RadioItem>\n                        </DropdownMenu.RadioGroup>\n                      </DropdownMenu.SubContent>\n                    </DropdownMenu.Portal>\n                  </DropdownMenu.Sub>\n                </DropdownMenu.Content>\n              </DropdownMenu.Portal>\n            </DropdownMenu.Root>\n          </div>\n        </div>\n        <Show when={selectedView() === 'queries'}>\n          <div\n            class={cx(\n              styles().overflowQueryContainer,\n              'tsqd-queries-overflow-container',\n            )}\n          >\n            <div class=\"tsqd-queries-container\">\n              <Key by={(q) => q.queryHash} each={queries()}>\n                {(query) => <QueryRow query={query()} />}\n              </Key>\n            </div>\n          </div>\n        </Show>\n        <Show when={selectedView() === 'mutations'}>\n          <div\n            class={cx(\n              styles().overflowQueryContainer,\n              'tsqd-mutations-overflow-container',\n            )}\n          >\n            <div class=\"tsqd-mutations-container\">\n              <Key by={(m) => m.mutationId} each={mutations()}>\n                {(mutation) => <MutationRow mutation={mutation()} />}\n              </Key>\n            </div>\n          </div>\n        </Show>\n      </div>\n      <Show when={selectedView() === 'queries' && selectedQueryHash()}>\n        <QueryDetails />\n      </Show>\n\n      <Show when={selectedView() === 'mutations' && selectedMutationId()}>\n        <MutationDetails />\n      </Show>\n    </>\n  )\n}\n\nconst QueryRow: Component<{ query: Query }> = (props) => {\n  const theme = useTheme()\n  const css = useQueryDevtoolsContext().shadowDOMTarget\n    ? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })\n    : goober.css\n  const styles = createMemo(() => {\n    return theme() === 'dark' ? darkStyles(css) : lightStyles(css)\n  })\n\n  const { colors, alpha } = tokens\n  const t = (light: string, dark: string) => (theme() === 'dark' ? dark : light)\n\n  const queryState = createSubscribeToQueryCacheBatcher(\n    (queryCache) =>\n      queryCache().find({\n        queryKey: props.query.queryKey,\n      })?.state,\n    true,\n    (e) => e.query.queryHash === props.query.queryHash,\n  )\n\n  const isDisabled = createSubscribeToQueryCacheBatcher(\n    (queryCache) =>\n      queryCache()\n        .find({\n          queryKey: props.query.queryKey,\n        })\n        ?.isDisabled() ?? false,\n    true,\n    (e) => e.query.queryHash === props.query.queryHash,\n  )\n\n  const isStatic = createSubscribeToQueryCacheBatcher(\n    (queryCache) =>\n      queryCache()\n        .find({\n          queryKey: props.query.queryKey,\n        })\n        ?.isStatic() ?? false,\n    true,\n    (e) => e.query.queryHash === props.query.queryHash,\n  )\n\n  const isStale = createSubscribeToQueryCacheBatcher(\n    (queryCache) =>\n      queryCache()\n        .find({\n          queryKey: props.query.queryKey,\n        })\n        ?.isStale() ?? false,\n    true,\n    (e) => e.query.queryHash === props.query.queryHash,\n  )\n\n  const observers = createSubscribeToQueryCacheBatcher(\n    (queryCache) =>\n      queryCache()\n        .find({\n          queryKey: props.query.queryKey,\n        })\n        ?.getObserversCount() ?? 0,\n    true,\n    (e) => e.query.queryHash === props.query.queryHash,\n  )\n\n  const color = createMemo(() =>\n    getQueryStatusColor({\n      queryState: queryState()!,\n      observerCount: observers(),\n      isStale: isStale(),\n    }),\n  )\n\n  const getObserverCountColorStyles = () => {\n    if (color() === 'gray') {\n      return css`\n        background-color: ${t(colors[color()][200], colors[color()][700])};\n        color: ${t(colors[color()][700], colors[color()][300])};\n      `\n    }\n\n    return css`\n      background-color: ${t(\n        colors[color()][200] + alpha[80],\n        colors[color()][900],\n      )};\n      color: ${t(colors[color()][800], colors[color()][300])};\n    `\n  }\n\n  return (\n    <Show when={queryState()}>\n      <button\n        onClick={() =>\n          setSelectedQueryHash(\n            props.query.queryHash === selectedQueryHash()\n              ? null\n              : props.query.queryHash,\n          )\n        }\n        class={cx(\n          styles().queryRow,\n          selectedQueryHash() === props.query.queryHash &&\n            styles().selectedQueryRow,\n          'tsqd-query-row',\n        )}\n        aria-label={`Query key ${props.query.queryHash}${isDisabled() ? ', disabled' : ''}${isStatic() ? ', static' : ''}`}\n      >\n        <div\n          class={cx(getObserverCountColorStyles(), 'tsqd-query-observer-count')}\n        >\n          {observers()}\n        </div>\n        <code class=\"tsqd-query-hash\">{props.query.queryHash}</code>\n        <Show when={isDisabled()}>\n          <div class=\"tsqd-query-disabled-indicator\" aria-hidden=\"true\">\n            disabled\n          </div>\n        </Show>\n        <Show when={isStatic()}>\n          <div class=\"tsqd-query-static-indicator\" aria-hidden=\"true\">\n            static\n          </div>\n        </Show>\n      </button>\n    </Show>\n  )\n}\n\nconst MutationRow: Component<{ mutation: Mutation }> = (props) => {\n  const theme = useTheme()\n  const css = useQueryDevtoolsContext().shadowDOMTarget\n    ? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })\n    : goober.css\n  const styles = createMemo(() => {\n    return theme() === 'dark' ? darkStyles(css) : lightStyles(css)\n  })\n\n  const { colors, alpha } = tokens\n  const t = (light: string, dark: string) => (theme() === 'dark' ? dark : light)\n\n  const mutationState = createSubscribeToMutationCacheBatcher(\n    (mutationCache) => {\n      const mutations = mutationCache().getAll()\n      const mutation = mutations.find(\n        (m) => m.mutationId === props.mutation.mutationId,\n      )\n      return mutation?.state\n    },\n  )\n\n  const isPaused = createSubscribeToMutationCacheBatcher((mutationCache) => {\n    const mutations = mutationCache().getAll()\n    const mutation = mutations.find(\n      (m) => m.mutationId === props.mutation.mutationId,\n    )\n    if (!mutation) return false\n    return mutation.state.isPaused\n  })\n\n  const status = createSubscribeToMutationCacheBatcher((mutationCache) => {\n    const mutations = mutationCache().getAll()\n    const mutation = mutations.find(\n      (m) => m.mutationId === props.mutation.mutationId,\n    )\n    if (!mutation) return 'idle'\n    return mutation.state.status\n  })\n\n  const color = createMemo(() =>\n    getMutationStatusColor({\n      isPaused: isPaused(),\n      status: status(),\n    }),\n  )\n\n  const getObserverCountColorStyles = () => {\n    if (color() === 'gray') {\n      return css`\n        background-color: ${t(colors[color()][200], colors[color()][700])};\n        color: ${t(colors[color()][700], colors[color()][300])};\n      `\n    }\n\n    return css`\n      background-color: ${t(\n        colors[color()][200] + alpha[80],\n        colors[color()][900],\n      )};\n      color: ${t(colors[color()][800], colors[color()][300])};\n    `\n  }\n\n  return (\n    <Show when={mutationState()}>\n      <button\n        onClick={() => {\n          setSelectedMutationId(\n            props.mutation.mutationId === selectedMutationId()\n              ? null\n              : props.mutation.mutationId,\n          )\n        }}\n        class={cx(\n          styles().queryRow,\n          selectedMutationId() === props.mutation.mutationId &&\n            styles().selectedQueryRow,\n          'tsqd-query-row',\n        )}\n        aria-label={`Mutation submitted at ${new Date(\n          props.mutation.state.submittedAt,\n        ).toLocaleString()}`}\n      >\n        <div\n          class={cx(getObserverCountColorStyles(), 'tsqd-query-observer-count')}\n        >\n          <Show when={color() === 'purple'}>\n            <PauseCircle />\n          </Show>\n          <Show when={color() === 'green'}>\n            <CheckCircle />\n          </Show>\n          <Show when={color() === 'red'}>\n            <XCircle />\n          </Show>\n          <Show when={color() === 'yellow'}>\n            <LoadingCircle />\n          </Show>\n        </div>\n        <code class=\"tsqd-query-hash\">\n          <Show when={props.mutation.options.mutationKey}>\n            {JSON.stringify(props.mutation.options.mutationKey)} -{' '}\n          </Show>\n          {new Date(props.mutation.state.submittedAt).toLocaleString()}\n        </code>\n      </button>\n    </Show>\n  )\n}\n\nconst QueryStatusCount: Component = () => {\n  const stale = createSubscribeToQueryCacheBatcher(\n    (queryCache) =>\n      queryCache()\n        .getAll()\n        .filter((q) => getQueryStatusLabel(q) === 'stale').length,\n  )\n\n  const fresh = createSubscribeToQueryCacheBatcher(\n    (queryCache) =>\n      queryCache()\n        .getAll()\n        .filter((q) => getQueryStatusLabel(q) === 'fresh').length,\n  )\n\n  const fetching = createSubscribeToQueryCacheBatcher(\n    (queryCache) =>\n      queryCache()\n        .getAll()\n        .filter((q) => getQueryStatusLabel(q) === 'fetching').length,\n  )\n\n  const paused = createSubscribeToQueryCacheBatcher(\n    (queryCache) =>\n      queryCache()\n        .getAll()\n        .filter((q) => getQueryStatusLabel(q) === 'paused').length,\n  )\n\n  const inactive = createSubscribeToQueryCacheBatcher(\n    (queryCache) =>\n      queryCache()\n        .getAll()\n        .filter((q) => getQueryStatusLabel(q) === 'inactive').length,\n  )\n\n  const theme = useTheme()\n  const css = useQueryDevtoolsContext().shadowDOMTarget\n    ? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })\n    : goober.css\n  const styles = createMemo(() => {\n    return theme() === 'dark' ? darkStyles(css) : lightStyles(css)\n  })\n\n  return (\n    <div\n      class={cx(styles().queryStatusContainer, 'tsqd-query-status-container')}\n    >\n      <QueryStatus label=\"Fresh\" color=\"green\" count={fresh()} />\n      <QueryStatus label=\"Fetching\" color=\"blue\" count={fetching()} />\n      <QueryStatus label=\"Paused\" color=\"purple\" count={paused()} />\n      <QueryStatus label=\"Stale\" color=\"yellow\" count={stale()} />\n      <QueryStatus label=\"Inactive\" color=\"gray\" count={inactive()} />\n    </div>\n  )\n}\n\nconst MutationStatusCount: Component = () => {\n  const success = createSubscribeToMutationCacheBatcher(\n    (mutationCache) =>\n      mutationCache()\n        .getAll()\n        .filter(\n          (m) =>\n            getMutationStatusColor({\n              isPaused: m.state.isPaused,\n              status: m.state.status,\n            }) === 'green',\n        ).length,\n  )\n\n  const pending = createSubscribeToMutationCacheBatcher(\n    (mutationCache) =>\n      mutationCache()\n        .getAll()\n        .filter(\n          (m) =>\n            getMutationStatusColor({\n              isPaused: m.state.isPaused,\n              status: m.state.status,\n            }) === 'yellow',\n        ).length,\n  )\n\n  const paused = createSubscribeToMutationCacheBatcher(\n    (mutationCache) =>\n      mutationCache()\n        .getAll()\n        .filter(\n          (m) =>\n            getMutationStatusColor({\n              isPaused: m.state.isPaused,\n              status: m.state.status,\n            }) === 'purple',\n        ).length,\n  )\n\n  const error = createSubscribeToMutationCacheBatcher(\n    (mutationCache) =>\n      mutationCache()\n        .getAll()\n        .filter(\n          (m) =>\n            getMutationStatusColor({\n              isPaused: m.state.isPaused,\n              status: m.state.status,\n            }) === 'red',\n        ).length,\n  )\n\n  const theme = useTheme()\n  const css = useQueryDevtoolsContext().shadowDOMTarget\n    ? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })\n    : goober.css\n  const styles = createMemo(() => {\n    return theme() === 'dark' ? darkStyles(css) : lightStyles(css)\n  })\n\n  return (\n    <div\n      class={cx(styles().queryStatusContainer, 'tsqd-query-status-container')}\n    >\n      <QueryStatus label=\"Paused\" color=\"purple\" count={paused()} />\n      <QueryStatus label=\"Pending\" color=\"yellow\" count={pending()} />\n      <QueryStatus label=\"Success\" color=\"green\" count={success()} />\n      <QueryStatus label=\"Error\" color=\"red\" count={error()} />\n    </div>\n  )\n}\n\nconst QueryStatus: Component<QueryStatusProps> = (props) => {\n  const theme = useTheme()\n  const css = useQueryDevtoolsContext().shadowDOMTarget\n    ? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })\n    : goober.css\n  const styles = createMemo(() => {\n    return theme() === 'dark' ? darkStyles(css) : lightStyles(css)\n  })\n\n  const { colors, alpha } = tokens\n  const t = (light: string, dark: string) => (theme() === 'dark' ? dark : light)\n\n  let tagRef!: HTMLButtonElement\n\n  const [mouseOver, setMouseOver] = createSignal(false)\n  const [focused, setFocused] = createSignal(false)\n\n  const showLabel = createMemo(() => {\n    if (selectedQueryHash()) {\n      if (panelWidth() < firstBreakpoint && panelWidth() > secondBreakpoint) {\n        return false\n      }\n    }\n    if (panelWidth() < secondBreakpoint) {\n      return false\n    }\n\n    return true\n  })\n\n  return (\n    <button\n      onFocus={() => setFocused(true)}\n      onBlur={() => setFocused(false)}\n      onMouseEnter={() => setMouseOver(true)}\n      onMouseLeave={() => {\n        setMouseOver(false)\n        setFocused(false)\n      }}\n      disabled={showLabel()}\n      ref={tagRef}\n      aria-label={`${props.label}: ${props.count}`}\n      class={cx(\n        styles().queryStatusTag,\n        !showLabel() &&\n          css`\n            cursor: pointer;\n            &:hover {\n              background: ${t(\n                  colors.gray[200],\n                  colors.darkGray[400],\n                )}${alpha[80]};\n            }\n          `,\n        'tsqd-query-status-tag',\n        `tsqd-query-status-tag-${props.label.toLowerCase()}`,\n      )}\n      {...(mouseOver() || focused()\n        ? {\n            'aria-describedby': 'tsqd-status-tooltip',\n          }\n        : {})}\n    >\n      <Show when={!showLabel() && (mouseOver() || focused())}>\n        <div\n          role=\"tooltip\"\n          id=\"tsqd-status-tooltip\"\n          class={cx(styles().statusTooltip, 'tsqd-query-status-tooltip')}\n        >\n          {props.label}\n        </div>\n      </Show>\n      <span\n        aria-hidden=\"true\"\n        class={cx(\n          css`\n            width: ${tokens.size[1.5]};\n            height: ${tokens.size[1.5]};\n            border-radius: ${tokens.border.radius.full};\n            background-color: ${tokens.colors[props.color][500]};\n          `,\n          'tsqd-query-status-tag-dot',\n        )}\n      />\n      <Show when={showLabel()}>\n        <span\n          class={cx(\n            styles().queryStatusTagLabel,\n            'tsqd-query-status-tag-label',\n          )}\n        >\n          {props.label}\n        </span>\n      </Show>\n      <span\n        class={cx(\n          styles().queryStatusCount,\n          props.count > 0 &&\n            props.color !== 'gray' &&\n            css`\n              background-color: ${t(\n                colors[props.color][100],\n                colors[props.color][900],\n              )};\n              color: ${t(colors[props.color][700], colors[props.color][300])};\n            `,\n          'tsqd-query-status-tag-count',\n        )}\n      >\n        {props.count}\n      </span>\n    </button>\n  )\n}\n\nconst QueryDetails = () => {\n  const theme = useTheme()\n  const css = useQueryDevtoolsContext().shadowDOMTarget\n    ? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })\n    : goober.css\n  const styles = createMemo(() => {\n    return theme() === 'dark' ? darkStyles(css) : lightStyles(css)\n  })\n\n  const { colors } = tokens\n  const t = (light: string, dark: string) => (theme() === 'dark' ? dark : light)\n\n  const queryClient = useQueryDevtoolsContext().client\n\n  const [restoringLoading, setRestoringLoading] = createSignal(false)\n  const [dataMode, setDataMode] = createSignal<'view' | 'edit'>('view')\n  const [dataEditError, setDataEditError] = createSignal<boolean>(false)\n\n  const errorTypes = createMemo(() => {\n    return useQueryDevtoolsContext().errorTypes || []\n  })\n\n  const activeQuery = createSubscribeToQueryCacheBatcher(\n    (queryCache) =>\n      queryCache()\n        .getAll()\n        .find((query) => query.queryHash === selectedQueryHash()),\n    false,\n  )\n\n  const activeQueryFresh = createSubscribeToQueryCacheBatcher((queryCache) => {\n    return queryCache()\n      .getAll()\n      .find((query) => query.queryHash === selectedQueryHash())\n  }, false)\n\n  const activeQueryState = createSubscribeToQueryCacheBatcher(\n    (queryCache) =>\n      queryCache()\n        .getAll()\n        .find((query) => query.queryHash === selectedQueryHash())?.state,\n    false,\n  )\n\n  const activeQueryStateData = createSubscribeToQueryCacheBatcher(\n    (queryCache) => {\n      return queryCache()\n        .getAll()\n        .find((query) => query.queryHash === selectedQueryHash())?.state.data\n    },\n    false,\n  )\n\n  const statusLabel = createSubscribeToQueryCacheBatcher((queryCache) => {\n    const query = queryCache()\n      .getAll()\n      .find((q) => q.queryHash === selectedQueryHash())\n    if (!query) return 'inactive'\n    return getQueryStatusLabel(query)\n  })\n\n  const queryStatus = createSubscribeToQueryCacheBatcher((queryCache) => {\n    const query = queryCache()\n      .getAll()\n      .find((q) => q.queryHash === selectedQueryHash())\n    if (!query) return 'pending'\n    return query.state.status\n  })\n\n  const observerCount = createSubscribeToQueryCacheBatcher(\n    (queryCache) =>\n      queryCache()\n        .getAll()\n        .find((query) => query.queryHash === selectedQueryHash())\n        ?.getObserversCount() ?? 0,\n  )\n\n  const color = createMemo(() => getQueryStatusColorByLabel(statusLabel()))\n\n  const handleRefetch = () => {\n    sendDevToolsEvent({ type: 'REFETCH', queryHash: activeQuery()?.queryHash })\n    const promise = activeQuery()?.fetch()\n    promise?.catch(() => {})\n  }\n\n  const triggerError = (errorType?: DevtoolsErrorType) => {\n    const activeQueryVal = activeQuery()\n    if (!activeQueryVal) return\n    sendDevToolsEvent({\n      type: 'TRIGGER_ERROR',\n      queryHash: activeQueryVal.queryHash,\n      metadata: { error: errorType?.name },\n    })\n    const error =\n      errorType?.initializer(activeQueryVal) ??\n      new Error('Unknown error from devtools')\n\n    const __previousQueryOptions = activeQueryVal.options\n\n    activeQueryVal.setState({\n      data: undefined,\n      status: 'error',\n      error,\n      fetchMeta: {\n        ...activeQueryVal.state.fetchMeta,\n        __previousQueryOptions,\n      } as any,\n    })\n  }\n\n  const restoreQueryAfterLoadingOrError = () => {\n    const activeQueryVal = activeQuery()\n    if (!activeQueryVal) return\n\n    sendDevToolsEvent({\n      type: 'RESTORE_LOADING',\n      queryHash: activeQueryVal.queryHash,\n    })\n    const previousState = activeQueryVal.state\n    const previousOptions = activeQueryVal.state.fetchMeta\n      ? (activeQueryVal.state.fetchMeta as any).__previousQueryOptions\n      : null\n\n    activeQueryVal.cancel({ silent: true })\n    activeQueryVal.setState({\n      ...previousState,\n      fetchStatus: 'idle',\n      fetchMeta: null,\n    })\n\n    if (previousOptions) {\n      activeQueryVal.fetch(previousOptions)\n    }\n  }\n\n  createEffect(() => {\n    if (statusLabel() !== 'fetching') {\n      setRestoringLoading(false)\n    }\n  })\n\n  const getQueryStatusColors = () => {\n    if (color() === 'gray') {\n      return css`\n        background-color: ${t(colors[color()][200], colors[color()][700])};\n        color: ${t(colors[color()][700], colors[color()][300])};\n        border-color: ${t(colors[color()][400], colors[color()][600])};\n      `\n    }\n    return css`\n      background-color: ${t(colors[color()][100], colors[color()][900])};\n      color: ${t(colors[color()][700], colors[color()][300])};\n      border-color: ${t(colors[color()][400], colors[color()][600])};\n    `\n  }\n\n  return (\n    <Show when={activeQuery() && activeQueryState()}>\n      <div\n        class={cx(styles().detailsContainer, 'tsqd-query-details-container')}\n      >\n        <div\n          role=\"heading\"\n          aria-level=\"2\"\n          class={cx(styles().detailsHeader, 'tsqd-query-details-header')}\n        >\n          Query Details\n        </div>\n        <div\n          class={cx(\n            styles().detailsBody,\n            'tsqd-query-details-summary-container',\n          )}\n        >\n          <div class=\"tsqd-query-details-summary\">\n            <pre>\n              <code>{displayValue(activeQuery()!.queryKey, true)}</code>\n            </pre>\n            <span\n              class={cx(styles().queryDetailsStatus, getQueryStatusColors())}\n              role=\"status\"\n              aria-live=\"polite\"\n            >\n              {statusLabel()}\n            </span>\n          </div>\n          <div class=\"tsqd-query-details-observers-count\">\n            <span>Observers:</span>\n            <span>{observerCount()}</span>\n          </div>\n          <div class=\"tsqd-query-details-last-updated\">\n            <span>Last Updated:</span>\n            <span>\n              {new Date(activeQueryState()!.dataUpdatedAt).toLocaleTimeString()}\n            </span>\n          </div>\n        </div>\n        <div\n          role=\"heading\"\n          aria-level=\"2\"\n          class={cx(styles().detailsHeader, 'tsqd-query-details-header')}\n        >\n          Actions\n        </div>\n        <div\n          class={cx(\n            styles().actionsBody,\n            'tsqd-query-details-actions-container',\n          )}\n        >\n          <button\n            class={cx(\n              css`\n                color: ${t(colors.blue[600], colors.blue[400])};\n              `,\n              'tsqd-query-details-actions-btn',\n              'tsqd-query-details-action-refetch',\n            )}\n            onClick={handleRefetch}\n            disabled={statusLabel() === 'fetching'}\n          >\n            <span\n              aria-hidden=\"true\"\n              class={css`\n                background-color: ${t(colors.blue[600], colors.blue[400])};\n              `}\n            ></span>\n            Refetch\n          </button>\n          <button\n            class={cx(\n              css`\n                color: ${t(colors.yellow[600], colors.yellow[400])};\n              `,\n              'tsqd-query-details-actions-btn',\n              'tsqd-query-details-action-invalidate',\n            )}\n            onClick={() => {\n              sendDevToolsEvent({\n                type: 'INVALIDATE',\n                queryHash: activeQuery()?.queryHash,\n              })\n              queryClient.invalidateQueries(activeQuery())\n            }}\n            disabled={queryStatus() === 'pending'}\n          >\n            <span\n              aria-hidden=\"true\"\n              class={css`\n                background-color: ${t(colors.yellow[600], colors.yellow[400])};\n              `}\n            ></span>\n            Invalidate\n          </button>\n          <button\n            class={cx(\n              css`\n                color: ${t(colors.gray[600], colors.gray[300])};\n              `,\n              'tsqd-query-details-actions-btn',\n              'tsqd-query-details-action-reset',\n            )}\n            onClick={() => {\n              sendDevToolsEvent({\n                type: 'RESET',\n                queryHash: activeQuery()?.queryHash,\n              })\n              queryClient.resetQueries(activeQuery())\n            }}\n            disabled={queryStatus() === 'pending'}\n          >\n            <span\n              aria-hidden=\"true\"\n              class={css`\n                background-color: ${t(colors.gray[600], colors.gray[400])};\n              `}\n            ></span>\n            Reset\n          </button>\n          <button\n            class={cx(\n              css`\n                color: ${t(colors.pink[500], colors.pink[400])};\n              `,\n              'tsqd-query-details-actions-btn',\n              'tsqd-query-details-action-remove',\n            )}\n            onClick={() => {\n              sendDevToolsEvent({\n                type: 'REMOVE',\n                queryHash: activeQuery()?.queryHash,\n              })\n              queryClient.removeQueries(activeQuery())\n              setSelectedQueryHash(null)\n            }}\n            disabled={statusLabel() === 'fetching'}\n          >\n            <span\n              aria-hidden=\"true\"\n              class={css`\n                background-color: ${t(colors.pink[500], colors.pink[400])};\n              `}\n            ></span>\n            Remove\n          </button>\n          <button\n            class={cx(\n              css`\n                color: ${t(colors.cyan[500], colors.cyan[400])};\n              `,\n              'tsqd-query-details-actions-btn',\n              'tsqd-query-details-action-loading',\n            )}\n            disabled={restoringLoading()}\n            onClick={() => {\n              if (activeQuery()?.state.data === undefined) {\n                setRestoringLoading(true)\n                restoreQueryAfterLoadingOrError()\n              } else {\n                const activeQueryVal = activeQuery()\n                if (!activeQueryVal) return\n                sendDevToolsEvent({\n                  type: 'TRIGGER_LOADING',\n                  queryHash: activeQueryVal.queryHash,\n                })\n                const __previousQueryOptions = activeQueryVal.options\n                // Trigger a fetch in order to trigger suspense as well.\n                activeQueryVal.fetch({\n                  ...__previousQueryOptions,\n                  queryFn: () => {\n                    return new Promise(() => {\n                      // Never resolve\n                    })\n                  },\n                  gcTime: -1,\n                })\n                activeQueryVal.setState({\n                  data: undefined,\n                  status: 'pending',\n                  fetchMeta: {\n                    ...activeQueryVal.state.fetchMeta,\n                    __previousQueryOptions,\n                  } as any,\n                })\n              }\n            }}\n          >\n            <span\n              aria-hidden=\"true\"\n              class={css`\n                background-color: ${t(colors.cyan[500], colors.cyan[400])};\n              `}\n            ></span>\n            {queryStatus() === 'pending' ? 'Restore' : 'Trigger'} Loading\n          </button>\n          <Show when={errorTypes().length === 0 || queryStatus() === 'error'}>\n            <button\n              class={cx(\n                css`\n                  color: ${t(colors.red[500], colors.red[400])};\n                `,\n                'tsqd-query-details-actions-btn',\n                'tsqd-query-details-action-error',\n              )}\n              onClick={() => {\n                if (!activeQuery()!.state.error) {\n                  triggerError()\n                } else {\n                  sendDevToolsEvent({\n                    type: 'RESTORE_ERROR',\n                    queryHash: activeQuery()?.queryHash,\n                  })\n                  queryClient.resetQueries(activeQuery())\n                }\n              }}\n              disabled={queryStatus() === 'pending'}\n            >\n              <span\n                aria-hidden=\"true\"\n                class={css`\n                  background-color: ${t(colors.red[500], colors.red[400])};\n                `}\n              ></span>\n              {queryStatus() === 'error' ? 'Restore' : 'Trigger'} Error\n            </button>\n          </Show>\n          <Show\n            when={!(errorTypes().length === 0 || queryStatus() === 'error')}\n          >\n            <div\n              class={cx(\n                styles().actionsSelect,\n                'tsqd-query-details-actions-btn',\n                'tsqd-query-details-action-error-multiple',\n              )}\n            >\n              <span\n                aria-hidden=\"true\"\n                class={css`\n                  background-color: ${tokens.colors.red[400]};\n                `}\n              ></span>\n              Trigger Error\n              <select\n                disabled={queryStatus() === 'pending'}\n                aria-label=\"Select error type to trigger\"\n                onChange={(e) => {\n                  const errorType = errorTypes().find(\n                    (et) => et.name === e.currentTarget.value,\n                  )\n\n                  triggerError(errorType)\n                }}\n              >\n                <option value=\"\" disabled selected></option>\n                <For each={errorTypes()}>\n                  {(errorType) => (\n                    <option value={errorType.name}>{errorType.name}</option>\n                  )}\n                </For>\n              </select>\n              <ChevronDown />\n            </div>\n          </Show>\n        </div>\n        <div\n          role=\"heading\"\n          aria-level=\"2\"\n          class={cx(styles().detailsHeader, 'tsqd-query-details-header')}\n        >\n          Data {dataMode() === 'view' ? 'Explorer' : 'Editor'}\n        </div>\n        <Show when={dataMode() === 'view'}>\n          <div\n            style={{\n              padding: tokens.size[2],\n            }}\n            class=\"tsqd-query-details-explorer-container tsqd-query-details-data-explorer\"\n          >\n            <Explorer\n              label=\"Data\"\n              defaultExpanded={['Data']}\n              value={activeQueryStateData()}\n              editable={true}\n              onEdit={() => setDataMode('edit')}\n              activeQuery={activeQuery()}\n            />\n          </div>\n        </Show>\n        <Show when={dataMode() === 'edit'}>\n          <form\n            class={cx(\n              styles().devtoolsEditForm,\n              'tsqd-query-details-data-editor',\n            )}\n            onSubmit={(e) => {\n              e.preventDefault()\n              const formData = new FormData(e.currentTarget)\n              const data = formData.get('data') as string\n              try {\n                const parsedData = JSON.parse(data)\n                activeQuery()!.setState({\n                  ...activeQuery()!.state,\n                  data: parsedData,\n                })\n                setDataMode('view')\n              } catch (error) {\n                setDataEditError(true)\n              }\n            }}\n          >\n            <textarea\n              name=\"data\"\n              aria-label=\"Edit query data as JSON\"\n              class={styles().devtoolsEditTextarea}\n              onFocus={() => setDataEditError(false)}\n              data-error={dataEditError()}\n              value={JSON.stringify(activeQueryStateData(), null, 2)}\n            ></textarea>\n            <div class={styles().devtoolsEditFormActions}>\n              <span class={styles().devtoolsEditFormError}>\n                {dataEditError() ? 'Invalid Value' : ''}\n              </span>\n              <div class={styles().devtoolsEditFormActionContainer}>\n                <button\n                  class={cx(\n                    styles().devtoolsEditFormAction,\n                    css`\n                      color: ${t(colors.gray[600], colors.gray[300])};\n                    `,\n                  )}\n                  type=\"button\"\n                  onClick={() => setDataMode('view')}\n                >\n                  Cancel\n                </button>\n                <button\n                  class={cx(\n                    styles().devtoolsEditFormAction,\n                    css`\n                      color: ${t(colors.blue[600], colors.blue[400])};\n                    `,\n                  )}\n                >\n                  Save\n                </button>\n              </div>\n            </div>\n          </form>\n        </Show>\n        <div\n          role=\"heading\"\n          aria-level=\"2\"\n          class={cx(styles().detailsHeader, 'tsqd-query-details-header')}\n        >\n          Query Explorer\n        </div>\n        <div\n          style={{\n            padding: tokens.size[2],\n          }}\n          class=\"tsqd-query-details-explorer-container tsqd-query-details-query-explorer\"\n        >\n          <Explorer\n            label=\"Query\"\n            defaultExpanded={['Query', 'queryKey']}\n            value={activeQueryFresh()}\n          />\n        </div>\n      </div>\n    </Show>\n  )\n}\n\nconst MutationDetails = () => {\n  const theme = useTheme()\n  const css = useQueryDevtoolsContext().shadowDOMTarget\n    ? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })\n    : goober.css\n  const styles = createMemo(() => {\n    return theme() === 'dark' ? darkStyles(css) : lightStyles(css)\n  })\n\n  const { colors } = tokens\n  const t = (light: string, dark: string) => (theme() === 'dark' ? dark : light)\n\n  const isPaused = createSubscribeToMutationCacheBatcher((mutationCache) => {\n    const mutations = mutationCache().getAll()\n    const mutation = mutations.find(\n      (m) => m.mutationId === selectedMutationId(),\n    )\n    if (!mutation) return false\n    return mutation.state.isPaused\n  })\n\n  const status = createSubscribeToMutationCacheBatcher((mutationCache) => {\n    const mutations = mutationCache().getAll()\n    const mutation = mutations.find(\n      (m) => m.mutationId === selectedMutationId(),\n    )\n    if (!mutation) return 'idle'\n    return mutation.state.status\n  })\n\n  const color = createMemo(() =>\n    getMutationStatusColor({\n      isPaused: isPaused(),\n      status: status(),\n    }),\n  )\n\n  const activeMutation = createSubscribeToMutationCacheBatcher(\n    (mutationCache) =>\n      mutationCache()\n        .getAll()\n        .find((mutation) => mutation.mutationId === selectedMutationId()),\n    false,\n  )\n\n  const getQueryStatusColors = () => {\n    if (color() === 'gray') {\n      return css`\n        background-color: ${t(colors[color()][200], colors[color()][700])};\n        color: ${t(colors[color()][700], colors[color()][300])};\n        border-color: ${t(colors[color()][400], colors[color()][600])};\n      `\n    }\n    return css`\n      background-color: ${t(colors[color()][100], colors[color()][900])};\n      color: ${t(colors[color()][700], colors[color()][300])};\n      border-color: ${t(colors[color()][400], colors[color()][600])};\n    `\n  }\n\n  return (\n    <Show when={activeMutation()}>\n      <div\n        class={cx(styles().detailsContainer, 'tsqd-query-details-container')}\n      >\n        <div\n          role=\"heading\"\n          aria-level=\"2\"\n          class={cx(styles().detailsHeader, 'tsqd-query-details-header')}\n        >\n          Mutation Details\n        </div>\n        <div\n          class={cx(\n            styles().detailsBody,\n            'tsqd-query-details-summary-container',\n          )}\n        >\n          <div class=\"tsqd-query-details-summary\">\n            <pre>\n              <code>\n                <Show\n                  when={activeMutation()!.options.mutationKey}\n                  fallback={'No mutationKey found'}\n                >\n                  {displayValue(activeMutation()!.options.mutationKey, true)}\n                </Show>\n              </code>\n            </pre>\n            <span\n              class={cx(styles().queryDetailsStatus, getQueryStatusColors())}\n              role=\"status\"\n              aria-live=\"polite\"\n            >\n              <Show when={color() === 'purple'}>pending</Show>\n              <Show when={color() !== 'purple'}>{status()}</Show>\n            </span>\n          </div>\n          <div class=\"tsqd-query-details-last-updated\">\n            <span>Submitted At:</span>\n            <span>\n              {new Date(\n                activeMutation()!.state.submittedAt,\n              ).toLocaleTimeString()}\n            </span>\n          </div>\n        </div>\n        <div\n          role=\"heading\"\n          aria-level=\"2\"\n          class={cx(styles().detailsHeader, 'tsqd-query-details-header')}\n        >\n          Variables Details\n        </div>\n        <div\n          style={{\n            padding: tokens.size[2],\n          }}\n          class=\"tsqd-query-details-explorer-container tsqd-query-details-query-explorer\"\n        >\n          <Explorer\n            label=\"Variables\"\n            defaultExpanded={['Variables']}\n            value={activeMutation()!.state.variables}\n          />\n        </div>\n        <div\n          role=\"heading\"\n          aria-level=\"2\"\n          class={cx(styles().detailsHeader, 'tsqd-query-details-header')}\n        >\n          Context Details\n        </div>\n        <div\n          style={{\n            padding: tokens.size[2],\n          }}\n          class=\"tsqd-query-details-explorer-container tsqd-query-details-query-explorer\"\n        >\n          <Explorer\n            label=\"Context\"\n            defaultExpanded={['Context']}\n            value={activeMutation()!.state.context}\n          />\n        </div>\n        <div\n          role=\"heading\"\n          aria-level=\"2\"\n          class={cx(styles().detailsHeader, 'tsqd-query-details-header')}\n        >\n          Data Explorer\n        </div>\n        <div\n          style={{\n            padding: tokens.size[2],\n          }}\n          class=\"tsqd-query-details-explorer-container tsqd-query-details-query-explorer\"\n        >\n          <Explorer\n            label=\"Data\"\n            defaultExpanded={['Data']}\n            value={activeMutation()!.state.data}\n          />\n        </div>\n        <div\n          role=\"heading\"\n          aria-level=\"2\"\n          class={cx(styles().detailsHeader, 'tsqd-query-details-header')}\n        >\n          Mutations Explorer\n        </div>\n        <div\n          style={{\n            padding: tokens.size[2],\n          }}\n          class=\"tsqd-query-details-explorer-container tsqd-query-details-query-explorer\"\n        >\n          <Explorer\n            label=\"Mutation\"\n            defaultExpanded={['Mutation']}\n            value={activeMutation()}\n          />\n        </div>\n      </div>\n    </Show>\n  )\n}\n\nconst queryCacheMap = new Map<\n  (q: Accessor<QueryCache>) => any,\n  {\n    setter: Setter<any>\n    shouldUpdate: (event: QueryCacheNotifyEvent) => boolean\n  }\n>()\n\nconst setupQueryCacheSubscription = () => {\n  const queryCache = createMemo(() => {\n    const client = useQueryDevtoolsContext().client\n    return client.getQueryCache()\n  })\n\n  const unsubscribe = queryCache().subscribe((q) => {\n    batch(() => {\n      for (const [callback, value] of queryCacheMap.entries()) {\n        if (!value.shouldUpdate(q)) continue\n        value.setter(callback(queryCache))\n      }\n    })\n  })\n\n  onCleanup(() => {\n    queryCacheMap.clear()\n    unsubscribe()\n  })\n\n  return unsubscribe\n}\n\nconst createSubscribeToQueryCacheBatcher = <T,>(\n  callback: (queryCache: Accessor<QueryCache>) => Exclude<T, Function>,\n  equalityCheck: boolean = true,\n  shouldUpdate: (event: QueryCacheNotifyEvent) => boolean = () => true,\n) => {\n  const queryCache = createMemo(() => {\n    const client = useQueryDevtoolsContext().client\n    return client.getQueryCache()\n  })\n\n  const [value, setValue] = createSignal<T>(\n    callback(queryCache),\n    !equalityCheck ? { equals: false } : undefined,\n  )\n\n  createEffect(() => {\n    setValue(callback(queryCache))\n  })\n\n  queryCacheMap.set(callback, {\n    setter: setValue,\n    shouldUpdate: shouldUpdate,\n  })\n\n  onCleanup(() => {\n    queryCacheMap.delete(callback)\n  })\n\n  return value\n}\n\nconst mutationCacheMap = new Map<\n  (q: Accessor<MutationCache>) => any,\n  Setter<any>\n>()\n\nconst setupMutationCacheSubscription = () => {\n  const mutationCache = createMemo(() => {\n    const client = useQueryDevtoolsContext().client\n    return client.getMutationCache()\n  })\n\n  const unsubscribe = mutationCache().subscribe(() => {\n    for (const [callback, setter] of mutationCacheMap.entries()) {\n      queueMicrotask(() => {\n        setter(callback(mutationCache))\n      })\n    }\n  })\n\n  onCleanup(() => {\n    mutationCacheMap.clear()\n    unsubscribe()\n  })\n\n  return unsubscribe\n}\n\nconst createSubscribeToMutationCacheBatcher = <T,>(\n  callback: (queryCache: Accessor<MutationCache>) => Exclude<T, Function>,\n  equalityCheck: boolean = true,\n) => {\n  const mutationCache = createMemo(() => {\n    const client = useQueryDevtoolsContext().client\n    return client.getMutationCache()\n  })\n\n  const [value, setValue] = createSignal<T>(\n    callback(mutationCache),\n    !equalityCheck ? { equals: false } : undefined,\n  )\n\n  createEffect(() => {\n    setValue(callback(mutationCache))\n  })\n\n  mutationCacheMap.set(callback, setValue)\n\n  onCleanup(() => {\n    mutationCacheMap.delete(callback)\n  })\n\n  return value\n}\n\ntype DevToolsActionType =\n  | 'REFETCH'\n  | 'INVALIDATE'\n  | 'RESET'\n  | 'REMOVE'\n  | 'TRIGGER_ERROR'\n  | 'RESTORE_ERROR'\n  | 'TRIGGER_LOADING'\n  | 'RESTORE_LOADING'\n  | 'CLEAR_MUTATION_CACHE'\n  | 'CLEAR_QUERY_CACHE'\n\nconst DEV_TOOLS_EVENT = '@tanstack/query-devtools-event'\n\nconst sendDevToolsEvent = ({\n  type,\n  queryHash,\n  metadata,\n}: {\n  type: DevToolsActionType\n  queryHash?: string\n  metadata?: Record<string, unknown>\n}) => {\n  const event = new CustomEvent(DEV_TOOLS_EVENT, {\n    detail: { type, queryHash, metadata },\n    bubbles: true,\n    cancelable: true,\n  })\n  window.dispatchEvent(event)\n}\n\nconst stylesFactory = (\n  theme: 'light' | 'dark',\n  css: (typeof goober)['css'],\n) => {\n  const { colors, font, size, alpha, shadow, border } = tokens\n\n  const t = (light: string, dark: string) => (theme === 'light' ? light : dark)\n\n  return {\n    devtoolsBtn: css`\n      z-index: 100000;\n      position: fixed;\n      padding: 4px;\n      text-align: left;\n\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      border-radius: 9999px;\n      box-shadow: ${shadow.md()};\n      overflow: hidden;\n\n      & div {\n        position: absolute;\n        top: -8px;\n        left: -8px;\n        right: -8px;\n        bottom: -8px;\n        border-radius: 9999px;\n\n        & svg {\n          position: absolute;\n          width: 100%;\n          height: 100%;\n        }\n        filter: blur(6px) saturate(1.2) contrast(1.1);\n      }\n\n      &:focus-within {\n        outline-offset: 2px;\n        outline: 3px solid ${colors.green[600]};\n      }\n\n      & button {\n        position: relative;\n        z-index: 1;\n        padding: 0;\n        border-radius: 9999px;\n        background-color: transparent;\n        border: none;\n        height: 40px;\n        display: flex;\n        width: 40px;\n        overflow: hidden;\n        cursor: pointer;\n        outline: none;\n        & svg {\n          position: absolute;\n          width: 100%;\n          height: 100%;\n        }\n      }\n    `,\n    panel: css`\n      position: fixed;\n      z-index: 9999;\n      display: flex;\n      gap: ${tokens.size[0.5]};\n      & * {\n        box-sizing: border-box;\n        text-transform: none;\n      }\n\n      & *::-webkit-scrollbar {\n        width: 7px;\n      }\n\n      & *::-webkit-scrollbar-track {\n        background: transparent;\n      }\n\n      & *::-webkit-scrollbar-thumb {\n        background: ${t(colors.gray[300], colors.darkGray[200])};\n      }\n\n      & *::-webkit-scrollbar-thumb:hover {\n        background: ${t(colors.gray[400], colors.darkGray[300])};\n      }\n    `,\n    parentPanel: css`\n      z-index: 9999;\n      display: flex;\n      height: 100%;\n      gap: ${tokens.size[0.5]};\n      & * {\n        box-sizing: border-box;\n        text-transform: none;\n      }\n\n      & *::-webkit-scrollbar {\n        width: 7px;\n      }\n\n      & *::-webkit-scrollbar-track {\n        background: transparent;\n      }\n\n      & *::-webkit-scrollbar-thumb {\n        background: ${t(colors.gray[300], colors.darkGray[200])};\n      }\n\n      & *::-webkit-scrollbar-thumb:hover {\n        background: ${t(colors.gray[400], colors.darkGray[300])};\n      }\n    `,\n    'devtoolsBtn-position-bottom-right': css`\n      bottom: 12px;\n      right: 12px;\n    `,\n    'devtoolsBtn-position-bottom-left': css`\n      bottom: 12px;\n      left: 12px;\n    `,\n    'devtoolsBtn-position-top-left': css`\n      top: 12px;\n      left: 12px;\n    `,\n    'devtoolsBtn-position-top-right': css`\n      top: 12px;\n      right: 12px;\n    `,\n    'devtoolsBtn-position-relative': css`\n      position: relative;\n    `,\n    'panel-position-top': css`\n      top: 0;\n      right: 0;\n      left: 0;\n      max-height: 90%;\n      min-height: ${size[14]};\n      border-bottom: ${t(colors.gray[400], colors.darkGray[300])} 1px solid;\n    `,\n    'panel-position-bottom': css`\n      bottom: 0;\n      right: 0;\n      left: 0;\n      max-height: 90%;\n      min-height: ${size[14]};\n      border-top: ${t(colors.gray[400], colors.darkGray[300])} 1px solid;\n    `,\n    'panel-position-right': css`\n      bottom: 0;\n      right: 0;\n      top: 0;\n      border-left: ${t(colors.gray[400], colors.darkGray[300])} 1px solid;\n      max-width: 90%;\n    `,\n    'panel-position-left': css`\n      bottom: 0;\n      left: 0;\n      top: 0;\n      border-right: ${t(colors.gray[400], colors.darkGray[300])} 1px solid;\n      max-width: 90%;\n    `,\n    closeBtn: css`\n      position: absolute;\n      cursor: pointer;\n      z-index: 5;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      outline: none;\n      background-color: ${t(colors.gray[50], colors.darkGray[700])};\n      &:hover {\n        background-color: ${t(colors.gray[200], colors.darkGray[500])};\n      }\n      &:focus-visible {\n        outline: 2px solid ${colors.blue[600]};\n      }\n      & svg {\n        color: ${t(colors.gray[600], colors.gray[400])};\n        width: ${size[2]};\n        height: ${size[2]};\n      }\n    `,\n    'closeBtn-position-top': css`\n      bottom: 0;\n      right: ${size[2]};\n      transform: translate(0, 100%);\n      border-right: ${t(colors.gray[400], colors.darkGray[300])} 1px solid;\n      border-left: ${t(colors.gray[400], colors.darkGray[300])} 1px solid;\n      border-top: none;\n      border-bottom: ${t(colors.gray[400], colors.darkGray[300])} 1px solid;\n      border-radius: 0px 0px ${border.radius.sm} ${border.radius.sm};\n      padding: ${size[0.5]} ${size[1.5]} ${size[1]} ${size[1.5]};\n\n      &::after {\n        content: ' ';\n        position: absolute;\n        bottom: 100%;\n        left: -${size[2.5]};\n        height: ${size[1.5]};\n        width: calc(100% + ${size[5]});\n      }\n\n      & svg {\n        transform: rotate(180deg);\n      }\n    `,\n    'closeBtn-position-bottom': css`\n      top: 0;\n      right: ${size[2]};\n      transform: translate(0, -100%);\n      border-right: ${t(colors.gray[400], colors.darkGray[300])} 1px solid;\n      border-left: ${t(colors.gray[400], colors.darkGray[300])} 1px solid;\n      border-top: ${t(colors.gray[400], colors.darkGray[300])} 1px solid;\n      border-bottom: none;\n      border-radius: ${border.radius.sm} ${border.radius.sm} 0px 0px;\n      padding: ${size[1]} ${size[1.5]} ${size[0.5]} ${size[1.5]};\n\n      &::after {\n        content: ' ';\n        position: absolute;\n        top: 100%;\n        left: -${size[2.5]};\n        height: ${size[1.5]};\n        width: calc(100% + ${size[5]});\n      }\n    `,\n    'closeBtn-position-right': css`\n      bottom: ${size[2]};\n      left: 0;\n      transform: translate(-100%, 0);\n      border-right: none;\n      border-left: ${t(colors.gray[400], colors.darkGray[300])} 1px solid;\n      border-top: ${t(colors.gray[400], colors.darkGray[300])} 1px solid;\n      border-bottom: ${t(colors.gray[400], colors.darkGray[300])} 1px solid;\n      border-radius: ${border.radius.sm} 0px 0px ${border.radius.sm};\n      padding: ${size[1.5]} ${size[0.5]} ${size[1.5]} ${size[1]};\n\n      &::after {\n        content: ' ';\n        position: absolute;\n        left: 100%;\n        height: calc(100% + ${size[5]});\n        width: ${size[1.5]};\n      }\n\n      & svg {\n        transform: rotate(-90deg);\n      }\n    `,\n    'closeBtn-position-left': css`\n      bottom: ${size[2]};\n      right: 0;\n      transform: translate(100%, 0);\n      border-left: none;\n      border-right: ${t(colors.gray[400], colors.darkGray[300])} 1px solid;\n      border-top: ${t(colors.gray[400], colors.darkGray[300])} 1px solid;\n      border-bottom: ${t(colors.gray[400], colors.darkGray[300])} 1px solid;\n      border-radius: 0px ${border.radius.sm} ${border.radius.sm} 0px;\n      padding: ${size[1.5]} ${size[1]} ${size[1.5]} ${size[0.5]};\n\n      &::after {\n        content: ' ';\n        position: absolute;\n        right: 100%;\n        height: calc(100% + ${size[5]});\n        width: ${size[1.5]};\n      }\n\n      & svg {\n        transform: rotate(90deg);\n      }\n    `,\n    queriesContainer: css`\n      flex: 1 1 700px;\n      background-color: ${t(colors.gray[50], colors.darkGray[700])};\n      display: flex;\n      flex-direction: column;\n      & * {\n        font-family: ui-sans-serif, Inter, system-ui, sans-serif, sans-serif;\n      }\n    `,\n    dragHandle: css`\n      position: absolute;\n      transition: background-color 0.125s ease;\n      &:hover {\n        background-color: ${colors.purple[400]}${t('', alpha[90])};\n      }\n      &:focus {\n        outline: none;\n        background-color: ${colors.purple[400]}${t('', alpha[90])};\n      }\n      &:focus-visible {\n        outline: 2px solid ${colors.blue[800]};\n        outline-offset: -2px;\n        background-color: ${colors.purple[400]}${t('', alpha[90])};\n      }\n      z-index: 4;\n    `,\n    'dragHandle-position-top': css`\n      bottom: 0;\n      width: 100%;\n      height: 3px;\n      cursor: ns-resize;\n    `,\n    'dragHandle-position-bottom': css`\n      top: 0;\n      width: 100%;\n      height: 3px;\n      cursor: ns-resize;\n    `,\n    'dragHandle-position-right': css`\n      left: 0;\n      width: 3px;\n      height: 100%;\n      cursor: ew-resize;\n    `,\n    'dragHandle-position-left': css`\n      right: 0;\n      width: 3px;\n      height: 100%;\n      cursor: ew-resize;\n    `,\n    row: css`\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      padding: ${tokens.size[2]} ${tokens.size[2.5]};\n      gap: ${tokens.size[2.5]};\n      border-bottom: ${t(colors.gray[300], colors.darkGray[500])} 1px solid;\n      align-items: center;\n      & > button {\n        padding: 0;\n        background: transparent;\n        border: none;\n        display: flex;\n        gap: ${size[0.5]};\n        flex-direction: column;\n      }\n    `,\n    logoAndToggleContainer: css`\n      display: flex;\n      gap: ${tokens.size[3]};\n      align-items: center;\n    `,\n    logo: css`\n      cursor: pointer;\n      display: flex;\n      flex-direction: column;\n      background-color: transparent;\n      border: none;\n      gap: ${tokens.size[0.5]};\n      padding: 0px;\n      &:hover {\n        opacity: 0.7;\n      }\n      &:focus-visible {\n        outline-offset: 4px;\n        border-radius: ${border.radius.xs};\n        outline: 2px solid ${colors.blue[800]};\n      }\n    `,\n    tanstackLogo: css`\n      font-size: ${font.size.md};\n      font-weight: ${font.weight.bold};\n      line-height: ${font.lineHeight.xs};\n      white-space: nowrap;\n      color: ${t(colors.gray[600], colors.gray[300])};\n    `,\n    queryFlavorLogo: css`\n      font-weight: ${font.weight.semibold};\n      font-size: ${font.size.xs};\n      background: linear-gradient(\n        to right,\n        ${t('#ea4037, #ff9b11', '#dd524b, #e9a03b')}\n      );\n      background-clip: text;\n      -webkit-background-clip: text;\n      line-height: 1;\n      -webkit-text-fill-color: transparent;\n      white-space: nowrap;\n    `,\n    queryStatusContainer: css`\n      display: flex;\n      gap: ${tokens.size[2]};\n      height: min-content;\n    `,\n    queryStatusTag: css`\n      display: flex;\n      gap: ${tokens.size[1.5]};\n      box-sizing: border-box;\n      height: ${tokens.size[6.5]};\n      background: ${t(colors.gray[50], colors.darkGray[500])};\n      color: ${t(colors.gray[700], colors.gray[300])};\n      border-radius: ${tokens.border.radius.sm};\n      font-size: ${font.size.sm};\n      padding: ${tokens.size[1]};\n      padding-left: ${tokens.size[1.5]};\n      align-items: center;\n      font-weight: ${font.weight.medium};\n      border: ${t('1px solid ' + colors.gray[300], '1px solid transparent')};\n      user-select: none;\n      position: relative;\n      &:focus-visible {\n        outline-offset: 2px;\n        outline: 2px solid ${colors.blue[800]};\n      }\n    `,\n    queryStatusTagLabel: css`\n      font-size: ${font.size.xs};\n    `,\n    queryStatusCount: css`\n      font-size: ${font.size.xs};\n      padding: 0 5px;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      color: ${t(colors.gray[500], colors.gray[400])};\n      background-color: ${t(colors.gray[200], colors.darkGray[300])};\n      border-radius: 2px;\n      font-variant-numeric: tabular-nums;\n      height: ${tokens.size[4.5]};\n    `,\n    statusTooltip: css`\n      position: absolute;\n      z-index: 1;\n      background-color: ${t(colors.gray[50], colors.darkGray[500])};\n      top: 100%;\n      left: 50%;\n      transform: translate(-50%, calc(${tokens.size[2]}));\n      padding: ${tokens.size[0.5]} ${tokens.size[2]};\n      border-radius: ${tokens.border.radius.sm};\n      font-size: ${font.size.xs};\n      border: 1px solid ${t(colors.gray[400], colors.gray[600])};\n      color: ${t(colors['gray'][600], colors['gray'][300])};\n\n      &::before {\n        top: 0px;\n        content: ' ';\n        display: block;\n        left: 50%;\n        transform: translate(-50%, -100%);\n        position: absolute;\n        border-color: transparent transparent\n          ${t(colors.gray[400], colors.gray[600])} transparent;\n        border-style: solid;\n        border-width: 7px;\n        /* transform: rotate(180deg); */\n      }\n\n      &::after {\n        top: 0px;\n        content: ' ';\n        display: block;\n        left: 50%;\n        transform: translate(-50%, calc(-100% + 2px));\n        position: absolute;\n        border-color: transparent transparent\n          ${t(colors.gray[100], colors.darkGray[500])} transparent;\n        border-style: solid;\n        border-width: 7px;\n      }\n    `,\n    filtersContainer: css`\n      display: flex;\n      gap: ${tokens.size[2]};\n      & > button {\n        cursor: pointer;\n        padding: ${tokens.size[0.5]} ${tokens.size[1.5]} ${tokens.size[0.5]}\n          ${tokens.size[2]};\n        border-radius: ${tokens.border.radius.sm};\n        background-color: ${t(colors.gray[100], colors.darkGray[400])};\n        border: 1px solid ${t(colors.gray[300], colors.darkGray[200])};\n        color: ${t(colors.gray[700], colors.gray[300])};\n        font-size: ${font.size.xs};\n        display: flex;\n        align-items: center;\n        line-height: ${font.lineHeight.sm};\n        gap: ${tokens.size[1.5]};\n        max-width: 160px;\n        &:focus-visible {\n          outline-offset: 2px;\n          border-radius: ${border.radius.xs};\n          outline: 2px solid ${colors.blue[800]};\n        }\n        & svg {\n          width: ${tokens.size[3]};\n          height: ${tokens.size[3]};\n          color: ${t(colors.gray[500], colors.gray[400])};\n        }\n      }\n    `,\n    filterInput: css`\n      padding: ${size[0.5]} ${size[2]};\n      border-radius: ${tokens.border.radius.sm};\n      background-color: ${t(colors.gray[100], colors.darkGray[400])};\n      display: flex;\n      box-sizing: content-box;\n      align-items: center;\n      gap: ${tokens.size[1.5]};\n      max-width: 160px;\n      min-width: 100px;\n      border: 1px solid ${t(colors.gray[300], colors.darkGray[200])};\n      height: min-content;\n      color: ${t(colors.gray[600], colors.gray[400])};\n      & > svg {\n        width: ${size[3]};\n        height: ${size[3]};\n      }\n      & input {\n        font-size: ${font.size.xs};\n        width: 100%;\n        background-color: ${t(colors.gray[100], colors.darkGray[400])};\n        border: none;\n        padding: 0;\n        line-height: ${font.lineHeight.sm};\n        color: ${t(colors.gray[700], colors.gray[300])};\n        &::placeholder {\n          color: ${t(colors.gray[700], colors.gray[300])};\n        }\n        &:focus {\n          outline: none;\n        }\n      }\n\n      &:focus-within {\n        outline-offset: 2px;\n        border-radius: ${border.radius.xs};\n        outline: 2px solid ${colors.blue[800]};\n      }\n    `,\n    filterSelect: css`\n      padding: ${tokens.size[0.5]} ${tokens.size[2]};\n      border-radius: ${tokens.border.radius.sm};\n      background-color: ${t(colors.gray[100], colors.darkGray[400])};\n      display: flex;\n      align-items: center;\n      gap: ${tokens.size[1.5]};\n      box-sizing: content-box;\n      max-width: 160px;\n      border: 1px solid ${t(colors.gray[300], colors.darkGray[200])};\n      height: min-content;\n      & > svg {\n        color: ${t(colors.gray[600], colors.gray[400])};\n        width: ${tokens.size[2]};\n        height: ${tokens.size[2]};\n      }\n      & > select {\n        appearance: none;\n        color: ${t(colors.gray[700], colors.gray[300])};\n        min-width: 100px;\n        line-height: ${font.lineHeight.sm};\n        font-size: ${font.size.xs};\n        background-color: ${t(colors.gray[100], colors.darkGray[400])};\n        border: none;\n        &:focus {\n          outline: none;\n        }\n      }\n      &:focus-within {\n        outline-offset: 2px;\n        border-radius: ${border.radius.xs};\n        outline: 2px solid ${colors.blue[800]};\n      }\n    `,\n    actionsContainer: css`\n      display: flex;\n      gap: ${tokens.size[2]};\n    `,\n    actionsBtn: css`\n      border-radius: ${tokens.border.radius.sm};\n      background-color: ${t(colors.gray[100], colors.darkGray[400])};\n      border: 1px solid ${t(colors.gray[300], colors.darkGray[200])};\n      width: ${tokens.size[6.5]};\n      height: ${tokens.size[6.5]};\n      justify-content: center;\n      display: flex;\n      align-items: center;\n      gap: ${tokens.size[1.5]};\n      max-width: 160px;\n      cursor: pointer;\n      padding: 0;\n      &:hover {\n        background-color: ${t(colors.gray[200], colors.darkGray[500])};\n      }\n      & svg {\n        color: ${t(colors.gray[700], colors.gray[300])};\n        width: ${tokens.size[3]};\n        height: ${tokens.size[3]};\n      }\n      &:focus-visible {\n        outline-offset: 2px;\n        border-radius: ${border.radius.xs};\n        outline: 2px solid ${colors.blue[800]};\n      }\n    `,\n    actionsBtnOffline: css`\n      & svg {\n        stroke: ${t(colors.yellow[700], colors.yellow[500])};\n        fill: ${t(colors.yellow[700], colors.yellow[500])};\n      }\n    `,\n    overflowQueryContainer: css`\n      flex: 1;\n      overflow-y: auto;\n      & > div {\n        display: flex;\n        flex-direction: column;\n      }\n    `,\n    queryRow: css`\n      display: flex;\n      align-items: center;\n      padding: 0;\n      border: none;\n      cursor: pointer;\n      color: ${t(colors.gray[700], colors.gray[300])};\n      background-color: ${t(colors.gray[50], colors.darkGray[700])};\n      line-height: 1;\n      &:focus {\n        outline: none;\n      }\n      &:focus-visible {\n        outline-offset: -2px;\n        border-radius: ${border.radius.xs};\n        outline: 2px solid ${colors.blue[800]};\n      }\n      &:hover .tsqd-query-hash {\n        background-color: ${t(colors.gray[200], colors.darkGray[600])};\n      }\n\n      & .tsqd-query-observer-count {\n        padding: 0 ${tokens.size[1]};\n        user-select: none;\n        min-width: ${tokens.size[6.5]};\n        align-self: stretch;\n        display: flex;\n        align-items: center;\n        justify-content: center;\n        font-size: ${font.size.xs};\n        font-weight: ${font.weight.medium};\n        border-bottom-width: 1px;\n        border-bottom-style: solid;\n        border-bottom: 1px solid ${t(colors.gray[300], colors.darkGray[700])};\n      }\n      & .tsqd-query-hash {\n        user-select: text;\n        font-size: ${font.size.xs};\n        display: flex;\n        align-items: center;\n        min-height: ${tokens.size[6]};\n        flex: 1;\n        padding: ${tokens.size[1]} ${tokens.size[2]};\n        font-family:\n          ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,\n          'Liberation Mono', 'Courier New', monospace;\n        border-bottom: 1px solid ${t(colors.gray[300], colors.darkGray[400])};\n        text-align: left;\n        text-overflow: clip;\n        word-break: break-word;\n      }\n\n      & .tsqd-query-disabled-indicator {\n        align-self: stretch;\n        display: flex;\n        align-items: center;\n        padding: 0 ${tokens.size[2]};\n        color: ${t(colors.gray[800], colors.gray[300])};\n        background-color: ${t(colors.gray[300], colors.darkGray[600])};\n        border-bottom: 1px solid ${t(colors.gray[300], colors.darkGray[400])};\n        font-size: ${font.size.xs};\n      }\n\n      & .tsqd-query-static-indicator {\n        align-self: stretch;\n        display: flex;\n        align-items: center;\n        padding: 0 ${tokens.size[2]};\n        color: ${t(colors.teal[800], colors.teal[300])};\n        background-color: ${t(colors.teal[100], colors.teal[900])};\n        border-bottom: 1px solid ${t(colors.teal[300], colors.teal[700])};\n        font-size: ${font.size.xs};\n      }\n    `,\n    selectedQueryRow: css`\n      background-color: ${t(colors.gray[200], colors.darkGray[500])};\n    `,\n    detailsContainer: css`\n      flex: 1 1 700px;\n      background-color: ${t(colors.gray[50], colors.darkGray[700])};\n      color: ${t(colors.gray[700], colors.gray[300])};\n      font-family: ui-sans-serif, Inter, system-ui, sans-serif, sans-serif;\n      display: flex;\n      flex-direction: column;\n      overflow-y: auto;\n      display: flex;\n      text-align: left;\n    `,\n    detailsHeader: css`\n      font-family: ui-sans-serif, Inter, system-ui, sans-serif, sans-serif;\n      position: sticky;\n      top: 0;\n      z-index: 2;\n      background-color: ${t(colors.gray[200], colors.darkGray[600])};\n      padding: ${tokens.size[1.5]} ${tokens.size[2]};\n      font-weight: ${font.weight.medium};\n      font-size: ${font.size.xs};\n      line-height: ${font.lineHeight.xs};\n      text-align: left;\n    `,\n    detailsBody: css`\n      margin: ${tokens.size[1.5]} 0px ${tokens.size[2]} 0px;\n      & > div {\n        display: flex;\n        align-items: stretch;\n        padding: 0 ${tokens.size[2]};\n        line-height: ${font.lineHeight.sm};\n        justify-content: space-between;\n        & > span {\n          font-size: ${font.size.xs};\n        }\n        & > span:nth-child(2) {\n          font-variant-numeric: tabular-nums;\n        }\n      }\n\n      & > div:first-child {\n        margin-bottom: ${tokens.size[1.5]};\n      }\n\n      & code {\n        font-family:\n          ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,\n          'Liberation Mono', 'Courier New', monospace;\n        margin: 0;\n        font-size: ${font.size.xs};\n        line-height: ${font.lineHeight.xs};\n        max-width: 100%;\n        white-space: pre-wrap;\n        overflow-wrap: anywhere;\n        word-break: break-word;\n      }\n\n      & pre {\n        margin: 0;\n        display: flex;\n        align-items: center;\n      }\n    `,\n    queryDetailsStatus: css`\n      border: 1px solid ${colors.darkGray[200]};\n      border-radius: ${tokens.border.radius.sm};\n      font-weight: ${font.weight.medium};\n      padding: ${tokens.size[1]} ${tokens.size[2.5]};\n    `,\n    actionsBody: css`\n      flex-wrap: wrap;\n      margin: ${tokens.size[2]} 0px ${tokens.size[2]} 0px;\n      display: flex;\n      gap: ${tokens.size[2]};\n      padding: 0px ${tokens.size[2]};\n      & > button {\n        font-family: ui-sans-serif, Inter, system-ui, sans-serif, sans-serif;\n        font-size: ${font.size.xs};\n        padding: ${tokens.size[1]} ${tokens.size[2]};\n        display: flex;\n        border-radius: ${tokens.border.radius.sm};\n        background-color: ${t(colors.gray[100], colors.darkGray[600])};\n        border: 1px solid ${t(colors.gray[300], colors.darkGray[400])};\n        align-items: center;\n        gap: ${tokens.size[2]};\n        font-weight: ${font.weight.medium};\n        line-height: ${font.lineHeight.xs};\n        cursor: pointer;\n        &:focus-visible {\n          outline-offset: 2px;\n          border-radius: ${border.radius.xs};\n          outline: 2px solid ${colors.blue[800]};\n        }\n        &:hover {\n          background-color: ${t(colors.gray[200], colors.darkGray[500])};\n        }\n\n        &:disabled {\n          opacity: 0.6;\n          cursor: not-allowed;\n        }\n\n        & > span {\n          width: ${size[1.5]};\n          height: ${size[1.5]};\n          border-radius: ${tokens.border.radius.full};\n        }\n      }\n    `,\n    actionsSelect: css`\n      font-size: ${font.size.xs};\n      padding: ${tokens.size[0.5]} ${tokens.size[2]};\n      display: flex;\n      border-radius: ${tokens.border.radius.sm};\n      overflow: hidden;\n      background-color: ${t(colors.gray[100], colors.darkGray[600])};\n      border: 1px solid ${t(colors.gray[300], colors.darkGray[400])};\n      align-items: center;\n      gap: ${tokens.size[2]};\n      font-weight: ${font.weight.medium};\n      line-height: ${font.lineHeight.sm};\n      color: ${t(colors.red[500], colors.red[400])};\n      cursor: pointer;\n      position: relative;\n      &:hover {\n        background-color: ${t(colors.gray[200], colors.darkGray[500])};\n      }\n      & > span {\n        width: ${size[1.5]};\n        height: ${size[1.5]};\n        border-radius: ${tokens.border.radius.full};\n      }\n      &:focus-within {\n        outline-offset: 2px;\n        border-radius: ${border.radius.xs};\n        outline: 2px solid ${colors.blue[800]};\n      }\n      & select {\n        position: absolute;\n        top: 0;\n        left: 0;\n        width: 100%;\n        height: 100%;\n        appearance: none;\n        background-color: transparent;\n        border: none;\n        color: transparent;\n        outline: none;\n      }\n\n      & svg path {\n        stroke: ${tokens.colors.red[400]};\n      }\n      & svg {\n        width: ${tokens.size[2]};\n        height: ${tokens.size[2]};\n      }\n    `,\n    settingsMenu: css`\n      display: flex;\n      & * {\n        font-family: ui-sans-serif, Inter, system-ui, sans-serif, sans-serif;\n      }\n      flex-direction: column;\n      gap: ${size[0.5]};\n      border-radius: ${tokens.border.radius.sm};\n      border: 1px solid ${t(colors.gray[300], colors.gray[700])};\n      background-color: ${t(colors.gray[50], colors.darkGray[600])};\n      font-size: ${font.size.xs};\n      color: ${t(colors.gray[700], colors.gray[300])};\n      z-index: 99999;\n      min-width: 120px;\n      padding: ${size[0.5]};\n    `,\n    settingsSubTrigger: css`\n      display: flex;\n      align-items: center;\n      justify-content: space-between;\n      border-radius: ${tokens.border.radius.xs};\n      padding: ${tokens.size[1]} ${tokens.size[1]};\n      cursor: pointer;\n      background-color: transparent;\n      border: none;\n      color: ${t(colors.gray[700], colors.gray[300])};\n      & svg {\n        color: ${t(colors.gray[600], colors.gray[400])};\n        transform: rotate(-90deg);\n        width: ${tokens.size[2]};\n        height: ${tokens.size[2]};\n      }\n      &:hover {\n        background-color: ${t(colors.gray[200], colors.darkGray[500])};\n      }\n      &:focus-visible {\n        outline-offset: 2px;\n        outline: 2px solid ${colors.blue[800]};\n      }\n      &.data-disabled {\n        opacity: 0.6;\n        cursor: not-allowed;\n      }\n    `,\n    settingsMenuHeader: css`\n      padding: ${tokens.size[1]} ${tokens.size[1]};\n      font-weight: ${font.weight.medium};\n      border-bottom: 1px solid ${t(colors.gray[300], colors.darkGray[400])};\n      color: ${t(colors.gray[500], colors.gray[400])};\n      font-size: ${font.size['xs']};\n    `,\n    settingsSubButton: css`\n      display: flex;\n      align-items: center;\n      justify-content: space-between;\n      color: ${t(colors.gray[700], colors.gray[300])};\n      font-size: ${font.size['xs']};\n      border-radius: ${tokens.border.radius.xs};\n      padding: ${tokens.size[1]} ${tokens.size[1]};\n      cursor: pointer;\n      background-color: transparent;\n      border: none;\n      & svg {\n        color: ${t(colors.gray[600], colors.gray[400])};\n      }\n      &:hover {\n        background-color: ${t(colors.gray[200], colors.darkGray[500])};\n      }\n      &:focus-visible {\n        outline-offset: 2px;\n        outline: 2px solid ${colors.blue[800]};\n      }\n      &[data-checked] {\n        background-color: ${t(colors.purple[100], colors.purple[900])};\n        color: ${t(colors.purple[700], colors.purple[300])};\n        & svg {\n          color: ${t(colors.purple[700], colors.purple[300])};\n        }\n        &:hover {\n          background-color: ${t(colors.purple[100], colors.purple[900])};\n        }\n      }\n    `,\n    viewToggle: css`\n      border-radius: ${tokens.border.radius.sm};\n      background-color: ${t(colors.gray[200], colors.darkGray[600])};\n      border: 1px solid ${t(colors.gray[300], colors.darkGray[200])};\n      display: flex;\n      padding: 0;\n      font-size: ${font.size.xs};\n      color: ${t(colors.gray[700], colors.gray[300])};\n      overflow: hidden;\n\n      &:has(:focus-visible) {\n        outline: 2px solid ${colors.blue[800]};\n      }\n\n      & .tsqd-radio-toggle {\n        opacity: 0.5;\n        display: flex;\n        & label {\n          display: flex;\n          align-items: center;\n          cursor: pointer;\n          line-height: ${font.lineHeight.md};\n        }\n\n        & label:hover {\n          background-color: ${t(colors.gray[100], colors.darkGray[500])};\n        }\n      }\n\n      & > [data-checked] {\n        opacity: 1;\n        background-color: ${t(colors.gray[100], colors.darkGray[400])};\n        & label:hover {\n          background-color: ${t(colors.gray[100], colors.darkGray[400])};\n        }\n      }\n\n      & .tsqd-radio-toggle:first-child {\n        & label {\n          padding: 0 ${tokens.size[1.5]} 0 ${tokens.size[2]};\n        }\n        border-right: 1px solid ${t(colors.gray[300], colors.darkGray[200])};\n      }\n\n      & .tsqd-radio-toggle:nth-child(2) {\n        & label {\n          padding: 0 ${tokens.size[2]} 0 ${tokens.size[1.5]};\n        }\n      }\n    `,\n    devtoolsEditForm: css`\n      padding: ${size[2]};\n      & > [data-error='true'] {\n        outline: 2px solid ${t(colors.red[200], colors.red[800])};\n        outline-offset: 2px;\n        border-radius: ${border.radius.xs};\n      }\n    `,\n    devtoolsEditTextarea: css`\n      width: 100%;\n      max-height: 500px;\n      font-family: 'Fira Code', monospace;\n      font-size: ${font.size.xs};\n      border-radius: ${border.radius.sm};\n      field-sizing: content;\n      padding: ${size[2]};\n      background-color: ${t(colors.gray[100], colors.darkGray[800])};\n      color: ${t(colors.gray[900], colors.gray[100])};\n      border: 1px solid ${t(colors.gray[200], colors.gray[700])};\n      resize: none;\n      &:focus {\n        outline-offset: 2px;\n        border-radius: ${border.radius.xs};\n        outline: 2px solid ${t(colors.blue[200], colors.blue[800])};\n      }\n    `,\n    devtoolsEditFormActions: css`\n      display: flex;\n      justify-content: space-between;\n      gap: ${size[2]};\n      align-items: center;\n      padding-top: ${size[1]};\n      font-size: ${font.size.xs};\n    `,\n    devtoolsEditFormError: css`\n      color: ${t(colors.red[700], colors.red[500])};\n    `,\n    devtoolsEditFormActionContainer: css`\n      display: flex;\n      gap: ${size[2]};\n    `,\n    devtoolsEditFormAction: css`\n      font-family: ui-sans-serif, Inter, system-ui, sans-serif, sans-serif;\n      font-size: ${font.size.xs};\n      padding: ${size[1]} ${tokens.size[2]};\n      display: flex;\n      border-radius: ${border.radius.sm};\n      background-color: ${t(colors.gray[100], colors.darkGray[600])};\n      border: 1px solid ${t(colors.gray[300], colors.darkGray[400])};\n      align-items: center;\n      gap: ${size[2]};\n      font-weight: ${font.weight.medium};\n      line-height: ${font.lineHeight.xs};\n      cursor: pointer;\n      &:focus-visible {\n        outline-offset: 2px;\n        border-radius: ${border.radius.xs};\n        outline: 2px solid ${colors.blue[800]};\n      }\n      &:hover {\n        background-color: ${t(colors.gray[200], colors.darkGray[500])};\n      }\n\n      &:disabled {\n        opacity: 0.6;\n        cursor: not-allowed;\n      }\n    `,\n  }\n}\n\nconst lightStyles = (css: (typeof goober)['css']) => stylesFactory('light', css)\nconst darkStyles = (css: (typeof goober)['css']) => stylesFactory('dark', css)\n"
  },
  {
    "path": "packages/query-devtools/src/DevtoolsComponent.tsx",
    "content": "import { createLocalStorage } from '@solid-primitives/storage'\nimport { createMemo } from 'solid-js'\nimport { Devtools } from './Devtools'\nimport { getPreferredColorScheme } from './utils'\nimport { THEME_PREFERENCE } from './constants'\nimport { PiPProvider, QueryDevtoolsContext, ThemeContext } from './contexts'\nimport type { Theme } from './contexts'\nimport type { DevtoolsComponentType } from './Devtools'\n\nconst DevtoolsComponent: DevtoolsComponentType = (props) => {\n  const [localStore, setLocalStore] = createLocalStorage({\n    prefix: 'TanstackQueryDevtools',\n  })\n\n  const colorScheme = getPreferredColorScheme()\n\n  const theme = createMemo(() => {\n    const preference = (props.theme ||\n      localStore.theme_preference ||\n      THEME_PREFERENCE) as Theme\n    if (preference !== 'system') return preference\n    return colorScheme()\n  })\n\n  return (\n    <QueryDevtoolsContext.Provider value={props}>\n      <PiPProvider localStore={localStore} setLocalStore={setLocalStore}>\n        <ThemeContext.Provider value={theme}>\n          <Devtools localStore={localStore} setLocalStore={setLocalStore} />\n        </ThemeContext.Provider>\n      </PiPProvider>\n    </QueryDevtoolsContext.Provider>\n  )\n}\n\nexport default DevtoolsComponent\n"
  },
  {
    "path": "packages/query-devtools/src/DevtoolsPanelComponent.tsx",
    "content": "import { createLocalStorage } from '@solid-primitives/storage'\nimport { createMemo } from 'solid-js'\nimport { ContentView, ParentPanel } from './Devtools'\nimport { getPreferredColorScheme } from './utils'\nimport { THEME_PREFERENCE } from './constants'\nimport { PiPProvider, QueryDevtoolsContext, ThemeContext } from './contexts'\nimport type { Theme } from './contexts'\nimport type { DevtoolsComponentType } from './Devtools'\n\nconst DevtoolsPanelComponent: DevtoolsComponentType = (props) => {\n  const [localStore, setLocalStore] = createLocalStorage({\n    prefix: 'TanstackQueryDevtools',\n  })\n\n  const colorScheme = getPreferredColorScheme()\n\n  const theme = createMemo(() => {\n    const preference = (props.theme ||\n      localStore.theme_preference ||\n      THEME_PREFERENCE) as Theme\n    if (preference !== 'system') return preference\n    return colorScheme()\n  })\n\n  return (\n    <QueryDevtoolsContext.Provider value={props}>\n      <PiPProvider\n        disabled\n        localStore={localStore}\n        setLocalStore={setLocalStore}\n      >\n        <ThemeContext.Provider value={theme}>\n          <ParentPanel>\n            <ContentView\n              localStore={localStore}\n              setLocalStore={setLocalStore}\n              onClose={props.onClose}\n              showPanelViewOnly\n            />\n          </ParentPanel>\n        </ThemeContext.Provider>\n      </PiPProvider>\n    </QueryDevtoolsContext.Provider>\n  )\n}\n\nexport default DevtoolsPanelComponent\n"
  },
  {
    "path": "packages/query-devtools/src/Explorer.tsx",
    "content": "import { serialize, stringify } from 'superjson'\nimport { clsx as cx } from 'clsx'\nimport {\n  Index,\n  Match,\n  Show,\n  Switch,\n  createMemo,\n  createSignal,\n  createUniqueId,\n} from 'solid-js'\nimport { Key } from '@solid-primitives/keyed'\nimport * as goober from 'goober'\nimport { tokens } from './theme'\nimport {\n  deleteNestedDataByPath,\n  displayValue,\n  updateNestedDataByPath,\n} from './utils'\nimport {\n  Check,\n  CopiedCopier,\n  Copier,\n  ErrorCopier,\n  List,\n  Pencil,\n  Trash,\n} from './icons'\nimport { useQueryDevtoolsContext, useTheme } from './contexts'\nimport type { Query } from '@tanstack/query-core'\n\n/**\n * Chunk elements in the array by size\n *\n * when the array cannot be chunked evenly by size, the last chunk will be\n * filled with the remaining elements\n *\n * @example\n * chunkArray(['a','b', 'c', 'd', 'e'], 2) // returns [['a','b'], ['c', 'd'], ['e']]\n */\nfunction chunkArray<T extends { label: string; value: unknown }>(\n  array: Array<T>,\n  size: number,\n): Array<Array<T>> {\n  if (size < 1) return []\n  let i = 0\n  const result: Array<Array<T>> = []\n  while (i < array.length) {\n    result.push(array.slice(i, i + size))\n    i = i + size\n  }\n  return result\n}\n\nconst Expander = (props: { expanded: boolean }) => {\n  const theme = useTheme()\n  const css = useQueryDevtoolsContext().shadowDOMTarget\n    ? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })\n    : goober.css\n  const styles = createMemo(() => {\n    return theme() === 'dark' ? darkStyles(css) : lightStyles(css)\n  })\n\n  return (\n    <span\n      class={cx(\n        styles().expander,\n        css`\n          transform: rotate(${props.expanded ? 90 : 0}deg);\n        `,\n        props.expanded &&\n          css`\n            & svg {\n              top: -1px;\n            }\n          `,\n      )}\n    >\n      <svg\n        width=\"16\"\n        height=\"16\"\n        viewBox=\"0 0 16 16\"\n        fill=\"none\"\n        xmlns=\"http://www.w3.org/2000/svg\"\n      >\n        <path\n          d=\"M6 12L10 8L6 4\"\n          stroke-width=\"2\"\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"round\"\n        />\n      </svg>\n    </span>\n  )\n}\n\ntype CopyState = 'NoCopy' | 'SuccessCopy' | 'ErrorCopy'\nconst CopyButton = (props: { value: unknown }) => {\n  const theme = useTheme()\n  const css = useQueryDevtoolsContext().shadowDOMTarget\n    ? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })\n    : goober.css\n  const styles = createMemo(() => {\n    return theme() === 'dark' ? darkStyles(css) : lightStyles(css)\n  })\n  const [copyState, setCopyState] = createSignal<CopyState>('NoCopy')\n\n  return (\n    <button\n      class={styles().actionButton}\n      title=\"Copy object to clipboard\"\n      aria-label={`${\n        copyState() === 'NoCopy'\n          ? 'Copy object to clipboard'\n          : copyState() === 'SuccessCopy'\n            ? 'Object copied to clipboard'\n            : 'Error copying object to clipboard'\n      }`}\n      onClick={\n        copyState() === 'NoCopy'\n          ? () => {\n              navigator.clipboard.writeText(stringify(props.value)).then(\n                () => {\n                  setCopyState('SuccessCopy')\n                  setTimeout(() => {\n                    setCopyState('NoCopy')\n                  }, 1500)\n                },\n                (err) => {\n                  console.error('Failed to copy: ', err)\n                  setCopyState('ErrorCopy')\n                  setTimeout(() => {\n                    setCopyState('NoCopy')\n                  }, 1500)\n                },\n              )\n            }\n          : undefined\n      }\n    >\n      <Switch>\n        <Match when={copyState() === 'NoCopy'}>\n          <Copier />\n        </Match>\n        <Match when={copyState() === 'SuccessCopy'}>\n          <CopiedCopier theme={theme()} />\n        </Match>\n        <Match when={copyState() === 'ErrorCopy'}>\n          <ErrorCopier />\n        </Match>\n      </Switch>\n    </button>\n  )\n}\n\nconst ClearArrayButton = (props: {\n  dataPath: Array<string>\n  activeQuery: Query\n}) => {\n  const theme = useTheme()\n  const css = useQueryDevtoolsContext().shadowDOMTarget\n    ? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })\n    : goober.css\n  const styles = createMemo(() => {\n    return theme() === 'dark' ? darkStyles(css) : lightStyles(css)\n  })\n  const queryClient = useQueryDevtoolsContext().client\n\n  return (\n    <button\n      class={styles().actionButton}\n      title={'Remove all items'}\n      aria-label={'Remove all items'}\n      onClick={() => {\n        const oldData = props.activeQuery.state.data\n        const newData = updateNestedDataByPath(oldData, props.dataPath, [])\n        queryClient.setQueryData(props.activeQuery.queryKey, newData)\n      }}\n    >\n      <List />\n    </button>\n  )\n}\n\nconst DeleteItemButton = (props: {\n  dataPath: Array<string>\n  activeQuery: Query\n}) => {\n  const theme = useTheme()\n  const css = useQueryDevtoolsContext().shadowDOMTarget\n    ? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })\n    : goober.css\n  const styles = createMemo(() => {\n    return theme() === 'dark' ? darkStyles(css) : lightStyles(css)\n  })\n  const queryClient = useQueryDevtoolsContext().client\n\n  return (\n    <button\n      class={cx(styles().actionButton)}\n      title={'Delete item'}\n      aria-label={'Delete item'}\n      onClick={() => {\n        const oldData = props.activeQuery.state.data\n        const newData = deleteNestedDataByPath(oldData, props.dataPath)\n        queryClient.setQueryData(props.activeQuery.queryKey, newData)\n      }}\n    >\n      <Trash />\n    </button>\n  )\n}\n\nconst ToggleValueButton = (props: {\n  dataPath: Array<string>\n  activeQuery: Query\n  value: boolean\n}) => {\n  const theme = useTheme()\n  const css = useQueryDevtoolsContext().shadowDOMTarget\n    ? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })\n    : goober.css\n  const styles = createMemo(() => {\n    return theme() === 'dark' ? darkStyles(css) : lightStyles(css)\n  })\n  const queryClient = useQueryDevtoolsContext().client\n\n  return (\n    <button\n      class={cx(\n        styles().actionButton,\n        css`\n          width: ${tokens.size[3.5]};\n          height: ${tokens.size[3.5]};\n        `,\n      )}\n      title={'Toggle value'}\n      aria-label={'Toggle value'}\n      onClick={() => {\n        const oldData = props.activeQuery.state.data\n        const newData = updateNestedDataByPath(\n          oldData,\n          props.dataPath,\n          !props.value,\n        )\n        queryClient.setQueryData(props.activeQuery.queryKey, newData)\n      }}\n    >\n      <Check theme={theme()} checked={props.value} />\n    </button>\n  )\n}\n\ntype ExplorerProps = {\n  editable?: boolean\n  label: string\n  value: unknown\n  defaultExpanded?: Array<string>\n  dataPath?: Array<string>\n  activeQuery?: Query\n  itemsDeletable?: boolean\n  onEdit?: () => void\n}\n\nfunction isIterable(x: any): x is Iterable<unknown> {\n  return Symbol.iterator in x\n}\n\nexport default function Explorer(props: ExplorerProps) {\n  const theme = useTheme()\n  const css = useQueryDevtoolsContext().shadowDOMTarget\n    ? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })\n    : goober.css\n  const styles = createMemo(() => {\n    return theme() === 'dark' ? darkStyles(css) : lightStyles(css)\n  })\n  const queryClient = useQueryDevtoolsContext().client\n\n  const [expanded, setExpanded] = createSignal(\n    (props.defaultExpanded || []).includes(props.label),\n  )\n  const toggleExpanded = () => setExpanded((old) => !old)\n  const [expandedPages, setExpandedPages] = createSignal<Array<number>>([])\n\n  const subEntries = createMemo(() => {\n    if (Array.isArray(props.value)) {\n      return props.value.map((d, i) => ({\n        label: i.toString(),\n        value: d,\n      }))\n    } else if (\n      props.value !== null &&\n      typeof props.value === 'object' &&\n      isIterable(props.value) &&\n      typeof props.value[Symbol.iterator] === 'function'\n    ) {\n      if (props.value instanceof Map) {\n        return Array.from(props.value, ([key, val]) => ({\n          label: key,\n          value: val,\n        }))\n      }\n      return Array.from(props.value, (val, i) => ({\n        label: i.toString(),\n        value: val,\n      }))\n    } else if (typeof props.value === 'object' && props.value !== null) {\n      return Object.entries(props.value).map(([key, val]) => ({\n        label: key,\n        value: val,\n      }))\n    }\n    return []\n  })\n\n  const type = createMemo<string>(() => {\n    if (Array.isArray(props.value)) {\n      return 'array'\n    } else if (\n      props.value !== null &&\n      typeof props.value === 'object' &&\n      isIterable(props.value) &&\n      typeof props.value[Symbol.iterator] === 'function'\n    ) {\n      return 'Iterable'\n    } else if (typeof props.value === 'object' && props.value !== null) {\n      return 'object'\n    }\n    return typeof props.value\n  })\n\n  const subEntryPages = createMemo(() => chunkArray(subEntries(), 100))\n\n  const currentDataPath = props.dataPath ?? []\n\n  const inputId = createUniqueId()\n\n  return (\n    <div class={styles().entry}>\n      <Show when={subEntryPages().length}>\n        <div class={styles().expanderButtonContainer}>\n          <button\n            class={styles().expanderButton}\n            onClick={() => toggleExpanded()}\n            aria-expanded={expanded() ? 'true' : 'false'}\n          >\n            <Expander expanded={expanded()} /> <span>{props.label}</span>{' '}\n            <span class={styles().info}>\n              {String(type()).toLowerCase() === 'iterable' ? '(Iterable) ' : ''}\n              {subEntries().length} {subEntries().length > 1 ? `items` : `item`}\n            </span>\n          </button>\n          <Show when={props.editable}>\n            <div class={styles().actions}>\n              <CopyButton value={props.value} />\n\n              <Show\n                when={props.itemsDeletable && props.activeQuery !== undefined}\n              >\n                <DeleteItemButton\n                  activeQuery={props.activeQuery!}\n                  dataPath={currentDataPath}\n                />\n              </Show>\n\n              <Show\n                when={type() === 'array' && props.activeQuery !== undefined}\n              >\n                <ClearArrayButton\n                  activeQuery={props.activeQuery!}\n                  dataPath={currentDataPath}\n                />\n              </Show>\n\n              <Show when={!!props.onEdit && !serialize(props.value).meta}>\n                <button\n                  class={styles().actionButton}\n                  title={'Bulk Edit Data'}\n                  aria-label={'Bulk Edit Data'}\n                  onClick={() => {\n                    props.onEdit?.()\n                  }}\n                >\n                  <Pencil />\n                </button>\n              </Show>\n            </div>\n          </Show>\n        </div>\n        <Show when={expanded()}>\n          <Show when={subEntryPages().length === 1}>\n            <div class={styles().subEntry}>\n              <Key each={subEntries()} by={(item) => item.label}>\n                {(entry) => {\n                  return (\n                    <Explorer\n                      defaultExpanded={props.defaultExpanded}\n                      label={entry().label}\n                      value={entry().value}\n                      editable={props.editable}\n                      dataPath={[...currentDataPath, entry().label]}\n                      activeQuery={props.activeQuery}\n                      itemsDeletable={\n                        type() === 'array' ||\n                        type() === 'Iterable' ||\n                        type() === 'object'\n                      }\n                    />\n                  )\n                }}\n              </Key>\n            </div>\n          </Show>\n          <Show when={subEntryPages().length > 1}>\n            <div class={styles().subEntry}>\n              <Index each={subEntryPages()}>\n                {(entries, index) => (\n                  <div>\n                    <div class={styles().entry}>\n                      <button\n                        onClick={() =>\n                          setExpandedPages((old) =>\n                            old.includes(index)\n                              ? old.filter((d) => d !== index)\n                              : [...old, index],\n                          )\n                        }\n                        class={styles().expanderButton}\n                      >\n                        <Expander expanded={expandedPages().includes(index)} />{' '}\n                        [{index * 100}...\n                        {index * 100 + 100 - 1}]\n                      </button>\n                      <Show when={expandedPages().includes(index)}>\n                        <div class={styles().subEntry}>\n                          <Key each={entries()} by={(entry) => entry.label}>\n                            {(entry) => (\n                              <Explorer\n                                defaultExpanded={props.defaultExpanded}\n                                label={entry().label}\n                                value={entry().value}\n                                editable={props.editable}\n                                dataPath={[...currentDataPath, entry().label]}\n                                activeQuery={props.activeQuery}\n                              />\n                            )}\n                          </Key>\n                        </div>\n                      </Show>\n                    </div>\n                  </div>\n                )}\n              </Index>\n            </div>\n          </Show>\n        </Show>\n      </Show>\n      <Show when={subEntryPages().length === 0}>\n        <div class={styles().row}>\n          <label for={inputId} class={styles().label}>\n            {props.label}:\n          </label>\n          <Show\n            when={\n              props.editable &&\n              props.activeQuery !== undefined &&\n              (type() === 'string' ||\n                type() === 'number' ||\n                type() === 'boolean')\n            }\n            fallback={\n              <span class={styles().value}>{displayValue(props.value)}</span>\n            }\n          >\n            <Show\n              when={\n                props.editable &&\n                props.activeQuery !== undefined &&\n                (type() === 'string' || type() === 'number')\n              }\n            >\n              <input\n                id={inputId}\n                type={type() === 'number' ? 'number' : 'text'}\n                class={cx(styles().value, styles().editableInput)}\n                value={props.value as string | number}\n                onChange={(changeEvent) => {\n                  const oldData = props.activeQuery!.state.data\n\n                  const newData = updateNestedDataByPath(\n                    oldData,\n                    currentDataPath,\n                    type() === 'number'\n                      ? changeEvent.target.valueAsNumber\n                      : changeEvent.target.value,\n                  )\n\n                  queryClient.setQueryData(props.activeQuery!.queryKey, newData)\n                }}\n              />\n            </Show>\n\n            <Show when={type() === 'boolean'}>\n              <span\n                class={cx(\n                  styles().value,\n                  styles().actions,\n                  styles().editableInput,\n                )}\n              >\n                <ToggleValueButton\n                  activeQuery={props.activeQuery!}\n                  dataPath={currentDataPath}\n                  value={props.value as boolean}\n                />\n                {displayValue(props.value)}\n              </span>\n            </Show>\n          </Show>\n\n          <Show\n            when={\n              props.editable &&\n              props.itemsDeletable &&\n              props.activeQuery !== undefined\n            }\n          >\n            <DeleteItemButton\n              activeQuery={props.activeQuery!}\n              dataPath={currentDataPath}\n            />\n          </Show>\n        </div>\n      </Show>\n    </div>\n  )\n}\n\nconst stylesFactory = (\n  theme: 'light' | 'dark',\n  css: (typeof goober)['css'],\n) => {\n  const { colors, font, size, border } = tokens\n  const t = (light: string, dark: string) => (theme === 'light' ? light : dark)\n  return {\n    entry: css`\n      & * {\n        font-size: ${font.size.xs};\n        font-family:\n          ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,\n          'Liberation Mono', 'Courier New', monospace;\n      }\n      position: relative;\n      outline: none;\n      word-break: break-word;\n    `,\n    subEntry: css`\n      margin: 0 0 0 0.5em;\n      padding-left: 0.75em;\n      border-left: 2px solid ${t(colors.gray[300], colors.darkGray[400])};\n      /* outline: 1px solid ${colors.teal[400]}; */\n    `,\n    expander: css`\n      & path {\n        stroke: ${colors.gray[400]};\n      }\n      & svg {\n        width: ${size[3]};\n        height: ${size[3]};\n      }\n      display: inline-flex;\n      align-items: center;\n      transition: all 0.1s ease;\n      /* outline: 1px solid ${colors.blue[400]}; */\n    `,\n    expanderButtonContainer: css`\n      display: flex;\n      align-items: center;\n      line-height: ${size[4]};\n      min-height: ${size[4]};\n      gap: ${size[2]};\n    `,\n    expanderButton: css`\n      cursor: pointer;\n      color: inherit;\n      font: inherit;\n      outline: inherit;\n      height: ${size[5]};\n      background: transparent;\n      border: none;\n      padding: 0;\n      display: inline-flex;\n      align-items: center;\n      gap: ${size[1]};\n      position: relative;\n      /* outline: 1px solid ${colors.green[400]}; */\n\n      &:focus-visible {\n        border-radius: ${border.radius.xs};\n        outline: 2px solid ${colors.blue[800]};\n      }\n\n      & svg {\n        position: relative;\n        left: 1px;\n      }\n    `,\n    info: css`\n      color: ${t(colors.gray[500], colors.gray[500])};\n      font-size: ${font.size.xs};\n      margin-left: ${size[1]};\n      /* outline: 1px solid ${colors.yellow[400]}; */\n    `,\n    label: css`\n      color: ${t(colors.gray[700], colors.gray[300])};\n      white-space: nowrap;\n    `,\n    value: css`\n      color: ${t(colors.purple[600], colors.purple[400])};\n      flex-grow: 1;\n    `,\n    actions: css`\n      display: inline-flex;\n      gap: ${size[2]};\n      align-items: center;\n    `,\n    row: css`\n      display: inline-flex;\n      gap: ${size[2]};\n      width: 100%;\n      margin: ${size[0.25]} 0px;\n      line-height: ${size[4.5]};\n      align-items: center;\n    `,\n    editableInput: css`\n      border: none;\n      padding: ${size[0.5]} ${size[1]} ${size[0.5]} ${size[1.5]};\n      flex-grow: 1;\n      border-radius: ${border.radius.xs};\n      background-color: ${t(colors.gray[200], colors.darkGray[500])};\n\n      &:hover {\n        background-color: ${t(colors.gray[300], colors.darkGray[600])};\n      }\n    `,\n    actionButton: css`\n      background-color: transparent;\n      color: ${t(colors.gray[500], colors.gray[500])};\n      border: none;\n      display: inline-flex;\n      padding: 0px;\n      align-items: center;\n      justify-content: center;\n      cursor: pointer;\n      width: ${size[3]};\n      height: ${size[3]};\n      position: relative;\n      z-index: 1;\n\n      &:hover svg {\n        color: ${t(colors.gray[600], colors.gray[400])};\n      }\n\n      &:focus-visible {\n        border-radius: ${border.radius.xs};\n        outline: 2px solid ${colors.blue[800]};\n        outline-offset: 2px;\n      }\n    `,\n  }\n}\n\nconst lightStyles = (css: (typeof goober)['css']) => stylesFactory('light', css)\nconst darkStyles = (css: (typeof goober)['css']) => stylesFactory('dark', css)\n"
  },
  {
    "path": "packages/query-devtools/src/TanstackQueryDevtools.tsx",
    "content": "import { render } from 'solid-js/web'\nimport { createSignal, lazy } from 'solid-js'\nimport { setupStyleSheet } from './utils'\nimport type {\n  QueryClient,\n  onlineManager as TOnlineManager,\n} from '@tanstack/query-core'\nimport type { DevtoolsComponentType } from './Devtools'\nimport type {\n  DevtoolsButtonPosition,\n  DevtoolsErrorType,\n  DevtoolsPosition,\n  QueryDevtoolsProps,\n  Theme,\n} from './contexts'\nimport type { Signal } from 'solid-js'\n\nexport interface TanstackQueryDevtoolsConfig extends QueryDevtoolsProps {\n  styleNonce?: string\n  shadowDOMTarget?: ShadowRoot\n}\n\nclass TanstackQueryDevtools {\n  #client: Signal<QueryClient>\n  #onlineManager: typeof TOnlineManager\n  #queryFlavor: string\n  #version: string\n  #isMounted = false\n  #styleNonce?: string\n  #shadowDOMTarget?: ShadowRoot\n  #buttonPosition: Signal<DevtoolsButtonPosition | undefined>\n  #position: Signal<DevtoolsPosition | undefined>\n  #initialIsOpen: Signal<boolean | undefined>\n  #errorTypes: Signal<Array<DevtoolsErrorType> | undefined>\n  #hideDisabledQueries: Signal<boolean | undefined>\n  #Component: DevtoolsComponentType | undefined\n  #theme: Signal<Theme | undefined>\n  #dispose?: () => void\n\n  constructor(config: TanstackQueryDevtoolsConfig) {\n    const {\n      client,\n      queryFlavor,\n      version,\n      onlineManager,\n      buttonPosition,\n      position,\n      initialIsOpen,\n      errorTypes,\n      styleNonce,\n      shadowDOMTarget,\n      hideDisabledQueries,\n      theme,\n    } = config\n    this.#client = createSignal(client)\n    this.#queryFlavor = queryFlavor\n    this.#version = version\n    this.#onlineManager = onlineManager\n    this.#styleNonce = styleNonce\n    this.#shadowDOMTarget = shadowDOMTarget\n    this.#buttonPosition = createSignal(buttonPosition)\n    this.#position = createSignal(position)\n    this.#initialIsOpen = createSignal(initialIsOpen)\n    this.#errorTypes = createSignal(errorTypes)\n    this.#hideDisabledQueries = createSignal(hideDisabledQueries)\n    this.#theme = createSignal(theme)\n  }\n\n  setButtonPosition(position: DevtoolsButtonPosition) {\n    this.#buttonPosition[1](position)\n  }\n\n  setPosition(position: DevtoolsPosition) {\n    this.#position[1](position)\n  }\n\n  setInitialIsOpen(isOpen: boolean) {\n    this.#initialIsOpen[1](isOpen)\n  }\n\n  setErrorTypes(errorTypes: Array<DevtoolsErrorType>) {\n    this.#errorTypes[1](errorTypes)\n  }\n\n  setClient(client: QueryClient) {\n    this.#client[1](client)\n  }\n\n  setTheme(theme?: Theme) {\n    this.#theme[1](theme)\n  }\n\n  mount<T extends HTMLElement>(el: T) {\n    if (this.#isMounted) {\n      throw new Error('Devtools is already mounted')\n    }\n    const dispose = render(() => {\n      const [btnPosition] = this.#buttonPosition\n      const [pos] = this.#position\n      const [isOpen] = this.#initialIsOpen\n      const [errors] = this.#errorTypes\n      const [hideDisabledQueries] = this.#hideDisabledQueries\n      const [queryClient] = this.#client\n      const [theme] = this.#theme\n      let Devtools: DevtoolsComponentType\n\n      if (this.#Component) {\n        Devtools = this.#Component\n      } else {\n        Devtools = lazy(() => import('./DevtoolsComponent'))\n        this.#Component = Devtools\n      }\n\n      setupStyleSheet(this.#styleNonce, this.#shadowDOMTarget)\n      return (\n        <Devtools\n          queryFlavor={this.#queryFlavor}\n          version={this.#version}\n          onlineManager={this.#onlineManager}\n          shadowDOMTarget={this.#shadowDOMTarget}\n          {...{\n            get client() {\n              return queryClient()\n            },\n            get buttonPosition() {\n              return btnPosition()\n            },\n            get position() {\n              return pos()\n            },\n            get initialIsOpen() {\n              return isOpen()\n            },\n            get errorTypes() {\n              return errors()\n            },\n            get hideDisabledQueries() {\n              return hideDisabledQueries()\n            },\n            get theme() {\n              return theme()\n            },\n          }}\n        />\n      )\n    }, el)\n    this.#isMounted = true\n    this.#dispose = dispose\n  }\n\n  unmount() {\n    if (!this.#isMounted) {\n      throw new Error('Devtools is not mounted')\n    }\n    this.#dispose?.()\n    this.#isMounted = false\n  }\n}\n\nexport { TanstackQueryDevtools }\n"
  },
  {
    "path": "packages/query-devtools/src/TanstackQueryDevtoolsPanel.tsx",
    "content": "import { render } from 'solid-js/web'\nimport { createSignal, lazy } from 'solid-js'\nimport { setupStyleSheet } from './utils'\nimport type {\n  QueryClient,\n  onlineManager as TOnlineManager,\n} from '@tanstack/query-core'\nimport type { DevtoolsComponentType } from './Devtools'\nimport type {\n  DevtoolsButtonPosition,\n  DevtoolsErrorType,\n  DevtoolsPosition,\n  QueryDevtoolsProps,\n  Theme,\n} from './contexts'\nimport type { Signal } from 'solid-js'\n\nexport interface TanstackQueryDevtoolsPanelConfig extends QueryDevtoolsProps {\n  styleNonce?: string\n  shadowDOMTarget?: ShadowRoot\n  onClose?: () => unknown\n}\n\nclass TanstackQueryDevtoolsPanel {\n  #client: Signal<QueryClient>\n  #onlineManager: typeof TOnlineManager\n  #queryFlavor: string\n  #version: string\n  #isMounted = false\n  #styleNonce?: string\n  #shadowDOMTarget?: ShadowRoot\n  #buttonPosition: Signal<DevtoolsButtonPosition | undefined>\n  #position: Signal<DevtoolsPosition | undefined>\n  #initialIsOpen: Signal<boolean | undefined>\n  #errorTypes: Signal<Array<DevtoolsErrorType> | undefined>\n  #hideDisabledQueries: Signal<boolean | undefined>\n  #onClose: Signal<(() => unknown) | undefined>\n  #Component: DevtoolsComponentType | undefined\n  #theme: Signal<Theme | undefined>\n  #dispose?: () => void\n\n  constructor(config: TanstackQueryDevtoolsPanelConfig) {\n    const {\n      client,\n      queryFlavor,\n      version,\n      onlineManager,\n      buttonPosition,\n      position,\n      initialIsOpen,\n      errorTypes,\n      styleNonce,\n      shadowDOMTarget,\n      onClose,\n      hideDisabledQueries,\n      theme,\n    } = config\n    this.#client = createSignal(client)\n    this.#queryFlavor = queryFlavor\n    this.#version = version\n    this.#onlineManager = onlineManager\n    this.#styleNonce = styleNonce\n    this.#shadowDOMTarget = shadowDOMTarget\n    this.#buttonPosition = createSignal(buttonPosition)\n    this.#position = createSignal(position)\n    this.#initialIsOpen = createSignal(initialIsOpen)\n    this.#errorTypes = createSignal(errorTypes)\n    this.#hideDisabledQueries = createSignal(hideDisabledQueries)\n    this.#onClose = createSignal(onClose)\n    this.#theme = createSignal(theme)\n  }\n\n  setButtonPosition(position: DevtoolsButtonPosition) {\n    this.#buttonPosition[1](position)\n  }\n\n  setPosition(position: DevtoolsPosition) {\n    this.#position[1](position)\n  }\n\n  setInitialIsOpen(isOpen: boolean) {\n    this.#initialIsOpen[1](isOpen)\n  }\n\n  setErrorTypes(errorTypes: Array<DevtoolsErrorType>) {\n    this.#errorTypes[1](errorTypes)\n  }\n\n  setClient(client: QueryClient) {\n    this.#client[1](client)\n  }\n\n  setOnClose(onClose: () => unknown) {\n    this.#onClose[1](() => onClose)\n  }\n\n  setTheme(theme?: Theme) {\n    this.#theme[1](theme)\n  }\n\n  mount<T extends HTMLElement>(el: T) {\n    if (this.#isMounted) {\n      throw new Error('Devtools is already mounted')\n    }\n    const dispose = render(() => {\n      const [btnPosition] = this.#buttonPosition\n      const [pos] = this.#position\n      const [isOpen] = this.#initialIsOpen\n      const [errors] = this.#errorTypes\n      const [hideDisabledQueries] = this.#hideDisabledQueries\n      const [queryClient] = this.#client\n      const [onClose] = this.#onClose\n      const [theme] = this.#theme\n      let Devtools: DevtoolsComponentType\n\n      if (this.#Component) {\n        Devtools = this.#Component\n      } else {\n        Devtools = lazy(() => import('./DevtoolsPanelComponent'))\n        this.#Component = Devtools\n      }\n\n      setupStyleSheet(this.#styleNonce, this.#shadowDOMTarget)\n      return (\n        <Devtools\n          queryFlavor={this.#queryFlavor}\n          version={this.#version}\n          onlineManager={this.#onlineManager}\n          shadowDOMTarget={this.#shadowDOMTarget}\n          {...{\n            get client() {\n              return queryClient()\n            },\n            get buttonPosition() {\n              return btnPosition()\n            },\n            get position() {\n              return pos()\n            },\n            get initialIsOpen() {\n              return isOpen()\n            },\n            get errorTypes() {\n              return errors()\n            },\n            get hideDisabledQueries() {\n              return hideDisabledQueries()\n            },\n            get onClose() {\n              return onClose()\n            },\n            get theme() {\n              return theme()\n            },\n          }}\n        />\n      )\n    }, el)\n    this.#isMounted = true\n    this.#dispose = dispose\n  }\n\n  unmount() {\n    if (!this.#isMounted) {\n      throw new Error('Devtools is not mounted')\n    }\n    this.#dispose?.()\n    this.#isMounted = false\n  }\n}\n\nexport { TanstackQueryDevtoolsPanel }\n"
  },
  {
    "path": "packages/query-devtools/src/__tests__/devtools.test.tsx",
    "content": "import { describe, expect, it } from 'vitest'\n\ndescribe('ReactQueryDevtools', () => {\n  it('should be able to open and close devtools', () => {\n    expect(1).toBe(1)\n  })\n})\n"
  },
  {
    "path": "packages/query-devtools/src/__tests__/utils.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\nimport { deleteNestedDataByPath, updateNestedDataByPath } from '../utils'\n\ndescribe('Utils tests', () => {\n  describe('updatedNestedDataByPath', () => {\n    describe('array', () => {\n      it('should update data correctly', () => {\n        const oldData = ['one', 'two', 'three']\n\n        const newData = updateNestedDataByPath(oldData, ['1'], 'new')\n\n        expect(newData).not.toBe(oldData) // should not be the same reference\n\n        expect(oldData).toMatchInlineSnapshot(`\n          [\n            \"one\",\n            \"two\",\n            \"three\",\n          ]\n        `)\n        expect(newData).toMatchInlineSnapshot(`\n          [\n            \"one\",\n            \"new\",\n            \"three\",\n          ]\n        `)\n      })\n    })\n\n    describe('object', () => {\n      it('should update data correctly', () => {\n        const oldData = { title: 'Hello world', id: 1, createdAt: '2021-01-01' }\n\n        const newData = updateNestedDataByPath(\n          oldData,\n          ['title'],\n          'Brave new world',\n        )\n\n        expect(newData).not.toBe(oldData) // should not be the same reference\n\n        expect(oldData).toMatchInlineSnapshot(`\n          {\n            \"createdAt\": \"2021-01-01\",\n            \"id\": 1,\n            \"title\": \"Hello world\",\n          }\n        `)\n        expect(newData).toMatchInlineSnapshot(`\n          {\n            \"createdAt\": \"2021-01-01\",\n            \"id\": 1,\n            \"title\": \"Brave new world\",\n          }\n        `)\n      })\n    })\n\n    describe('set', () => {\n      it('should update data correctly', () => {\n        const oldData = new Set([123, 321, 'hello', 'world'])\n\n        const newData = updateNestedDataByPath(oldData, ['2'], 'hi')\n\n        expect(newData).not.toBe(oldData) // should not be the same reference\n\n        expect(oldData).toMatchInlineSnapshot(`\n          Set {\n            123,\n            321,\n            \"hello\",\n            \"world\",\n          }\n        `)\n        expect(newData).toMatchInlineSnapshot(`\n          Set {\n            123,\n            321,\n            \"hi\",\n            \"world\",\n          }\n        `)\n      })\n    })\n\n    describe('map', () => {\n      it('should update data correctly', () => {\n        const oldData = new Map([\n          ['en', 'hello'],\n          ['fr', 'bonjour'],\n        ])\n\n        /* eslint-disable cspell/spellchecker */\n        const newData = updateNestedDataByPath(oldData, ['fr'], 'salut')\n\n        expect(newData).not.toBe(oldData) // should not be the same reference\n\n        expect(oldData).toMatchInlineSnapshot(`\n          Map {\n            \"en\" => \"hello\",\n            \"fr\" => \"bonjour\",\n          }\n        `)\n        expect(newData).toMatchInlineSnapshot(`\n          Map {\n            \"en\" => \"hello\",\n            \"fr\" => \"salut\",\n          }\n        `)\n      })\n      /* eslint-enable */\n    })\n\n    describe('nested data', () => {\n      it('should update data correctly', () => {\n        /* eslint-disable cspell/spellchecker */\n        const oldData = new Map([\n          [\n            'pumpkin-pie',\n            {\n              id: 1,\n              title: 'Pumpkin pie',\n              ingredients: new Set(['pumpkin', 'sugar', 'spices']),\n              steps: ['mix', 'bake', 'eat'],\n              translations: new Map([\n                ['en', 'Pumpkin pie'],\n                ['fr', 'Tarte à la citrouille'],\n              ]),\n            },\n          ],\n          [\n            'spaghetti-bolonese',\n            {\n              id: 2,\n              title: 'Spaghetti bolonese',\n              ingredients: new Set([\n                'spaghetti',\n                'tomato sauce',\n                'minced meat',\n              ]),\n              steps: ['cook', 'eat'],\n              translations: new Map([\n                ['en', 'Spaghetti bolonese'],\n                ['fr', 'Spaghetti bolonaise'],\n              ]),\n            },\n          ],\n        ])\n\n        const updatedObject = updateNestedDataByPath(\n          oldData,\n          ['pumpkin-pie', 'title'],\n          'Pumpkin pie with whipped cream',\n        )\n\n        const updatedArray = updateNestedDataByPath(\n          oldData,\n          ['spaghetti-bolonese', 'steps', '0'],\n          'prepare',\n        )\n\n        const updatedSet = updateNestedDataByPath(\n          oldData,\n          ['pumpkin-pie', 'ingredients', '1'],\n          'honey',\n        )\n\n        const updatedMap = updateNestedDataByPath(\n          oldData,\n          ['pumpkin-pie', 'translations', 'en'],\n          'Best pie ever',\n        )\n\n        expect(oldData).toMatchInlineSnapshot(`\n          Map {\n            \"pumpkin-pie\" => {\n              \"id\": 1,\n              \"ingredients\": Set {\n                \"pumpkin\",\n                \"sugar\",\n                \"spices\",\n              },\n              \"steps\": [\n                \"mix\",\n                \"bake\",\n                \"eat\",\n              ],\n              \"title\": \"Pumpkin pie\",\n              \"translations\": Map {\n                \"en\" => \"Pumpkin pie\",\n                \"fr\" => \"Tarte à la citrouille\",\n              },\n            },\n            \"spaghetti-bolonese\" => {\n              \"id\": 2,\n              \"ingredients\": Set {\n                \"spaghetti\",\n                \"tomato sauce\",\n                \"minced meat\",\n              },\n              \"steps\": [\n                \"cook\",\n                \"eat\",\n              ],\n              \"title\": \"Spaghetti bolonese\",\n              \"translations\": Map {\n                \"en\" => \"Spaghetti bolonese\",\n                \"fr\" => \"Spaghetti bolonaise\",\n              },\n            },\n          }\n        `)\n\n        expect(updatedObject).toMatchInlineSnapshot(`\n          Map {\n            \"pumpkin-pie\" => {\n              \"id\": 1,\n              \"ingredients\": Set {\n                \"pumpkin\",\n                \"sugar\",\n                \"spices\",\n              },\n              \"steps\": [\n                \"mix\",\n                \"bake\",\n                \"eat\",\n              ],\n              \"title\": \"Pumpkin pie with whipped cream\",\n              \"translations\": Map {\n                \"en\" => \"Pumpkin pie\",\n                \"fr\" => \"Tarte à la citrouille\",\n              },\n            },\n            \"spaghetti-bolonese\" => {\n              \"id\": 2,\n              \"ingredients\": Set {\n                \"spaghetti\",\n                \"tomato sauce\",\n                \"minced meat\",\n              },\n              \"steps\": [\n                \"cook\",\n                \"eat\",\n              ],\n              \"title\": \"Spaghetti bolonese\",\n              \"translations\": Map {\n                \"en\" => \"Spaghetti bolonese\",\n                \"fr\" => \"Spaghetti bolonaise\",\n              },\n            },\n          }\n        `)\n\n        expect(updatedArray).toMatchInlineSnapshot(`\n          Map {\n            \"pumpkin-pie\" => {\n              \"id\": 1,\n              \"ingredients\": Set {\n                \"pumpkin\",\n                \"sugar\",\n                \"spices\",\n              },\n              \"steps\": [\n                \"mix\",\n                \"bake\",\n                \"eat\",\n              ],\n              \"title\": \"Pumpkin pie\",\n              \"translations\": Map {\n                \"en\" => \"Pumpkin pie\",\n                \"fr\" => \"Tarte à la citrouille\",\n              },\n            },\n            \"spaghetti-bolonese\" => {\n              \"id\": 2,\n              \"ingredients\": Set {\n                \"spaghetti\",\n                \"tomato sauce\",\n                \"minced meat\",\n              },\n              \"steps\": [\n                \"prepare\",\n                \"eat\",\n              ],\n              \"title\": \"Spaghetti bolonese\",\n              \"translations\": Map {\n                \"en\" => \"Spaghetti bolonese\",\n                \"fr\" => \"Spaghetti bolonaise\",\n              },\n            },\n          }\n        `)\n\n        expect(updatedSet).toMatchInlineSnapshot(`\n          Map {\n            \"pumpkin-pie\" => {\n              \"id\": 1,\n              \"ingredients\": Set {\n                \"pumpkin\",\n                \"honey\",\n                \"spices\",\n              },\n              \"steps\": [\n                \"mix\",\n                \"bake\",\n                \"eat\",\n              ],\n              \"title\": \"Pumpkin pie\",\n              \"translations\": Map {\n                \"en\" => \"Pumpkin pie\",\n                \"fr\" => \"Tarte à la citrouille\",\n              },\n            },\n            \"spaghetti-bolonese\" => {\n              \"id\": 2,\n              \"ingredients\": Set {\n                \"spaghetti\",\n                \"tomato sauce\",\n                \"minced meat\",\n              },\n              \"steps\": [\n                \"cook\",\n                \"eat\",\n              ],\n              \"title\": \"Spaghetti bolonese\",\n              \"translations\": Map {\n                \"en\" => \"Spaghetti bolonese\",\n                \"fr\" => \"Spaghetti bolonaise\",\n              },\n            },\n          }\n        `)\n\n        expect(updatedMap).toMatchInlineSnapshot(`\n          Map {\n            \"pumpkin-pie\" => {\n              \"id\": 1,\n              \"ingredients\": Set {\n                \"pumpkin\",\n                \"sugar\",\n                \"spices\",\n              },\n              \"steps\": [\n                \"mix\",\n                \"bake\",\n                \"eat\",\n              ],\n              \"title\": \"Pumpkin pie\",\n              \"translations\": Map {\n                \"en\" => \"Best pie ever\",\n                \"fr\" => \"Tarte à la citrouille\",\n              },\n            },\n            \"spaghetti-bolonese\" => {\n              \"id\": 2,\n              \"ingredients\": Set {\n                \"spaghetti\",\n                \"tomato sauce\",\n                \"minced meat\",\n              },\n              \"steps\": [\n                \"cook\",\n                \"eat\",\n              ],\n              \"title\": \"Spaghetti bolonese\",\n              \"translations\": Map {\n                \"en\" => \"Spaghetti bolonese\",\n                \"fr\" => \"Spaghetti bolonaise\",\n              },\n            },\n          }\n        `)\n        /* eslint-enable */\n      })\n    })\n  })\n\n  describe('deleteNestedDataByPath', () => {\n    it('should delete item from array correctly', () => {\n      const oldData = ['one', 'two', 'three']\n\n      const newData = deleteNestedDataByPath(oldData, ['1'])\n\n      expect(newData).not.toBe(oldData) // should not be the same reference\n\n      expect(oldData).toMatchInlineSnapshot(`\n        [\n          \"one\",\n          \"two\",\n          \"three\",\n        ]\n      `)\n      expect(newData).toMatchInlineSnapshot(`\n        [\n          \"one\",\n          \"three\",\n        ]\n      `)\n    })\n\n    it('should delete item from object correctly', () => {\n      const oldData = { title: 'Hello world', id: 1, createdAt: '2021-01-01' }\n\n      const newData = deleteNestedDataByPath(oldData, ['createdAt'])\n\n      expect(newData).not.toBe(oldData) // should not be the same reference\n\n      expect(oldData).toMatchInlineSnapshot(`\n        {\n          \"createdAt\": \"2021-01-01\",\n          \"id\": 1,\n          \"title\": \"Hello world\",\n        }\n      `)\n      expect(newData).toMatchInlineSnapshot(`\n        {\n          \"id\": 1,\n          \"title\": \"Hello world\",\n        }\n      `)\n    })\n\n    it('should delete item from set', () => {\n      const oldData = new Set([123, 321, false, true])\n\n      const newData = deleteNestedDataByPath(oldData, ['1'])\n\n      expect(newData).not.toBe(oldData) // should not be the same reference\n\n      expect(oldData).toMatchInlineSnapshot(`\n      Set {\n        123,\n        321,\n        false,\n        true,\n      }\n    `)\n      expect(newData).toMatchInlineSnapshot(`\n      Set {\n        123,\n        false,\n        true,\n      }\n    `)\n    })\n\n    it('should delete item from map', () => {\n      const oldData = new Map([\n        ['123', 'one'],\n        ['hello', 'two'],\n        ['world', 'three'],\n      ])\n\n      const newData = deleteNestedDataByPath(oldData, ['world'])\n\n      expect(newData).not.toBe(oldData) // should not be the same reference\n\n      expect(oldData).toMatchInlineSnapshot(`\n      Map {\n        \"123\" => \"one\",\n        \"hello\" => \"two\",\n        \"world\" => \"three\",\n      }\n    `)\n      expect(newData).toMatchInlineSnapshot(`\n      Map {\n        \"123\" => \"one\",\n        \"hello\" => \"two\",\n      }\n    `)\n    })\n\n    describe('nested data', () => {\n      it('should delete nested items correctly', () => {\n        /* eslint-disable cspell/spellchecker */\n        const oldData = new Map([\n          [\n            'pumpkin-pie',\n            {\n              id: 1,\n              title: 'Pumpkin pie',\n              ingredients: new Set(['pumpkin', 'sugar', 'spices']),\n              steps: ['mix', 'bake', 'eat'],\n              translations: new Map([\n                ['en', 'Pumpkin pie'],\n                ['fr', 'Tarte à la citrouille'],\n              ]),\n            },\n          ],\n          [\n            'spaghetti-bolonese',\n            {\n              id: 2,\n              title: 'Spaghetti bolonese',\n              ingredients: new Set([\n                'spaghetti',\n                'tomato sauce',\n                'minced meat',\n              ]),\n              steps: ['cook', 'eat'],\n              translations: new Map([\n                ['en', 'Spaghetti bolonese'],\n                ['fr', 'Spaghetti bolonaise'],\n              ]),\n            },\n          ],\n        ])\n\n        const deletedFromSet = deleteNestedDataByPath(oldData, [\n          'spaghetti-bolonese',\n          'ingredients',\n          '0',\n        ])\n\n        const deletedFromArray = deleteNestedDataByPath(oldData, [\n          'pumpkin-pie',\n          'steps',\n          '1',\n        ])\n\n        const deletedFromObject = deleteNestedDataByPath(oldData, [\n          'pumpkin-pie',\n          'title',\n        ])\n\n        const deletedFromMap = deleteNestedDataByPath(oldData, [\n          'spaghetti-bolonese',\n          'translations',\n          'fr',\n        ])\n\n        expect(oldData).toMatchInlineSnapshot(`\n          Map {\n            \"pumpkin-pie\" => {\n              \"id\": 1,\n              \"ingredients\": Set {\n                \"pumpkin\",\n                \"sugar\",\n                \"spices\",\n              },\n              \"steps\": [\n                \"mix\",\n                \"bake\",\n                \"eat\",\n              ],\n              \"title\": \"Pumpkin pie\",\n              \"translations\": Map {\n                \"en\" => \"Pumpkin pie\",\n                \"fr\" => \"Tarte à la citrouille\",\n              },\n            },\n            \"spaghetti-bolonese\" => {\n              \"id\": 2,\n              \"ingredients\": Set {\n                \"spaghetti\",\n                \"tomato sauce\",\n                \"minced meat\",\n              },\n              \"steps\": [\n                \"cook\",\n                \"eat\",\n              ],\n              \"title\": \"Spaghetti bolonese\",\n              \"translations\": Map {\n                \"en\" => \"Spaghetti bolonese\",\n                \"fr\" => \"Spaghetti bolonaise\",\n              },\n            },\n          }\n        `)\n\n        expect(deletedFromSet).toMatchInlineSnapshot(`\n          Map {\n            \"pumpkin-pie\" => {\n              \"id\": 1,\n              \"ingredients\": Set {\n                \"pumpkin\",\n                \"sugar\",\n                \"spices\",\n              },\n              \"steps\": [\n                \"mix\",\n                \"bake\",\n                \"eat\",\n              ],\n              \"title\": \"Pumpkin pie\",\n              \"translations\": Map {\n                \"en\" => \"Pumpkin pie\",\n                \"fr\" => \"Tarte à la citrouille\",\n              },\n            },\n            \"spaghetti-bolonese\" => {\n              \"id\": 2,\n              \"ingredients\": Set {\n                \"tomato sauce\",\n                \"minced meat\",\n              },\n              \"steps\": [\n                \"cook\",\n                \"eat\",\n              ],\n              \"title\": \"Spaghetti bolonese\",\n              \"translations\": Map {\n                \"en\" => \"Spaghetti bolonese\",\n                \"fr\" => \"Spaghetti bolonaise\",\n              },\n            },\n          }\n        `)\n\n        expect(deletedFromArray).toMatchInlineSnapshot(`\n          Map {\n            \"pumpkin-pie\" => {\n              \"id\": 1,\n              \"ingredients\": Set {\n                \"pumpkin\",\n                \"sugar\",\n                \"spices\",\n              },\n              \"steps\": [\n                \"mix\",\n                \"eat\",\n              ],\n              \"title\": \"Pumpkin pie\",\n              \"translations\": Map {\n                \"en\" => \"Pumpkin pie\",\n                \"fr\" => \"Tarte à la citrouille\",\n              },\n            },\n            \"spaghetti-bolonese\" => {\n              \"id\": 2,\n              \"ingredients\": Set {\n                \"spaghetti\",\n                \"tomato sauce\",\n                \"minced meat\",\n              },\n              \"steps\": [\n                \"cook\",\n                \"eat\",\n              ],\n              \"title\": \"Spaghetti bolonese\",\n              \"translations\": Map {\n                \"en\" => \"Spaghetti bolonese\",\n                \"fr\" => \"Spaghetti bolonaise\",\n              },\n            },\n          }\n        `)\n\n        expect(deletedFromObject).toMatchInlineSnapshot(`\n          Map {\n            \"pumpkin-pie\" => {\n              \"id\": 1,\n              \"ingredients\": Set {\n                \"pumpkin\",\n                \"sugar\",\n                \"spices\",\n              },\n              \"steps\": [\n                \"mix\",\n                \"bake\",\n                \"eat\",\n              ],\n              \"translations\": Map {\n                \"en\" => \"Pumpkin pie\",\n                \"fr\" => \"Tarte à la citrouille\",\n              },\n            },\n            \"spaghetti-bolonese\" => {\n              \"id\": 2,\n              \"ingredients\": Set {\n                \"spaghetti\",\n                \"tomato sauce\",\n                \"minced meat\",\n              },\n              \"steps\": [\n                \"cook\",\n                \"eat\",\n              ],\n              \"title\": \"Spaghetti bolonese\",\n              \"translations\": Map {\n                \"en\" => \"Spaghetti bolonese\",\n                \"fr\" => \"Spaghetti bolonaise\",\n              },\n            },\n          }\n        `)\n\n        expect(deletedFromMap).toMatchInlineSnapshot(`\n          Map {\n            \"pumpkin-pie\" => {\n              \"id\": 1,\n              \"ingredients\": Set {\n                \"pumpkin\",\n                \"sugar\",\n                \"spices\",\n              },\n              \"steps\": [\n                \"mix\",\n                \"bake\",\n                \"eat\",\n              ],\n              \"title\": \"Pumpkin pie\",\n              \"translations\": Map {\n                \"en\" => \"Pumpkin pie\",\n                \"fr\" => \"Tarte à la citrouille\",\n              },\n            },\n            \"spaghetti-bolonese\" => {\n              \"id\": 2,\n              \"ingredients\": Set {\n                \"spaghetti\",\n                \"tomato sauce\",\n                \"minced meat\",\n              },\n              \"steps\": [\n                \"cook\",\n                \"eat\",\n              ],\n              \"title\": \"Spaghetti bolonese\",\n              \"translations\": Map {\n                \"en\" => \"Spaghetti bolonese\",\n              },\n            },\n          }\n        `)\n        /* eslint-enable */\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/query-devtools/src/constants.ts",
    "content": "import { mutationSortFns, sortFns } from './utils'\nimport type { DevtoolsButtonPosition, DevtoolsPosition } from './contexts'\n\nexport const firstBreakpoint = 1024\nexport const secondBreakpoint = 796\nexport const thirdBreakpoint = 700\n\nexport const BUTTON_POSITION: DevtoolsButtonPosition = 'bottom-right'\nexport const POSITION: DevtoolsPosition = 'bottom'\nexport const THEME_PREFERENCE = 'system'\nexport const INITIAL_IS_OPEN = false\nexport const DEFAULT_HEIGHT = 500\nexport const PIP_DEFAULT_HEIGHT = 500\nexport const DEFAULT_WIDTH = 500\nexport const DEFAULT_SORT_FN_NAME = Object.keys(sortFns)[0]\nexport const DEFAULT_SORT_ORDER = 1\nexport const DEFAULT_MUTATION_SORT_FN_NAME = Object.keys(mutationSortFns)[0]\n"
  },
  {
    "path": "packages/query-devtools/src/contexts/PiPContext.tsx",
    "content": "import {\n  createContext,\n  createEffect,\n  createMemo,\n  createSignal,\n  onCleanup,\n  useContext,\n} from 'solid-js'\nimport { clearDelegatedEvents, delegateEvents } from 'solid-js/web'\nimport { PIP_DEFAULT_HEIGHT } from '../constants'\nimport { useQueryDevtoolsContext } from './QueryDevtoolsContext'\nimport type { Accessor, JSX } from 'solid-js'\nimport type { StorageObject, StorageSetter } from '@solid-primitives/storage'\n\ninterface PiPProviderProps {\n  children: JSX.Element\n  localStore: StorageObject<string>\n  setLocalStore: StorageSetter<string, unknown>\n  disabled?: boolean\n}\n\ntype PiPContextType = {\n  pipWindow: Window | null\n  requestPipWindow: (width: number, height: number) => void\n  closePipWindow: () => void\n  disabled: boolean\n}\n\nclass PipOpenError extends Error {}\n\nconst PiPContext = createContext<Accessor<PiPContextType> | undefined>(\n  undefined,\n)\n\nexport const PiPProvider = (props: PiPProviderProps) => {\n  // Expose pipWindow that is currently active\n  const [pipWindow, setPipWindow] = createSignal<Window | null>(null)\n\n  // Close pipWindow programmatically\n  const closePipWindow = () => {\n    const w = pipWindow()\n    if (w != null) {\n      w.close()\n      setPipWindow(null)\n    }\n  }\n\n  // Open new pipWindow\n  const requestPipWindow = (width: number, height: number) => {\n    // We don't want to allow multiple requests.\n    if (pipWindow() != null) {\n      return\n    }\n\n    const pip = window.open(\n      '',\n      'TSQD-Devtools-Panel',\n      `width=${width},height=${height},popup`,\n    )\n\n    if (!pip) {\n      throw new PipOpenError(\n        'Failed to open popup. Please allow popups for this site to view the devtools in picture-in-picture mode.',\n      )\n    }\n\n    // Remove existing styles\n    pip.document.head.innerHTML = ''\n    // Remove existing body\n    pip.document.body.innerHTML = ''\n    // Clear Delegated Events\n    clearDelegatedEvents(pip.document)\n\n    pip.document.title = 'TanStack Query Devtools'\n    pip.document.body.style.margin = '0'\n\n    // Detect when window is closed by user\n    pip.addEventListener('pagehide', () => {\n      props.setLocalStore('pip_open', 'false')\n      setPipWindow(null)\n    })\n\n    // It is important to copy all parent window styles. Otherwise, there would be no CSS available at all\n    // https://developer.chrome.com/docs/web-platform/document-picture-in-picture/#copy-style-sheets-to-the-picture-in-picture-window\n    ;[\n      ...(useQueryDevtoolsContext().shadowDOMTarget || document).styleSheets,\n    ].forEach((styleSheet) => {\n      try {\n        const cssRules = [...styleSheet.cssRules]\n          .map((rule) => rule.cssText)\n          .join('')\n        const style = document.createElement('style')\n        const style_node = styleSheet.ownerNode\n        let style_id = ''\n\n        if (style_node && 'id' in style_node) {\n          style_id = style_node.id\n        }\n\n        if (style_id) {\n          style.setAttribute('id', style_id)\n        }\n        style.textContent = cssRules\n        pip.document.head.appendChild(style)\n      } catch (e) {\n        const link = document.createElement('link')\n        if (styleSheet.href == null) {\n          return\n        }\n\n        link.rel = 'stylesheet'\n        link.type = styleSheet.type\n        link.media = styleSheet.media.toString()\n        link.href = styleSheet.href\n        pip.document.head.appendChild(link)\n      }\n    })\n    delegateEvents(\n      [\n        'focusin',\n        'focusout',\n        'pointermove',\n        'keydown',\n        'pointerdown',\n        'pointerup',\n        'click',\n        'mousedown',\n        'input',\n      ],\n      pip.document,\n    )\n    props.setLocalStore('pip_open', 'true')\n    setPipWindow(pip)\n  }\n\n  createEffect(() => {\n    const pip_open = (props.localStore.pip_open ?? 'false') as 'true' | 'false'\n    if (pip_open === 'true' && !props.disabled) {\n      try {\n        requestPipWindow(\n          Number(window.innerWidth),\n          Number(props.localStore.height || PIP_DEFAULT_HEIGHT),\n        )\n      } catch (error) {\n        if (error instanceof PipOpenError) {\n          console.error(error.message)\n          props.setLocalStore('pip_open', 'false')\n          props.setLocalStore('open', 'false')\n          return\n        }\n        throw error\n      }\n    }\n  })\n\n  createEffect(() => {\n    // Setup mutation observer for goober styles with id `_goober\n    const gooberStyles = (\n      useQueryDevtoolsContext().shadowDOMTarget || document\n    ).querySelector('#_goober')\n    const w = pipWindow()\n    if (gooberStyles && w) {\n      const observer = new MutationObserver(() => {\n        const pip_style = (\n          useQueryDevtoolsContext().shadowDOMTarget || w.document\n        ).querySelector('#_goober')\n        if (pip_style) {\n          pip_style.textContent = gooberStyles.textContent\n        }\n      })\n      observer.observe(gooberStyles, {\n        childList: true, // observe direct children\n        subtree: true, // and lower descendants too\n        characterDataOldValue: true, // pass old data to callback\n      })\n      onCleanup(() => {\n        observer.disconnect()\n      })\n    }\n  })\n\n  const value = createMemo(() => ({\n    pipWindow: pipWindow(),\n    requestPipWindow,\n    closePipWindow,\n    disabled: props.disabled ?? false,\n  }))\n\n  return (\n    <PiPContext.Provider value={value}>{props.children}</PiPContext.Provider>\n  )\n}\n\nexport const usePiPWindow = () => {\n  const context = createMemo(() => {\n    const ctx = useContext(PiPContext)\n    if (!ctx) {\n      throw new Error('usePiPWindow must be used within a PiPProvider')\n    }\n    return ctx()\n  })\n  return context\n}\n"
  },
  {
    "path": "packages/query-devtools/src/contexts/QueryDevtoolsContext.ts",
    "content": "import { createContext, useContext } from 'solid-js'\nimport type { Query, QueryClient, onlineManager } from '@tanstack/query-core'\n\ntype XPosition = 'left' | 'right'\ntype YPosition = 'top' | 'bottom'\nexport type DevtoolsPosition = XPosition | YPosition\nexport type DevtoolsButtonPosition = `${YPosition}-${XPosition}` | 'relative'\nexport type Theme = 'dark' | 'light' | 'system'\n\nexport interface DevtoolsErrorType {\n  /**\n   * The name of the error.\n   */\n  name: string\n  /**\n   * How the error is initialized.\n   */\n  initializer: (query: Query) => Error\n}\n\nexport interface QueryDevtoolsProps {\n  readonly client: QueryClient\n  queryFlavor: string\n  version: string\n  onlineManager: typeof onlineManager\n\n  buttonPosition?: DevtoolsButtonPosition\n  position?: DevtoolsPosition\n  initialIsOpen?: boolean\n  errorTypes?: Array<DevtoolsErrorType>\n  shadowDOMTarget?: ShadowRoot\n  onClose?: () => unknown\n  hideDisabledQueries?: boolean\n  theme?: Theme\n}\n\nexport const QueryDevtoolsContext = createContext<QueryDevtoolsProps>({\n  client: undefined as unknown as QueryClient,\n  onlineManager: undefined as unknown as typeof onlineManager,\n  queryFlavor: '',\n  version: '',\n  shadowDOMTarget: undefined,\n})\n\nexport function useQueryDevtoolsContext() {\n  return useContext(QueryDevtoolsContext)\n}\n"
  },
  {
    "path": "packages/query-devtools/src/contexts/ThemeContext.ts",
    "content": "import { createContext, useContext } from 'solid-js'\nimport type { Accessor } from 'solid-js'\n\nexport const ThemeContext = createContext<Accessor<'light' | 'dark'>>(\n  () => 'dark' as const,\n)\n\nexport function useTheme() {\n  return useContext(ThemeContext)\n}\n"
  },
  {
    "path": "packages/query-devtools/src/contexts/index.ts",
    "content": "export * from './PiPContext'\nexport * from './QueryDevtoolsContext'\nexport * from './ThemeContext'\n"
  },
  {
    "path": "packages/query-devtools/src/icons/index.tsx",
    "content": "import { Show, createUniqueId } from 'solid-js'\n\nexport function Search() {\n  return (\n    <svg\n      width=\"14\"\n      height=\"14\"\n      viewBox=\"0 0 14 14\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <path\n        d=\"M13 13L9.00007 9M10.3333 5.66667C10.3333 8.244 8.244 10.3333 5.66667 10.3333C3.08934 10.3333 1 8.244 1 5.66667C1 3.08934 3.08934 1 5.66667 1C8.244 1 10.3333 3.08934 10.3333 5.66667Z\"\n        stroke=\"currentColor\"\n        stroke-width=\"1.66667\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n    </svg>\n  )\n}\n\nexport function Trash() {\n  return (\n    <svg\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <path\n        d=\"M9 3H15M3 6H21M19 6L18.2987 16.5193C18.1935 18.0975 18.1409 18.8867 17.8 19.485C17.4999 20.0118 17.0472 20.4353 16.5017 20.6997C15.882 21 15.0911 21 13.5093 21H10.4907C8.90891 21 8.11803 21 7.49834 20.6997C6.95276 20.4353 6.50009 20.0118 6.19998 19.485C5.85911 18.8867 5.8065 18.0975 5.70129 16.5193L5 6M10 10.5V15.5M14 10.5V15.5\"\n        stroke=\"currentColor\"\n        stroke-width=\"2\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n    </svg>\n  )\n}\n\nexport function ChevronDown() {\n  return (\n    <svg\n      width=\"10\"\n      height=\"6\"\n      viewBox=\"0 0 10 6\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <path\n        d=\"M1 1L5 5L9 1\"\n        stroke=\"currentColor\"\n        stroke-width=\"1.66667\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n    </svg>\n  )\n}\n\nexport function ArrowUp() {\n  return (\n    <svg\n      width=\"12\"\n      height=\"12\"\n      viewBox=\"0 0 16 16\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <path\n        d=\"M8 13.3333V2.66667M8 2.66667L4 6.66667M8 2.66667L12 6.66667\"\n        stroke=\"currentColor\"\n        stroke-width=\"1.66667\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n    </svg>\n  )\n}\n\nexport function ArrowDown() {\n  return (\n    <svg\n      width=\"12\"\n      height=\"12\"\n      viewBox=\"0 0 16 16\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <path\n        d=\"M8 2.66667V13.3333M8 13.3333L4 9.33333M8 13.3333L12 9.33333\"\n        stroke=\"currentColor\"\n        stroke-width=\"1.66667\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n    </svg>\n  )\n}\n\nexport function ArrowLeft() {\n  return (\n    <svg\n      width=\"12\"\n      height=\"12\"\n      viewBox=\"0 0 16 16\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      style={{\n        transform: 'rotate(90deg)',\n      }}\n    >\n      <path\n        d=\"M8 2.66667V13.3333M8 13.3333L4 9.33333M8 13.3333L12 9.33333\"\n        stroke=\"currentColor\"\n        stroke-width=\"1.66667\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n    </svg>\n  )\n}\n\nexport function ArrowRight() {\n  return (\n    <svg\n      width=\"12\"\n      height=\"12\"\n      viewBox=\"0 0 16 16\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      style={{\n        transform: 'rotate(-90deg)',\n      }}\n    >\n      <path\n        d=\"M8 2.66667V13.3333M8 13.3333L4 9.33333M8 13.3333L12 9.33333\"\n        stroke=\"currentColor\"\n        stroke-width=\"1.66667\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n    </svg>\n  )\n}\n\nexport function Sun() {\n  return (\n    <svg\n      viewBox=\"0 0 24 24\"\n      height=\"12\"\n      width=\"12\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <path\n        d=\"M12 2v2m0 16v2M4 12H2m4.314-5.686L4.9 4.9m12.786 1.414L19.1 4.9M6.314 17.69 4.9 19.104m12.786-1.414 1.414 1.414M22 12h-2m-3 0a5 5 0 1 1-10 0 5 5 0 0 1 10 0Z\"\n        stroke=\"currentColor\"\n        stroke-width=\"2\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      ></path>\n    </svg>\n  )\n}\n\nexport function Moon() {\n  return (\n    <svg\n      viewBox=\"0 0 24 24\"\n      height=\"12\"\n      width=\"12\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <path\n        d=\"M22 15.844a10.424 10.424 0 0 1-4.306.925c-5.779 0-10.463-4.684-10.463-10.462 0-1.536.33-2.994.925-4.307A10.464 10.464 0 0 0 2 11.538C2 17.316 6.684 22 12.462 22c4.243 0 7.896-2.526 9.538-6.156Z\"\n        stroke=\"currentColor\"\n        stroke-width=\"2\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      ></path>\n    </svg>\n  )\n}\n\nexport function Monitor() {\n  return (\n    <svg\n      viewBox=\"0 0 24 24\"\n      height=\"12\"\n      width=\"12\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <path\n        d=\"M8 21h8m-4-4v4m-5.2-4h10.4c1.68 0 2.52 0 3.162-.327a3 3 0 0 0 1.311-1.311C22 14.72 22 13.88 22 12.2V7.8c0-1.68 0-2.52-.327-3.162a3 3 0 0 0-1.311-1.311C19.72 3 18.88 3 17.2 3H6.8c-1.68 0-2.52 0-3.162.327a3 3 0 0 0-1.311 1.311C2 5.28 2 6.12 2 7.8v4.4c0 1.68 0 2.52.327 3.162a3 3 0 0 0 1.311 1.311C4.28 17 5.12 17 6.8 17Z\"\n        stroke=\"currentColor\"\n        stroke-width=\"2\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      ></path>\n    </svg>\n  )\n}\n\nexport function Wifi() {\n  return (\n    <svg\n      stroke=\"currentColor\"\n      fill=\"currentColor\"\n      stroke-width=\"0\"\n      viewBox=\"0 0 24 24\"\n      height=\"1em\"\n      width=\"1em\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <path fill=\"none\" d=\"M0 0h24v24H0z\"></path>\n      <path d=\"M1 9l2 2c4.97-4.97 13.03-4.97 18 0l2-2C16.93 2.93 7.08 2.93 1 9zm8 8l3 3 3-3a4.237 4.237 0 00-6 0zm-4-4l2 2a7.074 7.074 0 0110 0l2-2C15.14 9.14 8.87 9.14 5 13z\"></path>\n    </svg>\n  )\n}\n\nexport function Offline() {\n  return (\n    <svg\n      stroke-width=\"0\"\n      viewBox=\"0 0 24 24\"\n      height=\"1em\"\n      width=\"1em\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <path\n        fill=\"none\"\n        d=\"M24 .01c0-.01 0-.01 0 0L0 0v24h24V.01zM0 0h24v24H0V0zm0 0h24v24H0V0z\"\n      ></path>\n      <path d=\"M22.99 9C19.15 5.16 13.8 3.76 8.84 4.78l2.52 2.52c3.47-.17 6.99 1.05 9.63 3.7l2-2zm-4 4a9.793 9.793 0 00-4.49-2.56l3.53 3.53.96-.97zM2 3.05L5.07 6.1C3.6 6.82 2.22 7.78 1 9l1.99 2c1.24-1.24 2.67-2.16 4.2-2.77l2.24 2.24A9.684 9.684 0 005 13v.01L6.99 15a7.042 7.042 0 014.92-2.06L18.98 20l1.27-1.26L3.29 1.79 2 3.05zM9 17l3 3 3-3a4.237 4.237 0 00-6 0z\"></path>\n    </svg>\n  )\n}\n\nexport function Settings() {\n  return (\n    <svg\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <path\n        d=\"M9.3951 19.3711L9.97955 20.6856C10.1533 21.0768 10.4368 21.4093 10.7958 21.6426C11.1547 21.8759 11.5737 22.0001 12.0018 22C12.4299 22.0001 12.8488 21.8759 13.2078 21.6426C13.5667 21.4093 13.8503 21.0768 14.024 20.6856L14.6084 19.3711C14.8165 18.9047 15.1664 18.5159 15.6084 18.26C16.0532 18.0034 16.5678 17.8941 17.0784 17.9478L18.5084 18.1C18.9341 18.145 19.3637 18.0656 19.7451 17.8713C20.1265 17.6771 20.4434 17.3763 20.6573 17.0056C20.8715 16.635 20.9735 16.2103 20.9511 15.7829C20.9286 15.3555 20.7825 14.9438 20.5307 14.5978L19.684 13.4344C19.3825 13.0171 19.2214 12.5148 19.224 12C19.2239 11.4866 19.3865 10.9864 19.6884 10.5711L20.5351 9.40778C20.787 9.06175 20.933 8.65007 20.9555 8.22267C20.978 7.79528 20.8759 7.37054 20.6618 7C20.4479 6.62923 20.131 6.32849 19.7496 6.13423C19.3681 5.93997 18.9386 5.86053 18.5129 5.90556L17.0829 6.05778C16.5722 6.11141 16.0577 6.00212 15.6129 5.74556C15.17 5.48825 14.82 5.09736 14.6129 4.62889L14.024 3.31444C13.8503 2.92317 13.5667 2.59072 13.2078 2.3574C12.8488 2.12408 12.4299 1.99993 12.0018 2C11.5737 1.99993 11.1547 2.12408 10.7958 2.3574C10.4368 2.59072 10.1533 2.92317 9.97955 3.31444L9.3951 4.62889C9.18803 5.09736 8.83798 5.48825 8.3951 5.74556C7.95032 6.00212 7.43577 6.11141 6.9251 6.05778L5.49066 5.90556C5.06499 5.86053 4.6354 5.93997 4.25397 6.13423C3.87255 6.32849 3.55567 6.62923 3.34177 7C3.12759 7.37054 3.02555 7.79528 3.04804 8.22267C3.07052 8.65007 3.21656 9.06175 3.46844 9.40778L4.3151 10.5711C4.61704 10.9864 4.77964 11.4866 4.77955 12C4.77964 12.5134 4.61704 13.0137 4.3151 13.4289L3.46844 14.5922C3.21656 14.9382 3.07052 15.3499 3.04804 15.7773C3.02555 16.2047 3.12759 16.6295 3.34177 17C3.55589 17.3706 3.8728 17.6712 4.25417 17.8654C4.63554 18.0596 5.06502 18.1392 5.49066 18.0944L6.92066 17.9422C7.43133 17.8886 7.94587 17.9979 8.39066 18.2544C8.83519 18.511 9.18687 18.902 9.3951 19.3711Z\"\n        stroke=\"currentColor\"\n        stroke-width=\"2\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n      <path\n        d=\"M12 15C13.6568 15 15 13.6569 15 12C15 10.3431 13.6568 9 12 9C10.3431 9 8.99998 10.3431 8.99998 12C8.99998 13.6569 10.3431 15 12 15Z\"\n        stroke=\"currentColor\"\n        stroke-width=\"2\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n    </svg>\n  )\n}\n\nexport function PiPIcon() {\n  return (\n    <svg\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <path\n        d=\"M16 21H16.2C17.8802 21 18.7202 21 19.362 20.673C19.9265 20.3854 20.3854 19.9265 20.673 19.362C21 18.7202 21 17.8802 21 16.2V7.8C21 6.11984 21 5.27976 20.673 4.63803C20.3854 4.07354 19.9265 3.6146 19.362 3.32698C18.7202 3 17.8802 3 16.2 3H7.8C6.11984 3 5.27976 3 4.63803 3.32698C4.07354 3.6146 3.6146 4.07354 3.32698 4.63803C3 5.27976 3 6.11984 3 7.8V8M11.5 12.5L17 7M17 7H12M17 7V12M6.2 21H8.8C9.9201 21 10.4802 21 10.908 20.782C11.2843 20.5903 11.5903 20.2843 11.782 19.908C12 19.4802 12 18.9201 12 17.8V15.2C12 14.0799 12 13.5198 11.782 13.092C11.5903 12.7157 11.2843 12.4097 10.908 12.218C10.4802 12 9.92011 12 8.8 12H6.2C5.0799 12 4.51984 12 4.09202 12.218C3.71569 12.4097 3.40973 12.7157 3.21799 13.092C3 13.5198 3 14.0799 3 15.2V17.8C3 18.9201 3 19.4802 3.21799 19.908C3.40973 20.2843 3.71569 20.5903 4.09202 20.782C4.51984 21 5.07989 21 6.2 21Z\"\n        stroke=\"currentColor\"\n        stroke-width=\"2\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n    </svg>\n  )\n}\n\nexport function Copier() {\n  return (\n    <svg\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <path\n        class=\"copier\"\n        d=\"M8 8V5.2C8 4.0799 8 3.51984 8.21799 3.09202C8.40973 2.71569 8.71569 2.40973 9.09202 2.21799C9.51984 2 10.0799 2 11.2 2H18.8C19.9201 2 20.4802 2 20.908 2.21799C21.2843 2.40973 21.5903 2.71569 21.782 3.09202C22 3.51984 22 4.0799 22 5.2V12.8C22 13.9201 22 14.4802 21.782 14.908C21.5903 15.2843 21.2843 15.5903 20.908 15.782C20.4802 16 19.9201 16 18.8 16H16M5.2 22H12.8C13.9201 22 14.4802 22 14.908 21.782C15.2843 21.5903 15.5903 21.2843 15.782 20.908C16 20.4802 16 19.9201 16 18.8V11.2C16 10.0799 16 9.51984 15.782 9.09202C15.5903 8.71569 15.2843 8.40973 14.908 8.21799C14.4802 8 13.9201 8 12.8 8H5.2C4.0799 8 3.51984 8 3.09202 8.21799C2.71569 8.40973 2.40973 8.71569 2.21799 9.09202C2 9.51984 2 10.0799 2 11.2V18.8C2 19.9201 2 20.4802 2.21799 20.908C2.40973 21.2843 2.71569 21.5903 3.09202 21.782C3.51984 22 4.07989 22 5.2 22Z\"\n        stroke-width=\"2\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n        stroke=\"currentColor\"\n      />\n    </svg>\n  )\n}\n\nexport function Pencil() {\n  return (\n    <svg\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <path\n        d=\"M2.5 21.4998L8.04927 19.3655C8.40421 19.229 8.58168 19.1607 8.74772 19.0716C8.8952 18.9924 9.0358 18.901 9.16804 18.7984C9.31692 18.6829 9.45137 18.5484 9.72028 18.2795L21 6.99982C22.1046 5.89525 22.1046 4.10438 21 2.99981C19.8955 1.89525 18.1046 1.89524 17 2.99981L5.72028 14.2795C5.45138 14.5484 5.31692 14.6829 5.20139 14.8318C5.09877 14.964 5.0074 15.1046 4.92823 15.2521C4.83911 15.4181 4.77085 15.5956 4.63433 15.9506L2.5 21.4998ZM2.5 21.4998L4.55812 16.1488C4.7054 15.7659 4.77903 15.5744 4.90534 15.4867C5.01572 15.4101 5.1523 15.3811 5.2843 15.4063C5.43533 15.4351 5.58038 15.5802 5.87048 15.8703L8.12957 18.1294C8.41967 18.4195 8.56472 18.5645 8.59356 18.7155C8.61877 18.8475 8.58979 18.9841 8.51314 19.0945C8.42545 19.2208 8.23399 19.2944 7.85107 19.4417L2.5 21.4998Z\"\n        stroke=\"currentColor\"\n        stroke-width=\"2\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n    </svg>\n  )\n}\n\nexport function CopiedCopier(props: { theme: 'light' | 'dark' }) {\n  return (\n    <svg\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <path\n        d=\"M7.5 12L10.5 15L16.5 9M7.8 21H16.2C17.8802 21 18.7202 21 19.362 20.673C19.9265 20.3854 20.3854 19.9265 20.673 19.362C21 18.7202 21 17.8802 21 16.2V7.8C21 6.11984 21 5.27976 20.673 4.63803C20.3854 4.07354 19.9265 3.6146 19.362 3.32698C18.7202 3 17.8802 3 16.2 3H7.8C6.11984 3 5.27976 3 4.63803 3.32698C4.07354 3.6146 3.6146 4.07354 3.32698 4.63803C3 5.27976 3 6.11984 3 7.8V16.2C3 17.8802 3 18.7202 3.32698 19.362C3.6146 19.9265 4.07354 20.3854 4.63803 20.673C5.27976 21 6.11984 21 7.8 21Z\"\n        stroke={props.theme === 'dark' ? '#12B76A' : '#027A48'}\n        stroke-width=\"2\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n    </svg>\n  )\n}\n\nexport function ErrorCopier() {\n  return (\n    <svg\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <path\n        d=\"M9 9L15 15M15 9L9 15M7.8 21H16.2C17.8802 21 18.7202 21 19.362 20.673C19.9265 20.3854 20.3854 19.9265 20.673 19.362C21 18.7202 21 17.8802 21 16.2V7.8C21 6.11984 21 5.27976 20.673 4.63803C20.3854 4.07354 19.9265 3.6146 19.362 3.32698C18.7202 3 17.8802 3 16.2 3H7.8C6.11984 3 5.27976 3 4.63803 3.32698C4.07354 3.6146 3.6146 4.07354 3.32698 4.63803C3 5.27976 3 6.11984 3 7.8V16.2C3 17.8802 3 18.7202 3.32698 19.362C3.6146 19.9265 4.07354 20.3854 4.63803 20.673C5.27976 21 6.11984 21 7.8 21Z\"\n        stroke=\"#F04438\"\n        stroke-width=\"2\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n    </svg>\n  )\n}\n\nexport function List() {\n  return (\n    <svg\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      stroke-width=\"2\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <rect class=\"list\" width=\"20\" height=\"20\" y=\"2\" x=\"2\" rx=\"2\" />\n      <line class=\"list-item\" y1=\"7\" y2=\"7\" x1=\"6\" x2=\"18\" />\n      <line class=\"list-item\" y2=\"12\" y1=\"12\" x1=\"6\" x2=\"18\" />\n      <line class=\"list-item\" y1=\"17\" y2=\"17\" x1=\"6\" x2=\"18\" />\n    </svg>\n  )\n}\n\nexport function Check(props: { checked: boolean; theme: 'light' | 'dark' }) {\n  return (\n    <>\n      <Show when={props.checked}>\n        <svg\n          width=\"24\"\n          height=\"24\"\n          viewBox=\"0 0 24 24\"\n          fill=\"none\"\n          xmlns=\"http://www.w3.org/2000/svg\"\n        >\n          <path\n            d=\"M7.5 12L10.5 15L16.5 9M7.8 21H16.2C17.8802 21 18.7202 21 19.362 20.673C19.9265 20.3854 20.3854 19.9265 20.673 19.362C21 18.7202 21 17.8802 21 16.2V7.8C21 6.11984 21 5.27976 20.673 4.63803C20.3854 4.07354 19.9265 3.6146 19.362 3.32698C18.7202 3 17.8802 3 16.2 3H7.8C6.11984 3 5.27976 3 4.63803 3.32698C4.07354 3.6146 3.6146 4.07354 3.32698 4.63803C3 5.27976 3 6.11984 3 7.8V16.2C3 17.8802 3 18.7202 3.32698 19.362C3.6146 19.9265 4.07354 20.3854 4.63803 20.673C5.27976 21 6.11984 21 7.8 21Z\"\n            stroke={props.theme === 'dark' ? '#9B8AFB' : '#6938EF'}\n            stroke-width=\"2\"\n            stroke-linecap=\"round\"\n            stroke-linejoin=\"round\"\n          />\n        </svg>\n      </Show>\n      <Show when={!props.checked}>\n        <svg\n          viewBox=\"0 0 24 24\"\n          height=\"20\"\n          width=\"20\"\n          fill=\"none\"\n          xmlns=\"http://www.w3.org/2000/svg\"\n        >\n          <path\n            d=\"M3 7.8c0-1.68 0-2.52.327-3.162a3 3 0 0 1 1.311-1.311C5.28 3 6.12 3 7.8 3h8.4c1.68 0 2.52 0 3.162.327a3 3 0 0 1 1.311 1.311C21 5.28 21 6.12 21 7.8v8.4c0 1.68 0 2.52-.327 3.162a3 3 0 0 1-1.311 1.311C18.72 21 17.88 21 16.2 21H7.8c-1.68 0-2.52 0-3.162-.327a3 3 0 0 1-1.311-1.311C3 18.72 3 17.88 3 16.2V7.8Z\"\n            stroke={props.theme === 'dark' ? '#9B8AFB' : '#6938EF'}\n            stroke-width=\"2\"\n            stroke-linecap=\"round\"\n            stroke-linejoin=\"round\"\n          ></path>\n        </svg>\n      </Show>\n    </>\n  )\n}\n\nexport function CheckCircle() {\n  return (\n    <svg\n      width=\"14\"\n      height=\"14\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <path\n        d=\"M7.5 12L10.5 15L16.5 9M22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12Z\"\n        stroke=\"currentColor\"\n        stroke-width=\"2\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n    </svg>\n  )\n}\n\nexport function LoadingCircle() {\n  return (\n    <svg\n      width=\"14\"\n      height=\"14\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <path\n        d=\"M12 2V6M12 18V22M6 12H2M22 12H18M19.0784 19.0784L16.25 16.25M19.0784 4.99994L16.25 7.82837M4.92157 19.0784L7.75 16.25M4.92157 4.99994L7.75 7.82837\"\n        stroke=\"currentColor\"\n        stroke-width=\"2\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n      <animateTransform\n        attributeName=\"transform\"\n        attributeType=\"XML\"\n        type=\"rotate\"\n        from=\"0\"\n        to=\"360\"\n        dur=\"2s\"\n        repeatCount=\"indefinite\"\n      />\n    </svg>\n  )\n}\n\nexport function XCircle() {\n  return (\n    <svg\n      width=\"14\"\n      height=\"14\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <path\n        d=\"M15 9L9 15M9 9L15 15M22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12Z\"\n        stroke=\"currentColor\"\n        stroke-width=\"2\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n    </svg>\n  )\n}\n\nexport function PauseCircle() {\n  return (\n    <svg\n      width=\"14\"\n      height=\"14\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <path\n        d=\"M9.5 15V9M14.5 15V9M22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12Z\"\n        stroke=\"currentColor\"\n        stroke-width=\"2\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n    </svg>\n  )\n}\n\nexport function TanstackLogo() {\n  const id = createUniqueId()\n  return (\n    <svg version=\"1.0\" viewBox=\"0 0 633 633\">\n      <linearGradient\n        id={`a-${id}`}\n        x1=\"-666.45\"\n        x2=\"-666.45\"\n        y1=\"163.28\"\n        y2=\"163.99\"\n        gradientTransform=\"matrix(633 0 0 633 422177 -103358)\"\n        gradientUnits=\"userSpaceOnUse\"\n      >\n        <stop stop-color=\"#6BDAFF\" offset=\"0\" />\n        <stop stop-color=\"#F9FFB5\" offset=\".32\" />\n        <stop stop-color=\"#FFA770\" offset=\".71\" />\n        <stop stop-color=\"#FF7373\" offset=\"1\" />\n      </linearGradient>\n      <circle cx=\"316.5\" cy=\"316.5\" r=\"316.5\" fill={`url(#a-${id})`} />\n\n      <defs>\n        <filter\n          id={`am-${id}`}\n          x=\"-137.5\"\n          y=\"412\"\n          width=\"454\"\n          height=\"396.9\"\n          filterUnits=\"userSpaceOnUse\"\n        >\n          <feColorMatrix values=\"1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 1 0\" />\n        </filter>\n      </defs>\n\n      <mask\n        id={`b-${id}`}\n        x=\"-137.5\"\n        y=\"412\"\n        width=\"454\"\n        height=\"396.9\"\n        maskUnits=\"userSpaceOnUse\"\n      >\n        <g filter={`url(#am-${id})`}>\n          <circle cx=\"316.5\" cy=\"316.5\" r=\"316.5\" fill=\"#fff\" />\n        </g>\n      </mask>\n      <g mask={`url(#b-${id})`}>\n        <ellipse\n          cx=\"89.5\"\n          cy=\"610.5\"\n          rx=\"214.5\"\n          ry=\"186\"\n          fill=\"#015064\"\n          stroke=\"#00CFE2\"\n          stroke-width=\"25\"\n        />\n      </g>\n      <defs>\n        <filter\n          id={`ah-${id}`}\n          x=\"316.5\"\n          y=\"412\"\n          width=\"454\"\n          height=\"396.9\"\n          filterUnits=\"userSpaceOnUse\"\n        >\n          <feColorMatrix values=\"1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 1 0\" />\n        </filter>\n      </defs>\n\n      <mask\n        id={`k-${id}`}\n        x=\"316.5\"\n        y=\"412\"\n        width=\"454\"\n        height=\"396.9\"\n        maskUnits=\"userSpaceOnUse\"\n      >\n        <g filter={`url(#ah-${id})`}>\n          <circle cx=\"316.5\" cy=\"316.5\" r=\"316.5\" fill=\"#fff\" />\n        </g>\n      </mask>\n      <g mask={`url(#k-${id})`}>\n        <ellipse\n          cx=\"543.5\"\n          cy=\"610.5\"\n          rx=\"214.5\"\n          ry=\"186\"\n          fill=\"#015064\"\n          stroke=\"#00CFE2\"\n          stroke-width=\"25\"\n        />\n      </g>\n      <defs>\n        <filter\n          id={`ae-${id}`}\n          x=\"-137.5\"\n          y=\"450\"\n          width=\"454\"\n          height=\"396.9\"\n          filterUnits=\"userSpaceOnUse\"\n        >\n          <feColorMatrix values=\"1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 1 0\" />\n        </filter>\n      </defs>\n\n      <mask\n        id={`j-${id}`}\n        x=\"-137.5\"\n        y=\"450\"\n        width=\"454\"\n        height=\"396.9\"\n        maskUnits=\"userSpaceOnUse\"\n      >\n        <g filter={`url(#ae-${id})`}>\n          <circle cx=\"316.5\" cy=\"316.5\" r=\"316.5\" fill=\"#fff\" />\n        </g>\n      </mask>\n      <g mask={`url(#j-${id})`}>\n        <ellipse\n          cx=\"89.5\"\n          cy=\"648.5\"\n          rx=\"214.5\"\n          ry=\"186\"\n          fill=\"#015064\"\n          stroke=\"#00A8B8\"\n          stroke-width=\"25\"\n        />\n      </g>\n      <defs>\n        <filter\n          id={`ai-${id}`}\n          x=\"316.5\"\n          y=\"450\"\n          width=\"454\"\n          height=\"396.9\"\n          filterUnits=\"userSpaceOnUse\"\n        >\n          <feColorMatrix values=\"1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 1 0\" />\n        </filter>\n      </defs>\n\n      <mask\n        id={`i-${id}`}\n        x=\"316.5\"\n        y=\"450\"\n        width=\"454\"\n        height=\"396.9\"\n        maskUnits=\"userSpaceOnUse\"\n      >\n        <g filter={`url(#ai-${id})`}>\n          <circle cx=\"316.5\" cy=\"316.5\" r=\"316.5\" fill=\"#fff\" />\n        </g>\n      </mask>\n      <g mask={`url(#i-${id})`}>\n        <ellipse\n          cx=\"543.5\"\n          cy=\"648.5\"\n          rx=\"214.5\"\n          ry=\"186\"\n          fill=\"#015064\"\n          stroke=\"#00A8B8\"\n          stroke-width=\"25\"\n        />\n      </g>\n      <defs>\n        <filter\n          id={`aj-${id}`}\n          x=\"-137.5\"\n          y=\"486\"\n          width=\"454\"\n          height=\"396.9\"\n          filterUnits=\"userSpaceOnUse\"\n        >\n          <feColorMatrix values=\"1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 1 0\" />\n        </filter>\n      </defs>\n\n      <mask\n        id={`h-${id}`}\n        x=\"-137.5\"\n        y=\"486\"\n        width=\"454\"\n        height=\"396.9\"\n        maskUnits=\"userSpaceOnUse\"\n      >\n        <g filter={`url(#aj-${id})`}>\n          <circle cx=\"316.5\" cy=\"316.5\" r=\"316.5\" fill=\"#fff\" />\n        </g>\n      </mask>\n      <g mask={`url(#h-${id})`}>\n        <ellipse\n          cx=\"89.5\"\n          cy=\"684.5\"\n          rx=\"214.5\"\n          ry=\"186\"\n          fill=\"#015064\"\n          stroke=\"#007782\"\n          stroke-width=\"25\"\n        />\n      </g>\n      <defs>\n        <filter\n          id={`ag-${id}`}\n          x=\"316.5\"\n          y=\"486\"\n          width=\"454\"\n          height=\"396.9\"\n          filterUnits=\"userSpaceOnUse\"\n        >\n          <feColorMatrix values=\"1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 1 0\" />\n        </filter>\n      </defs>\n\n      <mask\n        id={`g-${id}`}\n        x=\"316.5\"\n        y=\"486\"\n        width=\"454\"\n        height=\"396.9\"\n        maskUnits=\"userSpaceOnUse\"\n      >\n        <g filter={`url(#ag-${id})`}>\n          <circle cx=\"316.5\" cy=\"316.5\" r=\"316.5\" fill=\"#fff\" />\n        </g>\n      </mask>\n      <g mask={`url(#g-${id})`}>\n        <ellipse\n          cx=\"543.5\"\n          cy=\"684.5\"\n          rx=\"214.5\"\n          ry=\"186\"\n          fill=\"#015064\"\n          stroke=\"#007782\"\n          stroke-width=\"25\"\n        />\n      </g>\n      <defs>\n        <filter\n          id={`af-${id}`}\n          x=\"272.2\"\n          y=\"308\"\n          width=\"176.9\"\n          height=\"129.3\"\n          filterUnits=\"userSpaceOnUse\"\n        >\n          <feColorMatrix values=\"1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 1 0\" />\n        </filter>\n      </defs>\n\n      <mask\n        id={`f-${id}`}\n        x=\"272.2\"\n        y=\"308\"\n        width=\"176.9\"\n        height=\"129.3\"\n        maskUnits=\"userSpaceOnUse\"\n      >\n        <g filter={`url(#af-${id})`}>\n          <circle cx=\"316.5\" cy=\"316.5\" r=\"316.5\" fill=\"#fff\" />\n        </g>\n      </mask>\n      <g mask={`url(#f-${id})`}>\n        <line\n          x1=\"436\"\n          x2=\"431\"\n          y1=\"403.2\"\n          y2=\"431.8\"\n          fill=\"none\"\n          stroke=\"#000\"\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"bevel\"\n          stroke-width=\"11\"\n        />\n\n        <line\n          x1=\"291\"\n          x2=\"280\"\n          y1=\"341.5\"\n          y2=\"403.5\"\n          fill=\"none\"\n          stroke=\"#000\"\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"bevel\"\n          stroke-width=\"11\"\n        />\n\n        <line\n          x1=\"332.9\"\n          x2=\"328.6\"\n          y1=\"384.1\"\n          y2=\"411.2\"\n          fill=\"none\"\n          stroke=\"#000\"\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"bevel\"\n          stroke-width=\"11\"\n        />\n\n        <linearGradient\n          id={`m-${id}`}\n          x1=\"-670.75\"\n          x2=\"-671.59\"\n          y1=\"164.4\"\n          y2=\"164.49\"\n          gradientTransform=\"matrix(-184.16 -32.472 -11.461 64.997 -121359 -32126)\"\n          gradientUnits=\"userSpaceOnUse\"\n        >\n          <stop stop-color=\"#EE2700\" offset=\"0\" />\n          <stop stop-color=\"#FF008E\" offset=\"1\" />\n        </linearGradient>\n\n        <path\n          d=\"m344.1 363 97.7 17.2c5.8 2.1 8.2 6.1 7.1 12.1s-4.7 9.2-11 9.9l-106-18.7-57.5-59.2c-3.2-4.8-2.9-9.1 0.8-12.8s8.3-4.4 13.7-2.1l55.2 53.6z\"\n          clip-rule=\"evenodd\"\n          fill={`url(#m-${id})`}\n          fill-rule=\"evenodd\"\n        />\n\n        <line\n          x1=\"428.2\"\n          x2=\"429.1\"\n          y1=\"384.5\"\n          y2=\"378\"\n          fill=\"none\"\n          stroke=\"#fff\"\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"bevel\"\n          stroke-width=\"7\"\n        />\n\n        <line\n          x1=\"395.2\"\n          x2=\"396.1\"\n          y1=\"379.5\"\n          y2=\"373\"\n          fill=\"none\"\n          stroke=\"#fff\"\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"bevel\"\n          stroke-width=\"7\"\n        />\n\n        <line\n          x1=\"362.2\"\n          x2=\"363.1\"\n          y1=\"373.5\"\n          y2=\"367.4\"\n          fill=\"none\"\n          stroke=\"#fff\"\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"bevel\"\n          stroke-width=\"7\"\n        />\n\n        <line\n          x1=\"324.2\"\n          x2=\"328.4\"\n          y1=\"351.3\"\n          y2=\"347.4\"\n          fill=\"none\"\n          stroke=\"#fff\"\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"bevel\"\n          stroke-width=\"7\"\n        />\n\n        <line\n          x1=\"303.2\"\n          x2=\"307.4\"\n          y1=\"331.3\"\n          y2=\"327.4\"\n          fill=\"none\"\n          stroke=\"#fff\"\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"bevel\"\n          stroke-width=\"7\"\n        />\n      </g>\n      <defs>\n        <filter\n          id={`ak-${id}`}\n          x=\"73.2\"\n          y=\"113.8\"\n          width=\"280.6\"\n          height=\"317.4\"\n          filterUnits=\"userSpaceOnUse\"\n        >\n          <feColorMatrix values=\"1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 1 0\" />\n        </filter>\n      </defs>\n\n      <mask\n        id={`e-${id}`}\n        x=\"73.2\"\n        y=\"113.8\"\n        width=\"280.6\"\n        height=\"317.4\"\n        maskUnits=\"userSpaceOnUse\"\n      >\n        <g filter={`url(#ak-${id})`}>\n          <circle cx=\"316.5\" cy=\"316.5\" r=\"316.5\" fill=\"#fff\" />\n        </g>\n      </mask>\n      <g mask={`url(#e-${id})`}>\n        <linearGradient\n          id={`n-${id}`}\n          x1=\"-672.16\"\n          x2=\"-672.16\"\n          y1=\"165.03\"\n          y2=\"166.03\"\n          gradientTransform=\"matrix(-100.18 48.861 97.976 200.88 -83342 -93.059)\"\n          gradientUnits=\"userSpaceOnUse\"\n        >\n          <stop stop-color=\"#A17500\" offset=\"0\" />\n          <stop stop-color=\"#5D2100\" offset=\"1\" />\n        </linearGradient>\n\n        <path\n          d=\"m192.3 203c8.1 37.3 14 73.6 17.8 109.1 3.8 35.4 2.8 75.1-3 119.2l61.2-16.7c-15.6-59-25.2-97.9-28.6-116.6s-10.8-51.9-22.1-99.6l-25.3 4.6\"\n          clip-rule=\"evenodd\"\n          fill={`url(#n-${id})`}\n          fill-rule=\"evenodd\"\n        />\n        <g stroke=\"#2F8A00\">\n          <linearGradient\n            id={`r-${id}`}\n            x1=\"-660.23\"\n            x2=\"-660.23\"\n            y1=\"166.72\"\n            y2=\"167.72\"\n            gradientTransform=\"matrix(92.683 4.8573 -2.0259 38.657 61680 -3088.6)\"\n            gradientUnits=\"userSpaceOnUse\"\n          >\n            <stop stop-color=\"#2F8A00\" offset=\"0\" />\n            <stop stop-color=\"#90FF57\" offset=\"1\" />\n          </linearGradient>\n\n          <path\n            d=\"m195 183.9s-12.6-22.1-36.5-29.9c-15.9-5.2-34.4-1.5-55.5 11.1 15.9 14.3 29.5 22.6 40.7 24.9 16.8 3.6 51.3-6.1 51.3-6.1z\"\n            clip-rule=\"evenodd\"\n            fill={`url(#r-${id})`}\n            fill-rule=\"evenodd\"\n            stroke-width=\"13\"\n          />\n\n          <linearGradient\n            id={`s-${id}`}\n            x1=\"-661.36\"\n            x2=\"-661.36\"\n            y1=\"164.18\"\n            y2=\"165.18\"\n            gradientTransform=\"matrix(110 5.7648 -6.3599 121.35 73933 -15933)\"\n            gradientUnits=\"userSpaceOnUse\"\n          >\n            <stop stop-color=\"#2F8A00\" offset=\"0\" />\n            <stop stop-color=\"#90FF57\" offset=\"1\" />\n          </linearGradient>\n\n          <path\n            d=\"m194.9 184.5s-47.5-8.5-83.2 15.7c-23.8 16.2-34.3 49.3-31.6 99.4 30.3-27.8 52.1-48.5 65.2-61.9 19.8-20.2 49.6-53.2 49.6-53.2z\"\n            clip-rule=\"evenodd\"\n            fill={`url(#s-${id})`}\n            fill-rule=\"evenodd\"\n            stroke-width=\"13\"\n          />\n\n          <linearGradient\n            id={`q-${id}`}\n            x1=\"-656.79\"\n            x2=\"-656.79\"\n            y1=\"165.15\"\n            y2=\"166.15\"\n            gradientTransform=\"matrix(62.954 3.2993 -3.5023 66.828 42156 -8754.1)\"\n            gradientUnits=\"userSpaceOnUse\"\n          >\n            <stop stop-color=\"#2F8A00\" offset=\"0\" />\n            <stop stop-color=\"#90FF57\" offset=\"1\" />\n          </linearGradient>\n\n          <path\n            d=\"m195 183.9c-0.8-21.9 6-38 20.6-48.2s29.8-15.4 45.5-15.3c-6.1 21.4-14.5 35.8-25.2 43.4s-24.4 14.2-40.9 20.1z\"\n            clip-rule=\"evenodd\"\n            fill={`url(#q-${id})`}\n            fill-rule=\"evenodd\"\n            stroke-width=\"13\"\n          />\n\n          <linearGradient\n            id={`p-${id}`}\n            x1=\"-663.07\"\n            x2=\"-663.07\"\n            y1=\"165.44\"\n            y2=\"166.44\"\n            gradientTransform=\"matrix(152.47 7.9907 -3.0936 59.029 101884 -4318.7)\"\n            gradientUnits=\"userSpaceOnUse\"\n          >\n            <stop stop-color=\"#2F8A00\" offset=\"0\" />\n            <stop stop-color=\"#90FF57\" offset=\"1\" />\n          </linearGradient>\n\n          <path\n            d=\"m194.9 184.5c31.9-30 64.1-39.7 96.7-29s50.8 30.4 54.6 59.1c-35.2-5.5-60.4-9.6-75.8-12.1-15.3-2.6-40.5-8.6-75.5-18z\"\n            clip-rule=\"evenodd\"\n            fill={`url(#p-${id})`}\n            fill-rule=\"evenodd\"\n            stroke-width=\"13\"\n          />\n\n          <linearGradient\n            id={`o-${id}`}\n            x1=\"-662.57\"\n            x2=\"-662.57\"\n            y1=\"164.44\"\n            y2=\"165.44\"\n            gradientTransform=\"matrix(136.46 7.1517 -5.2163 99.533 91536 -11442)\"\n            gradientUnits=\"userSpaceOnUse\"\n          >\n            <stop stop-color=\"#2F8A00\" offset=\"0\" />\n            <stop stop-color=\"#90FF57\" offset=\"1\" />\n          </linearGradient>\n\n          <path\n            d=\"m194.9 184.5c35.8-7.6 65.6-0.2 89.2 22s37.7 49 42.3 80.3c-39.8-9.7-68.3-23.8-85.5-42.4s-32.5-38.5-46-59.9z\"\n            clip-rule=\"evenodd\"\n            fill={`url(#o-${id})`}\n            fill-rule=\"evenodd\"\n            stroke-width=\"13\"\n          />\n\n          <linearGradient\n            id={`l-${id}`}\n            x1=\"-656.43\"\n            x2=\"-656.43\"\n            y1=\"163.86\"\n            y2=\"164.86\"\n            gradientTransform=\"matrix(60.866 3.1899 -8.7773 167.48 41560 -25168)\"\n            gradientUnits=\"userSpaceOnUse\"\n          >\n            <stop stop-color=\"#2F8A00\" offset=\"0\" />\n            <stop stop-color=\"#90FF57\" offset=\"1\" />\n          </linearGradient>\n\n          <path\n            d=\"m194.9 184.5c-33.6 13.8-53.6 35.7-60.1 65.6s-3.6 63.1 8.7 99.6c27.4-40.3 43.2-69.6 47.4-88s5.6-44.1 4-77.2z\"\n            clip-rule=\"evenodd\"\n            fill={`url(#l-${id})`}\n            fill-rule=\"evenodd\"\n            stroke-width=\"13\"\n          />\n          <path\n            d=\"m196.5 182.3c-14.8 21.6-25.1 41.4-30.8 59.4s-9.5 33-11.1 45.1\"\n            fill=\"none\"\n            stroke-linecap=\"round\"\n            stroke-width=\"8\"\n          />\n          <path\n            d=\"m194.9 185.7c-24.4 1.7-43.8 9-58.1 21.8s-24.7 25.4-31.3 37.8\"\n            fill=\"none\"\n            stroke-linecap=\"round\"\n            stroke-width=\"8\"\n          />\n          <path\n            d=\"m204.5 176.4c29.7-6.7 52-8.4 67-5.1s26.9 8.6 35.8 15.9\"\n            fill=\"none\"\n            stroke-linecap=\"round\"\n            stroke-width=\"8\"\n          />\n          <path\n            d=\"m196.5 181.4c20.3 9.9 38.2 20.5 53.9 31.9s27.4 22.1 35.1 32\"\n            fill=\"none\"\n            stroke-linecap=\"round\"\n            stroke-width=\"8\"\n          />\n        </g>\n      </g>\n      <defs>\n        <filter\n          id={`al-${id}`}\n          x=\"50.5\"\n          y=\"399\"\n          width=\"532\"\n          height=\"633\"\n          filterUnits=\"userSpaceOnUse\"\n        >\n          <feColorMatrix values=\"1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 1 0\" />\n        </filter>\n      </defs>\n\n      <mask\n        id={`d-${id}`}\n        x=\"50.5\"\n        y=\"399\"\n        width=\"532\"\n        height=\"633\"\n        maskUnits=\"userSpaceOnUse\"\n      >\n        <g filter={`url(#al-${id})`}>\n          <circle cx=\"316.5\" cy=\"316.5\" r=\"316.5\" fill=\"#fff\" />\n        </g>\n      </mask>\n      <g mask={`url(#d-${id})`}>\n        <linearGradient\n          id={`u-${id}`}\n          x1=\"-666.06\"\n          x2=\"-666.23\"\n          y1=\"163.36\"\n          y2=\"163.75\"\n          gradientTransform=\"matrix(532 0 0 633 354760 -102959)\"\n          gradientUnits=\"userSpaceOnUse\"\n        >\n          <stop stop-color=\"#FFF400\" offset=\"0\" />\n          <stop stop-color=\"#3C8700\" offset=\"1\" />\n        </linearGradient>\n\n        <ellipse\n          cx=\"316.5\"\n          cy=\"715.5\"\n          rx=\"266\"\n          ry=\"316.5\"\n          fill={`url(#u-${id})`}\n        />\n      </g>\n      <defs>\n        <filter\n          id={`ad-${id}`}\n          x=\"391\"\n          y=\"-24\"\n          width=\"288\"\n          height=\"283\"\n          filterUnits=\"userSpaceOnUse\"\n        >\n          <feColorMatrix values=\"1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 1 0\" />\n        </filter>\n      </defs>\n\n      <mask\n        id={`c-${id}`}\n        x=\"391\"\n        y=\"-24\"\n        width=\"288\"\n        height=\"283\"\n        maskUnits=\"userSpaceOnUse\"\n      >\n        <g filter={`url(#ad-${id})`}>\n          <circle cx=\"316.5\" cy=\"316.5\" r=\"316.5\" fill=\"#fff\" />\n        </g>\n      </mask>\n      <g mask={`url(#c-${id})`}>\n        <linearGradient\n          id={`t-${id}`}\n          x1=\"-664.56\"\n          x2=\"-664.56\"\n          y1=\"163.79\"\n          y2=\"164.79\"\n          gradientTransform=\"matrix(227 0 0 227 151421 -37204)\"\n          gradientUnits=\"userSpaceOnUse\"\n        >\n          <stop stop-color=\"#FFDF00\" offset=\"0\" />\n          <stop stop-color=\"#FF9D00\" offset=\"1\" />\n        </linearGradient>\n        <circle cx=\"565.5\" cy=\"89.5\" r=\"113.5\" fill={`url(#t-${id})`} />\n\n        <linearGradient\n          id={`v-${id}`}\n          x1=\"-644.5\"\n          x2=\"-645.77\"\n          y1=\"342\"\n          y2=\"342\"\n          gradientTransform=\"matrix(30 0 0 1 19770 -253)\"\n          gradientUnits=\"userSpaceOnUse\"\n        >\n          <stop stop-color=\"#FFA400\" offset=\"0\" />\n          <stop stop-color=\"#FF5E00\" offset=\"1\" />\n        </linearGradient>\n\n        <line\n          x1=\"427\"\n          x2=\"397\"\n          y1=\"89\"\n          y2=\"89\"\n          fill=\"none\"\n          stroke={`url(#v-${id})`}\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"bevel\"\n          stroke-width=\"12\"\n        />\n\n        <linearGradient\n          id={`aa-${id}`}\n          x1=\"-641.56\"\n          x2=\"-642.83\"\n          y1=\"196.02\"\n          y2=\"196.07\"\n          gradientTransform=\"matrix(26.5 0 0 5.5 17439 -1025.5)\"\n          gradientUnits=\"userSpaceOnUse\"\n        >\n          <stop stop-color=\"#FFA400\" offset=\"0\" />\n          <stop stop-color=\"#FF5E00\" offset=\"1\" />\n        </linearGradient>\n\n        <line\n          x1=\"430.5\"\n          x2=\"404\"\n          y1=\"55.5\"\n          y2=\"50\"\n          fill=\"none\"\n          stroke={`url(#aa-${id})`}\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"bevel\"\n          stroke-width=\"12\"\n        />\n\n        <linearGradient\n          id={`w-${id}`}\n          x1=\"-643.73\"\n          x2=\"-645\"\n          y1=\"185.83\"\n          y2=\"185.9\"\n          gradientTransform=\"matrix(29 0 0 8 19107 -1361)\"\n          gradientUnits=\"userSpaceOnUse\"\n        >\n          <stop stop-color=\"#FFA400\" offset=\"0\" />\n          <stop stop-color=\"#FF5E00\" offset=\"1\" />\n        </linearGradient>\n\n        <line\n          x1=\"431\"\n          x2=\"402\"\n          y1=\"122\"\n          y2=\"130\"\n          fill=\"none\"\n          stroke={`url(#w-${id})`}\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"bevel\"\n          stroke-width=\"12\"\n        />\n\n        <linearGradient\n          id={`ac-${id}`}\n          x1=\"-638.94\"\n          x2=\"-640.22\"\n          y1=\"177.09\"\n          y2=\"177.39\"\n          gradientTransform=\"matrix(24 0 0 13 15783 -2145)\"\n          gradientUnits=\"userSpaceOnUse\"\n        >\n          <stop stop-color=\"#FFA400\" offset=\"0\" />\n          <stop stop-color=\"#FF5E00\" offset=\"1\" />\n        </linearGradient>\n\n        <line\n          x1=\"442\"\n          x2=\"418\"\n          y1=\"153\"\n          y2=\"166\"\n          fill=\"none\"\n          stroke={`url(#ac-${id})`}\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"bevel\"\n          stroke-width=\"12\"\n        />\n\n        <linearGradient\n          id={`ab-${id}`}\n          x1=\"-633.42\"\n          x2=\"-634.7\"\n          y1=\"172.41\"\n          y2=\"173.31\"\n          gradientTransform=\"matrix(20 0 0 19 13137 -3096)\"\n          gradientUnits=\"userSpaceOnUse\"\n        >\n          <stop stop-color=\"#FFA400\" offset=\"0\" />\n          <stop stop-color=\"#FF5E00\" offset=\"1\" />\n        </linearGradient>\n\n        <line\n          x1=\"464\"\n          x2=\"444\"\n          y1=\"180\"\n          y2=\"199\"\n          fill=\"none\"\n          stroke={`url(#ab-${id})`}\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"bevel\"\n          stroke-width=\"12\"\n        />\n\n        <linearGradient\n          id={`y-${id}`}\n          x1=\"-619.05\"\n          x2=\"-619.52\"\n          y1=\"170.82\"\n          y2=\"171.82\"\n          gradientTransform=\"matrix(13.83 0 0 22.85 9050 -3703.4)\"\n          gradientUnits=\"userSpaceOnUse\"\n        >\n          <stop stop-color=\"#FFA400\" offset=\"0\" />\n          <stop stop-color=\"#FF5E00\" offset=\"1\" />\n        </linearGradient>\n\n        <line\n          x1=\"491.4\"\n          x2=\"477.5\"\n          y1=\"203\"\n          y2=\"225.9\"\n          fill=\"none\"\n          stroke={`url(#y-${id})`}\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"bevel\"\n          stroke-width=\"12\"\n        />\n\n        <linearGradient\n          id={`x-${id}`}\n          x1=\"-578.5\"\n          x2=\"-578.63\"\n          y1=\"170.31\"\n          y2=\"171.31\"\n          gradientTransform=\"matrix(7.5 0 0 24.5 4860 -3953)\"\n          gradientUnits=\"userSpaceOnUse\"\n        >\n          <stop stop-color=\"#FFA400\" offset=\"0\" />\n          <stop stop-color=\"#FF5E00\" offset=\"1\" />\n        </linearGradient>\n\n        <line\n          x1=\"524.5\"\n          x2=\"517\"\n          y1=\"219.5\"\n          y2=\"244\"\n          fill=\"none\"\n          stroke={`url(#x-${id})`}\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"bevel\"\n          stroke-width=\"12\"\n        />\n\n        <linearGradient\n          id={`z-${id}`}\n          x1=\"666.5\"\n          x2=\"666.5\"\n          y1=\"170.31\"\n          y2=\"171.31\"\n          gradientTransform=\"matrix(.5 0 0 24.5 231.5 -3944)\"\n          gradientUnits=\"userSpaceOnUse\"\n        >\n          <stop stop-color=\"#FFA400\" offset=\"0\" />\n          <stop stop-color=\"#FF5E00\" offset=\"1\" />\n        </linearGradient>\n\n        <line\n          x1=\"564.5\"\n          x2=\"565\"\n          y1=\"228.5\"\n          y2=\"253\"\n          fill=\"none\"\n          stroke={`url(#z-${id})`}\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"bevel\"\n          stroke-width=\"12\"\n        />\n      </g>\n    </svg>\n  )\n}\n"
  },
  {
    "path": "packages/query-devtools/src/index.ts",
    "content": "export type {\n  DevtoolsButtonPosition,\n  DevtoolsErrorType,\n  DevtoolsPosition,\n  Theme,\n} from './contexts'\nexport {\n  TanstackQueryDevtools,\n  type TanstackQueryDevtoolsConfig,\n} from './TanstackQueryDevtools'\nexport {\n  TanstackQueryDevtoolsPanel,\n  type TanstackQueryDevtoolsPanelConfig,\n} from './TanstackQueryDevtoolsPanel'\n"
  },
  {
    "path": "packages/query-devtools/src/theme.ts",
    "content": "export const tokens = {\n  colors: {\n    inherit: 'inherit',\n    current: 'currentColor',\n    transparent: 'transparent',\n    black: '#000000',\n    white: '#ffffff',\n    neutral: {\n      50: '#f9fafb',\n      100: '#f2f4f7',\n      200: '#eaecf0',\n      300: '#d0d5dd',\n      400: '#98a2b3',\n      500: '#667085',\n      600: '#475467',\n      700: '#344054',\n      800: '#1d2939',\n      900: '#101828',\n    },\n    darkGray: {\n      50: '#525c7a',\n      100: '#49536e',\n      200: '#414962',\n      300: '#394056',\n      400: '#313749',\n      500: '#292e3d',\n      600: '#212530',\n      700: '#191c24',\n      800: '#111318',\n      900: '#0b0d10',\n    },\n    gray: {\n      50: '#f9fafb',\n      100: '#f2f4f7',\n      200: '#eaecf0',\n      300: '#d0d5dd',\n      400: '#98a2b3',\n      500: '#667085',\n      600: '#475467',\n      700: '#344054',\n      800: '#1d2939',\n      900: '#101828',\n    },\n    blue: {\n      25: '#F5FAFF',\n      50: '#EFF8FF',\n      100: '#D1E9FF',\n      200: '#B2DDFF',\n      300: '#84CAFF',\n      400: '#53B1FD',\n      500: '#2E90FA',\n      600: '#1570EF',\n      700: '#175CD3',\n      800: '#1849A9',\n      900: '#194185',\n    },\n    green: {\n      25: '#F6FEF9',\n      50: '#ECFDF3',\n      100: '#D1FADF',\n      200: '#A6F4C5',\n      300: '#6CE9A6',\n      400: '#32D583',\n      500: '#12B76A',\n      600: '#039855',\n      700: '#027A48',\n      800: '#05603A',\n      900: '#054F31',\n    },\n    red: {\n      50: '#fef2f2',\n      100: '#fee2e2',\n      200: '#fecaca',\n      300: '#fca5a5',\n      400: '#f87171',\n      500: '#ef4444',\n      600: '#dc2626',\n      700: '#b91c1c',\n      800: '#991b1b',\n      900: '#7f1d1d',\n      950: '#450a0a',\n    },\n    yellow: {\n      25: '#FFFCF5',\n      50: '#FFFAEB',\n      100: '#FEF0C7',\n      200: '#FEDF89',\n      300: '#FEC84B',\n      400: '#FDB022',\n      500: '#F79009',\n      600: '#DC6803',\n      700: '#B54708',\n      800: '#93370D',\n      900: '#7A2E0E',\n    },\n    purple: {\n      25: '#FAFAFF',\n      50: '#F4F3FF',\n      100: '#EBE9FE',\n      200: '#D9D6FE',\n      300: '#BDB4FE',\n      400: '#9B8AFB',\n      500: '#7A5AF8',\n      600: '#6938EF',\n      700: '#5925DC',\n      800: '#4A1FB8',\n      900: '#3E1C96',\n    },\n    teal: {\n      25: '#F6FEFC',\n      50: '#F0FDF9',\n      100: '#CCFBEF',\n      200: '#99F6E0',\n      300: '#5FE9D0',\n      400: '#2ED3B7',\n      500: '#15B79E',\n      600: '#0E9384',\n      700: '#107569',\n      800: '#125D56',\n      900: '#134E48',\n    },\n    pink: {\n      25: '#fdf2f8',\n      50: '#fce7f3',\n      100: '#fbcfe8',\n      200: '#f9a8d4',\n      300: '#f472b6',\n      400: '#ec4899',\n      500: '#db2777',\n      600: '#be185d',\n      700: '#9d174d',\n      800: '#831843',\n      900: '#500724',\n    },\n    cyan: {\n      25: '#ecfeff',\n      50: '#cffafe',\n      100: '#a5f3fc',\n      200: '#67e8f9',\n      300: '#22d3ee',\n      400: '#06b6d4',\n      500: '#0891b2',\n      600: '#0e7490',\n      700: '#155e75',\n      800: '#164e63',\n      900: '#083344',\n    },\n  },\n  alpha: {\n    100: 'ff',\n    90: 'e5',\n    80: 'cc',\n    70: 'b3',\n    60: '99',\n    50: '80',\n    40: '66',\n    30: '4d',\n    20: '33',\n    10: '1a',\n    0: '00',\n  },\n  font: {\n    size: {\n      '2xs': 'calc(var(--tsqd-font-size) * 0.625)',\n      xs: 'calc(var(--tsqd-font-size) * 0.75)',\n      sm: 'calc(var(--tsqd-font-size) * 0.875)',\n      md: 'var(--tsqd-font-size)',\n      lg: 'calc(var(--tsqd-font-size) * 1.125)',\n      xl: 'calc(var(--tsqd-font-size) * 1.25)',\n      '2xl': 'calc(var(--tsqd-font-size) * 1.5)',\n      '3xl': 'calc(var(--tsqd-font-size) * 1.875)',\n      '4xl': 'calc(var(--tsqd-font-size) * 2.25)',\n      '5xl': 'calc(var(--tsqd-font-size) * 3)',\n      '6xl': 'calc(var(--tsqd-font-size) * 3.75)',\n      '7xl': 'calc(var(--tsqd-font-size) * 4.5)',\n      '8xl': 'calc(var(--tsqd-font-size) * 6)',\n      '9xl': 'calc(var(--tsqd-font-size) * 8)',\n    },\n    lineHeight: {\n      xs: 'calc(var(--tsqd-font-size) * 1)',\n      sm: 'calc(var(--tsqd-font-size) * 1.25)',\n      md: 'calc(var(--tsqd-font-size) * 1.5)',\n      lg: 'calc(var(--tsqd-font-size) * 1.75)',\n      xl: 'calc(var(--tsqd-font-size) * 2)',\n      '2xl': 'calc(var(--tsqd-font-size) * 2.25)',\n      '3xl': 'calc(var(--tsqd-font-size) * 2.5)',\n      '4xl': 'calc(var(--tsqd-font-size) * 2.75)',\n      '5xl': 'calc(var(--tsqd-font-size) * 3)',\n      '6xl': 'calc(var(--tsqd-font-size) * 3.25)',\n      '7xl': 'calc(var(--tsqd-font-size) * 3.5)',\n      '8xl': 'calc(var(--tsqd-font-size) * 3.75)',\n      '9xl': 'calc(var(--tsqd-font-size) * 4)',\n    },\n    weight: {\n      thin: '100',\n      extralight: '200',\n      light: '300',\n      normal: '400',\n      medium: '500',\n      semibold: '600',\n      bold: '700',\n      extrabold: '800',\n      black: '900',\n    },\n  },\n  breakpoints: {\n    xs: '320px',\n    sm: '640px',\n    md: '768px',\n    lg: '1024px',\n    xl: '1280px',\n    '2xl': '1536px',\n  },\n  border: {\n    radius: {\n      none: '0px',\n      xs: 'calc(var(--tsqd-font-size) * 0.125)',\n      sm: 'calc(var(--tsqd-font-size) * 0.25)',\n      md: 'calc(var(--tsqd-font-size) * 0.375)',\n      lg: 'calc(var(--tsqd-font-size) * 0.5)',\n      xl: 'calc(var(--tsqd-font-size) * 0.75)',\n      '2xl': 'calc(var(--tsqd-font-size) * 1)',\n      '3xl': 'calc(var(--tsqd-font-size) * 1.5)',\n      full: '9999px',\n    },\n  },\n  size: {\n    0: '0px',\n    0.25: 'calc(var(--tsqd-font-size) * 0.0625)',\n    0.5: 'calc(var(--tsqd-font-size) * 0.125)',\n    1: 'calc(var(--tsqd-font-size) * 0.25)',\n    1.5: 'calc(var(--tsqd-font-size) * 0.375)',\n    2: 'calc(var(--tsqd-font-size) * 0.5)',\n    2.5: 'calc(var(--tsqd-font-size) * 0.625)',\n    3: 'calc(var(--tsqd-font-size) * 0.75)',\n    3.5: 'calc(var(--tsqd-font-size) * 0.875)',\n    4: 'calc(var(--tsqd-font-size) * 1)',\n    4.5: 'calc(var(--tsqd-font-size) * 1.125)',\n    5: 'calc(var(--tsqd-font-size) * 1.25)',\n    5.5: 'calc(var(--tsqd-font-size) * 1.375)',\n    6: 'calc(var(--tsqd-font-size) * 1.5)',\n    6.5: 'calc(var(--tsqd-font-size) * 1.625)',\n    7: 'calc(var(--tsqd-font-size) * 1.75)',\n    8: 'calc(var(--tsqd-font-size) * 2)',\n    9: 'calc(var(--tsqd-font-size) * 2.25)',\n    10: 'calc(var(--tsqd-font-size) * 2.5)',\n    11: 'calc(var(--tsqd-font-size) * 2.75)',\n    12: 'calc(var(--tsqd-font-size) * 3)',\n    14: 'calc(var(--tsqd-font-size) * 3.5)',\n    16: 'calc(var(--tsqd-font-size) * 4)',\n    20: 'calc(var(--tsqd-font-size) * 5)',\n    24: 'calc(var(--tsqd-font-size) * 6)',\n    28: 'calc(var(--tsqd-font-size) * 7)',\n    32: 'calc(var(--tsqd-font-size) * 8)',\n    36: 'calc(var(--tsqd-font-size) * 9)',\n    40: 'calc(var(--tsqd-font-size) * 10)',\n    44: 'calc(var(--tsqd-font-size) * 11)',\n    48: 'calc(var(--tsqd-font-size) * 12)',\n    52: 'calc(var(--tsqd-font-size) * 13)',\n    56: 'calc(var(--tsqd-font-size) * 14)',\n    60: 'calc(var(--tsqd-font-size) * 15)',\n    64: 'calc(var(--tsqd-font-size) * 16)',\n    72: 'calc(var(--tsqd-font-size) * 18)',\n    80: 'calc(var(--tsqd-font-size) * 20)',\n    96: 'calc(var(--tsqd-font-size) * 24)',\n  },\n  shadow: {\n    xs: (_: string = 'rgb(0 0 0 / 0.1)') =>\n      `0 1px 2px 0 rgb(0 0 0 / 0.05)` as const,\n    sm: (color: string = 'rgb(0 0 0 / 0.1)') =>\n      `0 1px 3px 0 ${color}, 0 1px 2px -1px ${color}` as const,\n    md: (color: string = 'rgb(0 0 0 / 0.1)') =>\n      `0 4px 6px -1px ${color}, 0 2px 4px -2px ${color}` as const,\n    lg: (color: string = 'rgb(0 0 0 / 0.1)') =>\n      `0 10px 15px -3px ${color}, 0 4px 6px -4px ${color}` as const,\n    xl: (color: string = 'rgb(0 0 0 / 0.1)') =>\n      `0 20px 25px -5px ${color}, 0 8px 10px -6px ${color}` as const,\n    '2xl': (color: string = 'rgb(0 0 0 / 0.25)') =>\n      `0 25px 50px -12px ${color}` as const,\n    inner: (color: string = 'rgb(0 0 0 / 0.05)') =>\n      `inset 0 2px 4px 0 ${color}` as const,\n    none: () => `none` as const,\n  },\n  zIndices: {\n    hide: -1,\n    auto: 'auto',\n    base: 0,\n    docked: 10,\n    dropdown: 1000,\n    sticky: 1100,\n    banner: 1200,\n    overlay: 1300,\n    modal: 1400,\n    popover: 1500,\n    skipLink: 1600,\n    toast: 1700,\n    tooltip: 1800,\n  },\n} as const\n"
  },
  {
    "path": "packages/query-devtools/src/utils.tsx",
    "content": "import { serialize } from 'superjson'\nimport { createSignal, onCleanup, onMount } from 'solid-js'\nimport type { Mutation, Query } from '@tanstack/query-core'\nimport type { DevtoolsPosition } from './contexts'\n\nexport function getQueryStatusLabel(query: Query) {\n  return query.state.fetchStatus === 'fetching'\n    ? 'fetching'\n    : !query.getObserversCount()\n      ? 'inactive'\n      : query.state.fetchStatus === 'paused'\n        ? 'paused'\n        : query.isStale()\n          ? 'stale'\n          : 'fresh'\n}\n\ntype QueryStatusLabel = 'fresh' | 'stale' | 'paused' | 'inactive' | 'fetching'\n\nexport function getSidedProp<T extends string>(\n  prop: T,\n  side: DevtoolsPosition,\n) {\n  return `${prop}${\n    side.charAt(0).toUpperCase() + side.slice(1)\n  }` as `${T}${Capitalize<DevtoolsPosition>}`\n}\n\nexport function getQueryStatusColor({\n  queryState,\n  observerCount,\n  isStale,\n}: {\n  queryState: Query['state']\n  observerCount: number\n  isStale: boolean\n}) {\n  return queryState.fetchStatus === 'fetching'\n    ? 'blue'\n    : !observerCount\n      ? 'gray'\n      : queryState.fetchStatus === 'paused'\n        ? 'purple'\n        : isStale\n          ? 'yellow'\n          : 'green'\n}\n\nexport function getMutationStatusColor({\n  status,\n  isPaused,\n}: {\n  status: Mutation['state']['status']\n  isPaused: boolean\n}) {\n  return isPaused\n    ? 'purple'\n    : status === 'error'\n      ? 'red'\n      : status === 'pending'\n        ? 'yellow'\n        : status === 'success'\n          ? 'green'\n          : 'gray'\n}\n\nexport function getQueryStatusColorByLabel(label: QueryStatusLabel) {\n  return label === 'fresh'\n    ? 'green'\n    : label === 'stale'\n      ? 'yellow'\n      : label === 'paused'\n        ? 'purple'\n        : label === 'inactive'\n          ? 'gray'\n          : 'blue'\n}\n\n/**\n * Displays a string regardless the type of the data\n * @param {unknown} value Value to be stringified\n * @param {boolean} beautify Formats json to multiline\n */\nexport const displayValue = (value: unknown, beautify: boolean = false) => {\n  const { json } = serialize(value)\n\n  return JSON.stringify(json, null, beautify ? 2 : undefined)\n}\n\n// Sorting functions\ntype SortFn = (a: Query, b: Query) => number\n\nconst getStatusRank = (q: Query) =>\n  q.state.fetchStatus !== 'idle'\n    ? 0\n    : !q.getObserversCount()\n      ? 3\n      : q.isStale()\n        ? 2\n        : 1\n\nconst queryHashSort: SortFn = (a, b) => a.queryHash.localeCompare(b.queryHash)\n\nconst dateSort: SortFn = (a, b) =>\n  a.state.dataUpdatedAt < b.state.dataUpdatedAt ? 1 : -1\n\nconst statusAndDateSort: SortFn = (a, b) => {\n  if (getStatusRank(a) === getStatusRank(b)) {\n    return dateSort(a, b)\n  }\n\n  return getStatusRank(a) > getStatusRank(b) ? 1 : -1\n}\n\nexport const sortFns: Record<string, SortFn> = {\n  status: statusAndDateSort,\n  'query hash': queryHashSort,\n  'last updated': dateSort,\n}\n\ntype MutationSortFn = (a: Mutation, b: Mutation) => number\n\nconst getMutationStatusRank = (m: Mutation) =>\n  m.state.isPaused\n    ? 0\n    : m.state.status === 'error'\n      ? 2\n      : m.state.status === 'pending'\n        ? 1\n        : 3\n\nconst mutationDateSort: MutationSortFn = (a, b) =>\n  a.state.submittedAt < b.state.submittedAt ? 1 : -1\n\nconst mutationStatusSort: MutationSortFn = (a, b) => {\n  if (getMutationStatusRank(a) === getMutationStatusRank(b)) {\n    return mutationDateSort(a, b)\n  }\n\n  return getMutationStatusRank(a) > getMutationStatusRank(b) ? 1 : -1\n}\n\nexport const mutationSortFns: Record<string, MutationSortFn> = {\n  status: mutationStatusSort,\n  'last updated': mutationDateSort,\n}\n\nexport const convertRemToPixels = (rem: number) => {\n  return rem * parseFloat(getComputedStyle(document.documentElement).fontSize)\n}\n\nexport const getPreferredColorScheme = () => {\n  const [colorScheme, setColorScheme] = createSignal<'light' | 'dark'>('dark')\n\n  onMount(() => {\n    const query = window.matchMedia('(prefers-color-scheme: dark)')\n    setColorScheme(query.matches ? 'dark' : 'light')\n    const listener = (e: MediaQueryListEvent) => {\n      setColorScheme(e.matches ? 'dark' : 'light')\n    }\n    query.addEventListener('change', listener)\n    onCleanup(() => query.removeEventListener('change', listener))\n  })\n\n  return colorScheme\n}\n\n/**\n * updates nested data by path\n *\n * @param {unknown} oldData Data to be updated\n * @param {Array<string>} updatePath Path to the data to be updated\n * @param {unknown} value New value\n */\nexport const updateNestedDataByPath = (\n  oldData: unknown,\n  updatePath: Array<string>,\n  value: unknown,\n): any => {\n  if (updatePath.length === 0) {\n    return value\n  }\n\n  if (oldData instanceof Map) {\n    const newData = new Map(oldData)\n\n    if (updatePath.length === 1) {\n      newData.set(updatePath[0], value)\n      return newData\n    }\n\n    const [head, ...tail] = updatePath\n    newData.set(head, updateNestedDataByPath(newData.get(head), tail, value))\n    return newData\n  }\n\n  if (oldData instanceof Set) {\n    const setAsArray = updateNestedDataByPath(\n      Array.from(oldData),\n      updatePath,\n      value,\n    )\n\n    return new Set(setAsArray)\n  }\n\n  if (Array.isArray(oldData)) {\n    const newData = [...oldData]\n\n    if (updatePath.length === 1) {\n      // @ts-expect-error\n      newData[updatePath[0]] = value\n      return newData\n    }\n\n    const [head, ...tail] = updatePath\n    // @ts-expect-error\n    newData[head] = updateNestedDataByPath(newData[head], tail, value)\n\n    return newData\n  }\n\n  if (oldData instanceof Object) {\n    const newData = { ...oldData }\n\n    if (updatePath.length === 1) {\n      // @ts-expect-error\n      newData[updatePath[0]] = value\n      return newData\n    }\n\n    const [head, ...tail] = updatePath\n    // @ts-expect-error\n    newData[head] = updateNestedDataByPath(newData[head], tail, value)\n\n    return newData\n  }\n\n  return oldData\n}\n\n/**\n * Deletes nested data by path\n *\n * @param {unknown} oldData Data to be updated\n * @param {Array<string>} deletePath Path to the data to be deleted\n * @returns newData without the deleted items by path\n */\nexport const deleteNestedDataByPath = (\n  oldData: unknown,\n  deletePath: Array<string>,\n): any => {\n  if (oldData instanceof Map) {\n    const newData = new Map(oldData)\n\n    if (deletePath.length === 1) {\n      newData.delete(deletePath[0])\n      return newData\n    }\n\n    const [head, ...tail] = deletePath\n    newData.set(head, deleteNestedDataByPath(newData.get(head), tail))\n    return newData\n  }\n\n  if (oldData instanceof Set) {\n    const setAsArray = deleteNestedDataByPath(Array.from(oldData), deletePath)\n    return new Set(setAsArray)\n  }\n\n  if (Array.isArray(oldData)) {\n    const newData = [...oldData]\n\n    if (deletePath.length === 1) {\n      return newData.filter((_, idx) => idx.toString() !== deletePath[0])\n    }\n\n    const [head, ...tail] = deletePath\n\n    // @ts-expect-error\n    newData[head] = deleteNestedDataByPath(newData[head], tail)\n\n    return newData\n  }\n\n  if (oldData instanceof Object) {\n    const newData = { ...oldData }\n\n    if (deletePath.length === 1) {\n      // @ts-expect-error\n      delete newData[deletePath[0]]\n      return newData\n    }\n\n    const [head, ...tail] = deletePath\n    // @ts-expect-error\n    newData[head] = deleteNestedDataByPath(newData[head], tail)\n\n    return newData\n  }\n\n  return oldData\n}\n\n// Sets up the goober stylesheet\n// Adds a nonce to the style tag if needed\nexport const setupStyleSheet = (nonce?: string, target?: ShadowRoot) => {\n  if (!nonce) return\n  const styleExists =\n    document.querySelector('#_goober') || target?.querySelector('#_goober')\n\n  if (styleExists) return\n  const styleTag = document.createElement('style')\n  const textNode = document.createTextNode('')\n  styleTag.appendChild(textNode)\n  styleTag.id = '_goober'\n  styleTag.setAttribute('nonce', nonce)\n  if (target) {\n    target.appendChild(styleTag)\n  } else {\n    document.head.appendChild(styleTag)\n  }\n}\n"
  },
  {
    "path": "packages/query-devtools/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\",\n    \"jsx\": \"preserve\",\n    \"jsxImportSource\": \"solid-js\"\n  },\n  \"include\": [\"src\", \"*.config.*\", \"package.json\"],\n  \"references\": [{ \"path\": \"../query-core\" }]\n}\n"
  },
  {
    "path": "packages/query-devtools/tsconfig.prod.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"incremental\": false,\n    \"composite\": false,\n    \"rootDir\": \"../../\"\n  }\n}\n"
  },
  {
    "path": "packages/query-devtools/tsup.config.ts",
    "content": "import { defineConfig } from 'tsup'\nimport { generateTsupOptions, parsePresetOptions } from 'tsup-preset-solid'\n\nconst preset_options = {\n  entries: {\n    entry: 'src/index.ts',\n    dev_entry: true,\n  },\n  cjs: true,\n  drop_console: true,\n}\n\nexport default defineConfig(() => {\n  const parsed_data = parsePresetOptions(preset_options)\n  const tsup_options = generateTsupOptions(parsed_data)\n\n  tsup_options.forEach((tsup_option) => {\n    tsup_option.outDir = 'build'\n    tsup_option.experimentalDts = true\n    delete tsup_option.dts\n  })\n\n  return tsup_options\n})\n"
  },
  {
    "path": "packages/query-devtools/vite.config.ts",
    "content": "import solid from 'vite-plugin-solid'\nimport { defineConfig } from 'vitest/config'\n\nimport packageJson from './package.json'\n\nexport default defineConfig({\n  plugins: [solid()],\n  // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660\n  resolve: {\n    conditions: ['@tanstack/custom-condition'],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        conditions: ['@tanstack/custom-condition'],\n      },\n    },\n  },\n  test: {\n    name: packageJson.name,\n    dir: './src',\n    watch: false,\n    environment: 'jsdom',\n    coverage: {\n      enabled: true,\n      provider: 'istanbul',\n      include: ['src/**/*'],\n      exclude: ['src/__tests__/**'],\n    },\n    typecheck: { enabled: true },\n    restoreMocks: true,\n  },\n})\n"
  },
  {
    "path": "packages/query-persist-client-core/CHANGELOG.md",
    "content": "# @tanstack/query-persist-client-core\n\n## 5.92.4\n\n### Patch Changes\n\n- fix(streamedQuery): maintain error state on reset refetch with initialData defined ([#10287](https://github.com/TanStack/query/pull/10287))\n\n- Updated dependencies [[`248975e`](https://github.com/TanStack/query/commit/248975e896f585f6eaa505c796e73fcf7bfd1eec)]:\n  - @tanstack/query-core@5.91.2\n\n## 5.92.3\n\n### Patch Changes\n\n- Updated dependencies [[`a89aab9`](https://github.com/TanStack/query/commit/a89aab975581c25c113a26c8af486b4cafad272a)]:\n  - @tanstack/query-core@5.91.1\n\n## 5.92.2\n\n### Patch Changes\n\n- Updated dependencies [[`6fa901b`](https://github.com/TanStack/query/commit/6fa901b97a22a80d0fca3f6ed86237ff0cbdd13b)]:\n  - @tanstack/query-core@5.91.0\n\n## 5.92.1\n\n### Patch Changes\n\n- removeItem if deserialize fails ([#10190](https://github.com/TanStack/query/pull/10190))\n\n## 5.92.0\n\n### Minor Changes\n\n- Add removeQueries to experimental_createQueryPersister ([#10186](https://github.com/TanStack/query/pull/10186))\n\n## 5.91.19\n\n### Patch Changes\n\n- Updated dependencies [[`e7258c5`](https://github.com/TanStack/query/commit/e7258c5cb30cafa456cdb4e6bc75b43bf619954d)]:\n  - @tanstack/query-core@5.90.20\n\n## 5.91.18\n\n### Patch Changes\n\n- Updated dependencies [[`53fc74e`](https://github.com/TanStack/query/commit/53fc74ebb16730bd3317f039a69c6821386bae93)]:\n  - @tanstack/query-core@5.90.19\n\n## 5.91.17\n\n### Patch Changes\n\n- Updated dependencies [[`dea1614`](https://github.com/TanStack/query/commit/dea1614aaad5c572cf43cea54b64ac09dc4d5b41)]:\n  - @tanstack/query-core@5.90.18\n\n## 5.91.16\n\n### Patch Changes\n\n- Updated dependencies [[`269351b`](https://github.com/TanStack/query/commit/269351b8ce4b4846da3d320ac5b850ee6aada0d6)]:\n  - @tanstack/query-core@5.90.17\n\n## 5.91.15\n\n### Patch Changes\n\n- Updated dependencies [[`7f47906`](https://github.com/TanStack/query/commit/7f47906eaccc3f3aa5ce24b77a83bd7a620a237b)]:\n  - @tanstack/query-core@5.90.16\n\n## 5.91.14\n\n### Patch Changes\n\n- Updated dependencies [[`fccef79`](https://github.com/TanStack/query/commit/fccef797d57d4a9566517bba87c8377f363920f2)]:\n  - @tanstack/query-core@5.90.15\n\n## 5.91.13\n\n### Patch Changes\n\n- Updated dependencies [[`d576092`](https://github.com/TanStack/query/commit/d576092e2ece4ca3936add3eb0da5234c1d82ed4)]:\n  - @tanstack/query-core@5.90.14\n\n## 5.91.12\n\n### Patch Changes\n\n- Updated dependencies [[`4a0a78a`](https://github.com/TanStack/query/commit/4a0a78afbc2432f8cb6828035965853fa98c86a0)]:\n  - @tanstack/query-core@5.90.13\n\n## 5.91.11\n\n### Patch Changes\n\n- Updated dependencies [[`72d8ac5`](https://github.com/TanStack/query/commit/72d8ac5c592004b8f9c3ee086fcb9c3cd615ca05)]:\n  - @tanstack/query-core@5.90.12\n\n## 5.91.10\n\n### Patch Changes\n\n- Updated dependencies [[`c01b150`](https://github.com/TanStack/query/commit/c01b150e3673e11d6533768529a5e6fe3ebee68c)]:\n  - @tanstack/query-core@5.90.11\n\n## 5.91.9\n\n### Patch Changes\n\n- Updated dependencies [[`8e2e174`](https://github.com/TanStack/query/commit/8e2e174e9fd2e7b94cd232041e49c9d014d74e26), [`eb559a6`](https://github.com/TanStack/query/commit/eb559a66dc0d77dd46435f624fa64fc068bef9ae)]:\n  - @tanstack/query-core@5.90.10\n\n## 5.91.8\n\n### Patch Changes\n\n- Updated dependencies [[`08b211f`](https://github.com/TanStack/query/commit/08b211f8aa475e05d2f13a36517fc556861ef962)]:\n  - @tanstack/query-core@5.90.9\n\n## 5.91.7\n\n### Patch Changes\n\n- Updated dependencies [[`c0ec9fe`](https://github.com/TanStack/query/commit/c0ec9fe0d1426fe3f233adda3ebf23989ffaa110)]:\n  - @tanstack/query-core@5.90.8\n\n## 5.91.6\n\n### Patch Changes\n\n- Updated dependencies [[`b4cd121`](https://github.com/TanStack/query/commit/b4cd121a39d07cefaa3a3411136d342cc54ce8fb)]:\n  - @tanstack/query-core@5.90.7\n\n## 5.91.5\n\n### Patch Changes\n\n- Updated dependencies [[`1638c02`](https://github.com/TanStack/query/commit/1638c028df55648995d04431179904371a189772)]:\n  - @tanstack/query-core@5.90.6\n\n## 5.91.4\n\n### Patch Changes\n\n- Updated dependencies [[`e42ddfe`](https://github.com/TanStack/query/commit/e42ddfe919f34f847ca101aeef162c69845f9a1e)]:\n  - @tanstack/query-core@5.90.5\n\n## 5.91.3\n\n### Patch Changes\n\n- Updated dependencies [[`20ef922`](https://github.com/TanStack/query/commit/20ef922a0a7c3aee00150bf69123c338b0922922)]:\n  - @tanstack/query-core@5.90.4\n\n## 5.91.2\n\n### Patch Changes\n\n- Updated dependencies [[`4e1c433`](https://github.com/TanStack/query/commit/4e1c4338a72f7384600bbda99e44bc1891695df4)]:\n  - @tanstack/query-core@5.90.3\n\n## 5.91.1\n\n### Patch Changes\n\n- allow restoring null values ([#9747](https://github.com/TanStack/query/pull/9747))\n\n## 5.91.0\n\n### Minor Changes\n\n- Added a refetchOnRestore setting to control refetching after restoring persisted queries ([#9745](https://github.com/TanStack/query/pull/9745))\n"
  },
  {
    "path": "packages/query-persist-client-core/eslint.config.js",
    "content": "// @ts-check\n\nimport rootConfig from './root.eslint.config.js'\n\nexport default [...rootConfig]\n"
  },
  {
    "path": "packages/query-persist-client-core/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-persist-client-core\",\n  \"version\": \"5.92.4\",\n  \"description\": \"Set of utilities for interacting with persisters, which can save your queryClient for later use\",\n  \"author\": \"tannerlinsley\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/query-persist-client-core\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"scripts\": {\n    \"clean\": \"premove ./build ./coverage ./dist-ts\",\n    \"compile\": \"tsc --build\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:types\": \"npm-run-all --serial test:types:*\",\n    \"test:types:ts54\": \"node ../../node_modules/typescript54/lib/tsc.js --build\",\n    \"test:types:ts55\": \"node ../../node_modules/typescript55/lib/tsc.js --build\",\n    \"test:types:ts56\": \"node ../../node_modules/typescript56/lib/tsc.js --build\",\n    \"test:types:ts57\": \"node ../../node_modules/typescript57/lib/tsc.js --build\",\n    \"test:types:ts58\": \"node ../../node_modules/typescript58/lib/tsc.js --build\",\n    \"test:types:ts59\": \"node ../../node_modules/typescript59/lib/tsc.js --build\",\n    \"test:types:tscurrent\": \"tsc --build\",\n    \"test:types:ts60\": \"node ../../node_modules/typescript60/lib/tsc.js --build\",\n    \"test:lib\": \"vitest\",\n    \"test:lib:dev\": \"pnpm run test:lib --watch\",\n    \"test:build\": \"publint --strict && attw --pack\",\n    \"build\": \"tsup --tsconfig tsconfig.prod.json\"\n  },\n  \"type\": \"module\",\n  \"types\": \"build/legacy/index.d.ts\",\n  \"main\": \"build/legacy/index.cjs\",\n  \"module\": \"build/legacy/index.js\",\n  \"react-native\": \"src/index.ts\",\n  \"exports\": {\n    \".\": {\n      \"@tanstack/custom-condition\": \"./src/index.ts\",\n      \"import\": {\n        \"types\": \"./build/modern/index.d.ts\",\n        \"default\": \"./build/modern/index.js\"\n      },\n      \"require\": {\n        \"types\": \"./build/modern/index.d.cts\",\n        \"default\": \"./build/modern/index.cjs\"\n      }\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"sideEffects\": false,\n  \"files\": [\n    \"build\",\n    \"src\",\n    \"!src/__tests__\"\n  ],\n  \"dependencies\": {\n    \"@tanstack/query-core\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"@tanstack/query-test-utils\": \"workspace:*\",\n    \"npm-run-all2\": \"^5.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/query-persist-client-core/src/__tests__/createPersister.test.ts",
    "content": "import { afterAll, beforeAll, describe, expect, test, vi } from 'vitest'\nimport { Query, QueryClient, hashKey } from '@tanstack/query-core'\nimport {\n  PERSISTER_KEY_PREFIX,\n  experimental_createQueryPersister,\n} from '../createPersister'\nimport type { QueryFunctionContext, QueryKey } from '@tanstack/query-core'\nimport type { StoragePersisterOptions } from '../createPersister'\n\nfunction getFreshStorage() {\n  const storage = new Map()\n  return {\n    getItem: (key: string) => Promise.resolve(storage.get(key)),\n    setItem: (key: string, value: unknown) => {\n      storage.set(key, value)\n      return Promise.resolve()\n    },\n    removeItem: (key: string) => {\n      storage.delete(key)\n      return Promise.resolve()\n    },\n    entries: () => {\n      return Promise.resolve(Array.from(storage.entries()))\n    },\n  }\n}\n\nfunction setupPersister(\n  queryKey: QueryKey,\n  persisterOptions: StoragePersisterOptions,\n) {\n  const client = new QueryClient()\n  const context = {\n    meta: { foo: 'bar' },\n    client,\n    queryKey,\n    // @ts-expect-error\n    signal: undefined as AbortSignal,\n  } satisfies QueryFunctionContext\n  const queryHash = hashKey(queryKey)\n  const storageKey = `${PERSISTER_KEY_PREFIX}-${queryHash}`\n\n  const queryFn = vi.fn()\n\n  const persister = experimental_createQueryPersister(persisterOptions)\n\n  const query = new Query({\n    client,\n    queryHash,\n    queryKey,\n  })\n\n  return {\n    client,\n    context,\n    persister,\n    query,\n    queryFn,\n    queryHash,\n    queryKey,\n    storageKey,\n  }\n}\n\ndescribe('createPersister', () => {\n  beforeAll(() => {\n    vi.useFakeTimers()\n  })\n\n  afterAll(() => {\n    vi.useRealTimers()\n  })\n\n  test('should fetch if storage is not provided', async () => {\n    const { context, persister, query, queryFn } = setupPersister(['foo'], {\n      storage: undefined,\n    })\n\n    await persister.persisterFn(queryFn, context, query)\n\n    expect(queryFn).toHaveBeenCalledExactlyOnceWith(context)\n  })\n\n  test('should fetch if there is no stored data', async () => {\n    const storage = getFreshStorage()\n    const { context, persister, query, queryFn } = setupPersister(['foo'], {\n      storage,\n    })\n\n    await persister.persisterFn(queryFn, context, query)\n\n    expect(queryFn).toHaveBeenCalledExactlyOnceWith(context)\n  })\n\n  test('should fetch if query already has data', async () => {\n    const storage = getFreshStorage()\n    const { context, persister, query, queryFn } = setupPersister(['foo'], {\n      storage,\n    })\n    query.state.data = 'baz'\n\n    await persister.persisterFn(queryFn, context, query)\n\n    expect(queryFn).toHaveBeenCalledExactlyOnceWith(context)\n  })\n\n  test('should fetch if deserialization fails', async () => {\n    const storage = getFreshStorage()\n    const { context, persister, query, queryFn, storageKey } = setupPersister(\n      ['foo'],\n      {\n        storage,\n      },\n    )\n\n    await storage.setItem(storageKey, '{invalid[item')\n\n    await persister.persisterFn(queryFn, context, query)\n\n    expect(await storage.getItem(storageKey)).toBeUndefined()\n\n    expect(queryFn).toHaveBeenCalledExactlyOnceWith(context)\n  })\n\n  test('should remove stored item if `dataUpdatedAt` is empty', async () => {\n    const storage = getFreshStorage()\n    const { context, persister, query, queryFn, storageKey } = setupPersister(\n      ['foo'],\n      {\n        storage,\n      },\n    )\n\n    await storage.setItem(\n      storageKey,\n      JSON.stringify({\n        buster: '',\n        state: { dataUpdatedAt: undefined },\n      }),\n    )\n\n    await persister.persisterFn(queryFn, context, query)\n\n    expect(await storage.getItem(storageKey)).toBeUndefined()\n\n    expect(queryFn).toHaveBeenCalledExactlyOnceWith(context)\n  })\n\n  test('should remove stored item if its expired', async () => {\n    const storage = getFreshStorage()\n    const { context, persister, query, queryFn, storageKey } = setupPersister(\n      ['foo'],\n      {\n        storage,\n        maxAge: 100,\n      },\n    )\n\n    await storage.setItem(\n      storageKey,\n      JSON.stringify({\n        buster: '',\n        state: { dataUpdatedAt: Date.now() - 200 },\n      }),\n    )\n\n    await persister.persisterFn(queryFn, context, query)\n\n    expect(await storage.getItem(storageKey)).toBeUndefined()\n\n    expect(queryFn).toHaveBeenCalledExactlyOnceWith(context)\n  })\n\n  test('should remove stored item if its busted', async () => {\n    const storage = getFreshStorage()\n    const { context, persister, query, queryFn, storageKey } = setupPersister(\n      ['foo'],\n      {\n        storage,\n      },\n    )\n\n    await storage.setItem(\n      storageKey,\n      JSON.stringify({\n        buster: 'bust',\n        state: { dataUpdatedAt: Date.now() },\n      }),\n    )\n\n    await persister.persisterFn(queryFn, context, query)\n\n    expect(await storage.getItem(storageKey)).toBeUndefined()\n\n    expect(queryFn).toHaveBeenCalledExactlyOnceWith(context)\n  })\n\n  test('should restore item from the storage and set proper `updatedAt` values', async () => {\n    const storage = getFreshStorage()\n    const { context, persister, query, queryFn, storageKey } = setupPersister(\n      ['foo'],\n      {\n        storage,\n      },\n    )\n\n    const dataUpdatedAt = Date.now()\n\n    await storage.setItem(\n      storageKey,\n      JSON.stringify({\n        buster: '',\n        state: { dataUpdatedAt, data: '' },\n      }),\n    )\n\n    await persister.persisterFn(queryFn, context, query)\n    query.state.data = 'data0'\n    query.fetch = vi.fn()\n    expect(query.state.dataUpdatedAt).toEqual(0)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(queryFn).toHaveBeenCalledTimes(0)\n    expect(query.fetch).toHaveBeenCalledTimes(0)\n    expect(query.state.dataUpdatedAt).toEqual(dataUpdatedAt)\n  })\n\n  test('should restore item from the storage and refetch when `stale`', async () => {\n    const storage = getFreshStorage()\n    const { context, persister, query, queryFn, storageKey } = setupPersister(\n      ['foo'],\n      {\n        storage,\n      },\n    )\n\n    await storage.setItem(\n      storageKey,\n      JSON.stringify({\n        buster: '',\n        state: { dataUpdatedAt: Date.now(), data: '' },\n      }),\n    )\n\n    await persister.persisterFn(queryFn, context, query)\n    query.state.isInvalidated = true\n    query.fetch = vi.fn()\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(queryFn).toHaveBeenCalledTimes(0)\n    expect(query.fetch).toHaveBeenCalledTimes(1)\n  })\n\n  test('should restore item from the storage and refetch when `refetchOnRestore` is set to `always`', async () => {\n    const storage = getFreshStorage()\n    const { context, persister, query, queryFn, storageKey } = setupPersister(\n      ['foo'],\n      {\n        storage,\n        refetchOnRestore: 'always',\n      },\n    )\n\n    await storage.setItem(\n      storageKey,\n      JSON.stringify({\n        buster: '',\n        state: { dataUpdatedAt: Date.now() + 1000, data: '' },\n      }),\n    )\n\n    await persister.persisterFn(queryFn, context, query)\n    query.state.isInvalidated = true\n    query.fetch = vi.fn()\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(queryFn).toHaveBeenCalledTimes(0)\n    expect(query.fetch).toHaveBeenCalledTimes(1)\n  })\n\n  test('should restore item from the storage and NOT refetch when `refetchOnRestore` is set to false', async () => {\n    const storage = getFreshStorage()\n    const { context, persister, query, queryFn, storageKey } = setupPersister(\n      ['foo'],\n      {\n        storage,\n        refetchOnRestore: false,\n      },\n    )\n\n    await storage.setItem(\n      storageKey,\n      JSON.stringify({\n        buster: '',\n        state: { dataUpdatedAt: Date.now(), data: '' },\n      }),\n    )\n\n    await persister.persisterFn(queryFn, context, query)\n    query.state.isInvalidated = true\n    query.fetch = vi.fn()\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(queryFn).toHaveBeenCalledTimes(0)\n    expect(query.fetch).toHaveBeenCalledTimes(0)\n  })\n\n  test('should store item after successful fetch', async () => {\n    const storage = getFreshStorage()\n    const {\n      context,\n      persister,\n      query,\n      queryFn,\n      queryHash,\n      queryKey,\n      storageKey,\n    } = setupPersister(['foo'], {\n      storage,\n    })\n\n    await persister.persisterFn(queryFn, context, query)\n    query.setData('baz')\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(queryFn).toHaveBeenCalledExactlyOnceWith(context)\n\n    expect(JSON.parse(await storage.getItem(storageKey))).toMatchObject({\n      buster: '',\n      queryHash,\n      queryKey,\n      state: {\n        data: 'baz',\n      },\n    })\n  })\n\n  test('should skip stored item if not matched by filters', async () => {\n    const storage = getFreshStorage()\n    const { context, persister, query, queryFn, storageKey } = setupPersister(\n      ['foo'],\n      {\n        storage,\n        filters: {\n          predicate: () => {\n            return false\n          },\n        },\n      },\n    )\n\n    const dataUpdatedAt = Date.now()\n\n    await storage.setItem(\n      storageKey,\n      JSON.stringify({\n        buster: '',\n        state: { dataUpdatedAt },\n      }),\n    )\n\n    await persister.persisterFn(queryFn, context, query)\n    query.fetch = vi.fn()\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(queryFn).toHaveBeenCalledTimes(1)\n    expect(query.fetch).toHaveBeenCalledTimes(0)\n  })\n\n  test('should restore item from the storage with async deserializer', async () => {\n    const storage = getFreshStorage()\n    const { context, persister, query, queryFn, storageKey } = setupPersister(\n      ['foo'],\n      {\n        storage,\n        deserialize: (cachedString: string) =>\n          new Promise((resolve) => resolve(JSON.parse(cachedString))),\n      },\n    )\n\n    await storage.setItem(\n      storageKey,\n      JSON.stringify({\n        buster: '',\n        state: { dataUpdatedAt: Date.now(), data: '' },\n      }),\n    )\n\n    await persister.persisterFn(queryFn, context, query)\n    query.state.isInvalidated = true\n    query.fetch = vi.fn()\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(queryFn).toHaveBeenCalledTimes(0)\n    expect(query.fetch).toHaveBeenCalledTimes(1)\n  })\n\n  test('should store item after successful fetch with async serializer', async () => {\n    const storage = getFreshStorage()\n    const {\n      context,\n      persister,\n      query,\n      queryFn,\n      queryHash,\n      queryKey,\n      storageKey,\n    } = setupPersister(['foo'], {\n      storage,\n      serialize: (persistedQuery) =>\n        new Promise((resolve) => resolve(JSON.stringify(persistedQuery))),\n    })\n\n    await persister.persisterFn(queryFn, context, query)\n    query.setData('baz')\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(queryFn).toHaveBeenCalledExactlyOnceWith(context)\n\n    expect(JSON.parse(await storage.getItem(storageKey))).toMatchObject({\n      buster: '',\n      queryHash,\n      queryKey,\n      state: {\n        data: 'baz',\n      },\n    })\n  })\n\n  describe('persistQuery', () => {\n    test('Should properly persiste basic query', async () => {\n      const storage = getFreshStorage()\n      const { persister, query, queryHash, queryKey, storageKey } =\n        setupPersister(['foo'], {\n          storage,\n        })\n\n      query.setData('baz')\n      await persister.persistQuery(query)\n\n      expect(JSON.parse(await storage.getItem(storageKey))).toMatchObject({\n        buster: '',\n        queryHash,\n        queryKey,\n        state: {\n          dataUpdateCount: 1,\n          data: 'baz',\n          status: 'success',\n        },\n      })\n    })\n\n    test('Should skip persistance if storage is not provided', async () => {\n      const serializeMock = vi.fn()\n      const { persister, query } = setupPersister(['foo'], {\n        storage: null,\n        serialize: serializeMock,\n      })\n\n      query.setData('baz')\n      await persister.persistQuery(query)\n\n      expect(serializeMock).toHaveBeenCalledTimes(0)\n    })\n  })\n\n  describe('persistQueryByKey', () => {\n    test('Should skip persistance if storage is not provided', async () => {\n      const serializeMock = vi.fn()\n      const { persister, client, queryKey } = setupPersister(['foo'], {\n        storage: null,\n        serialize: serializeMock,\n      })\n\n      client.setQueryData(queryKey, 'baz')\n      await persister.persistQueryByKey(queryKey, client)\n\n      expect(serializeMock).toHaveBeenCalledTimes(0)\n    })\n\n    test('should skip persistance if query was not found', async () => {\n      const serializeMock = vi.fn()\n      const storage = getFreshStorage()\n      const { client, persister, queryKey } = setupPersister(['foo'], {\n        storage,\n        serialize: serializeMock,\n      })\n\n      client.setQueryData(queryKey, 'baz')\n      await persister.persistQueryByKey(['foo2'], client)\n\n      expect(serializeMock).toHaveBeenCalledTimes(0)\n    })\n\n    test('Should properly persiste basic query', async () => {\n      const storage = getFreshStorage()\n      const { persister, client, queryHash, queryKey, storageKey } =\n        setupPersister(['foo'], {\n          storage,\n        })\n\n      client.setQueryData(queryKey, 'baz')\n      await persister.persistQueryByKey(queryKey, client)\n\n      expect(JSON.parse(await storage.getItem(storageKey))).toMatchObject({\n        buster: '',\n        queryHash,\n        queryKey,\n        state: {\n          dataUpdateCount: 1,\n          data: 'baz',\n          status: 'success',\n        },\n      })\n    })\n  })\n\n  describe('persisterGc', () => {\n    test('should properly clean storage from busted entries', async () => {\n      const storage = getFreshStorage()\n      const { persister, client, query, queryKey } = setupPersister(['foo'], {\n        storage,\n      })\n      query.setState({\n        dataUpdatedAt: 1,\n        data: 'f',\n      })\n      client.getQueryCache().add(query)\n\n      await persister.persistQueryByKey(queryKey, client)\n\n      expect(await storage.entries()).toHaveLength(1)\n\n      await persister.persisterGc()\n      expect(await storage.entries()).toHaveLength(0)\n    })\n  })\n\n  describe('restoreQueries', () => {\n    test('should properly clean storage from busted entries', async () => {\n      const storage = getFreshStorage()\n      const { persister, client, query, queryKey } = setupPersister(['foo'], {\n        storage,\n      })\n      query.setState({\n        dataUpdatedAt: 1,\n        data: 'f',\n      })\n      client.getQueryCache().add(query)\n\n      await persister.persistQueryByKey(queryKey, client)\n\n      expect(await storage.entries()).toHaveLength(1)\n\n      await persister.restoreQueries(client)\n      expect(await storage.entries()).toHaveLength(0)\n    })\n\n    test('should properly restore queries from cache without filters', async () => {\n      const storage = getFreshStorage()\n      const { persister, client, queryKey } = setupPersister(['foo'], {\n        storage,\n      })\n      client.setQueryData(queryKey, 'foo')\n\n      await persister.persistQueryByKey(queryKey, client)\n\n      expect(await storage.entries()).toHaveLength(1)\n      client.clear()\n      expect(client.getQueryCache().getAll()).toHaveLength(0)\n\n      await persister.restoreQueries(client)\n      expect(client.getQueryCache().getAll()).toHaveLength(1)\n\n      expect(client.getQueryData(queryKey)).toEqual('foo')\n    })\n\n    test('should properly restore queries from cache', async () => {\n      const storage = getFreshStorage()\n      const { persister, client, queryKey } = setupPersister(['foo', 'bar'], {\n        storage,\n      })\n      client.setQueryData(queryKey, 'foo')\n\n      await persister.persistQueryByKey(queryKey, client)\n\n      expect(await storage.entries()).toHaveLength(1)\n      client.clear()\n      expect(client.getQueryCache().getAll()).toHaveLength(0)\n\n      await persister.restoreQueries(client, { queryKey })\n      expect(client.getQueryCache().getAll()).toHaveLength(1)\n\n      expect(client.getQueryData(queryKey)).toEqual('foo')\n    })\n\n    test('should not restore queries from cache if there is no match', async () => {\n      const storage = getFreshStorage()\n      const { persister, client, queryKey } = setupPersister(['foo', 'bar'], {\n        storage,\n      })\n      client.setQueryData(queryKey, 'foo')\n\n      await persister.persistQueryByKey(queryKey, client)\n\n      expect(await storage.entries()).toHaveLength(1)\n      client.clear()\n      expect(client.getQueryCache().getAll()).toHaveLength(0)\n\n      await persister.restoreQueries(client, { queryKey: ['bar'] })\n      expect(client.getQueryCache().getAll()).toHaveLength(0)\n    })\n\n    test('should properly restore queries from cache with partial match', async () => {\n      const storage = getFreshStorage()\n      const { persister, client, queryKey } = setupPersister(['foo', 'bar'], {\n        storage,\n      })\n      client.setQueryData(queryKey, 'foo')\n\n      await persister.persistQueryByKey(queryKey, client)\n\n      expect(await storage.entries()).toHaveLength(1)\n      client.clear()\n      expect(client.getQueryCache().getAll()).toHaveLength(0)\n\n      await persister.restoreQueries(client, { queryKey: ['foo'] })\n      expect(client.getQueryCache().getAll()).toHaveLength(1)\n\n      expect(client.getQueryData(queryKey)).toEqual('foo')\n    })\n\n    test('should not restore queries from cache with exact match if there is no match', async () => {\n      const storage = getFreshStorage()\n      const { persister, client, queryKey } = setupPersister(['foo', 'bar'], {\n        storage,\n      })\n      client.setQueryData(queryKey, 'foo')\n\n      await persister.persistQueryByKey(queryKey, client)\n\n      expect(await storage.entries()).toHaveLength(1)\n      client.clear()\n      expect(client.getQueryCache().getAll()).toHaveLength(0)\n\n      await persister.restoreQueries(client, { queryKey: ['foo'], exact: true })\n      expect(client.getQueryCache().getAll()).toHaveLength(0)\n    })\n\n    test('should restore queries from cache with exact match', async () => {\n      const storage = getFreshStorage()\n      const { persister, client, queryKey } = setupPersister(['foo', 'bar'], {\n        storage,\n      })\n      client.setQueryData(queryKey, 'foo')\n\n      await persister.persistQueryByKey(queryKey, client)\n\n      expect(await storage.entries()).toHaveLength(1)\n      client.clear()\n      expect(client.getQueryCache().getAll()).toHaveLength(0)\n\n      await persister.restoreQueries(client, {\n        queryKey: queryKey,\n        exact: true,\n      })\n      expect(client.getQueryCache().getAll()).toHaveLength(1)\n    })\n  })\n\n  describe('removeQueries', () => {\n    test('should remove restore queries from storage without filters', async () => {\n      const storage = getFreshStorage()\n      const { persister, client, queryKey } = setupPersister(['foo'], {\n        storage,\n      })\n      client.setQueryData(queryKey, 'foo')\n\n      await persister.persistQueryByKey(queryKey, client)\n\n      expect(await storage.entries()).toHaveLength(1)\n      await persister.removeQueries()\n      expect(await storage.entries()).toHaveLength(0)\n    })\n\n    test('should remove queries from storage', async () => {\n      const storage = getFreshStorage()\n      const { persister, client, queryKey } = setupPersister(['foo', 'bar'], {\n        storage,\n      })\n      client.setQueryData(queryKey, 'foo')\n\n      await persister.persistQueryByKey(queryKey, client)\n\n      expect(await storage.entries()).toHaveLength(1)\n      await persister.removeQueries({ queryKey })\n      expect(await storage.entries()).toHaveLength(0)\n    })\n\n    test('should not remove queries from storage if there is no match', async () => {\n      const storage = getFreshStorage()\n      const { persister, client, queryKey } = setupPersister(['foo', 'bar'], {\n        storage,\n      })\n      client.setQueryData(queryKey, 'foo')\n\n      await persister.persistQueryByKey(queryKey, client)\n\n      expect(await storage.entries()).toHaveLength(1)\n      await persister.removeQueries({ queryKey: ['bar'] })\n      expect(await storage.entries()).toHaveLength(1)\n    })\n\n    test('should properly remove queries from storage with partial match', async () => {\n      const storage = getFreshStorage()\n      const { persister, client, queryKey } = setupPersister(['foo', 'bar'], {\n        storage,\n      })\n      client.setQueryData(queryKey, 'foo')\n\n      await persister.persistQueryByKey(queryKey, client)\n\n      expect(await storage.entries()).toHaveLength(1)\n      await persister.removeQueries({ queryKey: ['foo'] })\n      expect(await storage.entries()).toHaveLength(0)\n    })\n\n    test('should not remove queries from storage with exact match if there is no match', async () => {\n      const storage = getFreshStorage()\n      const { persister, client, queryKey } = setupPersister(['foo', 'bar'], {\n        storage,\n      })\n      client.setQueryData(queryKey, 'foo')\n\n      await persister.persistQueryByKey(queryKey, client)\n\n      expect(await storage.entries()).toHaveLength(1)\n      await persister.removeQueries({ queryKey: ['foo'], exact: true })\n      expect(await storage.entries()).toHaveLength(1)\n    })\n\n    test('should remove queries from storage with exact match', async () => {\n      const storage = getFreshStorage()\n      const { persister, client, queryKey } = setupPersister(['foo', 'bar'], {\n        storage,\n      })\n      client.setQueryData(queryKey, 'foo')\n\n      await persister.persistQueryByKey(queryKey, client)\n\n      expect(await storage.entries()).toHaveLength(1)\n      await persister.removeQueries({\n        queryKey: queryKey,\n        exact: true,\n      })\n      expect(await storage.entries()).toHaveLength(0)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/query-persist-client-core/src/__tests__/persist.test.ts",
    "content": "import { describe, expect, test, vi } from 'vitest'\nimport { QueriesObserver, QueryClient } from '@tanstack/query-core'\nimport {\n  persistQueryClientRestore,\n  persistQueryClientSubscribe,\n} from '../persist'\nimport { createMockPersister, createSpyPersister } from './utils'\n\ndescribe('persistQueryClientSubscribe', () => {\n  test('should persist mutations', async () => {\n    const queryClient = new QueryClient()\n\n    const persister = createMockPersister()\n\n    const unsubscribe = persistQueryClientSubscribe({\n      queryClient,\n      persister,\n      dehydrateOptions: { shouldDehydrateMutation: () => true },\n    })\n\n    queryClient.getMutationCache().build(queryClient, {\n      mutationFn: (text: string) => Promise.resolve(text),\n    })\n\n    const result = await persister.restoreClient()\n\n    expect(result?.clientState.mutations).toHaveLength(1)\n\n    unsubscribe()\n  })\n})\n\ndescribe('persistQueryClientSave', () => {\n  test('should not be triggered on observer type events', () => {\n    const queryClient = new QueryClient()\n\n    const persister = createSpyPersister()\n\n    const unsubscribe = persistQueryClientSubscribe({\n      queryClient,\n      persister,\n    })\n\n    const queryKey = ['test']\n    const queryFn = vi.fn().mockReturnValue(1)\n    const observer = new QueriesObserver(queryClient, [{ queryKey, queryFn }])\n    const unsubscribeObserver = observer.subscribe(vi.fn())\n    observer\n      .getObservers()[0]\n      ?.setOptions({ queryKey, refetchOnWindowFocus: false })\n    unsubscribeObserver()\n\n    queryClient.setQueryData(queryKey, 2)\n\n    // persistClient should be called 3 times:\n    // 1. When query is added\n    // 2. When queryFn is resolved\n    // 3. When setQueryData is called\n    // All events fired by manipulating observers are ignored\n    expect(persister.persistClient).toHaveBeenCalledTimes(3)\n\n    unsubscribe()\n  })\n})\n\ndescribe('persistQueryClientRestore', () => {\n  test('should rethrow exceptions in `restoreClient`', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n\n    const consoleWarn = vi\n      .spyOn(console, 'warn')\n      .mockImplementation(() => undefined)\n\n    const queryClient = new QueryClient()\n\n    const restoreError = new Error('Error restoring client')\n\n    const persister = createSpyPersister()\n\n    persister.restoreClient = () => Promise.reject(restoreError)\n\n    await expect(\n      persistQueryClientRestore({\n        queryClient,\n        persister,\n      }),\n    ).rejects.toBe(restoreError)\n\n    expect(consoleMock).toHaveBeenCalledTimes(1)\n    expect(consoleWarn).toHaveBeenCalledTimes(1)\n    expect(consoleMock).toHaveBeenNthCalledWith(1, restoreError)\n\n    consoleMock.mockRestore()\n    consoleWarn.mockRestore()\n  })\n\n  test('should rethrow exceptions in `removeClient` before `restoreClient`', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n\n    const consoleWarn = vi\n      .spyOn(console, 'warn')\n      .mockImplementation(() => undefined)\n\n    const queryClient = new QueryClient()\n\n    const restoreError = new Error('Error restoring client')\n    const removeError = new Error('Error removing client')\n\n    const persister = createSpyPersister()\n\n    persister.restoreClient = () => Promise.reject(restoreError)\n    persister.removeClient = () => Promise.reject(removeError)\n\n    await expect(\n      persistQueryClientRestore({\n        queryClient,\n        persister,\n      }),\n    ).rejects.toBe(removeError)\n\n    expect(consoleMock).toHaveBeenCalledTimes(1)\n    expect(consoleWarn).toHaveBeenCalledTimes(1)\n    expect(consoleMock).toHaveBeenNthCalledWith(1, restoreError)\n\n    consoleMock.mockRestore()\n    consoleWarn.mockRestore()\n  })\n\n  test('should rethrow error in `removeClient`', async () => {\n    const queryClient = new QueryClient()\n\n    const persister = createSpyPersister()\n    const removeError = new Error('Error removing client')\n\n    persister.removeClient = () => Promise.reject(removeError)\n    persister.restoreClient = () => {\n      return Promise.resolve({\n        buster: 'random-buster',\n        clientState: {\n          mutations: [],\n          queries: [],\n        },\n        timestamp: new Date().getTime(),\n      })\n    }\n\n    await expect(\n      persistQueryClientRestore({\n        queryClient,\n        persister,\n      }),\n    ).rejects.toBe(removeError)\n  })\n})\n"
  },
  {
    "path": "packages/query-persist-client-core/src/__tests__/utils.ts",
    "content": "import { vi } from 'vitest'\nimport { sleep } from '@tanstack/query-test-utils'\nimport type { PersistedClient, Persister } from '../persist'\n\nexport function createMockPersister(): Persister {\n  let storedState: PersistedClient | undefined\n\n  return {\n    persistClient(persistClient: PersistedClient) {\n      storedState = persistClient\n    },\n    async restoreClient() {\n      await sleep(10)\n      return storedState\n    },\n    removeClient() {\n      storedState = undefined\n    },\n  }\n}\n\nexport function createSpyPersister(): Persister {\n  return {\n    persistClient: vi.fn(),\n    restoreClient: vi.fn(),\n    removeClient: vi.fn(),\n  }\n}\n"
  },
  {
    "path": "packages/query-persist-client-core/src/createPersister.ts",
    "content": "import {\n  hashKey,\n  matchQuery,\n  notifyManager,\n  partialMatchKey,\n} from '@tanstack/query-core'\nimport type {\n  Query,\n  QueryClient,\n  QueryFilters,\n  QueryFunctionContext,\n  QueryKey,\n  QueryState,\n} from '@tanstack/query-core'\n\nexport interface PersistedQuery {\n  buster: string\n  queryHash: string\n  queryKey: QueryKey\n  state: QueryState\n}\n\nexport type MaybePromise<T> = T | Promise<T>\n\nexport interface AsyncStorage<TStorageValue = string> {\n  getItem: (key: string) => MaybePromise<TStorageValue | undefined | null>\n  setItem: (key: string, value: TStorageValue) => MaybePromise<unknown>\n  removeItem: (key: string) => MaybePromise<void>\n  entries?: () => MaybePromise<Array<[key: string, value: TStorageValue]>>\n}\n\nexport interface StoragePersisterOptions<TStorageValue = string> {\n  /** The storage client used for setting and retrieving items from cache.\n   * For SSR pass in `undefined`.\n   */\n  storage: AsyncStorage<TStorageValue> | undefined | null\n  /**\n   * How to serialize the data to storage.\n   * @default `JSON.stringify`\n   */\n  serialize?: (persistedQuery: PersistedQuery) => MaybePromise<TStorageValue>\n  /**\n   * How to deserialize the data from storage.\n   * @default `JSON.parse`\n   */\n  deserialize?: (cachedString: TStorageValue) => MaybePromise<PersistedQuery>\n  /**\n   * A unique string that can be used to forcefully invalidate existing caches,\n   * if they do not share the same buster string\n   */\n  buster?: string\n  /**\n   * The max-allowed age of the cache in milliseconds.\n   * If a persisted cache is found that is older than this\n   * time, it will be discarded\n   * @default 24 hours\n   */\n  maxAge?: number\n  /**\n   * Prefix to be used for storage key.\n   * Storage key is a combination of prefix and query hash in a form of `prefix-queryHash`.\n   * @default 'tanstack-query'\n   */\n  prefix?: string\n  /**\n   * If set to `true`, the query will refetch on successful query restoration if the data is stale.\n   * If set to `false`, the query will not refetch on successful query restoration.\n   * If set to `'always'`, the query will always refetch on successful query restoration.\n   * Defaults to `true`.\n   */\n  refetchOnRestore?: boolean | 'always'\n  /**\n   * Filters to narrow down which Queries should be persisted.\n   */\n  filters?: QueryFilters\n}\n\nexport const PERSISTER_KEY_PREFIX = 'tanstack-query'\n\n/**\n * Warning: experimental feature.\n * This utility function enables fine-grained query persistence.\n * Simple add it as a `persister` parameter to `useQuery` or `defaultOptions` on `queryClient`.\n *\n * ```\n * useQuery({\n     queryKey: ['myKey'],\n     queryFn: fetcher,\n     persister: createPersister({\n       storage: localStorage,\n     }),\n   })\n   ```\n */\nexport function experimental_createQueryPersister<TStorageValue = string>({\n  storage,\n  buster = '',\n  maxAge = 1000 * 60 * 60 * 24,\n  serialize = JSON.stringify as Required<\n    StoragePersisterOptions<TStorageValue>\n  >['serialize'],\n  deserialize = JSON.parse as Required<\n    StoragePersisterOptions<TStorageValue>\n  >['deserialize'],\n  prefix = PERSISTER_KEY_PREFIX,\n  refetchOnRestore = true,\n  filters,\n}: StoragePersisterOptions<TStorageValue>) {\n  function isExpiredOrBusted(persistedQuery: PersistedQuery) {\n    if (persistedQuery.state.dataUpdatedAt) {\n      const queryAge = Date.now() - persistedQuery.state.dataUpdatedAt\n      const expired = queryAge > maxAge\n      const busted = persistedQuery.buster !== buster\n\n      if (expired || busted) {\n        return true\n      }\n\n      return false\n    }\n\n    return true\n  }\n\n  async function retrieveQuery<T>(\n    queryHash: string,\n    afterRestoreMacroTask?: (persistedQuery: PersistedQuery) => void,\n  ) {\n    if (storage != null) {\n      const storageKey = `${prefix}-${queryHash}`\n      try {\n        const storedData = await storage.getItem(storageKey)\n        if (storedData) {\n          let persistedQuery: PersistedQuery\n          try {\n            persistedQuery = await deserialize(storedData)\n          } catch {\n            await storage.removeItem(storageKey)\n            return\n          }\n\n          if (isExpiredOrBusted(persistedQuery)) {\n            await storage.removeItem(storageKey)\n          } else {\n            if (afterRestoreMacroTask) {\n              // Just after restoring we want to get fresh data from the server if it's stale\n              notifyManager.schedule(() =>\n                afterRestoreMacroTask(persistedQuery),\n              )\n            }\n            // We must resolve the promise here, as otherwise we will have `loading` state in the app until `queryFn` resolves\n            return persistedQuery.state.data as T\n          }\n        }\n      } catch (err) {\n        if (process.env.NODE_ENV === 'development') {\n          console.error(err)\n          console.warn(\n            'Encountered an error attempting to restore query cache from persisted location.',\n          )\n        }\n        await storage.removeItem(storageKey)\n      }\n    }\n\n    return\n  }\n\n  async function persistQueryByKey(\n    queryKey: QueryKey,\n    queryClient: QueryClient,\n  ) {\n    if (storage != null) {\n      const query = queryClient.getQueryCache().find({ queryKey })\n      if (query) {\n        await persistQuery(query)\n      } else {\n        if (process.env.NODE_ENV === 'development') {\n          console.warn(\n            'Could not find query to be persisted. QueryKey:',\n            JSON.stringify(queryKey),\n          )\n        }\n      }\n    }\n  }\n\n  async function persistQuery(query: Query) {\n    if (storage != null) {\n      const storageKey = `${prefix}-${query.queryHash}`\n      storage.setItem(\n        storageKey,\n        await serialize({\n          state: query.state,\n          queryKey: query.queryKey,\n          queryHash: query.queryHash,\n          buster: buster,\n        }),\n      )\n    }\n  }\n\n  async function persisterFn<T, TQueryKey extends QueryKey>(\n    queryFn: (context: QueryFunctionContext<TQueryKey>) => T | Promise<T>,\n    ctx: QueryFunctionContext<TQueryKey>,\n    query: Query,\n  ) {\n    const matchesFilter = filters ? matchQuery(filters, query) : true\n\n    // Try to restore only if we do not have any data in the cache and we have persister defined\n    if (matchesFilter && query.state.data === undefined && storage != null) {\n      const restoredData = await retrieveQuery(\n        query.queryHash,\n        (persistedQuery: PersistedQuery) => {\n          // Set proper updatedAt, since resolving in the first pass overrides those values\n          query.setState({\n            dataUpdatedAt: persistedQuery.state.dataUpdatedAt,\n            errorUpdatedAt: persistedQuery.state.errorUpdatedAt,\n          })\n\n          if (\n            refetchOnRestore === 'always' ||\n            (refetchOnRestore === true && query.isStale())\n          ) {\n            query.fetch()\n          }\n        },\n      )\n\n      if (restoredData !== undefined) {\n        return Promise.resolve(restoredData as T)\n      }\n    }\n\n    // If we did not restore, or restoration failed - fetch\n    const queryFnResult = await queryFn(ctx)\n\n    if (matchesFilter && storage != null) {\n      // Persist if we have storage defined, we use timeout to get proper state to be persisted\n      notifyManager.schedule(() => {\n        persistQuery(query)\n      })\n    }\n\n    return Promise.resolve(queryFnResult)\n  }\n\n  async function persisterGc() {\n    if (storage?.entries) {\n      const storageKeyPrefix = `${prefix}-`\n      const entries = await storage.entries()\n      for (const [key, value] of entries) {\n        if (key.startsWith(storageKeyPrefix)) {\n          let persistedQuery: PersistedQuery\n          try {\n            persistedQuery = await deserialize(value)\n          } catch {\n            await storage.removeItem(key)\n            continue\n          }\n          if (isExpiredOrBusted(persistedQuery)) {\n            await storage.removeItem(key)\n          }\n        }\n      }\n    } else if (process.env.NODE_ENV === 'development') {\n      throw new Error(\n        'Provided storage does not implement `entries` method. Garbage collection is not possible without ability to iterate over storage items.',\n      )\n    }\n  }\n\n  async function restoreQueries(\n    queryClient: QueryClient,\n    filters: Pick<QueryFilters, 'queryKey' | 'exact'> = {},\n  ): Promise<void> {\n    const { exact, queryKey } = filters\n\n    if (storage?.entries) {\n      const storageKeyPrefix = `${prefix}-`\n      const entries = await storage.entries()\n      for (const [key, value] of entries) {\n        if (key.startsWith(storageKeyPrefix)) {\n          let persistedQuery: PersistedQuery\n          try {\n            persistedQuery = await deserialize(value)\n          } catch {\n            await storage.removeItem(key)\n            continue\n          }\n          if (isExpiredOrBusted(persistedQuery)) {\n            await storage.removeItem(key)\n            continue\n          }\n\n          if (queryKey) {\n            if (exact) {\n              if (persistedQuery.queryHash !== hashKey(queryKey)) {\n                continue\n              }\n            } else if (!partialMatchKey(persistedQuery.queryKey, queryKey)) {\n              continue\n            }\n          }\n\n          queryClient.setQueryData(\n            persistedQuery.queryKey,\n            persistedQuery.state.data,\n            {\n              updatedAt: persistedQuery.state.dataUpdatedAt,\n            },\n          )\n        }\n      }\n    } else if (process.env.NODE_ENV === 'development') {\n      throw new Error(\n        'Provided storage does not implement `entries` method. Restoration of all stored entries is not possible without ability to iterate over storage items.',\n      )\n    }\n  }\n\n  async function removeQueries(\n    filters: Pick<QueryFilters, 'queryKey' | 'exact'> = {},\n  ): Promise<void> {\n    const { exact, queryKey } = filters\n\n    if (storage?.entries) {\n      const entries = await storage.entries()\n      const storageKeyPrefix = `${prefix}-`\n      for (const [key, value] of entries) {\n        if (key.startsWith(storageKeyPrefix)) {\n          if (!queryKey) {\n            await storage.removeItem(key)\n            continue\n          }\n\n          let persistedQuery: PersistedQuery\n          try {\n            persistedQuery = await deserialize(value)\n          } catch {\n            await storage.removeItem(key)\n            continue\n          }\n\n          if (exact) {\n            if (persistedQuery.queryHash !== hashKey(queryKey)) {\n              continue\n            }\n          } else if (!partialMatchKey(persistedQuery.queryKey, queryKey)) {\n            continue\n          }\n\n          await storage.removeItem(key)\n        }\n      }\n    } else if (process.env.NODE_ENV === 'development') {\n      throw new Error(\n        'Provided storage does not implement `entries` method. Removal of stored entries is not possible without ability to iterate over storage items.',\n      )\n    }\n  }\n\n  return {\n    persisterFn,\n    persistQuery,\n    persistQueryByKey,\n    retrieveQuery,\n    persisterGc,\n    restoreQueries,\n    removeQueries,\n  }\n}\n"
  },
  {
    "path": "packages/query-persist-client-core/src/index.ts",
    "content": "/* istanbul ignore file */\n\nexport * from './persist'\nexport * from './retryStrategies'\nexport * from './createPersister'\n"
  },
  {
    "path": "packages/query-persist-client-core/src/persist.ts",
    "content": "import { dehydrate, hydrate } from '@tanstack/query-core'\nimport type {\n  DehydrateOptions,\n  DehydratedState,\n  HydrateOptions,\n  NotifyEventType,\n  QueryClient,\n} from '@tanstack/query-core'\n\nexport type Promisable<T> = T | PromiseLike<T>\n\nexport interface Persister {\n  persistClient: (persistClient: PersistedClient) => Promisable<void>\n  restoreClient: () => Promisable<PersistedClient | undefined>\n  removeClient: () => Promisable<void>\n}\n\nexport interface PersistedClient {\n  timestamp: number\n  buster: string\n  clientState: DehydratedState\n}\n\nexport interface PersistQueryClientRootOptions {\n  /** The QueryClient to persist */\n  queryClient: QueryClient\n  /** The Persister interface for storing and restoring the cache\n   * to/from a persisted location */\n  persister: Persister\n  /** A unique string that can be used to forcefully\n   * invalidate existing caches if they do not share the same buster string */\n  buster?: string\n}\n\nexport interface PersistedQueryClientRestoreOptions extends PersistQueryClientRootOptions {\n  /** The max-allowed age of the cache in milliseconds.\n   * If a persisted cache is found that is older than this\n   * time, it will be discarded */\n  maxAge?: number\n  /** The options passed to the hydrate function */\n  hydrateOptions?: HydrateOptions\n}\n\nexport interface PersistedQueryClientSaveOptions extends PersistQueryClientRootOptions {\n  /** The options passed to the dehydrate function */\n  dehydrateOptions?: DehydrateOptions\n}\n\nexport interface PersistQueryClientOptions\n  extends\n    PersistedQueryClientRestoreOptions,\n    PersistedQueryClientSaveOptions,\n    PersistQueryClientRootOptions {}\n\n/**\n * Checks if emitted event is about cache change and not about observers.\n * Useful for persist, where we only want to trigger save when cache is changed.\n */\nconst cacheEventTypes: Array<NotifyEventType> = ['added', 'removed', 'updated']\n\nfunction isCacheEventType(eventType: NotifyEventType) {\n  return cacheEventTypes.includes(eventType)\n}\n\n/**\n * Restores persisted data to the QueryCache\n *  - data obtained from persister.restoreClient\n *  - data is hydrated using hydrateOptions\n * If data is expired, busted, empty, or throws, it runs persister.removeClient\n */\nexport async function persistQueryClientRestore({\n  queryClient,\n  persister,\n  maxAge = 1000 * 60 * 60 * 24,\n  buster = '',\n  hydrateOptions,\n}: PersistedQueryClientRestoreOptions) {\n  try {\n    const persistedClient = await persister.restoreClient()\n\n    if (persistedClient) {\n      if (persistedClient.timestamp) {\n        const expired = Date.now() - persistedClient.timestamp > maxAge\n        const busted = persistedClient.buster !== buster\n        if (expired || busted) {\n          return persister.removeClient()\n        } else {\n          hydrate(queryClient, persistedClient.clientState, hydrateOptions)\n        }\n      } else {\n        return persister.removeClient()\n      }\n    }\n  } catch (err) {\n    if (process.env.NODE_ENV !== 'production') {\n      console.error(err)\n      console.warn(\n        'Encountered an error attempting to restore client cache from persisted location. As a precaution, the persisted cache will be discarded.',\n      )\n    }\n\n    await persister.removeClient()\n\n    throw err\n  }\n}\n\n/**\n * Persists data from the QueryCache\n *  - data dehydrated using dehydrateOptions\n *  - data is persisted using persister.persistClient\n */\nexport async function persistQueryClientSave({\n  queryClient,\n  persister,\n  buster = '',\n  dehydrateOptions,\n}: PersistedQueryClientSaveOptions) {\n  const persistClient: PersistedClient = {\n    buster,\n    timestamp: Date.now(),\n    clientState: dehydrate(queryClient, dehydrateOptions),\n  }\n\n  await persister.persistClient(persistClient)\n}\n\n/**\n * Subscribe to QueryCache and MutationCache updates (for persisting)\n * @returns an unsubscribe function (to discontinue monitoring)\n */\nexport function persistQueryClientSubscribe(\n  props: PersistedQueryClientSaveOptions,\n) {\n  const unsubscribeQueryCache = props.queryClient\n    .getQueryCache()\n    .subscribe((event) => {\n      if (isCacheEventType(event.type)) {\n        persistQueryClientSave(props)\n      }\n    })\n\n  const unsubscribeMutationCache = props.queryClient\n    .getMutationCache()\n    .subscribe((event) => {\n      if (isCacheEventType(event.type)) {\n        persistQueryClientSave(props)\n      }\n    })\n\n  return () => {\n    unsubscribeQueryCache()\n    unsubscribeMutationCache()\n  }\n}\n\n/**\n * Restores persisted data to QueryCache and persists further changes.\n */\nexport function persistQueryClient(\n  props: PersistQueryClientOptions,\n): [() => void, Promise<void>] {\n  let hasUnsubscribed = false\n  let persistQueryClientUnsubscribe: (() => void) | undefined\n  const unsubscribe = () => {\n    hasUnsubscribed = true\n    persistQueryClientUnsubscribe?.()\n  }\n\n  // Attempt restore\n  const restorePromise = persistQueryClientRestore(props).then(() => {\n    if (!hasUnsubscribed) {\n      // Subscribe to changes in the query cache to trigger the save\n      persistQueryClientUnsubscribe = persistQueryClientSubscribe(props)\n    }\n  })\n\n  return [unsubscribe, restorePromise]\n}\n"
  },
  {
    "path": "packages/query-persist-client-core/src/retryStrategies.ts",
    "content": "import type { PersistedClient } from './persist'\n\nexport type PersistRetryer = (props: {\n  persistedClient: PersistedClient\n  error: Error\n  errorCount: number\n}) => PersistedClient | undefined\n\nexport const removeOldestQuery: PersistRetryer = ({ persistedClient }) => {\n  const mutations = [...persistedClient.clientState.mutations]\n  const queries = [...persistedClient.clientState.queries]\n  const client: PersistedClient = {\n    ...persistedClient,\n    clientState: { mutations, queries },\n  }\n\n  // sort queries by dataUpdatedAt (oldest first)\n  const sortedQueries = [...queries].sort(\n    (a, b) => a.state.dataUpdatedAt - b.state.dataUpdatedAt,\n  )\n\n  // clean oldest query\n  if (sortedQueries.length > 0) {\n    const oldestData = sortedQueries.shift()\n    client.clientState.queries = queries.filter((q) => q !== oldestData)\n    return client\n  }\n\n  return undefined\n}\n"
  },
  {
    "path": "packages/query-persist-client-core/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\"\n  },\n  \"include\": [\"src\", \"*.config.*\", \"package.json\"],\n  \"references\": [{ \"path\": \"../query-core\" }]\n}\n"
  },
  {
    "path": "packages/query-persist-client-core/tsconfig.prod.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"incremental\": false,\n    \"composite\": false,\n    \"rootDir\": \"../../\"\n  }\n}\n"
  },
  {
    "path": "packages/query-persist-client-core/tsup.config.ts",
    "content": "import { defineConfig } from 'tsup'\nimport { legacyConfig, modernConfig } from './root.tsup.config.js'\n\nexport default defineConfig([\n  modernConfig({ entry: ['src/*.ts'] }),\n  legacyConfig({ entry: ['src/*.ts'] }),\n])\n"
  },
  {
    "path": "packages/query-persist-client-core/vite.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nimport packageJson from './package.json'\n\nexport default defineConfig({\n  // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660\n  resolve: {\n    conditions: ['@tanstack/custom-condition'],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        conditions: ['@tanstack/custom-condition'],\n      },\n    },\n  },\n  test: {\n    name: packageJson.name,\n    dir: './src',\n    watch: false,\n    coverage: {\n      enabled: true,\n      provider: 'istanbul',\n      include: ['src/**/*'],\n      exclude: ['src/__tests__/**'],\n    },\n    typecheck: { enabled: true },\n    restoreMocks: true,\n  },\n})\n"
  },
  {
    "path": "packages/query-sync-storage-persister/CHANGELOG.md",
    "content": "# @tanstack/query-sync-storage-persister\n\n## 5.90.27\n\n### Patch Changes\n\n- fix(streamedQuery): maintain error state on reset refetch with initialData defined ([#10287](https://github.com/TanStack/query/pull/10287))\n\n- Updated dependencies [[`248975e`](https://github.com/TanStack/query/commit/248975e896f585f6eaa505c796e73fcf7bfd1eec)]:\n  - @tanstack/query-persist-client-core@5.92.4\n  - @tanstack/query-core@5.91.2\n\n## 5.90.26\n\n### Patch Changes\n\n- Updated dependencies [[`a89aab9`](https://github.com/TanStack/query/commit/a89aab975581c25c113a26c8af486b4cafad272a)]:\n  - @tanstack/query-core@5.91.1\n  - @tanstack/query-persist-client-core@5.92.3\n\n## 5.90.25\n\n### Patch Changes\n\n- Updated dependencies [[`6fa901b`](https://github.com/TanStack/query/commit/6fa901b97a22a80d0fca3f6ed86237ff0cbdd13b)]:\n  - @tanstack/query-core@5.91.0\n  - @tanstack/query-persist-client-core@5.92.2\n\n## 5.90.24\n\n### Patch Changes\n\n- Updated dependencies [[`e505568`](https://github.com/TanStack/query/commit/e505568f4d51c8281d38e9687091094b7d32a405)]:\n  - @tanstack/query-persist-client-core@5.92.1\n\n## 5.90.23\n\n### Patch Changes\n\n- Updated dependencies [[`978fc52`](https://github.com/TanStack/query/commit/978fc52728a8b9eb33f0a82f4ddf42a95815bd7f)]:\n  - @tanstack/query-persist-client-core@5.92.0\n\n## 5.90.22\n\n### Patch Changes\n\n- Updated dependencies [[`e7258c5`](https://github.com/TanStack/query/commit/e7258c5cb30cafa456cdb4e6bc75b43bf619954d)]:\n  - @tanstack/query-core@5.90.20\n  - @tanstack/query-persist-client-core@5.91.19\n\n## 5.90.21\n\n### Patch Changes\n\n- Updated dependencies [[`53fc74e`](https://github.com/TanStack/query/commit/53fc74ebb16730bd3317f039a69c6821386bae93)]:\n  - @tanstack/query-core@5.90.19\n  - @tanstack/query-persist-client-core@5.91.18\n\n## 5.90.20\n\n### Patch Changes\n\n- Updated dependencies [[`dea1614`](https://github.com/TanStack/query/commit/dea1614aaad5c572cf43cea54b64ac09dc4d5b41)]:\n  - @tanstack/query-core@5.90.18\n  - @tanstack/query-persist-client-core@5.91.17\n\n## 5.90.19\n\n### Patch Changes\n\n- Updated dependencies [[`269351b`](https://github.com/TanStack/query/commit/269351b8ce4b4846da3d320ac5b850ee6aada0d6)]:\n  - @tanstack/query-core@5.90.17\n  - @tanstack/query-persist-client-core@5.91.16\n\n## 5.90.18\n\n### Patch Changes\n\n- Updated dependencies [[`7f47906`](https://github.com/TanStack/query/commit/7f47906eaccc3f3aa5ce24b77a83bd7a620a237b)]:\n  - @tanstack/query-core@5.90.16\n  - @tanstack/query-persist-client-core@5.91.15\n\n## 5.90.17\n\n### Patch Changes\n\n- Updated dependencies [[`fccef79`](https://github.com/TanStack/query/commit/fccef797d57d4a9566517bba87c8377f363920f2)]:\n  - @tanstack/query-core@5.90.15\n  - @tanstack/query-persist-client-core@5.91.14\n\n## 5.90.16\n\n### Patch Changes\n\n- Updated dependencies [[`d576092`](https://github.com/TanStack/query/commit/d576092e2ece4ca3936add3eb0da5234c1d82ed4)]:\n  - @tanstack/query-core@5.90.14\n  - @tanstack/query-persist-client-core@5.91.13\n\n## 5.90.15\n\n### Patch Changes\n\n- Updated dependencies [[`4a0a78a`](https://github.com/TanStack/query/commit/4a0a78afbc2432f8cb6828035965853fa98c86a0)]:\n  - @tanstack/query-core@5.90.13\n  - @tanstack/query-persist-client-core@5.91.12\n\n## 5.90.14\n\n### Patch Changes\n\n- Updated dependencies [[`72d8ac5`](https://github.com/TanStack/query/commit/72d8ac5c592004b8f9c3ee086fcb9c3cd615ca05)]:\n  - @tanstack/query-core@5.90.12\n  - @tanstack/query-persist-client-core@5.91.11\n\n## 5.90.13\n\n### Patch Changes\n\n- Updated dependencies [[`c01b150`](https://github.com/TanStack/query/commit/c01b150e3673e11d6533768529a5e6fe3ebee68c)]:\n  - @tanstack/query-core@5.90.11\n  - @tanstack/query-persist-client-core@5.91.10\n\n## 5.90.12\n\n### Patch Changes\n\n- Updated dependencies [[`8e2e174`](https://github.com/TanStack/query/commit/8e2e174e9fd2e7b94cd232041e49c9d014d74e26), [`eb559a6`](https://github.com/TanStack/query/commit/eb559a66dc0d77dd46435f624fa64fc068bef9ae)]:\n  - @tanstack/query-core@5.90.10\n  - @tanstack/query-persist-client-core@5.91.9\n\n## 5.90.11\n\n### Patch Changes\n\n- Updated dependencies [[`08b211f`](https://github.com/TanStack/query/commit/08b211f8aa475e05d2f13a36517fc556861ef962)]:\n  - @tanstack/query-core@5.90.9\n  - @tanstack/query-persist-client-core@5.91.8\n\n## 5.90.10\n\n### Patch Changes\n\n- Updated dependencies [[`c0ec9fe`](https://github.com/TanStack/query/commit/c0ec9fe0d1426fe3f233adda3ebf23989ffaa110)]:\n  - @tanstack/query-core@5.90.8\n  - @tanstack/query-persist-client-core@5.91.7\n\n## 5.90.9\n\n### Patch Changes\n\n- Updated dependencies [[`b4cd121`](https://github.com/TanStack/query/commit/b4cd121a39d07cefaa3a3411136d342cc54ce8fb)]:\n  - @tanstack/query-core@5.90.7\n  - @tanstack/query-persist-client-core@5.91.6\n\n## 5.90.8\n\n### Patch Changes\n\n- Updated dependencies [[`1638c02`](https://github.com/TanStack/query/commit/1638c028df55648995d04431179904371a189772)]:\n  - @tanstack/query-core@5.90.6\n  - @tanstack/query-persist-client-core@5.91.5\n\n## 5.90.7\n\n### Patch Changes\n\n- Updated dependencies [[`e42ddfe`](https://github.com/TanStack/query/commit/e42ddfe919f34f847ca101aeef162c69845f9a1e)]:\n  - @tanstack/query-core@5.90.5\n  - @tanstack/query-persist-client-core@5.91.4\n\n## 5.90.6\n\n### Patch Changes\n\n- Updated dependencies [[`20ef922`](https://github.com/TanStack/query/commit/20ef922a0a7c3aee00150bf69123c338b0922922)]:\n  - @tanstack/query-core@5.90.4\n  - @tanstack/query-persist-client-core@5.91.3\n\n## 5.90.5\n\n### Patch Changes\n\n- Updated dependencies [[`4e1c433`](https://github.com/TanStack/query/commit/4e1c4338a72f7384600bbda99e44bc1891695df4)]:\n  - @tanstack/query-core@5.90.3\n  - @tanstack/query-persist-client-core@5.91.2\n\n## 5.90.4\n\n### Patch Changes\n\n- Updated dependencies [[`846d53d`](https://github.com/TanStack/query/commit/846d53d98992d50606c40634efa43dea9965b787)]:\n  - @tanstack/query-persist-client-core@5.91.1\n\n## 5.90.3\n\n### Patch Changes\n\n- Updated dependencies [[`5cd86c6`](https://github.com/TanStack/query/commit/5cd86c6ef1720b87b13e1ab70ee823616f1f029a)]:\n  - @tanstack/query-persist-client-core@5.91.0\n"
  },
  {
    "path": "packages/query-sync-storage-persister/eslint.config.js",
    "content": "// @ts-check\n\nimport rootConfig from './root.eslint.config.js'\n\nexport default [...rootConfig]\n"
  },
  {
    "path": "packages/query-sync-storage-persister/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-sync-storage-persister\",\n  \"version\": \"5.90.27\",\n  \"description\": \"A persister for synchronous storages, to be used with TanStack/Query\",\n  \"author\": \"tannerlinsley\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/query-sync-storage-persister\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"scripts\": {\n    \"clean\": \"premove ./build ./coverage ./dist-ts\",\n    \"compile\": \"tsc --build\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:types\": \"npm-run-all --serial test:types:*\",\n    \"test:types:ts54\": \"node ../../node_modules/typescript54/lib/tsc.js --build\",\n    \"test:types:ts55\": \"node ../../node_modules/typescript55/lib/tsc.js --build\",\n    \"test:types:ts56\": \"node ../../node_modules/typescript56/lib/tsc.js --build\",\n    \"test:types:ts57\": \"node ../../node_modules/typescript57/lib/tsc.js --build\",\n    \"test:types:ts58\": \"node ../../node_modules/typescript58/lib/tsc.js --build\",\n    \"test:types:ts59\": \"node ../../node_modules/typescript59/lib/tsc.js --build\",\n    \"test:types:tscurrent\": \"tsc --build\",\n    \"test:types:ts60\": \"node ../../node_modules/typescript60/lib/tsc.js --build\",\n    \"test:lib\": \"vitest\",\n    \"test:lib:dev\": \"pnpm run test:lib --watch\",\n    \"test:build\": \"publint --strict && attw --pack\",\n    \"build\": \"tsup --tsconfig tsconfig.prod.json\"\n  },\n  \"type\": \"module\",\n  \"types\": \"build/legacy/index.d.ts\",\n  \"main\": \"build/legacy/index.cjs\",\n  \"module\": \"build/legacy/index.js\",\n  \"react-native\": \"src/index.ts\",\n  \"exports\": {\n    \".\": {\n      \"@tanstack/custom-condition\": \"./src/index.ts\",\n      \"import\": {\n        \"types\": \"./build/modern/index.d.ts\",\n        \"default\": \"./build/modern/index.js\"\n      },\n      \"require\": {\n        \"types\": \"./build/modern/index.d.cts\",\n        \"default\": \"./build/modern/index.cjs\"\n      }\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"sideEffects\": false,\n  \"files\": [\n    \"build\",\n    \"src\",\n    \"!src/__tests__\"\n  ],\n  \"dependencies\": {\n    \"@tanstack/query-core\": \"workspace:*\",\n    \"@tanstack/query-persist-client-core\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"@tanstack/query-test-utils\": \"workspace:*\",\n    \"npm-run-all2\": \"^5.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/query-sync-storage-persister/src/__tests__/storageIsFull.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport {\n  MutationCache,\n  QueryCache,\n  QueryClient,\n  dehydrate,\n} from '@tanstack/query-core'\nimport { removeOldestQuery } from '@tanstack/query-persist-client-core'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { createSyncStoragePersister } from '../index'\n\nfunction getMockStorage(limitSize?: number) {\n  const dataSet = new Map<string, string>()\n  return {\n    getItem(key: string): string | null {\n      const value = dataSet.get(key)\n      return value === undefined ? null : value\n    },\n\n    setItem(key: string, value: string) {\n      if (limitSize !== undefined) {\n        const currentSize = Array.from(dataSet.entries()).reduce(\n          (n, d) => d[0].length + d[1].length + n,\n          0,\n        )\n        if (\n          currentSize - (dataSet.get(key)?.length || 0) + value.length >\n          limitSize\n        ) {\n          throw Error(\n            `Failed to execute 'setItem' on 'Storage': Setting the value of '${key}' exceeded the quota.`,\n          )\n        }\n      }\n      return dataSet.set(key, value)\n    },\n    removeItem(key: string) {\n      return dataSet.delete(key)\n    },\n  } as any as Storage\n}\n\ndescribe('create persister', () => {\n  test('basic store and recover', async () => {\n    const queryCache = new QueryCache()\n    const mutationCache = new MutationCache()\n    const queryClient = new QueryClient({ queryCache, mutationCache })\n\n    const storage = getMockStorage()\n    const persister = createSyncStoragePersister({\n      throttleTime: 0,\n      storage,\n    })\n\n    await queryClient.prefetchQuery({\n      queryKey: ['string'],\n      queryFn: () => Promise.resolve('string'),\n    })\n    await queryClient.prefetchQuery({\n      queryKey: ['number'],\n      queryFn: () => Promise.resolve(1),\n    })\n    await queryClient.prefetchQuery({\n      queryKey: ['boolean'],\n      queryFn: () => Promise.resolve(true),\n    })\n    await queryClient.prefetchQuery({\n      queryKey: ['null'],\n      queryFn: () => Promise.resolve(null),\n    })\n    await queryClient.prefetchQuery({\n      queryKey: ['array'],\n      queryFn: () => Promise.resolve(['string', 0]),\n    })\n\n    const persistClient = {\n      buster: 'test-buster',\n      timestamp: Date.now(),\n      clientState: dehydrate(queryClient),\n    }\n    persister.persistClient(persistClient)\n    await sleep(1)\n    const restoredClient = await persister.restoreClient()\n    expect(restoredClient).toEqual(persistClient)\n  })\n\n  test('should clean the old queries when storage full', async () => {\n    const queryCache = new QueryCache()\n    const mutationCache = new MutationCache()\n    const queryClient = new QueryClient({ queryCache, mutationCache })\n\n    const N = 2000\n    const storage = getMockStorage(N * 5) // can save 4 items;\n    const persister = createSyncStoragePersister({\n      throttleTime: 0,\n      storage,\n      retry: removeOldestQuery,\n    })\n\n    await queryClient.prefetchQuery({\n      queryKey: ['A'],\n      queryFn: () => Promise.resolve('A'.repeat(N)),\n    })\n    await sleep(1)\n    await queryClient.prefetchQuery({\n      queryKey: ['B'],\n      queryFn: () => Promise.resolve('B'.repeat(N)),\n    })\n    await sleep(1)\n    await queryClient.prefetchQuery({\n      queryKey: ['C'],\n      queryFn: () => Promise.resolve('C'.repeat(N)),\n    })\n    await sleep(1)\n    await queryClient.prefetchQuery({\n      queryKey: ['D'],\n      queryFn: () => Promise.resolve('D'.repeat(N)),\n    })\n\n    await sleep(1)\n    await queryClient.prefetchQuery({\n      queryKey: ['E'],\n      queryFn: () => Promise.resolve('E'.repeat(N)),\n    })\n\n    const persistClient = {\n      buster: 'test-limit',\n      timestamp: Date.now(),\n      clientState: dehydrate(queryClient),\n    }\n    persister.persistClient(persistClient)\n    await sleep(10)\n    const restoredClient = await persister.restoreClient()\n    expect(restoredClient?.clientState.queries.length).toEqual(4)\n    expect(\n      restoredClient?.clientState.queries.find((q) => q.queryKey[0] === 'A'),\n    ).toBeUndefined()\n    expect(\n      restoredClient?.clientState.queries.find((q) => q.queryKey[0] === 'B'),\n    ).not.toBeUndefined()\n\n    // update query Data\n    await queryClient.prefetchQuery({\n      queryKey: ['A'],\n      queryFn: () => Promise.resolve('a'.repeat(N)),\n    })\n    const updatedPersistClient = {\n      buster: 'test-limit',\n      timestamp: Date.now(),\n      clientState: dehydrate(queryClient),\n    }\n    persister.persistClient(updatedPersistClient)\n    await sleep(10)\n    const restoredClient2 = await persister.restoreClient()\n    expect(restoredClient2?.clientState.queries.length).toEqual(4)\n    expect(\n      restoredClient2?.clientState.queries.find((q) => q.queryKey[0] === 'A'),\n    ).toHaveProperty('state.data', 'a'.repeat(N))\n    expect(\n      restoredClient2?.clientState.queries.find((q) => q.queryKey[0] === 'B'),\n    ).toBeUndefined()\n  })\n  test('should clear storage as default error handling', async () => {\n    const queryCache = new QueryCache()\n    const mutationCache = new MutationCache()\n    const queryClient = new QueryClient({ queryCache, mutationCache })\n\n    const N = 2000\n    const storage = getMockStorage(0)\n    const persister = createSyncStoragePersister({\n      throttleTime: 0,\n      storage,\n      retry: removeOldestQuery,\n    })\n\n    await queryClient.prefetchQuery({\n      queryKey: ['A'],\n      queryFn: () => Promise.resolve('A'.repeat(N)),\n    })\n    await sleep(1)\n\n    const persistClient = {\n      buster: 'test-limit',\n      timestamp: Date.now(),\n      clientState: dehydrate(queryClient),\n    }\n    persister.persistClient(persistClient)\n    await sleep(10)\n    const restoredClient = await persister.restoreClient()\n    expect(restoredClient).toEqual(undefined)\n  })\n})\n"
  },
  {
    "path": "packages/query-sync-storage-persister/src/index.ts",
    "content": "import { timeoutManager } from '@tanstack/query-core'\nimport { noop } from './utils'\nimport type { ManagedTimerId } from '@tanstack/query-core'\nimport type {\n  PersistRetryer,\n  PersistedClient,\n  Persister,\n} from '@tanstack/query-persist-client-core'\n\ninterface Storage {\n  getItem: (key: string) => string | null\n  setItem: (key: string, value: string) => void\n  removeItem: (key: string) => void\n}\n\ninterface CreateSyncStoragePersisterOptions {\n  /** The storage client used for setting and retrieving items from cache.\n   * For SSR pass in `undefined`. Note that window.localStorage can be\n   * `null` in Android WebViews depending on how they are configured.\n   */\n  storage: Storage | undefined | null\n  /** The key to use when storing the cache */\n  key?: string\n  /** To avoid spamming,\n   * pass a time in ms to throttle saving the cache to disk */\n  throttleTime?: number\n  /**\n   * How to serialize the data to storage.\n   * @default `JSON.stringify`\n   */\n  serialize?: (client: PersistedClient) => string\n  /**\n   * How to deserialize the data from storage.\n   * @default `JSON.parse`\n   */\n  deserialize?: (cachedString: string) => PersistedClient\n\n  retry?: PersistRetryer\n}\n\n/**\n * @deprecated use `createAsyncStoragePersister` from `@tanstack/query-async-storage-persister` instead.\n */\nexport function createSyncStoragePersister({\n  storage,\n  key = `REACT_QUERY_OFFLINE_CACHE`,\n  throttleTime = 1000,\n  serialize = JSON.stringify,\n  deserialize = JSON.parse,\n  retry,\n}: CreateSyncStoragePersisterOptions): Persister {\n  if (storage) {\n    const trySave = (persistedClient: PersistedClient): Error | undefined => {\n      try {\n        storage.setItem(key, serialize(persistedClient))\n        return\n      } catch (error) {\n        return error as Error\n      }\n    }\n    return {\n      persistClient: throttle((persistedClient) => {\n        let client: PersistedClient | undefined = persistedClient\n        let error = trySave(client)\n        let errorCount = 0\n        while (error && client) {\n          errorCount++\n          client = retry?.({\n            persistedClient: client,\n            error,\n            errorCount,\n          })\n\n          if (client) {\n            error = trySave(client)\n          }\n        }\n      }, throttleTime),\n      restoreClient: () => {\n        const cacheString = storage.getItem(key)\n\n        if (!cacheString) {\n          return\n        }\n\n        return deserialize(cacheString)\n      },\n      removeClient: () => {\n        storage.removeItem(key)\n      },\n    }\n  }\n\n  return {\n    persistClient: noop,\n    restoreClient: noop,\n    removeClient: noop,\n  }\n}\n\nfunction throttle<TArgs extends Array<any>>(\n  func: (...args: TArgs) => any,\n  wait = 100,\n) {\n  let timer: ManagedTimerId | null = null\n  let params: TArgs\n  return function (...args: TArgs) {\n    params = args\n    if (timer === null) {\n      timer = timeoutManager.setTimeout(() => {\n        func(...params)\n        timer = null\n      }, wait)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/query-sync-storage-persister/src/utils.ts",
    "content": "export function noop(): void\nexport function noop(): undefined\nexport function noop() {}\n"
  },
  {
    "path": "packages/query-sync-storage-persister/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\"\n  },\n  \"include\": [\"src\", \"*.config.*\", \"package.json\"],\n  \"references\": [\n    { \"path\": \"../query-core\" },\n    { \"path\": \"../query-persist-client-core\" }\n  ]\n}\n"
  },
  {
    "path": "packages/query-sync-storage-persister/tsconfig.prod.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"incremental\": false,\n    \"composite\": false,\n    \"rootDir\": \"../../\"\n  }\n}\n"
  },
  {
    "path": "packages/query-sync-storage-persister/tsup.config.ts",
    "content": "import { defineConfig } from 'tsup'\nimport { legacyConfig, modernConfig } from './root.tsup.config.js'\n\nexport default defineConfig([\n  modernConfig({ entry: ['src/*.ts'] }),\n  legacyConfig({ entry: ['src/*.ts'] }),\n])\n"
  },
  {
    "path": "packages/query-sync-storage-persister/vite.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nimport packageJson from './package.json'\n\nexport default defineConfig({\n  // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660\n  resolve: {\n    conditions: ['@tanstack/custom-condition'],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        conditions: ['@tanstack/custom-condition'],\n      },\n    },\n  },\n  test: {\n    name: packageJson.name,\n    dir: './src',\n    watch: false,\n    coverage: {\n      enabled: true,\n      provider: 'istanbul',\n      include: ['src/**/*'],\n      exclude: ['src/__tests__/**'],\n    },\n    typecheck: { enabled: true },\n    restoreMocks: true,\n  },\n})\n"
  },
  {
    "path": "packages/query-test-utils/eslint.config.js",
    "content": "// @ts-check\n\nimport rootConfig from './root.eslint.config.js'\n\nexport default [...rootConfig]\n"
  },
  {
    "path": "packages/query-test-utils/package.json",
    "content": "{\n  \"name\": \"@tanstack/query-test-utils\",\n  \"version\": \"0.0.0\",\n  \"description\": \"Internal test utilities for TanStack Query\",\n  \"author\": \"Jonghyeon Ko <manudeli.ko@gmail.com>\",\n  \"private\": true,\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/query-test-utils\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"main\": \"src/index.ts\",\n  \"types\": \"src/index.ts\",\n  \"module\": \"src/index.ts\",\n  \"exports\": {\n    \".\": {\n      \"types\": \"./src/index.ts\",\n      \"default\": \"./src/index.ts\"\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"scripts\": {\n    \"clean\": \"premove ./build ./coverage ./dist-ts\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:types\": \"npm-run-all --serial test:types:*\",\n    \"test:types:tscurrent\": \"tsc --build\",\n    \"test:types:ts60\": \"node ../../node_modules/typescript60/lib/tsc.js --build\",\n    \"test:lib\": \"vitest\",\n    \"test:lib:dev\": \"pnpm run test:lib --watch\"\n  },\n  \"type\": \"module\",\n  \"devDependencies\": {\n    \"npm-run-all2\": \"^5.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/query-test-utils/src/__test__/queryKey.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\nimport { queryKey } from '../queryKey'\n\ndescribe('queryKey', () => {\n  it('should return a query key', () => {\n    const key = queryKey()\n    expect(key).toEqual(['query_1'])\n  })\n  it('should return a new query key each time', () => {\n    expect(queryKey()).not.toEqual(queryKey())\n  })\n})\n"
  },
  {
    "path": "packages/query-test-utils/src/__test__/sleep.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\nimport { sleep } from '../sleep'\n\ndescribe('sleep', () => {\n  it('should sleep for the given amount of time', async () => {\n    const start = Date.now()\n    await sleep(100)\n    const end = Date.now()\n    expect(end - start).toBeGreaterThanOrEqual(100)\n  })\n})\n"
  },
  {
    "path": "packages/query-test-utils/src/index.ts",
    "content": "export { sleep } from './sleep'\nexport { queryKey } from './queryKey'\nexport { mockVisibilityState } from './mockVisibilityState'\n"
  },
  {
    "path": "packages/query-test-utils/src/mockVisibilityState.ts",
    "content": "import { vi } from 'vitest'\nimport type { MockInstance } from 'vitest'\n\nexport const mockVisibilityState = (\n  value: DocumentVisibilityState,\n): MockInstance<() => DocumentVisibilityState> =>\n  vi.spyOn(document, 'visibilityState', 'get').mockReturnValue(value)\n"
  },
  {
    "path": "packages/query-test-utils/src/queryKey.ts",
    "content": "let queryKeyCount = 0\n\nexport const queryKey = (): Array<string> => {\n  queryKeyCount++\n  return [`query_${queryKeyCount}`]\n}\n"
  },
  {
    "path": "packages/query-test-utils/src/sleep.ts",
    "content": "export const sleep = (ms: number): Promise<void> =>\n  new Promise((resolve) => {\n    setTimeout(resolve, ms)\n  })\n"
  },
  {
    "path": "packages/query-test-utils/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\"\n  },\n  \"include\": [\"src\", \"*.config.*\", \"package.json\"]\n}\n"
  },
  {
    "path": "packages/query-test-utils/vite.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nimport packageJson from './package.json'\n\nexport default defineConfig({\n  // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660\n  resolve: {\n    conditions: ['@tanstack/custom-condition'],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        conditions: ['@tanstack/custom-condition'],\n      },\n    },\n  },\n  test: {\n    name: packageJson.name,\n    dir: './src',\n    watch: false,\n    coverage: { enabled: true, provider: 'istanbul', include: ['src/**/*'] },\n    typecheck: { enabled: true },\n    restoreMocks: true,\n  },\n})\n"
  },
  {
    "path": "packages/react-query/CHANGELOG.md",
    "content": "# @tanstack/react-query\n\n## 5.91.2\n\n### Patch Changes\n\n- fix(streamedQuery): maintain error state on reset refetch with initialData defined ([#10287](https://github.com/TanStack/query/pull/10287))\n\n- Updated dependencies [[`248975e`](https://github.com/TanStack/query/commit/248975e896f585f6eaa505c796e73fcf7bfd1eec)]:\n  - @tanstack/query-core@5.91.2\n\n## 5.91.1\n\n### Patch Changes\n\n- fix(core): cancel paused initial fetch when last observer unsubscribes ([#10291](https://github.com/TanStack/query/pull/10291))\n\n- Updated dependencies [[`a89aab9`](https://github.com/TanStack/query/commit/a89aab975581c25c113a26c8af486b4cafad272a)]:\n  - @tanstack/query-core@5.91.1\n\n## 5.91.0\n\n### Minor Changes\n\n- feat: environmentManager ([#10199](https://github.com/TanStack/query/pull/10199))\n\n### Patch Changes\n\n- Updated dependencies [[`6fa901b`](https://github.com/TanStack/query/commit/6fa901b97a22a80d0fca3f6ed86237ff0cbdd13b)]:\n  - @tanstack/query-core@5.91.0\n\n## 5.90.21\n\n### Patch Changes\n\n- refactor(react-query/useQueries): remove unreachable 'willFetch' branch in suspense promise collection ([#10082](https://github.com/TanStack/query/pull/10082))\n\n## 5.90.20\n\n### Patch Changes\n\n- Updated dependencies [[`e7258c5`](https://github.com/TanStack/query/commit/e7258c5cb30cafa456cdb4e6bc75b43bf619954d)]:\n  - @tanstack/query-core@5.90.20\n\n## 5.90.19\n\n### Patch Changes\n\n- Updated dependencies [[`53fc74e`](https://github.com/TanStack/query/commit/53fc74ebb16730bd3317f039a69c6821386bae93)]:\n  - @tanstack/query-core@5.90.19\n\n## 5.90.18\n\n### Patch Changes\n\n- Updated dependencies [[`dea1614`](https://github.com/TanStack/query/commit/dea1614aaad5c572cf43cea54b64ac09dc4d5b41)]:\n  - @tanstack/query-core@5.90.18\n\n## 5.90.17\n\n### Patch Changes\n\n- Updated dependencies [[`269351b`](https://github.com/TanStack/query/commit/269351b8ce4b4846da3d320ac5b850ee6aada0d6)]:\n  - @tanstack/query-core@5.90.17\n\n## 5.90.16\n\n### Patch Changes\n\n- fix(react-query): allow retryOnMount when throwOnError is function ([#9338](https://github.com/TanStack/query/pull/9338))\n\n- Updated dependencies [[`7f47906`](https://github.com/TanStack/query/commit/7f47906eaccc3f3aa5ce24b77a83bd7a620a237b)]:\n  - @tanstack/query-core@5.90.16\n\n## 5.90.15\n\n### Patch Changes\n\n- Updated dependencies [[`fccef79`](https://github.com/TanStack/query/commit/fccef797d57d4a9566517bba87c8377f363920f2)]:\n  - @tanstack/query-core@5.90.15\n\n## 5.90.14\n\n### Patch Changes\n\n- Updated dependencies [[`d576092`](https://github.com/TanStack/query/commit/d576092e2ece4ca3936add3eb0da5234c1d82ed4)]:\n  - @tanstack/query-core@5.90.14\n\n## 5.90.13\n\n### Patch Changes\n\n- Updated dependencies [[`4a0a78a`](https://github.com/TanStack/query/commit/4a0a78afbc2432f8cb6828035965853fa98c86a0)]:\n  - @tanstack/query-core@5.90.13\n\n## 5.90.12\n\n### Patch Changes\n\n- Updated dependencies [[`72d8ac5`](https://github.com/TanStack/query/commit/72d8ac5c592004b8f9c3ee086fcb9c3cd615ca05)]:\n  - @tanstack/query-core@5.90.12\n\n## 5.90.11\n\n### Patch Changes\n\n- Prevent infinite render loops when useSuspenseQueries has duplicate queryKeys ([#9886](https://github.com/TanStack/query/pull/9886))\n\n- Updated dependencies [[`c01b150`](https://github.com/TanStack/query/commit/c01b150e3673e11d6533768529a5e6fe3ebee68c)]:\n  - @tanstack/query-core@5.90.11\n\n## 5.90.10\n\n### Patch Changes\n\n- Updated dependencies [[`8e2e174`](https://github.com/TanStack/query/commit/8e2e174e9fd2e7b94cd232041e49c9d014d74e26), [`eb559a6`](https://github.com/TanStack/query/commit/eb559a66dc0d77dd46435f624fa64fc068bef9ae)]:\n  - @tanstack/query-core@5.90.10\n\n## 5.90.9\n\n### Patch Changes\n\n- Updated dependencies [[`08b211f`](https://github.com/TanStack/query/commit/08b211f8aa475e05d2f13a36517fc556861ef962)]:\n  - @tanstack/query-core@5.90.9\n\n## 5.90.8\n\n### Patch Changes\n\n- Updated dependencies [[`c0ec9fe`](https://github.com/TanStack/query/commit/c0ec9fe0d1426fe3f233adda3ebf23989ffaa110)]:\n  - @tanstack/query-core@5.90.8\n\n## 5.90.7\n\n### Patch Changes\n\n- Updated dependencies [[`b4cd121`](https://github.com/TanStack/query/commit/b4cd121a39d07cefaa3a3411136d342cc54ce8fb)]:\n  - @tanstack/query-core@5.90.7\n\n## 5.90.6\n\n### Patch Changes\n\n- Updated dependencies [[`1638c02`](https://github.com/TanStack/query/commit/1638c028df55648995d04431179904371a189772)]:\n  - @tanstack/query-core@5.90.6\n\n## 5.90.5\n\n### Patch Changes\n\n- Updated dependencies [[`e42ddfe`](https://github.com/TanStack/query/commit/e42ddfe919f34f847ca101aeef162c69845f9a1e)]:\n  - @tanstack/query-core@5.90.5\n\n## 5.90.4\n\n### Patch Changes\n\n- Updated dependencies [[`20ef922`](https://github.com/TanStack/query/commit/20ef922a0a7c3aee00150bf69123c338b0922922)]:\n  - @tanstack/query-core@5.90.4\n\n## 5.90.3\n\n### Patch Changes\n\n- Avoid unhandled promise rejection errors during de/rehydration of pending queries. ([#9752](https://github.com/TanStack/query/pull/9752))\n\n- Updated dependencies [[`4e1c433`](https://github.com/TanStack/query/commit/4e1c4338a72f7384600bbda99e44bc1891695df4)]:\n  - @tanstack/query-core@5.90.3\n"
  },
  {
    "path": "packages/react-query/README.md",
    "content": "<img src=\"https://static.scarf.sh/a.png?x-pxid=be2d8a11-9712-4c1d-9963-580b2d4fb133\" />\n\n![TanStack Query Header](https://github.com/TanStack/query/raw/main/media/repo-header.png)\n\nHooks for fetching, caching and updating asynchronous data in React\n\n<a href=\"https://twitter.com/intent/tweet?button_hashtag=TanStack\" target=\"\\_parent\">\n  <img alt=\"#TanStack\" src=\"https://img.shields.io/twitter/url?color=%2308a0e9&label=%23TanStack&style=social&url=https%3A%2F%2Ftwitter.com%2Fintent%2Ftweet%3Fbutton_hashtag%3DTanStack\">\n</a><a href=\"https://discord.com/invite/WrRKjPJ\" target=\"\\_parent\">\n  <img alt=\"\" src=\"https://img.shields.io/badge/Discord-TanStack-%235865F2\" />\n</a><a href=\"https://github.com/TanStack/query/actions?query=workflow%3A%22react-query+tests%22\">\n<img src=\"https://github.com/TanStack/query/workflows/react-query%20tests/badge.svg\" />\n</a><a href=\"https://www.npmjs.com/package/@tanstack/query-core\" target=\"\\_parent\">\n  <img alt=\"\" src=\"https://img.shields.io/npm/dm/@tanstack/query-core.svg\" />\n</a><a href=\"https://bundlejs.com/?q=%40tanstack%2Freact-query&config=%7B%22esbuild%22%3A%7B%22external%22%3A%5B%22react%22%2C%22react-dom%22%5D%7D%7D&badge=\" target=\"\\_parent\">\n  <img alt=\"\" src=\"https://deno.bundlejs.com/?q=@tanstack/react-query&config={%22esbuild%22:{%22external%22:[%22react%22,%22react-dom%22]}}&badge=detailed\" />\n</a><a href=\"#badge\">\n    <img alt=\"semantic-release\" src=\"https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg\">\n  </a><a href=\"https://github.com/TanStack/query/discussions\">\n  <img alt=\"Join the discussion on Github\" src=\"https://img.shields.io/badge/Github%20Discussions%20%26%20Support-Chat%20now!-blue\" />\n</a><a href=\"https://bestofjs.org/projects/tanstack-query\"><img alt=\"Best of JS\" src=\"https://img.shields.io/endpoint?url=https://bestofjs-serverless.now.sh/api/project-badge?fullName=TanStack%2Fquery%26since=daily\" /></a><a href=\"https://github.com/TanStack/query/\" target=\"\\_parent\">\n  <img alt=\"\" src=\"https://img.shields.io/github/stars/TanStack/query.svg?style=social&label=Star\" />\n</a><a href=\"https://twitter.com/tannerlinsley\" target=\"\\_parent\">\n  <img alt=\"\" src=\"https://img.shields.io/twitter/follow/tannerlinsley.svg?style=social&label=Follow\" />\n</a> <a href=\"https://gitpod.io/from-referrer/\">\n  <img src=\"https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod\" alt=\"Gitpod Ready-to-Code\"/>\n</a>\n\nEnjoy this library? Try the entire [TanStack](https://tanstack.com)! [TanStack Table](https://github.com/TanStack/table), [TanStack Router](https://github.com/tanstack/router), [TanStack Virtual](https://github.com/tanstack/virtual), [React Charts](https://github.com/TanStack/react-charts), [React Ranger](https://github.com/TanStack/ranger)\n\n## Visit [tanstack.com/query](https://tanstack.com/query) for docs, guides, API and more!\n\n## Quick Features\n\n- Transport/protocol/backend agnostic data fetching (REST, GraphQL, promises, whatever!)\n- Auto Caching + Refetching (stale-while-revalidate, Window Refocus, Polling/Realtime)\n- Parallel + Dependent Queries\n- Mutations + Reactive Query Refetching\n- Multi-layer Cache + Automatic Garbage Collection\n- Paginated + Cursor-based Queries\n- Load-More + Infinite Scroll Queries w/ Scroll Recovery\n- Request Cancellation\n- [React Suspense](https://react.dev/reference/react/Suspense) + Fetch-As-You-Render Query Prefetching\n- Dedicated Devtools\n\n### [Become a Sponsor!](https://github.com/sponsors/tannerlinsley/)\n\n<!-- Use the force, Luke -->\n"
  },
  {
    "path": "packages/react-query/eslint.config.js",
    "content": "// @ts-check\n\nimport pluginReact from '@eslint-react/eslint-plugin'\nimport reactHooks from 'eslint-plugin-react-hooks'\nimport rootConfig from './root.eslint.config.js'\n\nexport default [\n  ...rootConfig,\n  // @ts-expect-error wtf\n  ...reactHooks.configs['recommended-latest'],\n  {\n    files: ['**/*.{ts,tsx}'],\n    ...pluginReact.configs.recommended,\n    rules: {\n      '@eslint-react/no-context-provider': 'off', // We need to be React 18 compatible\n      'react-hooks/exhaustive-deps': 'error',\n      'react-hooks/rules-of-hooks': 'error',\n      'react-hooks/unsupported-syntax': 'error',\n      'react-hooks/incompatible-library': 'error',\n    },\n  },\n  {\n    files: ['**/__tests__/**'],\n    rules: {\n      '@eslint-react/dom/no-missing-button-type': 'off',\n      '@typescript-eslint/no-unnecessary-condition': 'off',\n    },\n  },\n]\n"
  },
  {
    "path": "packages/react-query/package.json",
    "content": "{\n  \"name\": \"@tanstack/react-query\",\n  \"version\": \"5.91.2\",\n  \"description\": \"Hooks for managing, caching and syncing asynchronous and remote data in React\",\n  \"author\": \"tannerlinsley\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/react-query\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"scripts\": {\n    \"clean\": \"premove ./build ./coverage ./dist-ts\",\n    \"compile\": \"tsc --build\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:types\": \"npm-run-all --serial test:types:*\",\n    \"test:types:ts54\": \"node ../../node_modules/typescript54/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts55\": \"node ../../node_modules/typescript55/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts56\": \"node ../../node_modules/typescript56/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts57\": \"node ../../node_modules/typescript57/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts58\": \"node ../../node_modules/typescript58/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts59\": \"node ../../node_modules/typescript59/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:tscurrent\": \"tsc --build\",\n    \"test:types:ts60\": \"node ../../node_modules/typescript60/lib/tsc.js --build\",\n    \"test:lib\": \"vitest\",\n    \"test:lib:dev\": \"pnpm run test:lib --watch\",\n    \"test:build\": \"publint --strict && attw --pack\",\n    \"build\": \"pnpm build:tsup && pnpm build:codemods\",\n    \"build:tsup\": \"tsup --tsconfig tsconfig.prod.json\",\n    \"build:codemods\": \"cpy ../query-codemods/* ./build/codemods\"\n  },\n  \"type\": \"module\",\n  \"types\": \"build/legacy/index.d.ts\",\n  \"main\": \"build/legacy/index.cjs\",\n  \"module\": \"build/legacy/index.js\",\n  \"react-native\": \"src/index.ts\",\n  \"exports\": {\n    \".\": {\n      \"@tanstack/custom-condition\": \"./src/index.ts\",\n      \"import\": {\n        \"types\": \"./build/modern/index.d.ts\",\n        \"default\": \"./build/modern/index.js\"\n      },\n      \"require\": {\n        \"types\": \"./build/modern/index.d.cts\",\n        \"default\": \"./build/modern/index.cjs\"\n      }\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"sideEffects\": false,\n  \"files\": [\n    \"build\",\n    \"src\",\n    \"!src/__tests__\",\n    \"!build/codemods/node_modules\",\n    \"!build/codemods/vite.config.ts\",\n    \"!build/codemods/**/__testfixtures__\",\n    \"!build/codemods/**/__tests__\"\n  ],\n  \"dependencies\": {\n    \"@tanstack/query-core\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"@tanstack/query-persist-client-core\": \"workspace:*\",\n    \"@tanstack/query-test-utils\": \"workspace:*\",\n    \"@testing-library/react\": \"^16.1.0\",\n    \"@testing-library/react-render-stream\": \"^2.0.2\",\n    \"@types/react\": \"^19.2.7\",\n    \"@types/react-dom\": \"^19.2.3\",\n    \"@vitejs/plugin-react\": \"^4.3.4\",\n    \"cpy-cli\": \"^5.0.0\",\n    \"npm-run-all2\": \"^5.0.0\",\n    \"react\": \"^19.2.1\",\n    \"react-dom\": \"^19.2.1\",\n    \"react-error-boundary\": \"^4.1.2\"\n  },\n  \"peerDependencies\": {\n    \"react\": \"^18 || ^19\"\n  }\n}\n"
  },
  {
    "path": "packages/react-query/src/HydrationBoundary.tsx",
    "content": "'use client'\nimport * as React from 'react'\n\nimport { hydrate } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport type {\n  DehydratedState,\n  HydrateOptions,\n  OmitKeyof,\n  QueryClient,\n} from '@tanstack/query-core'\n\nexport interface HydrationBoundaryProps {\n  state: DehydratedState | null | undefined\n  options?: OmitKeyof<HydrateOptions, 'defaultOptions'> & {\n    defaultOptions?: OmitKeyof<\n      Exclude<HydrateOptions['defaultOptions'], undefined>,\n      'mutations'\n    >\n  }\n  children?: React.ReactNode\n  queryClient?: QueryClient\n}\n\nexport const HydrationBoundary = ({\n  children,\n  options = {},\n  state,\n  queryClient,\n}: HydrationBoundaryProps) => {\n  const client = useQueryClient(queryClient)\n\n  const optionsRef = React.useRef(options)\n  React.useEffect(() => {\n    optionsRef.current = options\n  })\n\n  // This useMemo is for performance reasons only, everything inside it must\n  // be safe to run in every render and code here should be read as \"in render\".\n  //\n  // This code needs to happen during the render phase, because after initial\n  // SSR, hydration needs to happen _before_ children render. Also, if hydrating\n  // during a transition, we want to hydrate as much as is safe in render so\n  // we can prerender as much as possible.\n  //\n  // For any queries that already exist in the cache, we want to hold back on\n  // hydrating until _after_ the render phase. The reason for this is that during\n  // transitions, we don't want the existing queries and observers to update to\n  // the new data on the current page, only _after_ the transition is committed.\n  // If the transition is aborted, we will have hydrated any _new_ queries, but\n  // we throw away the fresh data for any existing ones to avoid unexpectedly\n  // updating the UI.\n  const hydrationQueue: DehydratedState['queries'] | undefined =\n    React.useMemo(() => {\n      if (state) {\n        if (typeof state !== 'object') {\n          return\n        }\n\n        const queryCache = client.getQueryCache()\n        // State is supplied from the outside and we might as well fail\n        // gracefully if it has the wrong shape, so while we type `queries`\n        // as required, we still provide a fallback.\n        // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n        const queries = state.queries || []\n\n        const newQueries: DehydratedState['queries'] = []\n        const existingQueries: DehydratedState['queries'] = []\n        for (const dehydratedQuery of queries) {\n          const existingQuery = queryCache.get(dehydratedQuery.queryHash)\n\n          if (!existingQuery) {\n            newQueries.push(dehydratedQuery)\n          } else {\n            const hydrationIsNewer =\n              dehydratedQuery.state.dataUpdatedAt >\n                existingQuery.state.dataUpdatedAt ||\n              (dehydratedQuery.promise &&\n                existingQuery.state.status !== 'pending' &&\n                existingQuery.state.fetchStatus !== 'fetching' &&\n                dehydratedQuery.dehydratedAt !== undefined &&\n                dehydratedQuery.dehydratedAt >\n                  existingQuery.state.dataUpdatedAt)\n\n            if (hydrationIsNewer) {\n              existingQueries.push(dehydratedQuery)\n            }\n          }\n        }\n\n        if (newQueries.length > 0) {\n          // It's actually fine to call this with queries/state that already exists\n          // in the cache, or is older. hydrate() is idempotent for queries.\n          // eslint-disable-next-line react-hooks/refs\n          hydrate(client, { queries: newQueries }, optionsRef.current)\n        }\n        if (existingQueries.length > 0) {\n          return existingQueries\n        }\n      }\n      return undefined\n    }, [client, state])\n\n  React.useEffect(() => {\n    if (hydrationQueue) {\n      hydrate(client, { queries: hydrationQueue }, optionsRef.current)\n    }\n  }, [client, hydrationQueue])\n\n  return children as React.ReactElement\n}\n"
  },
  {
    "path": "packages/react-query/src/IsRestoringProvider.ts",
    "content": "'use client'\nimport * as React from 'react'\n\nconst IsRestoringContext = React.createContext(false)\n\nexport const useIsRestoring = () => React.useContext(IsRestoringContext)\nexport const IsRestoringProvider = IsRestoringContext.Provider\n"
  },
  {
    "path": "packages/react-query/src/QueryClientProvider.tsx",
    "content": "'use client'\nimport * as React from 'react'\n\nimport type { QueryClient } from '@tanstack/query-core'\n\nexport const QueryClientContext = React.createContext<QueryClient | undefined>(\n  undefined,\n)\n\nexport const useQueryClient = (queryClient?: QueryClient) => {\n  const client = React.useContext(QueryClientContext)\n\n  if (queryClient) {\n    return queryClient\n  }\n\n  if (!client) {\n    throw new Error('No QueryClient set, use QueryClientProvider to set one')\n  }\n\n  return client\n}\n\nexport type QueryClientProviderProps = {\n  client: QueryClient\n  children?: React.ReactNode\n}\n\nexport const QueryClientProvider = ({\n  client,\n  children,\n}: QueryClientProviderProps): React.JSX.Element => {\n  React.useEffect(() => {\n    client.mount()\n    return () => {\n      client.unmount()\n    }\n  }, [client])\n\n  return (\n    <QueryClientContext.Provider value={client}>\n      {children}\n    </QueryClientContext.Provider>\n  )\n}\n"
  },
  {
    "path": "packages/react-query/src/QueryErrorResetBoundary.tsx",
    "content": "'use client'\nimport * as React from 'react'\n\n// CONTEXT\nexport type QueryErrorResetFunction = () => void\nexport type QueryErrorIsResetFunction = () => boolean\nexport type QueryErrorClearResetFunction = () => void\n\nexport interface QueryErrorResetBoundaryValue {\n  clearReset: QueryErrorClearResetFunction\n  isReset: QueryErrorIsResetFunction\n  reset: QueryErrorResetFunction\n}\n\nfunction createValue(): QueryErrorResetBoundaryValue {\n  let isReset = false\n  return {\n    clearReset: () => {\n      isReset = false\n    },\n    reset: () => {\n      isReset = true\n    },\n    isReset: () => {\n      return isReset\n    },\n  }\n}\n\nconst QueryErrorResetBoundaryContext = React.createContext(createValue())\n\n// HOOK\n\nexport const useQueryErrorResetBoundary = () =>\n  React.useContext(QueryErrorResetBoundaryContext)\n\n// COMPONENT\n\nexport type QueryErrorResetBoundaryFunction = (\n  value: QueryErrorResetBoundaryValue,\n) => React.ReactNode\n\nexport interface QueryErrorResetBoundaryProps {\n  children: QueryErrorResetBoundaryFunction | React.ReactNode\n}\n\nexport const QueryErrorResetBoundary = ({\n  children,\n}: QueryErrorResetBoundaryProps) => {\n  const [value] = React.useState(() => createValue())\n  return (\n    <QueryErrorResetBoundaryContext.Provider value={value}>\n      {typeof children === 'function' ? children(value) : children}\n    </QueryErrorResetBoundaryContext.Provider>\n  )\n}\n"
  },
  {
    "path": "packages/react-query/src/__tests__/HydrationBoundary.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport * as React from 'react'\nimport { render } from '@testing-library/react'\nimport * as coreModule from '@tanstack/query-core'\nimport { sleep } from '@tanstack/query-test-utils'\nimport {\n  HydrationBoundary,\n  QueryClient,\n  QueryClientProvider,\n  dehydrate,\n  useQuery,\n} from '..'\nimport type { hydrate } from '@tanstack/query-core'\n\ndescribe('React hydration', () => {\n  let stringifiedState: string\n\n  beforeEach(async () => {\n    vi.useFakeTimers()\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: ['string'],\n      queryFn: () => sleep(10).then(() => ['stringCached']),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n    const dehydrated = dehydrate(queryClient)\n    stringifiedState = JSON.stringify(dehydrated)\n    queryClient.clear()\n  })\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('should hydrate queries to the cache on context', async () => {\n    const dehydratedState = JSON.parse(stringifiedState)\n    const queryClient = new QueryClient()\n\n    function Page() {\n      const { data } = useQuery({\n        queryKey: ['string'],\n        queryFn: () => sleep(20).then(() => ['string']),\n      })\n      return (\n        <div>\n          <h1>{data}</h1>\n        </div>\n      )\n    }\n\n    const rendered = render(\n      <QueryClientProvider client={queryClient}>\n        <HydrationBoundary state={dehydratedState}>\n          <Page />\n        </HydrationBoundary>\n      </QueryClientProvider>,\n    )\n\n    expect(rendered.getByText('stringCached')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(21)\n    expect(rendered.getByText('string')).toBeInTheDocument()\n    queryClient.clear()\n  })\n\n  test('should hydrate queries to the cache on custom context', async () => {\n    const queryClientInner = new QueryClient()\n    const queryClientOuter = new QueryClient()\n\n    const dehydratedState = JSON.parse(stringifiedState)\n\n    function Page() {\n      const { data } = useQuery({\n        queryKey: ['string'],\n        queryFn: () => sleep(20).then(() => ['string']),\n      })\n      return (\n        <div>\n          <h1>{data}</h1>\n        </div>\n      )\n    }\n\n    const rendered = render(\n      <QueryClientProvider client={queryClientOuter}>\n        <QueryClientProvider client={queryClientInner}>\n          <HydrationBoundary state={dehydratedState}>\n            <Page />\n          </HydrationBoundary>\n        </QueryClientProvider>\n      </QueryClientProvider>,\n    )\n\n    expect(rendered.getByText('stringCached')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(21)\n    expect(rendered.getByText('string')).toBeInTheDocument()\n\n    queryClientInner.clear()\n    queryClientOuter.clear()\n  })\n\n  describe('ReactQueryCacheProvider with hydration support', () => {\n    test('should hydrate new queries if queries change', async () => {\n      const dehydratedState = JSON.parse(stringifiedState)\n      const queryClient = new QueryClient()\n\n      function Page({ queryKey }: { queryKey: [string] }) {\n        const { data } = useQuery({\n          queryKey,\n          queryFn: () => sleep(20).then(() => queryKey),\n        })\n        return (\n          <div>\n            <h1>{data}</h1>\n          </div>\n        )\n      }\n\n      const rendered = render(\n        <QueryClientProvider client={queryClient}>\n          <HydrationBoundary state={dehydratedState}>\n            <Page queryKey={['string']} />\n          </HydrationBoundary>\n        </QueryClientProvider>,\n      )\n\n      expect(rendered.getByText('stringCached')).toBeInTheDocument()\n      await vi.advanceTimersByTimeAsync(21)\n      expect(rendered.getByText('string')).toBeInTheDocument()\n\n      const intermediateClient = new QueryClient()\n\n      intermediateClient.prefetchQuery({\n        queryKey: ['string'],\n        queryFn: () => sleep(20).then(() => ['should change']),\n      })\n      intermediateClient.prefetchQuery({\n        queryKey: ['added'],\n        queryFn: () => sleep(20).then(() => ['added']),\n      })\n      await vi.advanceTimersByTimeAsync(20)\n      const dehydrated = dehydrate(intermediateClient)\n      intermediateClient.clear()\n\n      rendered.rerender(\n        <QueryClientProvider client={queryClient}>\n          <HydrationBoundary state={dehydrated}>\n            <Page queryKey={['string']} />\n            <Page queryKey={['added']} />\n          </HydrationBoundary>\n        </QueryClientProvider>,\n      )\n\n      // Existing observer should not have updated at this point,\n      // as that would indicate a side effect in the render phase\n      expect(rendered.getByText('string')).toBeInTheDocument()\n      // New query data should be available immediately\n      expect(rendered.getByText('added')).toBeInTheDocument()\n\n      await vi.advanceTimersByTimeAsync(0)\n      // After effects phase has had time to run, the observer should have updated\n      expect(rendered.queryByText('string')).not.toBeInTheDocument()\n      expect(rendered.getByText('should change')).toBeInTheDocument()\n\n      queryClient.clear()\n    })\n\n    // When we hydrate in transitions that are later aborted, it could be\n    // confusing to both developers and users if we suddenly updated existing\n    // state on the screen (why did this update when it was not stale, nothing\n    // remounted, I didn't change tabs etc?).\n    // Any queries that does not exist in the cache yet can still be hydrated\n    // since they don't have any observers on the current page that would update.\n    test('should hydrate new but not existing queries if transition is aborted', async () => {\n      const initialDehydratedState = JSON.parse(stringifiedState)\n      const queryClient = new QueryClient()\n\n      function Page({ queryKey }: { queryKey: [string] }) {\n        const { data } = useQuery({\n          queryKey,\n          queryFn: () => sleep(20).then(() => queryKey),\n        })\n        return (\n          <div>\n            <h1>{data}</h1>\n          </div>\n        )\n      }\n\n      const rendered = render(\n        <QueryClientProvider client={queryClient}>\n          <HydrationBoundary state={initialDehydratedState}>\n            <Page queryKey={['string']} />\n          </HydrationBoundary>\n        </QueryClientProvider>,\n      )\n\n      expect(rendered.getByText('stringCached')).toBeInTheDocument()\n      await vi.advanceTimersByTimeAsync(21)\n      expect(rendered.getByText('string')).toBeInTheDocument()\n\n      const intermediateClient = new QueryClient()\n      intermediateClient.prefetchQuery({\n        queryKey: ['string'],\n        queryFn: () => sleep(20).then(() => ['should not change']),\n      })\n      intermediateClient.prefetchQuery({\n        queryKey: ['added'],\n        queryFn: () => sleep(20).then(() => ['added']),\n      })\n      await vi.advanceTimersByTimeAsync(20)\n\n      const newDehydratedState = dehydrate(intermediateClient)\n      intermediateClient.clear()\n\n      function Thrower(): never {\n        throw new Promise(() => {\n          // Never resolve\n        })\n      }\n\n      React.startTransition(() => {\n        rendered.rerender(\n          <React.Suspense fallback=\"loading\">\n            <QueryClientProvider client={queryClient}>\n              <HydrationBoundary state={newDehydratedState}>\n                <Page queryKey={['string']} />\n                <Page queryKey={['added']} />\n                <Thrower />\n              </HydrationBoundary>\n            </QueryClientProvider>\n          </React.Suspense>,\n        )\n\n        expect(rendered.getByText('loading')).toBeInTheDocument()\n      })\n\n      React.startTransition(() => {\n        rendered.rerender(\n          <QueryClientProvider client={queryClient}>\n            <HydrationBoundary state={initialDehydratedState}>\n              <Page queryKey={['string']} />\n              <Page queryKey={['added']} />\n            </HydrationBoundary>\n          </QueryClientProvider>,\n        )\n\n        // This query existed before the transition so it should stay the same\n        expect(rendered.getByText('string')).toBeInTheDocument()\n        expect(\n          rendered.queryByText('should not change'),\n        ).not.toBeInTheDocument()\n        // New query data should be available immediately because it was\n        // hydrated in the previous transition, even though the new dehydrated\n        // state did not contain it\n        expect(rendered.getByText('added')).toBeInTheDocument()\n      })\n\n      await vi.advanceTimersByTimeAsync(20)\n      // It should stay the same even after effects have had a chance to run\n      expect(rendered.getByText('string')).toBeInTheDocument()\n      expect(rendered.queryByText('should not change')).not.toBeInTheDocument()\n\n      queryClient.clear()\n    })\n\n    test('should hydrate queries to new cache if cache changes', async () => {\n      const dehydratedState = JSON.parse(stringifiedState)\n      const queryClient = new QueryClient()\n\n      function Page() {\n        const { data } = useQuery({\n          queryKey: ['string'],\n          queryFn: () => sleep(20).then(() => ['string']),\n        })\n        return (\n          <div>\n            <h1>{data}</h1>\n          </div>\n        )\n      }\n\n      const rendered = render(\n        <QueryClientProvider client={queryClient}>\n          <HydrationBoundary state={dehydratedState}>\n            <Page />\n          </HydrationBoundary>\n        </QueryClientProvider>,\n      )\n\n      expect(rendered.getByText('stringCached')).toBeInTheDocument()\n      await vi.advanceTimersByTimeAsync(21)\n      expect(rendered.getByText('string')).toBeInTheDocument()\n      const newClientQueryClient = new QueryClient()\n\n      rendered.rerender(\n        <QueryClientProvider client={newClientQueryClient}>\n          <HydrationBoundary state={dehydratedState}>\n            <Page />\n          </HydrationBoundary>\n        </QueryClientProvider>,\n      )\n\n      await vi.advanceTimersByTimeAsync(20)\n      expect(rendered.getByText('string')).toBeInTheDocument()\n\n      queryClient.clear()\n      newClientQueryClient.clear()\n    })\n  })\n\n  test('should not hydrate queries if state is null', async () => {\n    const queryClient = new QueryClient()\n\n    const hydrateSpy = vi.spyOn(coreModule, 'hydrate')\n\n    function Page() {\n      return null\n    }\n\n    render(\n      <QueryClientProvider client={queryClient}>\n        <HydrationBoundary state={null}>\n          <Page />\n        </HydrationBoundary>\n      </QueryClientProvider>,\n    )\n\n    await Promise.all(\n      Array.from({ length: 1000 }).map(async (_, index) => {\n        await vi.advanceTimersByTimeAsync(index)\n        expect(hydrateSpy).toHaveBeenCalledTimes(0)\n      }),\n    )\n\n    hydrateSpy.mockRestore()\n    queryClient.clear()\n  })\n\n  test('should not hydrate queries if state is undefined', async () => {\n    const queryClient = new QueryClient()\n\n    const hydrateSpy = vi.spyOn(coreModule, 'hydrate')\n\n    function Page() {\n      return null\n    }\n\n    render(\n      <QueryClientProvider client={queryClient}>\n        <HydrationBoundary state={undefined}>\n          <Page />\n        </HydrationBoundary>\n      </QueryClientProvider>,\n    )\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(hydrateSpy).toHaveBeenCalledTimes(0)\n\n    hydrateSpy.mockRestore()\n    queryClient.clear()\n  })\n\n  test('should not hydrate queries if state is not an object', async () => {\n    const queryClient = new QueryClient()\n\n    const hydrateSpy = vi.spyOn(coreModule, 'hydrate')\n\n    function Page() {\n      return null\n    }\n\n    render(\n      <QueryClientProvider client={queryClient}>\n        <HydrationBoundary state={'invalid-state' as any}>\n          <Page />\n        </HydrationBoundary>\n      </QueryClientProvider>,\n    )\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(hydrateSpy).toHaveBeenCalledTimes(0)\n\n    hydrateSpy.mockRestore()\n    queryClient.clear()\n  })\n\n  test('should handle state without queries property gracefully', async () => {\n    const queryClient = new QueryClient()\n\n    const hydrateSpy = vi.spyOn(coreModule, 'hydrate')\n\n    function Page() {\n      return null\n    }\n\n    render(\n      <QueryClientProvider client={queryClient}>\n        <HydrationBoundary state={{} as any}>\n          <Page />\n        </HydrationBoundary>\n      </QueryClientProvider>,\n    )\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(hydrateSpy).toHaveBeenCalledTimes(0)\n\n    hydrateSpy.mockRestore()\n    queryClient.clear()\n  })\n\n  // https://github.com/TanStack/query/issues/8677\n  test('should not infinite loop when hydrating promises that resolve to errors', async () => {\n    const originalHydrate = coreModule.hydrate\n    const hydrateSpy = vi.spyOn(coreModule, 'hydrate')\n    let hydrationCount = 0\n    hydrateSpy.mockImplementation((...args: Parameters<typeof hydrate>) => {\n      hydrationCount++\n      // Arbitrary number\n      if (hydrationCount > 10) {\n        // This is a rough way to detect it. Calling hydrate multiple times with\n        // the same data is usually fine, but in this case it indicates the\n        // logic in HydrationBoundary is not working as expected.\n        throw new Error('Too many hydrations detected')\n      }\n      return originalHydrate(...args)\n    })\n\n    // For the bug to trigger, there needs to already be a query in the cache,\n    // with a dataUpdatedAt earlier than the dehydratedAt of the next query\n    const clientQueryClient = new QueryClient()\n    clientQueryClient.prefetchQuery({\n      queryKey: ['promise'],\n      queryFn: () => sleep(20).then(() => 'existing'),\n    })\n    await vi.advanceTimersByTimeAsync(20)\n\n    const prefetchQueryClient = new QueryClient({\n      defaultOptions: {\n        dehydrate: {\n          shouldDehydrateQuery: () => true,\n        },\n      },\n    })\n    prefetchQueryClient.prefetchQuery({\n      queryKey: ['promise'],\n      queryFn: () =>\n        sleep(10).then(() => Promise.reject(new Error('Query failed'))),\n    })\n\n    const dehydratedState = dehydrate(prefetchQueryClient)\n\n    // Mimic what React/our synchronous thenable does for already rejected promises\n    // @ts-expect-error\n    dehydratedState.queries[0].promise.status = 'failure'\n\n    function Page() {\n      const { data } = useQuery({\n        queryKey: ['promise'],\n        queryFn: () => sleep(20).then(() => ['new']),\n      })\n      return (\n        <div>\n          <h1>{data}</h1>\n        </div>\n      )\n    }\n\n    const rendered = render(\n      <QueryClientProvider client={clientQueryClient}>\n        <HydrationBoundary state={dehydratedState}>\n          <Page />\n        </HydrationBoundary>\n      </QueryClientProvider>,\n    )\n\n    expect(rendered.getByText('existing')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(21)\n    expect(rendered.getByText('new')).toBeInTheDocument()\n\n    hydrateSpy.mockRestore()\n    prefetchQueryClient.clear()\n    clientQueryClient.clear()\n  })\n\n  test('should not refetch when query has enabled set to false', async () => {\n    const queryFn = vi.fn()\n    const queryClient = new QueryClient()\n\n    function Page() {\n      const { data } = useQuery({\n        queryKey: ['string'],\n        queryFn,\n        enabled: false,\n      })\n      return <div>{JSON.stringify(data)}</div>\n    }\n\n    const rendered = render(\n      <QueryClientProvider client={queryClient}>\n        <HydrationBoundary state={JSON.parse(stringifiedState)}>\n          <Page />\n        </HydrationBoundary>\n      </QueryClientProvider>,\n    )\n\n    expect(rendered.getByText('[\"stringCached\"]')).toBeInTheDocument()\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(queryFn).toHaveBeenCalledTimes(0)\n    expect(rendered.getByText('[\"stringCached\"]')).toBeInTheDocument()\n\n    queryClient.clear()\n  })\n\n  test('should not refetch when query has staleTime set to Infinity', async () => {\n    const queryFn = vi.fn()\n    const queryClient = new QueryClient()\n\n    function Page() {\n      const { data } = useQuery({\n        queryKey: ['string'],\n        queryFn,\n        staleTime: Infinity,\n      })\n      return <div>{JSON.stringify(data)}</div>\n    }\n\n    const rendered = render(\n      <QueryClientProvider client={queryClient}>\n        <HydrationBoundary state={JSON.parse(stringifiedState)}>\n          <Page />\n        </HydrationBoundary>\n      </QueryClientProvider>,\n    )\n\n    expect(rendered.getByText('[\"stringCached\"]')).toBeInTheDocument()\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(queryFn).toHaveBeenCalledTimes(0)\n    expect(rendered.getByText('[\"stringCached\"]')).toBeInTheDocument()\n\n    queryClient.clear()\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/QueryClientProvider.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { render } from '@testing-library/react'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport {\n  QueryCache,\n  QueryClient,\n  QueryClientProvider,\n  useQuery,\n  useQueryClient,\n} from '..'\n\ndescribe('QueryClientProvider', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('sets a specific cache for all queries to use', async () => {\n    const key = queryKey()\n\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({ queryCache })\n\n    function Page() {\n      const { data } = useQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'test'),\n      })\n\n      return (\n        <div>\n          <h1>{data}</h1>\n        </div>\n      )\n    }\n\n    const rendered = render(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('test')).toBeInTheDocument()\n\n    expect(queryCache.find({ queryKey: key })).toBeDefined()\n  })\n\n  test('allows multiple caches to be partitioned', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    const queryCache1 = new QueryCache()\n    const queryCache2 = new QueryCache()\n\n    const queryClient1 = new QueryClient({ queryCache: queryCache1 })\n    const queryClient2 = new QueryClient({ queryCache: queryCache2 })\n\n    function Page1() {\n      const { data } = useQuery({\n        queryKey: key1,\n        queryFn: () => sleep(10).then(() => 'test1'),\n      })\n\n      return (\n        <div>\n          <h1>{data}</h1>\n        </div>\n      )\n    }\n    function Page2() {\n      const { data } = useQuery({\n        queryKey: key2,\n        queryFn: () => sleep(10).then(() => 'test2'),\n      })\n\n      return (\n        <div>\n          <h1>{data}</h1>\n        </div>\n      )\n    }\n\n    const rendered = render(\n      <>\n        <QueryClientProvider client={queryClient1}>\n          <Page1 />\n        </QueryClientProvider>\n        <QueryClientProvider client={queryClient2}>\n          <Page2 />\n        </QueryClientProvider>\n      </>,\n    )\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('test1')).toBeInTheDocument()\n    expect(rendered.getByText('test2')).toBeInTheDocument()\n\n    expect(queryCache1.find({ queryKey: key1 })).toBeDefined()\n    expect(queryCache1.find({ queryKey: key2 })).not.toBeDefined()\n    expect(queryCache2.find({ queryKey: key1 })).not.toBeDefined()\n    expect(queryCache2.find({ queryKey: key2 })).toBeDefined()\n  })\n\n  test(\"uses defaultOptions for queries when they don't provide their own config\", async () => {\n    const key = queryKey()\n\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({\n      queryCache,\n      defaultOptions: {\n        queries: {\n          gcTime: Infinity,\n        },\n      },\n    })\n\n    function Page() {\n      const { data } = useQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'test'),\n      })\n\n      return (\n        <div>\n          <h1>{data}</h1>\n        </div>\n      )\n    }\n\n    const rendered = render(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('test')).toBeInTheDocument()\n\n    expect(queryCache.find({ queryKey: key })).toBeDefined()\n    expect(queryCache.find({ queryKey: key })?.options.gcTime).toBe(Infinity)\n  })\n\n  describe('useQueryClient', () => {\n    test('should throw an error if no query client has been set', () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n\n      function Page() {\n        useQueryClient()\n        return null\n      }\n\n      expect(() => render(<Page />)).toThrow(\n        'No QueryClient set, use QueryClientProvider to set one',\n      )\n\n      consoleMock.mockRestore()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/QueryResetErrorBoundary.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { act, fireEvent } from '@testing-library/react'\nimport { ErrorBoundary } from 'react-error-boundary'\nimport * as React from 'react'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport {\n  QueryCache,\n  QueryClient,\n  QueryErrorResetBoundary,\n  useQueries,\n  useQuery,\n  useSuspenseQueries,\n  useSuspenseQuery,\n} from '..'\nimport { renderWithClient } from './utils'\n\ndescribe('QueryErrorResetBoundary', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  const queryCache = new QueryCache()\n  const queryClient = new QueryClient({ queryCache })\n\n  describe('useQuery', () => {\n    it('should retry fetch if the reset error boundary has been reset', async () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n      const key = queryKey()\n\n      let succeed = false\n\n      function Page() {\n        const { data } = useQuery({\n          queryKey: key,\n          queryFn: () =>\n            sleep(10).then(() => {\n              if (!succeed) throw new Error('Error')\n              return 'data'\n            }),\n          retry: false,\n          throwOnError: true,\n        })\n\n        return <div>{data}</div>\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          {({ reset }) => (\n            <ErrorBoundary\n              onReset={reset}\n              fallbackRender={({ resetErrorBoundary }) => (\n                <div>\n                  <div>error boundary</div>\n                  <button\n                    onClick={() => {\n                      resetErrorBoundary()\n                    }}\n                  >\n                    retry\n                  </button>\n                </div>\n              )}\n            >\n              <Page />\n            </ErrorBoundary>\n          )}\n        </QueryErrorResetBoundary>,\n      )\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      succeed = true\n\n      fireEvent.click(rendered.getByText('retry'))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('data')).toBeInTheDocument()\n\n      consoleMock.mockRestore()\n    })\n\n    it('should not throw error if query is disabled', async () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n      const key = queryKey()\n\n      let succeed = false\n\n      function Page() {\n        const { data, status } = useQuery({\n          queryKey: key,\n          queryFn: () =>\n            sleep(10).then(() => {\n              if (!succeed) throw new Error('Error')\n              return 'data'\n            }),\n          retry: false,\n          enabled: !succeed,\n          throwOnError: true,\n        })\n\n        return (\n          <div>\n            <div>status: {status}</div>\n            <div>{data}</div>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          {({ reset }) => (\n            <ErrorBoundary\n              onReset={reset}\n              fallbackRender={({ resetErrorBoundary }) => (\n                <div>\n                  <div>error boundary</div>\n                  <button\n                    onClick={() => {\n                      resetErrorBoundary()\n                    }}\n                  >\n                    retry\n                  </button>\n                </div>\n              )}\n            >\n              <Page />\n            </ErrorBoundary>\n          )}\n        </QueryErrorResetBoundary>,\n      )\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      succeed = true\n\n      fireEvent.click(rendered.getByText('retry'))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('status: error')).toBeInTheDocument()\n\n      consoleMock.mockRestore()\n    })\n\n    it('should not throw error if query is disabled, and refetch if query becomes enabled again', async () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n\n      const key = queryKey()\n\n      let succeed = false\n\n      function Page() {\n        const [enabled, setEnabled] = React.useState(false)\n        const { data } = useQuery({\n          queryKey: key,\n          queryFn: () =>\n            sleep(10).then(() => {\n              if (!succeed) throw new Error('Error')\n              return 'data'\n            }),\n          retry: false,\n          enabled,\n          throwOnError: true,\n        })\n\n        React.useEffect(() => {\n          setEnabled(true)\n        }, [])\n\n        return <div>{data}</div>\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          {({ reset }) => (\n            <ErrorBoundary\n              onReset={reset}\n              fallbackRender={({ resetErrorBoundary }) => (\n                <div>\n                  <div>error boundary</div>\n                  <button\n                    onClick={() => {\n                      resetErrorBoundary()\n                    }}\n                  >\n                    retry\n                  </button>\n                </div>\n              )}\n            >\n              <Page />\n            </ErrorBoundary>\n          )}\n        </QueryErrorResetBoundary>,\n      )\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      succeed = true\n\n      fireEvent.click(rendered.getByText('retry'))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('data')).toBeInTheDocument()\n\n      consoleMock.mockRestore()\n    })\n\n    it('should throw error if query is disabled and manually refetch', async () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n\n      const key = queryKey()\n\n      function Page() {\n        const { data, refetch, status, fetchStatus } = useQuery<string>({\n          queryKey: key,\n          queryFn: () =>\n            sleep(10).then(() => Promise.reject(new Error('Error'))),\n          retry: false,\n          enabled: false,\n          throwOnError: true,\n        })\n\n        return (\n          <div>\n            <button onClick={() => refetch()}>refetch</button>\n            <div>\n              status: {status}, fetchStatus: {fetchStatus}\n            </div>\n            <div>{data}</div>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          {({ reset }) => (\n            <ErrorBoundary\n              onReset={reset}\n              fallbackRender={({ resetErrorBoundary }) => (\n                <div>\n                  <div>error boundary</div>\n                  <button\n                    onClick={() => {\n                      resetErrorBoundary()\n                    }}\n                  >\n                    retry\n                  </button>\n                </div>\n              )}\n            >\n              <Page />\n            </ErrorBoundary>\n          )}\n        </QueryErrorResetBoundary>,\n      )\n\n      expect(\n        rendered.getByText('status: pending, fetchStatus: idle'),\n      ).toBeInTheDocument()\n      await vi.advanceTimersByTimeAsync(11)\n      expect(\n        rendered.getByText('status: pending, fetchStatus: idle'),\n      ).toBeInTheDocument()\n\n      fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n\n      consoleMock.mockRestore()\n    })\n\n    it('should not retry fetch if the reset error boundary has not been reset', async () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n\n      const key = queryKey()\n\n      let succeed = false\n\n      function Page() {\n        const { data } = useQuery({\n          queryKey: key,\n          queryFn: () =>\n            sleep(10).then(() => {\n              if (!succeed) throw new Error('Error')\n              return 'data'\n            }),\n          retry: false,\n          throwOnError: true,\n        })\n\n        return <div>{data}</div>\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          {() => (\n            <ErrorBoundary\n              fallbackRender={({ resetErrorBoundary }) => (\n                <div>\n                  <div>error boundary</div>\n                  <button\n                    onClick={() => {\n                      resetErrorBoundary()\n                    }}\n                  >\n                    retry\n                  </button>\n                </div>\n              )}\n            >\n              <Page />\n            </ErrorBoundary>\n          )}\n        </QueryErrorResetBoundary>,\n      )\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      succeed = true\n\n      fireEvent.click(rendered.getByText('retry'))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n\n      consoleMock.mockRestore()\n    })\n\n    it('should retry fetch if the reset error boundary has been reset and the query contains data from a previous fetch', async () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n\n      const key = queryKey()\n\n      let succeed = false\n\n      function Page() {\n        const { data } = useQuery({\n          queryKey: key,\n          queryFn: () =>\n            sleep(10).then(() => {\n              if (!succeed) throw new Error('Error')\n              return 'data'\n            }),\n          retry: false,\n          throwOnError: true,\n          initialData: 'initial',\n        })\n\n        return <div>{data}</div>\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          {({ reset }) => (\n            <ErrorBoundary\n              onReset={reset}\n              fallbackRender={({ resetErrorBoundary }) => (\n                <div>\n                  <div>error boundary</div>\n                  <button\n                    onClick={() => {\n                      resetErrorBoundary()\n                    }}\n                  >\n                    retry\n                  </button>\n                </div>\n              )}\n            >\n              <Page />\n            </ErrorBoundary>\n          )}\n        </QueryErrorResetBoundary>,\n      )\n\n      expect(rendered.getByText('initial')).toBeInTheDocument()\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      succeed = true\n\n      fireEvent.click(rendered.getByText('retry'))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('data')).toBeInTheDocument()\n\n      consoleMock.mockRestore()\n    })\n\n    it('should not retry fetch if the reset error boundary has not been reset after a previous reset', async () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n\n      const key = queryKey()\n\n      let succeed = false\n      let shouldReset = false\n\n      function Page() {\n        const { data } = useQuery({\n          queryKey: key,\n          queryFn: () =>\n            sleep(10).then(() => {\n              if (!succeed) throw new Error('Error')\n              return 'data'\n            }),\n          retry: false,\n          throwOnError: true,\n        })\n\n        return <div>{data}</div>\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          {({ reset }) => (\n            <ErrorBoundary\n              onReset={() => {\n                if (shouldReset) {\n                  reset()\n                }\n              }}\n              fallbackRender={({ resetErrorBoundary }) => (\n                <div>\n                  <div>error boundary</div>\n                  <button\n                    onClick={() => {\n                      resetErrorBoundary()\n                    }}\n                  >\n                    retry\n                  </button>\n                </div>\n              )}\n            >\n              <Page />\n            </ErrorBoundary>\n          )}\n        </QueryErrorResetBoundary>,\n      )\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      succeed = false\n      shouldReset = true\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      succeed = true\n      shouldReset = false\n\n      fireEvent.click(rendered.getByText('retry'))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n\n      succeed = true\n      shouldReset = true\n\n      fireEvent.click(rendered.getByText('retry'))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('data')).toBeInTheDocument()\n\n      consoleMock.mockRestore()\n    })\n\n    it('should throw again on error after the reset error boundary has been reset', async () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n\n      const key = queryKey()\n      let fetchCount = 0\n\n      function Page() {\n        const { data } = useQuery<string>({\n          queryKey: key,\n          queryFn: () =>\n            sleep(10).then(() => {\n              fetchCount++\n              throw new Error('Error')\n            }),\n          retry: false,\n          throwOnError: true,\n        })\n\n        return <div>{data}</div>\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          {({ reset }) => (\n            <ErrorBoundary\n              onReset={reset}\n              fallbackRender={({ resetErrorBoundary }) => (\n                <div>\n                  <div>error boundary</div>\n                  <button\n                    onClick={() => {\n                      resetErrorBoundary()\n                    }}\n                  >\n                    retry\n                  </button>\n                </div>\n              )}\n            >\n              <Page />\n            </ErrorBoundary>\n          )}\n        </QueryErrorResetBoundary>,\n      )\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      fireEvent.click(rendered.getByText('retry'))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      fireEvent.click(rendered.getByText('retry'))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n\n      expect(fetchCount).toBe(3)\n\n      consoleMock.mockRestore()\n    })\n\n    it('should never render the component while the query is in error state', async () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n\n      const key = queryKey()\n      let fetchCount = 0\n      let renders = 0\n\n      function Page() {\n        const { data } = useSuspenseQuery({\n          queryKey: key,\n          queryFn: () =>\n            sleep(10).then(() => {\n              fetchCount++\n              if (fetchCount > 2) return 'data'\n              throw new Error('Error')\n            }),\n          retry: false,\n        })\n\n        renders++\n\n        return <div>{data}</div>\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          {({ reset }) => (\n            <ErrorBoundary\n              onReset={reset}\n              fallbackRender={({ resetErrorBoundary }) => (\n                <div>\n                  <div>error boundary</div>\n                  <button\n                    onClick={() => {\n                      resetErrorBoundary()\n                    }}\n                  >\n                    retry\n                  </button>\n                </div>\n              )}\n            >\n              <React.Suspense fallback={<div>loading</div>}>\n                <Page />\n              </React.Suspense>\n            </ErrorBoundary>\n          )}\n        </QueryErrorResetBoundary>,\n      )\n\n      expect(rendered.getByText('loading')).toBeInTheDocument()\n      await act(() => vi.advanceTimersByTimeAsync(10))\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      fireEvent.click(rendered.getByText('retry'))\n      expect(rendered.getByText('loading')).toBeInTheDocument()\n      await act(() => vi.advanceTimersByTimeAsync(10))\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      fireEvent.click(rendered.getByText('retry'))\n      expect(rendered.getByText('loading')).toBeInTheDocument()\n      await act(() => vi.advanceTimersByTimeAsync(10))\n      expect(rendered.getByText('data')).toBeInTheDocument()\n\n      expect(fetchCount).toBe(3)\n      expect(renders).toBe(1)\n\n      consoleMock.mockRestore()\n    })\n\n    it('should render children', () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n\n      function Page() {\n        return (\n          <div>\n            <span>page</span>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          <Page />\n        </QueryErrorResetBoundary>,\n      )\n\n      expect(rendered.queryByText('page')).not.toBeNull()\n\n      consoleMock.mockRestore()\n    })\n\n    it('should show error boundary when using tracked queries even though we do not track the error field', async () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n\n      const key = queryKey()\n\n      let succeed = false\n\n      function Page() {\n        const { data } = useQuery({\n          queryKey: key,\n          queryFn: () =>\n            sleep(10).then(() => {\n              if (!succeed) throw new Error('Error')\n              return 'data'\n            }),\n          retry: false,\n          throwOnError: true,\n        })\n\n        return <div>{data}</div>\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          {({ reset }) => (\n            <ErrorBoundary\n              onReset={reset}\n              fallbackRender={({ resetErrorBoundary }) => (\n                <div>\n                  <div>error boundary</div>\n                  <button\n                    onClick={() => {\n                      resetErrorBoundary()\n                    }}\n                  >\n                    retry\n                  </button>\n                </div>\n              )}\n            >\n              <Page />\n            </ErrorBoundary>\n          )}\n        </QueryErrorResetBoundary>,\n      )\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      succeed = true\n\n      fireEvent.click(rendered.getByText('retry'))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('data')).toBeInTheDocument()\n\n      consoleMock.mockRestore()\n    })\n\n    it('should refetch after error when staleTime is Infinity and previous data exists (#9728)', async () => {\n      const key = queryKey()\n      const queryFn = vi.fn()\n      let count = 0\n\n      queryFn.mockImplementation(async () => {\n        await sleep(10)\n        count++\n        if (count === 2) {\n          throw new Error('Error ' + count)\n        }\n        return 'Success ' + count\n      })\n\n      function Page() {\n        const [_, forceUpdate] = React.useState(0)\n\n        React.useEffect(() => {\n          forceUpdate(1)\n        }, [])\n\n        const { data, refetch } = useQuery({\n          queryKey: key,\n          queryFn,\n          retry: false,\n          staleTime: Infinity,\n          throwOnError: true,\n        })\n\n        return (\n          <div>\n            <div>Data: {data}</div>\n            <button onClick={() => refetch()}>Refetch</button>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <React.StrictMode>\n          <QueryErrorResetBoundary>\n            {({ reset }) => (\n              <ErrorBoundary\n                onReset={reset}\n                fallbackRender={({ resetErrorBoundary }) => (\n                  <div>\n                    <div>Status: error</div>\n                    <button onClick={resetErrorBoundary}>Retry</button>\n                  </div>\n                )}\n              >\n                <Page />\n              </ErrorBoundary>\n            )}\n          </QueryErrorResetBoundary>\n        </React.StrictMode>,\n      )\n\n      // 1. First mount -> fetching -> Success\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('Data: Success 1')).toBeInTheDocument()\n      expect(queryFn).toHaveBeenCalledTimes(1)\n\n      // 2. Click Refetch -> Triggers fetch -> Fails (Error 2) -> ErrorBoundary\n      fireEvent.click(rendered.getByText('Refetch'))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('Status: error')).toBeInTheDocument()\n      expect(queryFn).toHaveBeenCalledTimes(2)\n\n      // 3. Click Retry -> Remounts\n      // Because staleTime is Infinity and we have Data from (1),\n      // AND we are in Error state.\n      fireEvent.click(rendered.getByText('Retry'))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('Data: Success 3')).toBeInTheDocument()\n      expect(queryFn).toHaveBeenCalledTimes(3)\n    })\n  })\n\n  describe('useQueries', () => {\n    it('should retry fetch if the reset error boundary has been reset', async () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n      const key = queryKey()\n\n      let succeed = false\n\n      function Page() {\n        const [{ data }] = useQueries({\n          queries: [\n            {\n              queryKey: key,\n              queryFn: () =>\n                sleep(10).then(() => {\n                  if (!succeed) throw new Error('Error')\n                  return 'data'\n                }),\n              retry: false,\n              throwOnError: true,\n              retryOnMount: true,\n            },\n          ],\n        })\n\n        return <div>{data}</div>\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          {({ reset }) => (\n            <ErrorBoundary\n              onReset={reset}\n              fallbackRender={({ resetErrorBoundary }) => (\n                <div>\n                  <div>error boundary</div>\n                  <button\n                    onClick={() => {\n                      resetErrorBoundary()\n                    }}\n                  >\n                    retry\n                  </button>\n                </div>\n              )}\n            >\n              <Page />\n            </ErrorBoundary>\n          )}\n        </QueryErrorResetBoundary>,\n      )\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      succeed = true\n\n      fireEvent.click(rendered.getByText('retry'))\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.getByText('data')).toBeInTheDocument()\n\n      consoleMock.mockRestore()\n    })\n\n    it('with suspense should retry fetch if the reset error boundary has been reset', async () => {\n      const key = queryKey()\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n\n      let succeed = false\n\n      function Page() {\n        const [{ data }] = useSuspenseQueries({\n          queries: [\n            {\n              queryKey: key,\n              queryFn: () =>\n                sleep(10).then(() => {\n                  if (!succeed) throw new Error('Error')\n                  return 'data'\n                }),\n              retry: false,\n              retryOnMount: true,\n            },\n          ],\n        })\n\n        return <div>{data}</div>\n      }\n\n      const rendered = renderWithClient(\n        queryClient,\n        <QueryErrorResetBoundary>\n          {({ reset }) => (\n            <ErrorBoundary\n              onReset={reset}\n              fallbackRender={({ resetErrorBoundary }) => (\n                <div>\n                  <div>error boundary</div>\n                  <button\n                    onClick={() => {\n                      resetErrorBoundary()\n                    }}\n                  >\n                    retry\n                  </button>\n                </div>\n              )}\n            >\n              <React.Suspense fallback=\"loading\">\n                <Page />\n              </React.Suspense>\n            </ErrorBoundary>\n          )}\n        </QueryErrorResetBoundary>,\n      )\n\n      expect(rendered.getByText('loading')).toBeInTheDocument()\n      await act(() => vi.advanceTimersByTimeAsync(10))\n      expect(rendered.getByText('error boundary')).toBeInTheDocument()\n      expect(rendered.getByText('retry')).toBeInTheDocument()\n\n      succeed = true\n\n      fireEvent.click(rendered.getByText('retry'))\n      expect(rendered.getByText('loading')).toBeInTheDocument()\n      await act(() => vi.advanceTimersByTimeAsync(10))\n      expect(rendered.getByText('data')).toBeInTheDocument()\n\n      consoleMock.mockRestore()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/fine-grained-persister.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport * as React from 'react'\nimport {\n  PERSISTER_KEY_PREFIX,\n  experimental_createQueryPersister,\n} from '@tanstack/query-persist-client-core'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { QueryCache, QueryClient, hashKey, useQuery } from '..'\nimport { renderWithClient } from './utils'\n\ndescribe('fine grained persister', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  const queryCache = new QueryCache()\n  const queryClient = new QueryClient({ queryCache })\n\n  it('should restore query state from persister and not refetch', async () => {\n    const key = queryKey()\n    const hash = hashKey(key)\n    const spy = vi.fn(() => Promise.resolve('Works from queryFn'))\n\n    const mapStorage = new Map()\n    const storage = {\n      getItem: (itemKey: string) => Promise.resolve(mapStorage.get(itemKey)),\n      setItem: (itemKey: string, value: unknown) => {\n        mapStorage.set(itemKey, value)\n        return Promise.resolve()\n      },\n      removeItem: (itemKey: string) => {\n        mapStorage.delete(itemKey)\n        return Promise.resolve()\n      },\n    }\n\n    await storage.setItem(\n      `${PERSISTER_KEY_PREFIX}-${hash}`,\n      JSON.stringify({\n        buster: '',\n        queryHash: hash,\n        queryKey: key,\n        state: {\n          dataUpdatedAt: Date.now(),\n          data: 'Works from persister',\n        },\n      }),\n    )\n\n    function Test() {\n      const [_, setRef] = React.useState<HTMLDivElement | null>()\n\n      const { data } = useQuery({\n        queryKey: key,\n        queryFn: spy,\n        persister: experimental_createQueryPersister({\n          storage,\n        }).persisterFn,\n        staleTime: 5000,\n      })\n\n      return <div ref={(value) => setRef(value)}>{data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Test />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Works from persister')).toBeInTheDocument()\n    expect(spy).not.toHaveBeenCalled()\n  })\n\n  it('should restore query state from persister and refetch', async () => {\n    const key = queryKey()\n    const hash = hashKey(key)\n    const spy = vi.fn(async () => {\n      await sleep(5)\n\n      return 'Works from queryFn'\n    })\n\n    const mapStorage = new Map()\n    const storage = {\n      getItem: (itemKey: string) => Promise.resolve(mapStorage.get(itemKey)),\n      setItem: (itemKey: string, value: unknown) => {\n        mapStorage.set(itemKey, value)\n        return Promise.resolve()\n      },\n      removeItem: (itemKey: string) => {\n        mapStorage.delete(itemKey)\n        return Promise.resolve()\n      },\n    }\n\n    await storage.setItem(\n      `${PERSISTER_KEY_PREFIX}-${hash}`,\n      JSON.stringify({\n        buster: '',\n        queryHash: hash,\n        queryKey: key,\n        state: {\n          dataUpdatedAt: Date.now(),\n          data: 'Works from persister',\n        },\n      }),\n    )\n\n    function Test() {\n      const [_, setRef] = React.useState<HTMLDivElement | null>()\n\n      const { data } = useQuery({\n        queryKey: key,\n        queryFn: spy,\n        persister: experimental_createQueryPersister({\n          storage,\n        }).persisterFn,\n      })\n\n      return <div ref={(value) => setRef(value)}>{data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Test />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Works from persister')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(6)\n    expect(rendered.getByText('Works from queryFn')).toBeInTheDocument()\n    expect(spy).toHaveBeenCalledTimes(1)\n  })\n\n  it('should store query state to persister after fetch', async () => {\n    const key = queryKey()\n    const hash = hashKey(key)\n    const spy = vi.fn(() => Promise.resolve('Works from queryFn'))\n\n    const mapStorage = new Map()\n    const storage = {\n      getItem: (itemKey: string) => Promise.resolve(mapStorage.get(itemKey)),\n      setItem: (itemKey: string, value: unknown) => {\n        mapStorage.set(itemKey, value)\n        return Promise.resolve()\n      },\n      removeItem: (itemKey: string) => {\n        mapStorage.delete(itemKey)\n        return Promise.resolve()\n      },\n    }\n\n    function Test() {\n      const [_, setRef] = React.useState<HTMLDivElement | null>()\n\n      const { data } = useQuery({\n        queryKey: key,\n        queryFn: spy,\n        persister: experimental_createQueryPersister({\n          storage,\n        }).persisterFn,\n      })\n\n      return <div ref={(value) => setRef(value)}>{data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Test />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Works from queryFn')).toBeInTheDocument()\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    const storedItem = await storage.getItem(`${PERSISTER_KEY_PREFIX}-${hash}`)\n    expect(JSON.parse(storedItem)).toMatchObject({\n      state: {\n        data: 'Works from queryFn',\n      },\n    })\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx",
    "content": "import { assertType, describe, expectTypeOf, it, test } from 'vitest'\nimport { QueryClient, dataTagSymbol, skipToken } from '@tanstack/query-core'\nimport { infiniteQueryOptions } from '../infiniteQueryOptions'\nimport { useInfiniteQuery } from '../useInfiniteQuery'\nimport { useSuspenseInfiniteQuery } from '../useSuspenseInfiniteQuery'\nimport { useQuery } from '../useQuery'\nimport type {\n  DataTag,\n  InfiniteData,\n  InitialDataFunction,\n} from '@tanstack/query-core'\n\ndescribe('infiniteQueryOptions', () => {\n  it('should not allow excess properties', () => {\n    assertType(\n      infiniteQueryOptions({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve('data'),\n        getNextPageParam: () => 1,\n        initialPageParam: 1,\n        // @ts-expect-error this is a good error, because stallTime does not exist!\n        stallTime: 1000,\n      }),\n    )\n  })\n  it('should infer types for callbacks', () => {\n    infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('data'),\n      staleTime: 1000,\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n      select: (data) => {\n        expectTypeOf(data).toEqualTypeOf<InfiniteData<string, number>>()\n      },\n    })\n  })\n  it('should work when passed to useInfiniteQuery', () => {\n    const options = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    const { data } = useInfiniteQuery(options)\n\n    // known issue: type of pageParams is unknown when returned from useInfiniteQuery\n    expectTypeOf(data).toEqualTypeOf<\n      InfiniteData<string, unknown> | undefined\n    >()\n  })\n  it('should work when passed to useSuspenseInfiniteQuery', () => {\n    const options = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    const { data } = useSuspenseInfiniteQuery(options)\n\n    expectTypeOf(data).toEqualTypeOf<InfiniteData<string, unknown>>()\n  })\n  it('should work when passed to fetchInfiniteQuery', async () => {\n    const options = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    const data = await new QueryClient().fetchInfiniteQuery(options)\n\n    expectTypeOf(data).toEqualTypeOf<InfiniteData<string, number>>()\n  })\n  it('should tag the queryKey with the result type of the QueryFn', () => {\n    const { queryKey } = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<InfiniteData<string>>()\n  })\n  it('should tag the queryKey even if no promise is returned', () => {\n    const { queryKey } = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => 'string',\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<InfiniteData<string>>()\n  })\n  it('should tag the queryKey with the result type of the QueryFn if select is used', () => {\n    const { queryKey } = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      select: (data) => data.pages,\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<InfiniteData<string>>()\n  })\n  it('should return the proper type when passed to getQueryData', () => {\n    const { queryKey } = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryData(queryKey)\n\n    expectTypeOf(data).toEqualTypeOf<\n      InfiniteData<string, unknown> | undefined\n    >()\n  })\n  it('should properly type when passed to setQueryData', () => {\n    const { queryKey } = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.setQueryData(queryKey, (prev) => {\n      expectTypeOf(prev).toEqualTypeOf<\n        InfiniteData<string, unknown> | undefined\n      >()\n      return prev\n    })\n\n    expectTypeOf(data).toEqualTypeOf<\n      InfiniteData<string, unknown> | undefined\n    >()\n  })\n  it('should throw a type error when using queryFn with skipToken in a suspense query', () => {\n    const options = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn:\n        Math.random() > 0.5 ? skipToken : () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n    // @ts-expect-error TS2345\n    const { data } = useSuspenseInfiniteQuery(options)\n    expectTypeOf(data).toEqualTypeOf<InfiniteData<string, unknown>>()\n  })\n\n  test('should not be allowed to be passed to non-infinite query functions', () => {\n    const queryClient = new QueryClient()\n    const options = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n    assertType(\n      // @ts-expect-error cannot pass infinite options to non-infinite query functions\n      useQuery(options),\n    )\n    assertType(\n      // @ts-expect-error cannot pass infinite options to non-infinite query functions\n      queryClient.ensureQueryData(options),\n    )\n    assertType(\n      // @ts-expect-error cannot pass infinite options to non-infinite query functions\n      queryClient.fetchQuery(options),\n    )\n    assertType(\n      // @ts-expect-error cannot pass infinite options to non-infinite query functions\n      queryClient.prefetchQuery(options),\n    )\n  })\n\n  test('allow optional initialData function', () => {\n    const initialData: { example: boolean } | undefined = { example: true }\n    const queryOptions = infiniteQueryOptions({\n      queryKey: ['example'],\n      queryFn: () => initialData,\n      initialData: initialData\n        ? () => ({ pages: [initialData], pageParams: [] })\n        : undefined,\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n    expectTypeOf(queryOptions.initialData).toMatchTypeOf<\n      | InitialDataFunction<InfiniteData<{ example: boolean }, number>>\n      | InfiniteData<{ example: boolean }, number>\n      | undefined\n    >()\n  })\n\n  test('allow optional initialData object', () => {\n    const initialData: { example: boolean } | undefined = { example: true }\n    const queryOptions = infiniteQueryOptions({\n      queryKey: ['example'],\n      queryFn: () => initialData,\n      initialData: initialData\n        ? { pages: [initialData], pageParams: [] }\n        : undefined,\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n    expectTypeOf(queryOptions.initialData).toMatchTypeOf<\n      | InitialDataFunction<InfiniteData<{ example: boolean }, number>>\n      | InfiniteData<{ example: boolean }, number>\n      | undefined\n    >()\n  })\n\n  it('should return a custom query key type', () => {\n    type MyQueryKey = [Array<string>, { type: 'foo' }]\n\n    const options = infiniteQueryOptions({\n      queryKey: [['key'], { type: 'foo' }] as MyQueryKey,\n      queryFn: () => Promise.resolve(1),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    expectTypeOf(options.queryKey).toEqualTypeOf<\n      DataTag<MyQueryKey, InfiniteData<number>, Error>\n    >()\n  })\n\n  it('should return a custom query key type with datatag', () => {\n    type MyQueryKey = DataTag<\n      [Array<string>, { type: 'foo' }],\n      number,\n      Error & { myMessage: string }\n    >\n\n    const options = infiniteQueryOptions({\n      queryKey: [['key'], { type: 'foo' }] as MyQueryKey,\n      queryFn: () => Promise.resolve(1),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    expectTypeOf(options.queryKey).toEqualTypeOf<\n      DataTag<MyQueryKey, InfiniteData<number>, Error & { myMessage: string }>\n    >()\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/infiniteQueryOptions.test.tsx",
    "content": "import { describe, expect, it } from 'vitest'\n\nimport { infiniteQueryOptions } from '../infiniteQueryOptions'\nimport type { UseInfiniteQueryOptions } from '../types'\n\ndescribe('infiniteQueryOptions', () => {\n  it('should return the object received as a parameter without any modification.', () => {\n    const object: UseInfiniteQueryOptions = {\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n      getNextPageParam: () => null,\n      initialPageParam: null,\n    }\n\n    expect(infiniteQueryOptions(object)).toBe(object)\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/mutationOptions.test-d.tsx",
    "content": "import { assertType, describe, expectTypeOf, it } from 'vitest'\nimport { QueryClient } from '@tanstack/query-core'\nimport { useIsMutating, useMutation, useMutationState } from '..'\nimport { mutationOptions } from '../mutationOptions'\nimport type {\n  DefaultError,\n  MutationFunctionContext,\n  MutationState,\n  WithRequired,\n} from '@tanstack/query-core'\nimport type { UseMutationOptions, UseMutationResult } from '../types'\n\ndescribe('mutationOptions', () => {\n  it('should not allow excess properties', () => {\n    // @ts-expect-error this is a good error, because onMutates does not exist!\n    mutationOptions({\n      mutationFn: () => Promise.resolve(5),\n      mutationKey: ['key'],\n      onMutates: 1000,\n      onSuccess: (data) => {\n        expectTypeOf(data).toEqualTypeOf<number>()\n      },\n    })\n  })\n\n  it('should infer types for callbacks', () => {\n    mutationOptions({\n      mutationFn: () => Promise.resolve(5),\n      mutationKey: ['key'],\n      onSuccess: (data) => {\n        expectTypeOf(data).toEqualTypeOf<number>()\n      },\n    })\n  })\n\n  it('should infer types for onError callback', () => {\n    mutationOptions({\n      mutationFn: () => {\n        throw new Error('fail')\n      },\n      mutationKey: ['key'],\n      onError: (error) => {\n        expectTypeOf(error).toEqualTypeOf<DefaultError>()\n      },\n    })\n  })\n\n  it('should infer types for variables', () => {\n    mutationOptions<number, DefaultError, { id: string }>({\n      mutationFn: (vars) => {\n        expectTypeOf(vars).toEqualTypeOf<{ id: string }>()\n        return Promise.resolve(5)\n      },\n      mutationKey: ['with-vars'],\n    })\n  })\n\n  it('should infer result type correctly', () => {\n    mutationOptions<number, DefaultError, void, { name: string }>({\n      mutationFn: () => Promise.resolve(5),\n      mutationKey: ['key'],\n      onMutate: () => {\n        return { name: 'onMutateResult' }\n      },\n      onSuccess: (_data, _variables, onMutateResult) => {\n        expectTypeOf(onMutateResult).toEqualTypeOf<{ name: string }>()\n      },\n    })\n  })\n\n  it('should infer context type correctly', () => {\n    mutationOptions<number>({\n      mutationFn: (_variables, context) => {\n        expectTypeOf(context).toEqualTypeOf<MutationFunctionContext>()\n        return Promise.resolve(5)\n      },\n      mutationKey: ['key'],\n      onMutate: (_variables, context) => {\n        expectTypeOf(context).toEqualTypeOf<MutationFunctionContext>()\n      },\n      onSuccess: (_data, _variables, _onMutateResult, context) => {\n        expectTypeOf(context).toEqualTypeOf<MutationFunctionContext>()\n      },\n      onError: (_error, _variables, _onMutateResult, context) => {\n        expectTypeOf(context).toEqualTypeOf<MutationFunctionContext>()\n      },\n      onSettled: (_data, _error, _variables, _onMutateResult, context) => {\n        expectTypeOf(context).toEqualTypeOf<MutationFunctionContext>()\n      },\n    })\n  })\n\n  it('should error if mutationFn return type mismatches TData', () => {\n    assertType(\n      mutationOptions<number>({\n        // @ts-expect-error this is a good error, because return type is string, not number\n        mutationFn: async () => Promise.resolve('wrong return'),\n      }),\n    )\n  })\n\n  it('should allow mutationKey to be omitted', () => {\n    return mutationOptions({\n      mutationFn: () => Promise.resolve(123),\n      onSuccess: (data) => {\n        expectTypeOf(data).toEqualTypeOf<number>()\n      },\n    })\n  })\n\n  it('should infer all types when not explicitly provided', () => {\n    expectTypeOf(\n      mutationOptions({\n        mutationFn: (id: string) => Promise.resolve(id.length),\n        mutationKey: ['key'],\n        onSuccess: (data) => {\n          expectTypeOf(data).toEqualTypeOf<number>()\n        },\n      }),\n    ).toEqualTypeOf<\n      WithRequired<\n        UseMutationOptions<number, DefaultError, string>,\n        'mutationKey'\n      >\n    >()\n    expectTypeOf(\n      mutationOptions({\n        mutationFn: (id: string) => Promise.resolve(id.length),\n        onSuccess: (data) => {\n          expectTypeOf(data).toEqualTypeOf<number>()\n        },\n      }),\n    ).toEqualTypeOf<\n      Omit<UseMutationOptions<number, DefaultError, string>, 'mutationKey'>\n    >()\n  })\n\n  it('should infer types when used with useMutation', () => {\n    const mutation = useMutation(\n      mutationOptions({\n        mutationKey: ['key'],\n        mutationFn: () => Promise.resolve('data'),\n        onSuccess: (data) => {\n          expectTypeOf(data).toEqualTypeOf<string>()\n        },\n      }),\n    )\n    expectTypeOf(mutation).toEqualTypeOf<\n      UseMutationResult<string, DefaultError, void, unknown>\n    >()\n\n    useMutation(\n      // should allow when used with useMutation without mutationKey\n      mutationOptions({\n        mutationFn: () => Promise.resolve('data'),\n        onSuccess: (data) => {\n          expectTypeOf(data).toEqualTypeOf<string>()\n        },\n      }),\n    )\n  })\n\n  it('should infer types when used with useIsMutating', () => {\n    const isMutating = useIsMutating(\n      mutationOptions({\n        mutationKey: ['key'],\n        mutationFn: () => Promise.resolve(5),\n      }),\n    )\n    expectTypeOf(isMutating).toEqualTypeOf<number>()\n\n    useIsMutating(\n      // @ts-expect-error filters should have mutationKey\n      mutationOptions({\n        mutationFn: () => Promise.resolve(5),\n      }),\n    )\n  })\n\n  it('should infer types when used with queryClient.isMutating', () => {\n    const queryClient = new QueryClient()\n\n    const isMutating = queryClient.isMutating(\n      mutationOptions({\n        mutationKey: ['key'],\n        mutationFn: () => Promise.resolve(5),\n      }),\n    )\n    expectTypeOf(isMutating).toEqualTypeOf<number>()\n\n    queryClient.isMutating(\n      // @ts-expect-error filters should have mutationKey\n      mutationOptions({\n        mutationFn: () => Promise.resolve(5),\n      }),\n    )\n  })\n\n  it('should infer types when used with useMutationState', () => {\n    const mutationState = useMutationState({\n      filters: mutationOptions({\n        mutationKey: ['key'],\n        mutationFn: () => Promise.resolve(5),\n      }),\n    })\n    expectTypeOf(mutationState).toEqualTypeOf<\n      Array<MutationState<unknown, Error, unknown, unknown>>\n    >()\n\n    useMutationState({\n      // @ts-expect-error filters should have mutationKey\n      filters: mutationOptions({\n        mutationFn: () => Promise.resolve(5),\n      }),\n    })\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/mutationOptions.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { QueryClient } from '@tanstack/query-core'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { fireEvent } from '@testing-library/react'\nimport { mutationOptions } from '../mutationOptions'\nimport { useIsMutating, useMutation, useMutationState } from '..'\nimport { renderWithClient } from './utils'\nimport type { MutationState } from '@tanstack/query-core'\nimport type { UseMutationOptions } from '../types'\n\ndescribe('mutationOptions', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should return the object received as a parameter without any modification (with mutationKey in mutationOptions)', () => {\n    const object: UseMutationOptions = {\n      mutationKey: ['key'],\n      mutationFn: () => sleep(10).then(() => 5),\n    } as const\n\n    expect(mutationOptions(object)).toBe(object)\n  })\n\n  it('should return the object received as a parameter without any modification (without mutationKey in mutationOptions)', () => {\n    const object: UseMutationOptions = {\n      mutationFn: () => sleep(10).then(() => 5),\n    } as const\n\n    expect(mutationOptions(object)).toBe(object)\n  })\n\n  it('should return the number of fetching mutations when used with useIsMutating (with mutationKey in mutationOptions)', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n    const mutationOpts = mutationOptions({\n      mutationKey: ['key'],\n      mutationFn: () => sleep(50).then(() => 'data'),\n    })\n\n    function IsMutating() {\n      const isMutating = useIsMutating()\n\n      isMutatingArray.push(isMutating)\n\n      return null\n    }\n\n    function Mutation() {\n      const { mutate } = useMutation(mutationOpts)\n\n      return (\n        <div>\n          <button onClick={() => mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    function Page() {\n      return (\n        <div>\n          <IsMutating />\n          <Mutation />\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    expect(isMutatingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isMutatingArray[1]).toEqual(1)\n    await vi.advanceTimersByTimeAsync(51)\n    expect(isMutatingArray[2]).toEqual(0)\n    expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0)\n  })\n\n  it('should return the number of fetching mutations when used with useIsMutating (without mutationKey in mutationOptions)', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n    const mutationOpts = mutationOptions({\n      mutationFn: () => sleep(50).then(() => 'data'),\n    })\n\n    function IsMutating() {\n      const isMutating = useIsMutating()\n\n      isMutatingArray.push(isMutating)\n\n      return null\n    }\n\n    function Mutation() {\n      const { mutate } = useMutation(mutationOpts)\n\n      return (\n        <div>\n          <button onClick={() => mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    function Page() {\n      return (\n        <div>\n          <IsMutating />\n          <Mutation />\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    expect(isMutatingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isMutatingArray[1]).toEqual(1)\n    await vi.advanceTimersByTimeAsync(51)\n    expect(isMutatingArray[2]).toEqual(0)\n    expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0)\n  })\n\n  it('should return the number of fetching mutations when used with useIsMutating', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['key'],\n      mutationFn: () => sleep(50).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(50).then(() => 'data2'),\n    })\n\n    function IsMutating() {\n      const isMutating = useIsMutating()\n\n      isMutatingArray.push(isMutating)\n\n      return null\n    }\n\n    function Mutation() {\n      const { mutate: mutate1 } = useMutation(mutationOpts1)\n      const { mutate: mutate2 } = useMutation(mutationOpts2)\n\n      return (\n        <div>\n          <button onClick={() => mutate1()}>mutate1</button>\n          <button onClick={() => mutate2()}>mutate2</button>\n        </div>\n      )\n    }\n\n    function Page() {\n      return (\n        <div>\n          <IsMutating />\n          <Mutation />\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n    expect(isMutatingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isMutatingArray[1]).toEqual(2)\n    await vi.advanceTimersByTimeAsync(51)\n    expect(isMutatingArray[2]).toEqual(0)\n    expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0)\n  })\n\n  it('should return the number of fetching mutations when used with useIsMutating (filter mutationOpts1.mutationKey)', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['key'],\n      mutationFn: () => sleep(50).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(50).then(() => 'data2'),\n    })\n\n    function IsMutating() {\n      const isMutating = useIsMutating({\n        mutationKey: mutationOpts1.mutationKey,\n      })\n\n      isMutatingArray.push(isMutating)\n\n      return null\n    }\n\n    function Mutation() {\n      const { mutate: mutate1 } = useMutation(mutationOpts1)\n      const { mutate: mutate2 } = useMutation(mutationOpts2)\n\n      return (\n        <div>\n          <button onClick={() => mutate1()}>mutate1</button>\n          <button onClick={() => mutate2()}>mutate2</button>\n        </div>\n      )\n    }\n\n    function Page() {\n      return (\n        <div>\n          <IsMutating />\n          <Mutation />\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n    expect(isMutatingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isMutatingArray[1]).toEqual(1)\n    await vi.advanceTimersByTimeAsync(51)\n    expect(isMutatingArray[2]).toEqual(0)\n    expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0)\n  })\n\n  it('should return the number of fetching mutations when used with queryClient.isMutating (with mutationKey in mutationOptions)', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n    const mutationOpts = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(500).then(() => 'data'),\n    })\n\n    function Mutation() {\n      const isMutating = queryClient.isMutating(mutationOpts)\n      const { mutate } = useMutation(mutationOpts)\n\n      isMutatingArray.push(isMutating)\n\n      return (\n        <div>\n          <button onClick={() => mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Mutation />)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    expect(isMutatingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isMutatingArray[1]).toEqual(1)\n    await vi.advanceTimersByTimeAsync(501)\n    expect(isMutatingArray[2]).toEqual(0)\n    expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0)\n  })\n\n  it('should return the number of fetching mutations when used with queryClient.isMutating (without mutationKey in mutationOptions)', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n    const mutationOpts = mutationOptions({\n      mutationFn: () => sleep(500).then(() => 'data'),\n    })\n\n    function Mutation() {\n      const isMutating = queryClient.isMutating()\n      const { mutate } = useMutation(mutationOpts)\n\n      isMutatingArray.push(isMutating)\n\n      return (\n        <div>\n          <button onClick={() => mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Mutation />)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    expect(isMutatingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isMutatingArray[1]).toEqual(1)\n    await vi.advanceTimersByTimeAsync(501)\n    expect(isMutatingArray[2]).toEqual(0)\n    expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0)\n  })\n\n  it('should return the number of fetching mutations when used with queryClient.isMutating', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(500).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(500).then(() => 'data2'),\n    })\n\n    function Mutation() {\n      const isMutating = queryClient.isMutating()\n      const { mutate: mutate1 } = useMutation(mutationOpts1)\n      const { mutate: mutate2 } = useMutation(mutationOpts2)\n\n      isMutatingArray.push(isMutating)\n\n      return (\n        <div>\n          <button onClick={() => mutate1()}>mutate1</button>\n          <button onClick={() => mutate2()}>mutate2</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Mutation />)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n    expect(isMutatingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isMutatingArray[1]).toEqual(2)\n    await vi.advanceTimersByTimeAsync(501)\n    expect(isMutatingArray[2]).toEqual(0)\n    expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0)\n  })\n\n  it('should return the number of fetching mutations when used with queryClient.isMutating (filter mutationOpt1.mutationKey)', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(500).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(500).then(() => 'data2'),\n    })\n\n    function Mutation() {\n      const isMutating = queryClient.isMutating({\n        mutationKey: mutationOpts1.mutationKey,\n      })\n      const { mutate: mutate1 } = useMutation(mutationOpts1)\n      const { mutate: mutate2 } = useMutation(mutationOpts2)\n\n      isMutatingArray.push(isMutating)\n\n      return (\n        <div>\n          <button onClick={() => mutate1()}>mutate1</button>\n          <button onClick={() => mutate2()}>mutate2</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Mutation />)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n    expect(isMutatingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isMutatingArray[1]).toEqual(1)\n    await vi.advanceTimersByTimeAsync(501)\n    expect(isMutatingArray[2]).toEqual(0)\n    expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0)\n  })\n\n  it('should return the number of fetching mutations when used with useMutationState (with mutationKey in mutationOptions)', async () => {\n    const mutationStateArray: Array<\n      MutationState<unknown, Error, unknown, unknown>\n    > = []\n    const queryClient = new QueryClient()\n    const mutationOpts = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(10).then(() => 'data'),\n    })\n\n    function Mutation() {\n      const { mutate } = useMutation(mutationOpts)\n      const data = useMutationState({\n        filters: { mutationKey: mutationOpts.mutationKey, status: 'success' },\n      })\n\n      mutationStateArray.push(...data)\n\n      return (\n        <div>\n          <button onClick={() => mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Mutation />)\n\n    expect(mutationStateArray.length).toEqual(0)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(mutationStateArray.length).toEqual(1)\n    expect(mutationStateArray[0]?.data).toEqual('data')\n  })\n\n  it('should return the number of fetching mutations when used with useMutationState (without mutationKey in mutationOptions)', async () => {\n    const mutationStateArray: Array<\n      MutationState<unknown, Error, unknown, unknown>\n    > = []\n    const queryClient = new QueryClient()\n    const mutationOpts = mutationOptions({\n      mutationFn: () => sleep(10).then(() => 'data'),\n    })\n\n    function Mutation() {\n      const { mutate } = useMutation(mutationOpts)\n      const data = useMutationState({\n        filters: { status: 'success' },\n      })\n\n      mutationStateArray.push(...data)\n\n      return (\n        <div>\n          <button onClick={() => mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Mutation />)\n\n    expect(mutationStateArray.length).toEqual(0)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(mutationStateArray.length).toEqual(1)\n    expect(mutationStateArray[0]?.data).toEqual('data')\n  })\n\n  it('should return the number of fetching mutations when used with useMutationState', async () => {\n    const mutationStateArray: Array<\n      MutationState<unknown, Error, unknown, unknown>\n    > = []\n    const queryClient = new QueryClient()\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(10).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(10).then(() => 'data2'),\n    })\n\n    function Mutation() {\n      const { mutate: mutate1 } = useMutation(mutationOpts1)\n      const { mutate: mutate2 } = useMutation(mutationOpts2)\n      const data = useMutationState({\n        filters: { status: 'success' },\n      })\n\n      mutationStateArray.push(...data)\n\n      return (\n        <div>\n          <button onClick={() => mutate1()}>mutate1</button>\n          <button onClick={() => mutate2()}>mutate2</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Mutation />)\n\n    expect(mutationStateArray.length).toEqual(0)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(mutationStateArray.length).toEqual(2)\n    expect(mutationStateArray[0]?.data).toEqual('data1')\n    expect(mutationStateArray[1]?.data).toEqual('data2')\n  })\n\n  it('should return the number of fetching mutations when used with useMutationState (filter mutationOpt1.mutationKey)', async () => {\n    const mutationStateArray: Array<\n      MutationState<unknown, Error, unknown, unknown>\n    > = []\n    const queryClient = new QueryClient()\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(10).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(10).then(() => 'data2'),\n    })\n\n    function Mutation() {\n      const { mutate: mutate1 } = useMutation(mutationOpts1)\n      const { mutate: mutate2 } = useMutation(mutationOpts2)\n      const data = useMutationState({\n        filters: { mutationKey: mutationOpts1.mutationKey, status: 'success' },\n      })\n\n      mutationStateArray.push(...data)\n\n      return (\n        <div>\n          <button onClick={() => mutate1()}>mutate1</button>\n          <button onClick={() => mutate2()}>mutate2</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Mutation />)\n\n    expect(mutationStateArray.length).toEqual(0)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(mutationStateArray.length).toEqual(1)\n    expect(mutationStateArray[0]?.data).toEqual('data1')\n    expect(mutationStateArray[1]).toBeFalsy()\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/queryOptions.test-d.tsx",
    "content": "import { assertType, describe, expectTypeOf, it } from 'vitest'\nimport {\n  QueriesObserver,\n  QueryClient,\n  dataTagSymbol,\n  skipToken,\n} from '@tanstack/query-core'\nimport { queryOptions } from '../queryOptions'\nimport { useQuery } from '../useQuery'\nimport { useQueries } from '../useQueries'\nimport { useSuspenseQuery } from '../useSuspenseQuery'\nimport type { AnyUseQueryOptions } from '../types'\nimport type {\n  DataTag,\n  InitialDataFunction,\n  QueryObserverResult,\n} from '@tanstack/query-core'\n\ndescribe('queryOptions', () => {\n  it('should not allow excess properties', () => {\n    assertType(\n      queryOptions({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        // @ts-expect-error this is a good error, because stallTime does not exist!\n        stallTime: 1000,\n      }),\n    )\n  })\n  it('should infer types for callbacks', () => {\n    queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n      staleTime: 1000,\n      select: (data) => {\n        expectTypeOf(data).toEqualTypeOf<number>()\n      },\n    })\n  })\n  it('should work when passed to useQuery', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const { data } = useQuery(options)\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n  it('should work when passed to useSuspenseQuery', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const { data } = useSuspenseQuery(options)\n    expectTypeOf(data).toEqualTypeOf<number>()\n  })\n\n  it('should work when passed to fetchQuery', async () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const data = await new QueryClient().fetchQuery(options)\n    expectTypeOf(data).toEqualTypeOf<number>()\n  })\n  it('should work when passed to useQueries', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const [{ data }] = useQueries({\n      queries: [options],\n    })\n\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n  it('should tag the queryKey with the result type of the QueryFn', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<number>()\n  })\n  it('should tag the queryKey even if no promise is returned', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => 5,\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<number>()\n  })\n  it('should tag the queryKey with unknown if there is no queryFn', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<unknown>()\n  })\n  it('should tag the queryKey with the result type of the QueryFn if select is used', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n      select: (data) => data.toString(),\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<number>()\n  })\n  it('should return the proper type when passed to getQueryData', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryData(queryKey)\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n  it('should return the proper type when passed to getQueryState', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n    const state = queryClient.getQueryState(queryKey)\n    expectTypeOf(state?.data).toEqualTypeOf<number | undefined>()\n  })\n  it('should properly type updaterFn when passed to setQueryData', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.setQueryData(queryKey, (prev) => {\n      expectTypeOf(prev).toEqualTypeOf<number | undefined>()\n      return prev\n    })\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n  it('should properly type value when passed to setQueryData', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n\n    // @ts-expect-error value should be a number\n    queryClient.setQueryData(queryKey, '5')\n    // @ts-expect-error value should be a number\n    queryClient.setQueryData(queryKey, () => '5')\n\n    const data = queryClient.setQueryData(queryKey, 5)\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n\n  it('should infer even if there is a conditional skipToken', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryData(options.queryKey)\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n\n  it('should infer to unknown if we disable a query with just a skipToken', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: skipToken,\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryData(options.queryKey)\n    expectTypeOf(data).toEqualTypeOf<unknown>()\n  })\n\n  it('should throw a type error when using queryFn with skipToken in a suspense query', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),\n    })\n    // @ts-expect-error TS2345\n    const { data } = useSuspenseQuery(options)\n    expectTypeOf(data).toEqualTypeOf<number>()\n  })\n\n  it('should return the proper type when passed to QueriesObserver', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n    const queriesObserver = new QueriesObserver(queryClient, [options])\n    expectTypeOf(queriesObserver).toEqualTypeOf<\n      QueriesObserver<Array<QueryObserverResult>>\n    >()\n  })\n\n  it('should allow undefined response in initialData', () => {\n    assertType((id: string | null) =>\n      queryOptions({\n        queryKey: ['todo', id],\n        queryFn: () =>\n          Promise.resolve({\n            id: '1',\n            title: 'Do Laundry',\n          }),\n        initialData: () =>\n          !id\n            ? undefined\n            : {\n                id,\n                title: 'Initial Data',\n              },\n      }),\n    )\n  })\n\n  it('should allow optional initialData object', () => {\n    const testFn = (id?: string) => {\n      const options = queryOptions({\n        queryKey: ['test'],\n        queryFn: () => Promise.resolve('something string'),\n        initialData: id ? 'initial string' : undefined,\n      })\n      expectTypeOf(options.initialData).toMatchTypeOf<\n        InitialDataFunction<string> | string | undefined\n      >()\n    }\n    testFn('id')\n    testFn()\n  })\n\n  it('should be passable to UseQueryOptions', () => {\n    function somethingWithQueryOptions<TQueryOpts extends AnyUseQueryOptions>(\n      options: TQueryOpts,\n    ) {\n      return options.queryKey\n    }\n\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(1),\n    })\n\n    assertType(somethingWithQueryOptions(options))\n  })\n\n  it('should return a custom query key type', () => {\n    type MyQueryKey = [Array<string>, { type: 'foo' }]\n\n    const options = queryOptions({\n      queryKey: [['key'], { type: 'foo' }] as MyQueryKey,\n      queryFn: () => Promise.resolve(1),\n    })\n\n    expectTypeOf(options.queryKey).toEqualTypeOf<\n      DataTag<MyQueryKey, number, Error>\n    >()\n  })\n\n  it('should return a custom query key type with datatag', () => {\n    type MyQueryKey = DataTag<\n      [Array<string>, { type: 'foo' }],\n      number,\n      Error & { myMessage: string }\n    >\n\n    const options = queryOptions({\n      queryKey: [['key'], { type: 'foo' }] as MyQueryKey,\n      queryFn: () => Promise.resolve(1),\n    })\n\n    expectTypeOf(options.queryKey).toEqualTypeOf<\n      DataTag<MyQueryKey, number, Error & { myMessage: string }>\n    >()\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/queryOptions.test.tsx",
    "content": "import { describe, expect, it } from 'vitest'\nimport { queryOptions } from '../queryOptions'\nimport type { UseQueryOptions } from '../types'\n\ndescribe('queryOptions', () => {\n  it('should return the object received as a parameter without any modification.', () => {\n    const object: UseQueryOptions = {\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    } as const\n\n    expect(queryOptions(object)).toBe(object)\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/ssr-hydration.test.tsx",
    "content": "import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'\nimport { hydrateRoot } from 'react-dom/client'\nimport { act } from 'react'\nimport * as ReactDOMServer from 'react-dom/server'\nimport {\n  QueryCache,\n  QueryClient,\n  QueryClientProvider,\n  dehydrate,\n  hydrate,\n  useQuery,\n} from '..'\nimport { setIsServer } from './utils'\n\nconst ReactHydrate = (element: React.ReactElement, container: Element) => {\n  let root: any\n  act(() => {\n    root = hydrateRoot(container, element)\n  })\n  return () => {\n    root.unmount()\n  }\n}\n\nasync function fetchData<TData>(value: TData, ms?: number): Promise<TData> {\n  await vi.advanceTimersByTimeAsync(ms || 1)\n  return value\n}\n\nfunction PrintStateComponent({ componentName, result }: any): any {\n  return `${componentName} - status:${result.status} fetching:${result.isFetching} data:${result.data}`\n}\n\ndescribe('Server side rendering with de/rehydration', () => {\n  let previousIsReactActEnvironment: unknown\n  beforeAll(() => {\n    // @ts-expect-error we expect IS_REACT_ACT_ENVIRONMENT to exist\n    previousIsReactActEnvironment = globalThis.IS_REACT_ACT_ENVIRONMENT = true\n    vi.useFakeTimers()\n  })\n\n  afterAll(() => {\n    // @ts-expect-error we expect IS_REACT_ACT_ENVIRONMENT to exist\n    globalThis.IS_REACT_ACT_ENVIRONMENT = previousIsReactActEnvironment\n    vi.useRealTimers()\n  })\n\n  it('should not mismatch on success', async () => {\n    const consoleMock = vi.spyOn(console, 'error')\n    consoleMock.mockImplementation(() => undefined)\n\n    const fetchDataSuccess = vi.fn<typeof fetchData>(fetchData)\n\n    // -- Shared part --\n    function SuccessComponent() {\n      const result = useQuery({\n        queryKey: ['success'],\n        queryFn: () => fetchDataSuccess('success!'),\n      })\n      return (\n        <PrintStateComponent componentName=\"SuccessComponent\" result={result} />\n      )\n    }\n\n    // -- Server part --\n    setIsServer(true)\n\n    const prefetchCache = new QueryCache()\n    const prefetchClient = new QueryClient({\n      queryCache: prefetchCache,\n    })\n    await prefetchClient.prefetchQuery({\n      queryKey: ['success'],\n      queryFn: () => fetchDataSuccess('success'),\n    })\n    const dehydratedStateServer = dehydrate(prefetchClient)\n    const renderCache = new QueryCache()\n    const renderClient = new QueryClient({\n      queryCache: renderCache,\n    })\n    hydrate(renderClient, dehydratedStateServer)\n    const markup = ReactDOMServer.renderToString(\n      <QueryClientProvider client={renderClient}>\n        <SuccessComponent />\n      </QueryClientProvider>,\n    )\n    const stringifiedState = JSON.stringify(dehydratedStateServer)\n    renderClient.clear()\n    setIsServer(false)\n\n    const expectedMarkup =\n      'SuccessComponent - status:success fetching:true data:success'\n\n    expect(markup).toBe(expectedMarkup)\n    expect(fetchDataSuccess).toHaveBeenCalledTimes(1)\n\n    // -- Client part --\n    const el = document.createElement('div')\n    el.innerHTML = markup\n\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({ queryCache })\n    hydrate(queryClient, JSON.parse(stringifiedState))\n\n    const unmount = ReactHydrate(\n      <QueryClientProvider client={queryClient}>\n        <SuccessComponent />\n      </QueryClientProvider>,\n      el,\n    )\n\n    // Check that we have no React hydration mismatches\n    expect(consoleMock).toHaveBeenCalledTimes(0)\n\n    expect(fetchDataSuccess).toHaveBeenCalledTimes(2)\n    expect(el.innerHTML).toBe(expectedMarkup)\n\n    unmount()\n    queryClient.clear()\n    consoleMock.mockRestore()\n  })\n\n  it('should not mismatch on error', async () => {\n    const consoleMock = vi.spyOn(console, 'error')\n    consoleMock.mockImplementation(() => undefined)\n\n    const fetchDataError = vi.fn(() => {\n      throw new Error('fetchDataError')\n    })\n\n    // -- Shared part --\n    function ErrorComponent() {\n      const result = useQuery({\n        queryKey: ['error'],\n        queryFn: () => fetchDataError(),\n        retry: false,\n      })\n      return (\n        <PrintStateComponent componentName=\"ErrorComponent\" result={result} />\n      )\n    }\n\n    // -- Server part --\n    setIsServer(true)\n    const prefetchCache = new QueryCache()\n    const prefetchClient = new QueryClient({\n      queryCache: prefetchCache,\n    })\n    await prefetchClient.prefetchQuery({\n      queryKey: ['error'],\n      queryFn: () => fetchDataError(),\n    })\n    const dehydratedStateServer = dehydrate(prefetchClient)\n    const renderCache = new QueryCache()\n    const renderClient = new QueryClient({\n      queryCache: renderCache,\n    })\n    hydrate(renderClient, dehydratedStateServer)\n    const markup = ReactDOMServer.renderToString(\n      <QueryClientProvider client={renderClient}>\n        <ErrorComponent />\n      </QueryClientProvider>,\n    )\n    const stringifiedState = JSON.stringify(dehydratedStateServer)\n    renderClient.clear()\n    setIsServer(false)\n\n    const expectedMarkup =\n      'ErrorComponent - status:pending fetching:true data:undefined'\n\n    expect(markup).toBe(expectedMarkup)\n\n    // -- Client part --\n    const el = document.createElement('div')\n    el.innerHTML = markup\n\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({ queryCache })\n    hydrate(queryClient, JSON.parse(stringifiedState))\n\n    const unmount = ReactHydrate(\n      <QueryClientProvider client={queryClient}>\n        <ErrorComponent />\n      </QueryClientProvider>,\n      el,\n    )\n\n    expect(consoleMock).toHaveBeenCalledTimes(0)\n    expect(fetchDataError).toHaveBeenCalledTimes(2)\n    expect(el.innerHTML).toBe(expectedMarkup)\n    await vi.advanceTimersByTimeAsync(50)\n    expect(fetchDataError).toHaveBeenCalledTimes(2)\n    expect(el.innerHTML).toBe(\n      'ErrorComponent - status:error fetching:false data:undefined',\n    )\n\n    unmount()\n    queryClient.clear()\n    consoleMock.mockRestore()\n  })\n\n  it('should not mismatch on queries that were not prefetched', async () => {\n    const consoleMock = vi.spyOn(console, 'error')\n    consoleMock.mockImplementation(() => undefined)\n\n    const fetchDataSuccess = vi.fn<typeof fetchData>(fetchData)\n\n    // -- Shared part --\n    function SuccessComponent() {\n      const result = useQuery({\n        queryKey: ['success'],\n        queryFn: () => fetchDataSuccess('success!'),\n      })\n      return (\n        <PrintStateComponent componentName=\"SuccessComponent\" result={result} />\n      )\n    }\n\n    // -- Server part --\n    setIsServer(true)\n\n    const prefetchClient = new QueryClient()\n    const dehydratedStateServer = dehydrate(prefetchClient)\n    const renderClient = new QueryClient()\n    hydrate(renderClient, dehydratedStateServer)\n    const markup = ReactDOMServer.renderToString(\n      <QueryClientProvider client={renderClient}>\n        <SuccessComponent />\n      </QueryClientProvider>,\n    )\n    const stringifiedState = JSON.stringify(dehydratedStateServer)\n    renderClient.clear()\n    setIsServer(false)\n\n    const expectedMarkup =\n      'SuccessComponent - status:pending fetching:true data:undefined'\n\n    expect(markup).toBe(expectedMarkup)\n\n    // -- Client part --\n    const el = document.createElement('div')\n    el.innerHTML = markup\n\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({ queryCache })\n    hydrate(queryClient, JSON.parse(stringifiedState))\n\n    const unmount = ReactHydrate(\n      <QueryClientProvider client={queryClient}>\n        <SuccessComponent />\n      </QueryClientProvider>,\n      el,\n    )\n\n    // Check that we have no React hydration mismatches\n    expect(consoleMock).toHaveBeenCalledTimes(0)\n    expect(fetchDataSuccess).toHaveBeenCalledTimes(1)\n    expect(el.innerHTML).toBe(expectedMarkup)\n    await vi.advanceTimersByTimeAsync(50)\n    expect(fetchDataSuccess).toHaveBeenCalledTimes(1)\n    expect(el.innerHTML).toBe(\n      'SuccessComponent - status:success fetching:false data:success!',\n    )\n\n    unmount()\n    queryClient.clear()\n    consoleMock.mockRestore()\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/ssr.test.tsx",
    "content": "import * as React from 'react'\nimport { renderToString } from 'react-dom/server'\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport {\n  QueryCache,\n  QueryClient,\n  QueryClientProvider,\n  useInfiniteQuery,\n  useIsFetching,\n  useMutation,\n  useMutationState,\n  useQueries,\n  useQuery,\n} from '..'\nimport { setIsServer } from './utils'\n\ndescribe('Server Side Rendering', () => {\n  setIsServer(true)\n\n  let queryCache: QueryCache\n  let queryClient: QueryClient\n\n  beforeEach(() => {\n    vi.useFakeTimers()\n    queryCache = new QueryCache()\n    queryClient = new QueryClient({ queryCache })\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should not trigger fetch', () => {\n    const key = queryKey()\n    const queryFn = vi.fn(() => sleep(10).then(() => 'data'))\n\n    function Page() {\n      const query = useQuery({ queryKey: key, queryFn })\n\n      const content = `status ${query.status}`\n\n      return (\n        <div>\n          <div>{content}</div>\n        </div>\n      )\n    }\n\n    const markup = renderToString(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    expect(markup).toContain('status pending')\n    expect(queryFn).toHaveBeenCalledTimes(0)\n\n    queryCache.clear()\n  })\n\n  it('should add prefetched data to cache', async () => {\n    const key = queryKey()\n\n    const promise = queryClient.fetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'data'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const data = await promise\n\n    expect(data).toBe('data')\n    expect(queryCache.find({ queryKey: key })?.state.data).toBe('data')\n\n    queryCache.clear()\n  })\n\n  it('should return existing data from the cache', async () => {\n    const key = queryKey()\n    const queryFn = vi.fn(() => sleep(10).then(() => 'data'))\n\n    function Page() {\n      const query = useQuery({ queryKey: key, queryFn })\n\n      const content = `status ${query.status}`\n\n      return (\n        <div>\n          <div>{content}</div>\n        </div>\n      )\n    }\n\n    queryClient.prefetchQuery({ queryKey: key, queryFn })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const markup = renderToString(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    expect(markup).toContain('status success')\n    expect(queryFn).toHaveBeenCalledTimes(1)\n\n    queryCache.clear()\n  })\n\n  it('should add initialData to the cache', () => {\n    const key = queryKey()\n\n    function Page() {\n      const [page, setPage] = React.useState(1)\n      const { data } = useQuery({\n        queryKey: [key, page],\n        queryFn: () => sleep(10).then(() => page),\n        initialData: 1,\n      })\n\n      return (\n        <div>\n          <h1 data-testid=\"title\">{data}</h1>\n          <button onClick={() => setPage(page + 1)}>next</button>\n        </div>\n      )\n    }\n\n    renderToString(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    const keys = queryCache.getAll().map((query) => query.queryKey)\n\n    expect(keys).toEqual([[key, 1]])\n\n    queryCache.clear()\n  })\n\n  it('useInfiniteQuery should return the correct state', async () => {\n    const key = queryKey()\n    const queryFn = vi.fn(() => sleep(10).then(() => 'page 1'))\n\n    function Page() {\n      const query = useInfiniteQuery({\n        queryKey: key,\n        queryFn,\n        getNextPageParam: () => undefined,\n        initialPageParam: 0,\n      })\n      return (\n        <ul>\n          {query.data?.pages.map((page) => (\n            <li key={page}>{page}</li>\n          ))}\n        </ul>\n      )\n    }\n\n    queryClient.prefetchInfiniteQuery({\n      queryKey: key,\n      queryFn,\n      initialPageParam: 0,\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const markup = renderToString(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    expect(markup).toContain('page 1')\n    expect(queryFn).toHaveBeenCalledTimes(1)\n\n    queryCache.clear()\n  })\n\n  it('useIsFetching should return 0 after prefetch completes', async () => {\n    const key = queryKey()\n    const queryFn = () => sleep(10).then(() => 'data')\n\n    function Page() {\n      const { data } = useQuery({ queryKey: key, queryFn })\n      const isFetching = useIsFetching()\n\n      return (\n        <div>\n          <div>{data}</div>\n          <div>{`isFetching: ${isFetching}`}</div>\n        </div>\n      )\n    }\n\n    queryClient.prefetchQuery({ queryKey: key, queryFn })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const markup = renderToString(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    expect(markup).toContain('data')\n    expect(markup).toContain('isFetching: 0')\n\n    queryCache.clear()\n  })\n\n  it('useQueries should return existing data from the cache', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const queryFn1 = () => sleep(10).then(() => 'data1')\n    const queryFn2 = () => sleep(10).then(() => 'data2')\n\n    function Page() {\n      const queries = useQueries({\n        queries: [\n          { queryKey: key1, queryFn: queryFn1 },\n          { queryKey: key2, queryFn: queryFn2 },\n        ],\n      })\n\n      return (\n        <div>\n          <div>{`status1: ${queries[0].status}`}</div>\n          <div>{`status2: ${queries[1].status}`}</div>\n          <div>{`data1: ${queries[0].data}`}</div>\n          <div>{`data2: ${queries[1].data}`}</div>\n        </div>\n      )\n    }\n\n    queryClient.prefetchQuery({ queryKey: key1, queryFn: queryFn1 })\n    queryClient.prefetchQuery({ queryKey: key2, queryFn: queryFn2 })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const markup = renderToString(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    expect(markup).toContain('status1: success')\n    expect(markup).toContain('status2: success')\n    expect(markup).toContain('data1: data1')\n    expect(markup).toContain('data2: data2')\n\n    queryCache.clear()\n  })\n\n  it('useMutation should return idle status', () => {\n    function Page() {\n      const mutation = useMutation({\n        mutationFn: () => sleep(10).then(() => 'data'),\n      })\n\n      return <div>{`status: ${mutation.status}`}</div>\n    }\n\n    const markup = renderToString(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    expect(markup).toContain('status: idle')\n\n    queryCache.clear()\n  })\n\n  it('useMutationState should return empty array', () => {\n    function Page() {\n      const mutationState = useMutationState()\n\n      return <div>{`mutationState: ${mutationState.length}`}</div>\n    }\n\n    const markup = renderToString(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    expect(markup).toContain('mutationState: 0')\n\n    queryCache.clear()\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/suspense.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { act, render } from '@testing-library/react'\nimport { Suspense } from 'react'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { QueryClient, QueryClientProvider, useSuspenseQuery } from '..'\nimport type { StaleTime } from '@tanstack/query-core'\nimport type { QueryKey } from '..'\n\nfunction renderWithSuspense(client: QueryClient, ui: React.ReactNode) {\n  return render(\n    <QueryClientProvider client={client}>\n      <Suspense fallback=\"loading\">{ui}</Suspense>\n    </QueryClientProvider>,\n  )\n}\n\nfunction createTestQuery(options: {\n  fetchCount: { count: number }\n  queryKey: QueryKey\n  staleTime?: StaleTime | (() => StaleTime)\n}) {\n  return function TestComponent() {\n    const { data } = useSuspenseQuery({\n      queryKey: options.queryKey,\n      queryFn: () =>\n        sleep(10).then(() => {\n          options.fetchCount.count++\n          return 'data'\n        }),\n      staleTime: options.staleTime,\n    })\n    return <div>data: {data}</div>\n  }\n}\n\ndescribe('Suspense Timer Tests', () => {\n  let queryClient: QueryClient\n  let fetchCount: { count: number }\n\n  beforeEach(() => {\n    vi.useFakeTimers()\n    queryClient = new QueryClient({\n      defaultOptions: {\n        queries: {\n          retry: false,\n        },\n      },\n    })\n    fetchCount = { count: 0 }\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should enforce minimum staleTime of 1000ms when using suspense with number', async () => {\n    const TestComponent = createTestQuery({\n      fetchCount,\n      queryKey: ['test'],\n      staleTime: 10,\n    })\n\n    const rendered = renderWithSuspense(queryClient, <TestComponent />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data: data')).toBeInTheDocument()\n\n    rendered.rerender(\n      <QueryClientProvider client={queryClient}>\n        <Suspense fallback=\"loading\">\n          <TestComponent />\n        </Suspense>\n      </QueryClientProvider>,\n    )\n\n    await act(() => vi.advanceTimersByTimeAsync(100))\n\n    expect(fetchCount.count).toBe(1)\n  })\n\n  it('should enforce minimum staleTime of 1000ms when using suspense with function', async () => {\n    const TestComponent = createTestQuery({\n      fetchCount,\n      queryKey: ['test-func'],\n      staleTime: () => 10,\n    })\n\n    const rendered = renderWithSuspense(queryClient, <TestComponent />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data: data')).toBeInTheDocument()\n\n    rendered.rerender(\n      <QueryClientProvider client={queryClient}>\n        <Suspense fallback=\"loading\">\n          <TestComponent />\n        </Suspense>\n      </QueryClientProvider>,\n    )\n\n    await act(() => vi.advanceTimersByTimeAsync(100))\n\n    expect(fetchCount.count).toBe(1)\n  })\n\n  it('should respect staleTime when value is greater than 1000ms', async () => {\n    const TestComponent = createTestQuery({\n      fetchCount,\n      queryKey: queryKey(),\n      staleTime: 2000,\n    })\n\n    const rendered = renderWithSuspense(queryClient, <TestComponent />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data: data')).toBeInTheDocument()\n\n    rendered.rerender(\n      <QueryClientProvider client={queryClient}>\n        <Suspense fallback=\"loading\">\n          <TestComponent />\n        </Suspense>\n      </QueryClientProvider>,\n    )\n\n    await act(() => vi.advanceTimersByTimeAsync(1500))\n\n    expect(fetchCount.count).toBe(1)\n  })\n\n  it('should enforce minimum staleTime when undefined is provided', async () => {\n    const TestComponent = createTestQuery({\n      fetchCount,\n      queryKey: queryKey(),\n      staleTime: undefined,\n    })\n\n    const rendered = renderWithSuspense(queryClient, <TestComponent />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data: data')).toBeInTheDocument()\n\n    rendered.rerender(\n      <QueryClientProvider client={queryClient}>\n        <Suspense fallback=\"loading\">\n          <TestComponent />\n        </Suspense>\n      </QueryClientProvider>,\n    )\n\n    await act(() => vi.advanceTimersByTimeAsync(500))\n\n    expect(fetchCount.count).toBe(1)\n  })\n\n  it('should preserve staleTime when value is static', async () => {\n    const TestComponent = createTestQuery({\n      fetchCount,\n      queryKey: queryKey(),\n      staleTime: 'static',\n    })\n\n    const rendered = renderWithSuspense(queryClient, <TestComponent />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data: data')).toBeInTheDocument()\n\n    rendered.rerender(\n      <QueryClientProvider client={queryClient}>\n        <Suspense fallback=\"loading\">\n          <TestComponent />\n        </Suspense>\n      </QueryClientProvider>,\n    )\n\n    await act(() => vi.advanceTimersByTimeAsync(2000))\n\n    expect(fetchCount.count).toBe(1)\n  })\n\n  it('should preserve staleTime when function returns static', async () => {\n    const TestComponent = createTestQuery({\n      fetchCount,\n      queryKey: queryKey(),\n      staleTime: () => 'static',\n    })\n\n    const rendered = renderWithSuspense(queryClient, <TestComponent />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data: data')).toBeInTheDocument()\n\n    rendered.rerender(\n      <QueryClientProvider client={queryClient}>\n        <Suspense fallback=\"loading\">\n          <TestComponent />\n        </Suspense>\n      </QueryClientProvider>,\n    )\n\n    await act(() => vi.advanceTimersByTimeAsync(2000))\n\n    expect(fetchCount.count).toBe(1)\n  })\n\n  it('should respect staleTime when function returns value greater than 1000ms', async () => {\n    const TestComponent = createTestQuery({\n      fetchCount,\n      queryKey: queryKey(),\n      staleTime: () => 3000,\n    })\n\n    const rendered = renderWithSuspense(queryClient, <TestComponent />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data: data')).toBeInTheDocument()\n\n    rendered.rerender(\n      <QueryClientProvider client={queryClient}>\n        <Suspense fallback=\"loading\">\n          <TestComponent />\n        </Suspense>\n      </QueryClientProvider>,\n    )\n\n    await act(() => vi.advanceTimersByTimeAsync(2000))\n\n    expect(fetchCount.count).toBe(1)\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/useInfiniteQuery.test-d.tsx",
    "content": "import { describe, expectTypeOf, it } from 'vitest'\nimport { QueryClient } from '@tanstack/query-core'\nimport { useInfiniteQuery } from '../useInfiniteQuery'\nimport type { InfiniteData } from '@tanstack/query-core'\n\ndescribe('pageParam', () => {\n  it('initialPageParam should define type of param passed to queryFunctionContext', () => {\n    useInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: ({ pageParam }) => {\n        expectTypeOf(pageParam).toEqualTypeOf<number>()\n      },\n      initialPageParam: 1,\n      getNextPageParam: () => undefined,\n    })\n  })\n\n  it('direction should be passed to queryFn of useInfiniteQuery', () => {\n    useInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: ({ direction }) => {\n        expectTypeOf(direction).toEqualTypeOf<'forward' | 'backward'>()\n      },\n      initialPageParam: 1,\n      getNextPageParam: () => undefined,\n    })\n  })\n\n  it('initialPageParam should define type of param passed to queryFunctionContext for fetchInfiniteQuery', () => {\n    const queryClient = new QueryClient()\n    queryClient.fetchInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: ({ pageParam }) => {\n        expectTypeOf(pageParam).toEqualTypeOf<number>()\n      },\n      initialPageParam: 1,\n    })\n  })\n\n  it('initialPageParam should define type of param passed to queryFunctionContext for prefetchInfiniteQuery', () => {\n    const queryClient = new QueryClient()\n    queryClient.prefetchInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: ({ pageParam }) => {\n        expectTypeOf(pageParam).toEqualTypeOf<number>()\n      },\n      initialPageParam: 1,\n    })\n  })\n})\ndescribe('select', () => {\n  it('should still return paginated data if no select result', () => {\n    const infiniteQuery = useInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: ({ pageParam }) => {\n        return pageParam * 5\n      },\n      initialPageParam: 1,\n      getNextPageParam: () => undefined,\n    })\n\n    // TODO: Order of generics prevents pageParams to be typed correctly. Using `unknown` for now\n    expectTypeOf(infiniteQuery.data).toEqualTypeOf<\n      InfiniteData<number, unknown> | undefined\n    >()\n  })\n\n  it('should be able to transform data to arbitrary result', () => {\n    const infiniteQuery = useInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: ({ pageParam }) => {\n        return pageParam * 5\n      },\n      initialPageParam: 1,\n      getNextPageParam: () => undefined,\n      select: (data) => {\n        expectTypeOf(data).toEqualTypeOf<InfiniteData<number, number>>()\n        return 'selected' as const\n      },\n    })\n\n    expectTypeOf(infiniteQuery.data).toEqualTypeOf<'selected' | undefined>()\n  })\n})\ndescribe('getNextPageParam / getPreviousPageParam', () => {\n  it('should get typed params', () => {\n    const infiniteQuery = useInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: ({ pageParam }) => {\n        return String(pageParam)\n      },\n      initialPageParam: 1,\n      getNextPageParam: (lastPage, allPages, lastPageParam, allPageParams) => {\n        expectTypeOf(lastPage).toEqualTypeOf<string>()\n        expectTypeOf(allPages).toEqualTypeOf<Array<string>>()\n        expectTypeOf(lastPageParam).toEqualTypeOf<number>()\n        expectTypeOf(allPageParams).toEqualTypeOf<Array<number>>()\n        return undefined\n      },\n      getPreviousPageParam: (\n        firstPage,\n        allPages,\n        firstPageParam,\n        allPageParams,\n      ) => {\n        expectTypeOf(firstPage).toEqualTypeOf<string>()\n        expectTypeOf(allPages).toEqualTypeOf<Array<string>>()\n        expectTypeOf(firstPageParam).toEqualTypeOf<number>()\n        expectTypeOf(allPageParams).toEqualTypeOf<Array<number>>()\n        return undefined\n      },\n    })\n\n    // TODO: Order of generics prevents pageParams to be typed correctly. Using `unknown` for now\n    expectTypeOf(infiniteQuery.data).toEqualTypeOf<\n      InfiniteData<string, unknown> | undefined\n    >()\n  })\n})\n\ndescribe('error booleans', () => {\n  it('should not be permanently `false`', () => {\n    const {\n      isFetchNextPageError,\n      isFetchPreviousPageError,\n      isLoadingError,\n      isRefetchError,\n    } = useInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: ({ pageParam }) => {\n        return pageParam * 5\n      },\n      initialPageParam: 1,\n      getNextPageParam: () => undefined,\n    })\n\n    expectTypeOf(isFetchNextPageError).toEqualTypeOf<boolean>()\n    expectTypeOf(isFetchPreviousPageError).toEqualTypeOf<boolean>()\n    expectTypeOf(isLoadingError).toEqualTypeOf<boolean>()\n    expectTypeOf(isRefetchError).toEqualTypeOf<boolean>()\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/useInfiniteQuery.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { fireEvent, render } from '@testing-library/react'\nimport * as React from 'react'\nimport {\n  createRenderStream,\n  useTrackRenders,\n} from '@testing-library/react-render-stream'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport {\n  QueryCache,\n  QueryClient,\n  QueryClientProvider,\n  keepPreviousData,\n  useInfiniteQuery,\n} from '..'\nimport { renderWithClient, setActTimeout } from './utils'\nimport type {\n  InfiniteData,\n  QueryFunctionContext,\n  UseInfiniteQueryResult,\n} from '..'\nimport type { Mock } from 'vitest'\n\ninterface Result {\n  items: Array<number>\n  nextId?: number\n  prevId?: number\n  ts: number\n}\n\nconst pageSize = 10\n\nconst fetchItems = async (\n  page: number,\n  ts: number,\n  noNext?: boolean,\n  noPrev?: boolean,\n): Promise<Result> => {\n  await sleep(10)\n  return {\n    items: [...new Array(10)].fill(null).map((_, d) => page * pageSize + d),\n    nextId: noNext ? undefined : page + 1,\n    prevId: noPrev ? undefined : page - 1,\n    ts,\n  }\n}\n\ndescribe('useInfiniteQuery', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  const queryCache = new QueryCache()\n  const queryClient = new QueryClient({\n    queryCache,\n    defaultOptions: {\n      queries: {\n        experimental_prefetchInRender: true,\n      },\n    },\n  })\n\n  it('should return the correct states for a successful query', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        getNextPageParam: (lastPage) => lastPage + 1,\n        initialPageParam: 0,\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toEqual({\n      data: undefined,\n      dataUpdatedAt: 0,\n      error: null,\n      errorUpdatedAt: 0,\n      failureCount: 0,\n      failureReason: null,\n      errorUpdateCount: 0,\n      fetchNextPage: expect.any(Function),\n      fetchPreviousPage: expect.any(Function),\n      hasNextPage: false,\n      hasPreviousPage: false,\n      isError: false,\n      isFetched: false,\n      isFetchedAfterMount: false,\n      isFetching: true,\n      isPaused: false,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isLoading: true,\n      isPending: true,\n      isInitialLoading: true,\n      isLoadingError: false,\n      isPlaceholderData: false,\n      isRefetchError: false,\n      isRefetching: false,\n      isStale: true,\n      isSuccess: false,\n      isEnabled: true,\n      refetch: expect.any(Function),\n      status: 'pending',\n      fetchStatus: 'fetching',\n      promise: expect.any(Promise),\n    })\n    expect(states[1]).toEqual({\n      data: { pages: [0], pageParams: [0] },\n      dataUpdatedAt: expect.any(Number),\n      error: null,\n      errorUpdatedAt: 0,\n      failureCount: 0,\n      failureReason: null,\n      errorUpdateCount: 0,\n      fetchNextPage: expect.any(Function),\n      fetchPreviousPage: expect.any(Function),\n      hasNextPage: true,\n      hasPreviousPage: false,\n      isError: false,\n      isFetched: true,\n      isFetchedAfterMount: true,\n      isFetching: false,\n      isPaused: false,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isLoading: false,\n      isPending: false,\n      isInitialLoading: false,\n      isLoadingError: false,\n      isPlaceholderData: false,\n      isRefetchError: false,\n      isRefetching: false,\n      isStale: true,\n      isSuccess: true,\n      isEnabled: true,\n      refetch: expect.any(Function),\n      status: 'success',\n      fetchStatus: 'idle',\n      promise: expect.any(Promise),\n    })\n  })\n\n  it('should not throw when fetchNextPage returns an error', async () => {\n    const key = queryKey()\n    let noThrow = false\n\n    function Page() {\n      const start = 1\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) =>\n          sleep(10).then(() => {\n            if (pageParam === 2) throw new Error('error')\n            return pageParam\n          }),\n        retry: 1,\n        retryDelay: 10,\n        getNextPageParam: (lastPage) => lastPage + 1,\n        initialPageParam: start,\n      })\n\n      const { fetchNextPage } = state\n\n      React.useEffect(() => {\n        setActTimeout(() => {\n          fetchNextPage()\n            .then(() => {\n              noThrow = true\n            })\n            .catch(() => undefined)\n        }, 20)\n      }, [fetchNextPage])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(50)\n    expect(noThrow).toBe(true)\n  })\n\n  it('should keep the previous data when placeholderData is set', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<string>>> = []\n\n    function Page() {\n      const [order, setOrder] = React.useState('desc')\n\n      const state = useInfiniteQuery({\n        queryKey: [key, order],\n        queryFn: ({ pageParam }) =>\n          sleep(10).then(() => `${pageParam}-${order}`),\n        getNextPageParam: () => 1,\n        initialPageParam: 0,\n        placeholderData: keepPreviousData,\n        notifyOnChangeProps: 'all',\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <button onClick={() => state.fetchNextPage()}>fetchNextPage</button>\n          <button onClick={() => setOrder('asc')}>order</button>\n          <div>data: {state.data?.pages.join(',') ?? 'null'}</div>\n          <div>isFetching: {String(state.isFetching)}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 0-desc')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 0-desc,1-desc')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /order/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 0-asc')).toBeInTheDocument()\n    expect(rendered.getByText('isFetching: false')).toBeInTheDocument()\n\n    expect(states.length).toBe(6)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: false,\n      isPlaceholderData: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: ['0-desc'] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    expect(states[2]).toMatchObject({\n      data: { pages: ['0-desc'] },\n      isFetching: true,\n      isFetchingNextPage: true,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    expect(states[3]).toMatchObject({\n      data: { pages: ['0-desc', '1-desc'] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Set state\n    expect(states[4]).toMatchObject({\n      data: { pages: ['0-desc', '1-desc'] },\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    expect(states[5]).toMatchObject({\n      data: { pages: ['0-asc'] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n  })\n\n  it('should be able to select a part of the data', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<string>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => ({ count: 1 })),\n        select: (data) => ({\n          pages: data.pages.map((x) => `count: ${x.count}`),\n          pageParams: data.pageParams,\n        }),\n        getNextPageParam: () => undefined,\n        initialPageParam: 0,\n      })\n      states.push(state)\n\n      return <div>{state.data?.pages.join(',')}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('count: 1')).toBeInTheDocument()\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isSuccess: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: ['count: 1'] },\n      isSuccess: true,\n    })\n  })\n\n  it('should be able to select a new result and not cause infinite renders', async () => {\n    const key = queryKey()\n    const states: Array<\n      UseInfiniteQueryResult<InfiniteData<{ count: number; id: number }>>\n    > = []\n    let selectCalled = 0\n\n    function Page() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => ({ count: 1 })),\n        select: React.useCallback((data: InfiniteData<{ count: number }>) => {\n          selectCalled++\n          return {\n            pages: data.pages.map((x) => ({ ...x, id: Math.random() })),\n            pageParams: data.pageParams,\n          }\n        }, []),\n        getNextPageParam: () => undefined,\n        initialPageParam: 0,\n      })\n      states.push(state)\n\n      return (\n        <div>\n          {state.data?.pages.map((page) => (\n            <div key={page.id}>count: {page.count}</div>\n          ))}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('count: 1')).toBeInTheDocument()\n\n    expect(states.length).toBe(2)\n    expect(selectCalled).toBe(1)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isSuccess: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: [{ count: 1 }] },\n      isSuccess: true,\n    })\n  })\n\n  it('should be able to reverse the data', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        select: (data) => ({\n          pages: [...data.pages].reverse(),\n          pageParams: [...data.pageParams].reverse(),\n        }),\n        notifyOnChangeProps: 'all',\n        getNextPageParam: () => 1,\n        initialPageParam: 0,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <button onClick={() => state.fetchNextPage()}>fetchNextPage</button>\n          <div>data: {state.data?.pages.join(',') ?? 'null'}</div>\n          <div>isFetching: {state.isFetching}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 1,0')).toBeInTheDocument()\n\n    expect(states.length).toBe(4)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isSuccess: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: [0] },\n      isSuccess: true,\n    })\n    expect(states[2]).toMatchObject({\n      data: { pages: [0] },\n      isSuccess: true,\n    })\n    expect(states[3]).toMatchObject({\n      data: { pages: [1, 0] },\n      isSuccess: true,\n    })\n  })\n\n  it('should be able to fetch a previous page', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const start = 10\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        initialPageParam: start,\n        getNextPageParam: (lastPage) => lastPage + 1,\n        getPreviousPageParam: (firstPage) => firstPage - 1,\n        notifyOnChangeProps: 'all',\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <div>data: {state.data?.pages.join(',') ?? null}</div>\n          <button onClick={() => state.fetchPreviousPage()}>\n            fetch previous page\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 10')).toBeInTheDocument()\n\n    fireEvent.click(\n      rendered.getByRole('button', { name: /fetch previous page/i }),\n    )\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 9,10')).toBeInTheDocument()\n\n    expect(states.length).toBe(4)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      hasNextPage: false,\n      hasPreviousPage: false,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isFetchingPreviousPage: false,\n      isSuccess: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: [10] },\n      hasNextPage: true,\n      hasPreviousPage: true,\n      isFetching: false,\n      isFetchingNextPage: false,\n      isFetchingPreviousPage: false,\n      isSuccess: true,\n    })\n    expect(states[2]).toMatchObject({\n      data: { pages: [10] },\n      hasNextPage: true,\n      hasPreviousPage: true,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isFetchingPreviousPage: true,\n      isSuccess: true,\n    })\n    expect(states[3]).toMatchObject({\n      data: { pages: [9, 10] },\n      hasNextPage: true,\n      hasPreviousPage: true,\n      isFetching: false,\n      isFetchingNextPage: false,\n      isFetchingPreviousPage: false,\n      isSuccess: true,\n    })\n  })\n\n  it('should be able to refetch when providing page params automatically', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        initialPageParam: 10,\n        getPreviousPageParam: (firstPage) => firstPage - 1,\n        getNextPageParam: (lastPage) => lastPage + 1,\n        notifyOnChangeProps: 'all',\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <button onClick={() => state.fetchNextPage()}>fetchNextPage</button>\n          <button onClick={() => state.fetchPreviousPage()}>\n            fetchPreviousPage\n          </button>\n          <button onClick={() => state.refetch()}>refetch</button>\n          <div>data: {state.data?.pages.join(',') ?? 'null'}</div>\n          <div>isFetching: {String(state.isFetching)}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 10')).toBeInTheDocument()\n    fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 10,11')).toBeInTheDocument()\n    fireEvent.click(\n      rendered.getByRole('button', { name: /fetchPreviousPage/i }),\n    )\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 9,10,11')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n    expect(rendered.getByText('isFetching: false')).toBeInTheDocument()\n\n    await vi.advanceTimersByTimeAsync(31)\n    expect(states.length).toBe(8)\n    // Initial fetch\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isRefetching: false,\n    })\n    // Initial fetch done\n    expect(states[1]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isRefetching: false,\n    })\n    // Fetch next page\n    expect(states[2]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: true,\n      isFetchingNextPage: true,\n      isRefetching: false,\n    })\n    // Fetch next page done\n    expect(states[3]).toMatchObject({\n      data: { pages: [10, 11] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isRefetching: false,\n    })\n    // Fetch previous page\n    expect(states[4]).toMatchObject({\n      data: { pages: [10, 11] },\n      isFetching: true,\n      isFetchingNextPage: false,\n      isFetchingPreviousPage: true,\n      isRefetching: false,\n    })\n    // Fetch previous page done\n    expect(states[5]).toMatchObject({\n      data: { pages: [9, 10, 11] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isFetchingPreviousPage: false,\n      isRefetching: false,\n    })\n    // Refetch\n    expect(states[6]).toMatchObject({\n      data: { pages: [9, 10, 11] },\n      isFetching: true,\n      isFetchingNextPage: false,\n      isFetchingPreviousPage: false,\n      isRefetching: true,\n    })\n    // Refetch done\n    expect(states[7]).toMatchObject({\n      data: { pages: [9, 10, 11] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isFetchingPreviousPage: false,\n      isRefetching: false,\n    })\n  })\n\n  it('should return the correct states when refetch fails', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n    let isRefetch = false\n\n    function Page() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) =>\n          sleep(10).then(() => {\n            if (isRefetch) throw new Error()\n            return pageParam\n          }),\n        initialPageParam: 10,\n        getPreviousPageParam: (firstPage) => firstPage - 1,\n        getNextPageParam: (lastPage) => lastPage + 1,\n        notifyOnChangeProps: 'all',\n        retry: false,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <button\n            onClick={() => {\n              isRefetch = true\n              state.refetch()\n            }}\n          >\n            refetch\n          </button>\n          <div>data: {state.data?.pages.join(',') ?? 'null'}</div>\n          <div>isFetching: {String(state.isFetching)}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 10')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n    expect(rendered.getByText('isFetching: false')).toBeInTheDocument()\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(states.length).toBe(4)\n    // Initial fetch\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n    // Initial fetch done\n    expect(states[1]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: false,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n    // Refetch\n    expect(states[2]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: true,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: true,\n    })\n    // Refetch failed\n    expect(states[3]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: false,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: true,\n      isRefetching: false,\n    })\n  })\n\n  it('should return the correct states when fetchNextPage fails', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) =>\n          sleep(10).then(() => {\n            if (pageParam !== 10) throw new Error()\n            return pageParam\n          }),\n        initialPageParam: 10,\n        getPreviousPageParam: (firstPage) => firstPage - 1,\n        getNextPageParam: (lastPage) => lastPage + 1,\n        notifyOnChangeProps: 'all',\n        retry: false,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <button onClick={() => state.fetchNextPage()}>fetchNextPage</button>\n          <div>data: {state.data?.pages.join(',') ?? 'null'}</div>\n          <div>isFetching: {String(state.isFetching)}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 10')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i }))\n    expect(rendered.getByText('isFetching: false')).toBeInTheDocument()\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(states.length).toBe(4)\n    // Initial fetch\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n    // Initial fetch done\n    expect(states[1]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: false,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n    // Fetch next page\n    expect(states[2]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: true,\n      isFetchNextPageError: false,\n      isFetchingNextPage: true,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n    // Fetch next page failed\n    expect(states[3]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: false,\n      isFetchNextPageError: true,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n  })\n\n  it('should return the correct states when fetchPreviousPage fails', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) =>\n          sleep(10).then(() => {\n            if (pageParam !== 10) throw new Error()\n            return pageParam\n          }),\n        initialPageParam: 10,\n        getPreviousPageParam: (firstPage) => firstPage - 1,\n        getNextPageParam: (lastPage) => lastPage + 1,\n        notifyOnChangeProps: 'all',\n        retry: false,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <button onClick={() => state.fetchPreviousPage()}>\n            fetchPreviousPage\n          </button>\n          <div>data: {state.data?.pages.join(',') ?? 'null'}</div>\n          <div>isFetching: {String(state.isFetching)}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 10')).toBeInTheDocument()\n\n    fireEvent.click(\n      rendered.getByRole('button', { name: /fetchPreviousPage/i }),\n    )\n    expect(rendered.getByText('isFetching: false')).toBeInTheDocument()\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(states.length).toBe(4)\n    // Initial fetch\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n    // Initial fetch done\n    expect(states[1]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: false,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n    // Fetch previous page\n    expect(states[2]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: true,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: true,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n    // Fetch previous page failed\n    expect(states[3]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: false,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: true,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n  })\n\n  it('should silently cancel any ongoing fetch when fetching more', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const start = 10\n      const { data, fetchNextPage, refetch, status, fetchStatus } =\n        useInfiniteQuery({\n          queryKey: key,\n          queryFn: ({ pageParam }) => sleep(50).then(() => pageParam),\n          initialPageParam: start,\n          getNextPageParam: (lastPage) => lastPage + 1,\n        })\n\n      return (\n        <div>\n          <button onClick={() => fetchNextPage()}>fetchNextPage</button>\n          <button onClick={() => refetch()}>refetch</button>\n          <div>data: {JSON.stringify(data)}</div>\n          <div>\n            status: {status}, {fetchStatus}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(51)\n    expect(rendered.getByText('status: success, idle')).toBeInTheDocument()\n    expect(\n      rendered.getByText('data: {\"pages\":[10],\"pageParams\":[10]}'),\n    ).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('status: success, fetching')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i }))\n    await vi.advanceTimersByTimeAsync(51)\n    expect(rendered.getByText('status: success, idle')).toBeInTheDocument()\n    expect(\n      rendered.getByText('data: {\"pages\":[10,11],\"pageParams\":[10,11]}'),\n    ).toBeInTheDocument()\n  })\n\n  it('should silently cancel an ongoing fetchNextPage request when another fetchNextPage is invoked', async () => {\n    const key = queryKey()\n    const start = 10\n    const onAborts: Array<Mock<(...args: Array<any>) => any>> = []\n    const abortListeners: Array<Mock<(...args: Array<any>) => any>> = []\n    const fetchPage = vi.fn<\n      (context: QueryFunctionContext<typeof key, number>) => Promise<number>\n    >(async ({ pageParam, signal }) => {\n      const onAbort = vi.fn()\n      const abortListener = vi.fn()\n      onAborts.push(onAbort)\n      abortListeners.push(abortListener)\n      signal.onabort = onAbort\n      signal.addEventListener('abort', abortListener)\n      await sleep(50)\n      return pageParam\n    })\n\n    function Page() {\n      const { fetchNextPage } = useInfiniteQuery({\n        queryKey: key,\n        queryFn: fetchPage,\n        initialPageParam: start,\n        getNextPageParam: (lastPage) => lastPage + 1,\n      })\n\n      React.useEffect(() => {\n        setActTimeout(() => {\n          fetchNextPage()\n        }, 100)\n        setActTimeout(() => {\n          fetchNextPage()\n        }, 110)\n      }, [fetchNextPage])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(160)\n\n    const expectedCallCount = 3\n    expect(fetchPage).toBeCalledTimes(expectedCallCount)\n    expect(onAborts).toHaveLength(expectedCallCount)\n    expect(abortListeners).toHaveLength(expectedCallCount)\n\n    let callIndex = 0\n    const firstCtx = fetchPage.mock.calls[callIndex]![0]\n    expect(firstCtx.pageParam).toEqual(start)\n    expect(firstCtx.queryKey).toEqual(key)\n    expect(firstCtx.signal).toBeInstanceOf(AbortSignal)\n    expect(firstCtx.signal.aborted).toBe(false)\n    expect(onAborts[callIndex]).not.toHaveBeenCalled()\n    expect(abortListeners[callIndex]).not.toHaveBeenCalled()\n\n    callIndex = 1\n    const secondCtx = fetchPage.mock.calls[callIndex]![0]\n    expect(secondCtx.pageParam).toBe(11)\n    expect(secondCtx.queryKey).toEqual(key)\n    expect(secondCtx.signal).toBeInstanceOf(AbortSignal)\n    expect(secondCtx.signal.aborted).toBe(true)\n    expect(onAborts[callIndex]).toHaveBeenCalledTimes(1)\n    expect(abortListeners[callIndex]).toHaveBeenCalledTimes(1)\n\n    callIndex = 2\n    const thirdCtx = fetchPage.mock.calls[callIndex]![0]\n    expect(thirdCtx.pageParam).toBe(11)\n    expect(thirdCtx.queryKey).toEqual(key)\n    expect(thirdCtx.signal).toBeInstanceOf(AbortSignal)\n    expect(thirdCtx.signal.aborted).toBe(false)\n    expect(onAborts[callIndex]).not.toHaveBeenCalled()\n    expect(abortListeners[callIndex]).not.toHaveBeenCalled()\n  })\n\n  it('should not cancel an ongoing fetchNextPage request when another fetchNextPage is invoked if `cancelRefetch: false` is used', async () => {\n    const key = queryKey()\n    const start = 10\n    const onAborts: Array<Mock<(...args: Array<any>) => any>> = []\n    const abortListeners: Array<Mock<(...args: Array<any>) => any>> = []\n    const fetchPage = vi.fn<\n      (context: QueryFunctionContext<typeof key, number>) => Promise<number>\n    >(async ({ pageParam, signal }) => {\n      const onAbort = vi.fn()\n      const abortListener = vi.fn()\n      onAborts.push(onAbort)\n      abortListeners.push(abortListener)\n      signal.onabort = onAbort\n      signal.addEventListener('abort', abortListener)\n      await sleep(50)\n      return pageParam\n    })\n\n    function Page() {\n      const { fetchNextPage } = useInfiniteQuery({\n        queryKey: key,\n        queryFn: fetchPage,\n        initialPageParam: start,\n        getNextPageParam: (lastPage) => lastPage + 1,\n      })\n\n      React.useEffect(() => {\n        setActTimeout(() => {\n          fetchNextPage()\n        }, 100)\n        setActTimeout(() => {\n          fetchNextPage({ cancelRefetch: false })\n        }, 110)\n      }, [fetchNextPage])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(160)\n\n    const expectedCallCount = 2\n    expect(fetchPage).toBeCalledTimes(expectedCallCount)\n    expect(onAborts).toHaveLength(expectedCallCount)\n    expect(abortListeners).toHaveLength(expectedCallCount)\n\n    let callIndex = 0\n    const firstCtx = fetchPage.mock.calls[callIndex]![0]\n    expect(firstCtx.pageParam).toEqual(start)\n    expect(firstCtx.queryKey).toEqual(key)\n    expect(firstCtx.signal).toBeInstanceOf(AbortSignal)\n    expect(firstCtx.signal.aborted).toBe(false)\n    expect(onAborts[callIndex]).not.toHaveBeenCalled()\n    expect(abortListeners[callIndex]).not.toHaveBeenCalled()\n\n    callIndex = 1\n    const secondCtx = fetchPage.mock.calls[callIndex]![0]\n    expect(secondCtx.pageParam).toBe(11)\n    expect(secondCtx.queryKey).toEqual(key)\n    expect(secondCtx.signal).toBeInstanceOf(AbortSignal)\n    expect(secondCtx.signal.aborted).toBe(false)\n    expect(onAborts[callIndex]).not.toHaveBeenCalled()\n    expect(abortListeners[callIndex]).not.toHaveBeenCalled()\n  })\n\n  it('should keep fetching first page when not loaded yet and triggering fetch more', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const start = 10\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(50).then(() => pageParam),\n        initialPageParam: start,\n        getNextPageParam: (lastPage) => lastPage + 1,\n        notifyOnChangeProps: 'all',\n      })\n\n      states.push(state)\n\n      const { fetchNextPage } = state\n\n      React.useEffect(() => {\n        setActTimeout(() => {\n          fetchNextPage()\n        }, 10)\n      }, [fetchNextPage])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(60)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      hasNextPage: false,\n      data: undefined,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: false,\n    })\n    expect(states[1]).toMatchObject({\n      hasNextPage: true,\n      data: { pages: [10] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n  })\n\n  it('should stop fetching additional pages when the component is unmounted and AbortSignal is consumed', async () => {\n    const key = queryKey()\n    let fetches = 0\n\n    const initialData = { pages: [1, 2, 3, 4], pageParams: [0, 1, 2, 3] }\n\n    function List() {\n      useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) =>\n          sleep(50).then(() => {\n            fetches++\n            return pageParam * 10\n          }),\n        initialData,\n        initialPageParam: 0,\n        getNextPageParam: (_, allPages) => {\n          return allPages.length === 4 ? undefined : allPages.length\n        },\n      })\n\n      return null\n    }\n\n    function Page() {\n      const [show, setShow] = React.useState(true)\n\n      React.useEffect(() => {\n        setActTimeout(() => {\n          setShow(false)\n        }, 75)\n      }, [])\n\n      return show ? <List /> : null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(125)\n\n    expect(fetches).toBe(2)\n    expect(queryClient.getQueryState(key)).toMatchObject({\n      data: initialData,\n      status: 'success',\n      error: null,\n    })\n  })\n\n  it('should be able to set new pages with the query client', async () => {\n    const key = queryKey()\n\n    let multiplier = 1\n\n    function Page() {\n      const [firstPage, setFirstPage] = React.useState(0)\n\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) =>\n          sleep(10).then(() => multiplier * pageParam),\n        getNextPageParam: (lastPage) => lastPage + 1,\n        initialPageParam: firstPage,\n      })\n\n      return (\n        <div>\n          <button\n            onClick={() => {\n              queryClient.setQueryData(key, {\n                pages: [7, 8],\n                pageParams: [7, 8],\n              })\n              setFirstPage(7)\n            }}\n          >\n            setPages\n          </button>\n          <button onClick={() => state.refetch()}>refetch</button>\n          <div>data: {JSON.stringify(state.data)}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(\n      rendered.getByText('data: {\"pages\":[0],\"pageParams\":[0]}'),\n    ).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /setPages/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(\n      rendered.getByText('data: {\"pages\":[7,8],\"pageParams\":[7,8]}'),\n    ).toBeInTheDocument()\n\n    multiplier = 2\n\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n    await vi.advanceTimersByTimeAsync(21)\n    expect(\n      rendered.getByText('data: {\"pages\":[14,30],\"pageParams\":[7,15]}'),\n    ).toBeInTheDocument()\n  })\n\n  it('should only refetch the first page when initialData is provided', async () => {\n    vi.useRealTimers()\n\n    const key = queryKey()\n\n    const renderStream =\n      createRenderStream<UseInfiniteQueryResult<InfiniteData<number>>>()\n\n    function Page() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        initialData: { pages: [1], pageParams: [1] },\n        getNextPageParam: (lastPage) => lastPage + 1,\n        initialPageParam: 0,\n        notifyOnChangeProps: 'all',\n      })\n\n      renderStream.replaceSnapshot(state)\n\n      return (\n        <button onClick={() => state.fetchNextPage()}>fetchNextPage</button>\n      )\n    }\n\n    const rendered = await renderStream.render(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    {\n      const { snapshot } = await renderStream.takeRender()\n      expect(snapshot).toMatchObject({\n        data: { pages: [1] },\n        hasNextPage: true,\n        isFetching: true,\n        isFetchingNextPage: false,\n        isSuccess: true,\n      })\n    }\n\n    {\n      const { snapshot } = await renderStream.takeRender()\n      expect(snapshot).toMatchObject({\n        data: { pages: [1] },\n        hasNextPage: true,\n        isFetching: false,\n        isFetchingNextPage: false,\n        isSuccess: true,\n      })\n    }\n\n    fireEvent.click(rendered.getByText('fetchNextPage'))\n\n    {\n      const { snapshot } = await renderStream.takeRender()\n      expect(snapshot).toMatchObject({\n        data: { pages: [1] },\n        hasNextPage: true,\n        isFetching: true,\n        isFetchingNextPage: true,\n        isSuccess: true,\n      })\n    }\n    {\n      const { snapshot } = await renderStream.takeRender()\n      expect(snapshot).toMatchObject({\n        data: { pages: [1, 2] },\n        hasNextPage: true,\n        isFetching: false,\n        isFetchingNextPage: false,\n        isSuccess: true,\n      })\n    }\n  })\n\n  it('should set hasNextPage to false if getNextPageParam returns undefined', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        getNextPageParam: () => undefined,\n        initialPageParam: 1,\n      })\n\n      states.push(state)\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      hasNextPage: false,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: [1] },\n      hasNextPage: false,\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n  })\n\n  it('should compute hasNextPage correctly using initialData', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        initialData: { pages: [10], pageParams: [10] },\n        getNextPageParam: (lastPage) => (lastPage === 10 ? 11 : undefined),\n        initialPageParam: 10,\n      })\n\n      states.push(state)\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: { pages: [10] },\n      hasNextPage: true,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: [10] },\n      hasNextPage: true,\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n  })\n\n  it('should compute hasNextPage correctly for falsy getFetchMore return value using initialData', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        initialPageParam: 10,\n        initialData: { pages: [10], pageParams: [10] },\n        getNextPageParam: () => undefined,\n      })\n\n      states.push(state)\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: { pages: [10] },\n      hasNextPage: false,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: [10] },\n      hasNextPage: false,\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n  })\n\n  it('should not use selected data when computing hasNextPage', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<string>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        getNextPageParam: (lastPage) => (lastPage === 1 ? 2 : undefined),\n        select: (data) => ({\n          pages: data.pages.map((x) => x.toString()),\n          pageParams: data.pageParams,\n        }),\n        initialPageParam: 1,\n      })\n\n      states.push(state)\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      hasNextPage: false,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: ['1'] },\n      hasNextPage: true,\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n  })\n\n  it('should build fresh cursors on refetch', async () => {\n    const key = queryKey()\n\n    const genItems = (size: number) =>\n      [...new Array(size)].fill(null).map((_, d) => d)\n    const items = genItems(15)\n    const limit = 3\n\n    const fetchItemsWithLimit = (cursor = 0, ts: number) =>\n      sleep(10).then(() => ({\n        nextId: cursor + limit,\n        items: items.slice(cursor, cursor + limit),\n        ts,\n      }))\n\n    function Page() {\n      const fetchCountRef = React.useRef(0)\n      const {\n        status,\n        data,\n        error,\n        isFetchingNextPage,\n        fetchNextPage,\n        hasNextPage,\n        refetch,\n      } = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) =>\n          fetchItemsWithLimit(pageParam, fetchCountRef.current++),\n        initialPageParam: 0,\n        getNextPageParam: (lastPage) => lastPage.nextId,\n      })\n\n      return (\n        <div>\n          <h1>Pagination</h1>\n          {status === 'pending' ? (\n            'Loading...'\n          ) : status === 'error' ? (\n            <span>Error: {error.message}</span>\n          ) : (\n            <>\n              <div>Data:</div>\n              {data.pages.map((page, i) => (\n                <div key={i}>\n                  <div>\n                    Page {i}: {page.ts}\n                  </div>\n                  <div key={i}>\n                    {page.items.map((item) => (\n                      <p key={item}>Item: {item}</p>\n                    ))}\n                  </div>\n                </div>\n              ))}\n              <div>\n                <button\n                  onClick={() => fetchNextPage()}\n                  disabled={!hasNextPage || isFetchingNextPage}\n                >\n                  {isFetchingNextPage\n                    ? 'Loading more...'\n                    : hasNextPage\n                      ? 'Load More'\n                      : 'Nothing more to load'}\n                </button>\n                <button onClick={() => refetch()}>Refetch</button>\n                <button\n                  onClick={() => {\n                    // Imagine that this mutation happens somewhere else\n                    // makes an actual network request\n                    // and calls invalidateQueries in an onSuccess\n                    items.splice(4, 1)\n                    queryClient.invalidateQueries({ queryKey: key })\n                  }}\n                >\n                  Remove item\n                </button>\n              </div>\n              <div>{!isFetchingNextPage ? 'Background Updating...' : null}</div>\n            </>\n          )}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('Loading...')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Item: 2')).toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('Load More'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Loading more...')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Item: 5')).toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 0')).toBeInTheDocument()\n    expect(rendered.getByText('Page 1: 1')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('Load More'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Loading more...')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Item: 8')).toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 0')).toBeInTheDocument()\n    expect(rendered.getByText('Page 1: 1')).toBeInTheDocument()\n    expect(rendered.getByText('Page 2: 2')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('Refetch'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Background Updating...')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(31)\n    expect(rendered.getByText('Item: 8')).toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 3')).toBeInTheDocument()\n    expect(rendered.getByText('Page 1: 4')).toBeInTheDocument()\n    expect(rendered.getByText('Page 2: 5')).toBeInTheDocument()\n    // ensure that Item: 4 is rendered before removing it\n    expect(rendered.queryAllByText('Item: 4')).toHaveLength(1)\n\n    // remove Item: 4\n    fireEvent.click(rendered.getByText('Remove item'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Background Updating...')).toBeInTheDocument()\n    // ensure that an additional item is rendered (it means that cursors were properly rebuilt)\n    await vi.advanceTimersByTimeAsync(31)\n    expect(rendered.getByText('Item: 9')).toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 6')).toBeInTheDocument()\n    expect(rendered.getByText('Page 1: 7')).toBeInTheDocument()\n    expect(rendered.getByText('Page 2: 8')).toBeInTheDocument()\n    // ensure that Item: 4 is no longer rendered\n    expect(rendered.queryAllByText('Item: 4')).toHaveLength(0)\n  })\n\n  it('should compute hasNextPage correctly for falsy getFetchMore return value on refetching', async () => {\n    const key = queryKey()\n    const MAX = 2\n\n    function Page() {\n      const fetchCountRef = React.useRef(0)\n      const [isRemovedLastPage, setIsRemovedLastPage] =\n        React.useState<boolean>(false)\n      const {\n        status,\n        data,\n        error,\n        isFetching,\n        isFetchingNextPage,\n        fetchNextPage,\n        hasNextPage,\n        refetch,\n      } = useInfiniteQuery({\n        queryKey: key,\n        queryFn: ({ pageParam }) =>\n          fetchItems(\n            pageParam,\n            fetchCountRef.current++,\n            pageParam === MAX || (pageParam === MAX - 1 && isRemovedLastPage),\n          ),\n        getNextPageParam: (lastPage) => lastPage.nextId,\n        initialPageParam: 0,\n      })\n\n      return (\n        <div>\n          <h1>Pagination</h1>\n          {status === 'pending' ? (\n            'Loading...'\n          ) : status === 'error' ? (\n            <span>Error: {error.message}</span>\n          ) : (\n            <>\n              <div>Data:</div>\n              {data.pages.map((page, i) => (\n                <div key={i}>\n                  <div>\n                    Page {i}: {page.ts}\n                  </div>\n                  <div key={i}>\n                    {page.items.map((item) => (\n                      <p key={item}>Item: {item}</p>\n                    ))}\n                  </div>\n                </div>\n              ))}\n              <div>\n                <button\n                  onClick={() => fetchNextPage()}\n                  disabled={!hasNextPage || isFetchingNextPage}\n                >\n                  {isFetchingNextPage\n                    ? 'Loading more...'\n                    : hasNextPage\n                      ? 'Load More'\n                      : 'Nothing more to load'}\n                </button>\n                <button onClick={() => refetch()}>Refetch</button>\n                <button onClick={() => setIsRemovedLastPage(true)}>\n                  Remove Last Page\n                </button>\n              </div>\n              <div>\n                {isFetching && !isFetchingNextPage\n                  ? 'Background Updating...'\n                  : null}\n              </div>\n            </>\n          )}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('Loading...')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Item: 9')).toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('Load More'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Loading more...')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Item: 19')).toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 0')).toBeInTheDocument()\n    expect(rendered.getByText('Page 1: 1')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('Load More'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Loading more...')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Item: 29')).toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 0')).toBeInTheDocument()\n    expect(rendered.getByText('Page 1: 1')).toBeInTheDocument()\n    expect(rendered.getByText('Page 2: 2')).toBeInTheDocument()\n    expect(rendered.getByText('Nothing more to load')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('Remove Last Page'))\n    fireEvent.click(rendered.getByText('Refetch'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Background Updating...')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(21)\n    expect(rendered.queryByText('Item: 29')).not.toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 3')).toBeInTheDocument()\n    expect(rendered.getByText('Page 1: 4')).toBeInTheDocument()\n    expect(rendered.queryByText('Page 2: 5')).not.toBeInTheDocument()\n    expect(rendered.getByText('Nothing more to load')).toBeInTheDocument()\n  })\n\n  it('should cancel the query function when there are no more subscriptions', () => {\n    const key = queryKey()\n    let cancelFn: Mock = vi.fn()\n\n    const queryFn = ({ signal }: { signal?: AbortSignal }) => {\n      const promise = new Promise<string>((resolve, reject) => {\n        cancelFn = vi.fn(() => reject('Cancelled'))\n        signal?.addEventListener('abort', cancelFn)\n        sleep(1000).then(() => resolve('OK'))\n      })\n\n      return promise\n    }\n\n    function Inner() {\n      const state = useInfiniteQuery({\n        queryKey: key,\n        queryFn,\n        getNextPageParam: () => undefined,\n        initialPageParam: 0,\n      })\n      return (\n        <div>\n          <h1>Status: {state.status}</h1>\n        </div>\n      )\n    }\n\n    function Page() {\n      const [isVisible, setIsVisible] = React.useState(true)\n\n      return (\n        <>\n          <button onClick={() => setIsVisible(false)}>hide</button>\n          {isVisible && <Inner />}\n          <div>{isVisible ? 'visible' : 'hidden'}</div>\n        </>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('visible')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: 'hide' }))\n    expect(rendered.getByText('hidden')).toBeInTheDocument()\n\n    expect(cancelFn).toHaveBeenCalled()\n  })\n\n  it('should use provided custom queryClient', async () => {\n    const key = queryKey()\n    const queryFn = () => sleep(10).then(() => 'custom client')\n\n    function Page() {\n      const { data } = useInfiniteQuery(\n        {\n          queryKey: key,\n          queryFn,\n          getNextPageParam: () => undefined,\n          initialPageParam: 0,\n        },\n        queryClient,\n      )\n\n      return <div>data: {data?.pages[0]}</div>\n    }\n\n    const rendered = render(<Page></Page>)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: custom client')).toBeInTheDocument()\n  })\n\n  it('should work with React.use()', async () => {\n    vi.useRealTimers()\n\n    const key = queryKey()\n\n    const renderStream = createRenderStream({ snapshotDOM: true })\n\n    function Loading() {\n      useTrackRenders()\n      return <>loading...</>\n    }\n\n    function MyComponent() {\n      useTrackRenders()\n      const fetchCountRef = React.useRef(0)\n      const query = useInfiniteQuery({\n        queryFn: ({ pageParam }) =>\n          fetchItems(pageParam, fetchCountRef.current++),\n        getNextPageParam: (lastPage) => lastPage.nextId,\n        initialPageParam: 0,\n        queryKey: key,\n      })\n      const data = React.use(query.promise)\n      return (\n        <>\n          {data.pages.map((page, index) => (\n            <React.Fragment key={page.ts}>\n              <div>\n                <div>Page: {index + 1}</div>\n              </div>\n              {page.items.map((item) => (\n                <p key={item}>Item: {item}</p>\n              ))}\n            </React.Fragment>\n          ))}\n          <button onClick={() => query.fetchNextPage()}>fetchNextPage</button>\n        </>\n      )\n    }\n\n    function Page() {\n      useTrackRenders()\n      return (\n        <React.Suspense fallback={<Loading />}>\n          <MyComponent />\n        </React.Suspense>\n      )\n    }\n\n    const rendered = await renderStream.render(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('loading...')\n      expect(renderedComponents).toEqual([Page, Loading])\n    }\n\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('Page: 1')\n      withinDOM().getByText('Item: 1')\n      expect(renderedComponents).toEqual([MyComponent])\n    }\n\n    // click button\n    rendered.getByRole('button', { name: 'fetchNextPage' }).click()\n\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('Page: 1')\n      expect(renderedComponents).toEqual([MyComponent])\n    }\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/useIsFetching.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { fireEvent, render } from '@testing-library/react'\nimport * as React from 'react'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { QueryCache, QueryClient, useIsFetching, useQuery } from '..'\nimport { renderWithClient, setActTimeout } from './utils'\n\ndescribe('useIsFetching', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/105\n  it('should update as queries start and stop fetching', async () => {\n    const queryClient = new QueryClient()\n    const key = queryKey()\n\n    function IsFetching() {\n      const isFetching = useIsFetching()\n\n      return <div>isFetching: {isFetching}</div>\n    }\n\n    function Query() {\n      const [ready, setReady] = React.useState(false)\n\n      useQuery({\n        queryKey: key,\n        queryFn: () => sleep(50).then(() => 'test'),\n        enabled: ready,\n      })\n\n      return <button onClick={() => setReady(true)}>setReady</button>\n    }\n\n    function Page() {\n      return (\n        <div>\n          <IsFetching />\n          <Query />\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('isFetching: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /setReady/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('isFetching: 1')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(51)\n    expect(rendered.getByText('isFetching: 0')).toBeInTheDocument()\n  })\n\n  it('should not update state while rendering', async () => {\n    const queryClient = new QueryClient()\n\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    const isFetchingArray: Array<number> = []\n\n    function IsFetching() {\n      const isFetching = useIsFetching()\n\n      isFetchingArray.push(isFetching)\n\n      return null\n    }\n\n    function FirstQuery() {\n      useQuery({\n        queryKey: key1,\n        queryFn: () => sleep(100).then(() => 'data1'),\n      })\n\n      return null\n    }\n\n    function SecondQuery() {\n      useQuery({\n        queryKey: key2,\n        queryFn: () => sleep(100).then(() => 'data2'),\n      })\n\n      return null\n    }\n\n    function Page() {\n      const [renderSecond, setRenderSecond] = React.useState(false)\n\n      React.useEffect(() => {\n        setActTimeout(() => {\n          setRenderSecond(true)\n        }, 50)\n      }, [])\n\n      return (\n        <>\n          <IsFetching />\n          <FirstQuery />\n          {renderSecond && <SecondQuery />}\n        </>\n      )\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    expect(isFetchingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isFetchingArray[1]).toEqual(1)\n    await vi.advanceTimersByTimeAsync(50)\n    expect(isFetchingArray[2]).toEqual(1)\n    await vi.advanceTimersByTimeAsync(1)\n    expect(isFetchingArray[3]).toEqual(2)\n    await vi.advanceTimersByTimeAsync(50)\n    expect(isFetchingArray[4]).toEqual(1)\n    await vi.advanceTimersByTimeAsync(50)\n    expect(isFetchingArray[5]).toEqual(0)\n\n    expect(isFetchingArray).toEqual([0, 1, 1, 2, 1, 0])\n  })\n\n  it('should be able to filter', async () => {\n    const queryClient = new QueryClient()\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    const isFetchingArray: Array<number> = []\n\n    function One() {\n      useQuery({\n        queryKey: key1,\n        queryFn: () => sleep(10).then(() => 'test1'),\n      })\n\n      return null\n    }\n\n    function Two() {\n      useQuery({\n        queryKey: key2,\n        queryFn: () => sleep(20).then(() => 'test2'),\n      })\n\n      return null\n    }\n\n    function Page() {\n      const [started, setStarted] = React.useState(false)\n      const isFetching = useIsFetching({ queryKey: key1 })\n\n      isFetchingArray.push(isFetching)\n\n      return (\n        <div>\n          <button onClick={() => setStarted(true)}>setStarted</button>\n          <div>isFetching: {isFetching}</div>\n          {started ? (\n            <>\n              <One />\n              <Two />\n            </>\n          ) : null}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('isFetching: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /setStarted/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('isFetching: 1')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('isFetching: 0')).toBeInTheDocument()\n\n    // at no point should we have isFetching: 2\n    expect(isFetchingArray).toEqual(expect.not.arrayContaining([2]))\n  })\n\n  it('should show the correct fetching state when mounted after a query', async () => {\n    const queryClient = new QueryClient()\n    const key = queryKey()\n\n    function Page() {\n      useQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'test'),\n      })\n\n      const isFetching = useIsFetching()\n\n      return (\n        <div>\n          <div>isFetching: {isFetching}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('isFetching: 1')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('isFetching: 0')).toBeInTheDocument()\n  })\n\n  it('should use provided custom queryClient', async () => {\n    const onSuccess = vi.fn()\n\n    const queryCache = new QueryCache({ onSuccess })\n    const queryClient = new QueryClient({ queryCache })\n    const key = queryKey()\n\n    function Page() {\n      useQuery(\n        {\n          queryKey: key,\n          queryFn: () => sleep(10).then(() => 'test'),\n        },\n        queryClient,\n      )\n\n      const isFetching = useIsFetching({}, queryClient)\n\n      return (\n        <div>\n          <div>isFetching: {isFetching}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(<Page />)\n\n    expect(rendered.getByText('isFetching: 1')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('isFetching: 0')).toBeInTheDocument()\n    expect(onSuccess).toHaveBeenCalledOnce()\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/useMutation.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { fireEvent, render } from '@testing-library/react'\nimport * as React from 'react'\nimport { ErrorBoundary } from 'react-error-boundary'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { MutationCache, QueryCache, QueryClient, useMutation } from '..'\nimport {\n  mockOnlineManagerIsOnline,\n  renderWithClient,\n  setActTimeout,\n} from './utils'\nimport type { UseMutationResult } from '../types'\n\ndescribe('useMutation', () => {\n  let queryCache: QueryCache\n  let mutationCache: MutationCache\n  let queryClient: QueryClient\n\n  beforeEach(() => {\n    queryCache = new QueryCache()\n    mutationCache = new MutationCache()\n    queryClient = new QueryClient({\n      queryCache,\n      mutationCache,\n    })\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should be able to reset `data`', async () => {\n    function Page() {\n      const {\n        mutate,\n        data = 'empty',\n        reset,\n      } = useMutation({ mutationFn: () => Promise.resolve('mutation') })\n\n      return (\n        <div>\n          <h1>{data}</h1>\n          <button onClick={() => reset()}>reset</button>\n          <button onClick={() => mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    const { getByRole } = renderWithClient(queryClient, <Page />)\n\n    expect(getByRole('heading').textContent).toBe('empty')\n\n    fireEvent.click(getByRole('button', { name: /mutate/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(getByRole('heading').textContent).toBe('mutation')\n\n    fireEvent.click(getByRole('button', { name: /reset/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(getByRole('heading').textContent).toBe('empty')\n  })\n\n  it('should be able to reset `error`', async () => {\n    function Page() {\n      const { mutate, error, reset } = useMutation<string, Error>({\n        mutationFn: () => {\n          const err = new Error('Expected mock error. All is well!')\n          err.stack = ''\n          return Promise.reject(err)\n        },\n      })\n\n      return (\n        <div>\n          {error && <h1>{error.message}</h1>}\n          <button onClick={() => reset()}>reset</button>\n          <button onClick={() => mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    const { getByRole, queryByRole } = renderWithClient(queryClient, <Page />)\n\n    expect(queryByRole('heading')).toBeNull()\n\n    fireEvent.click(getByRole('button', { name: /mutate/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(getByRole('heading').textContent).toBe(\n      'Expected mock error. All is well!',\n    )\n\n    fireEvent.click(getByRole('button', { name: /reset/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(queryByRole('heading')).toBeNull()\n  })\n\n  it('should be able to call `onSuccess` and `onSettled` after each successful mutate', async () => {\n    let count = 0\n    const onSuccessMock = vi.fn()\n    const onSettledMock = vi.fn()\n\n    function Page() {\n      const { mutate } = useMutation({\n        mutationFn: (vars: { count: number }) => Promise.resolve(vars.count),\n\n        onSuccess: (data) => {\n          onSuccessMock(data)\n        },\n        onSettled: (data) => {\n          onSettledMock(data)\n        },\n      })\n\n      return (\n        <div>\n          <h1>{count}</h1>\n          <button onClick={() => mutate({ count: ++count })}>mutate</button>\n        </div>\n      )\n    }\n\n    const { getByRole } = renderWithClient(queryClient, <Page />)\n\n    expect(getByRole('heading').textContent).toBe('0')\n\n    fireEvent.click(getByRole('button', { name: /mutate/i }))\n    fireEvent.click(getByRole('button', { name: /mutate/i }))\n    fireEvent.click(getByRole('button', { name: /mutate/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(getByRole('heading').textContent).toBe('3')\n    expect(onSuccessMock).toHaveBeenCalledTimes(3)\n\n    expect(onSuccessMock).toHaveBeenCalledWith(1)\n    expect(onSuccessMock).toHaveBeenCalledWith(2)\n    expect(onSuccessMock).toHaveBeenCalledWith(3)\n\n    expect(onSettledMock).toHaveBeenCalledTimes(3)\n\n    expect(onSettledMock).toHaveBeenCalledWith(1)\n    expect(onSettledMock).toHaveBeenCalledWith(2)\n    expect(onSettledMock).toHaveBeenCalledWith(3)\n  })\n\n  it('should set correct values for `failureReason` and `failureCount` on multiple mutate calls', async () => {\n    let count = 0\n    type Value = { count: number }\n\n    const mutateFn = vi.fn<(value: Value) => Promise<Value>>()\n\n    mutateFn.mockImplementationOnce(() => {\n      return Promise.reject(new Error('Error test Jonas'))\n    })\n\n    mutateFn.mockImplementation(async (value) => {\n      await sleep(10)\n      return Promise.resolve(value)\n    })\n\n    function Page() {\n      const { mutate, failureCount, failureReason, data, status } = useMutation(\n        { mutationFn: mutateFn },\n      )\n\n      return (\n        <div>\n          <h1>Data {data?.count}</h1>\n          <h2>Status {status}</h2>\n          <h2>Failed {failureCount} times</h2>\n          <h2>Failed because {failureReason?.message ?? 'null'}</h2>\n          <button onClick={() => mutate({ count: ++count })}>mutate</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('Data')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Status error')).toBeInTheDocument()\n    expect(rendered.getByText('Failed 1 times')).toBeInTheDocument()\n    expect(\n      rendered.getByText('Failed because Error test Jonas'),\n    ).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Status pending')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Status success')).toBeInTheDocument()\n    expect(rendered.getByText('Data 2')).toBeInTheDocument()\n    expect(rendered.getByText('Failed 0 times')).toBeInTheDocument()\n    expect(rendered.getByText('Failed because null')).toBeInTheDocument()\n  })\n\n  it('should be able to call `onError` and `onSettled` after each failed mutate', async () => {\n    const onErrorMock = vi.fn()\n    const onSettledMock = vi.fn()\n    let count = 0\n\n    function Page() {\n      const { mutate } = useMutation({\n        mutationFn: (vars: { count: number }) => {\n          const error = new Error(\n            `Expected mock error. All is well! ${vars.count}`,\n          )\n          error.stack = ''\n          return Promise.reject(error)\n        },\n        onError: (error: Error) => {\n          onErrorMock(error.message)\n        },\n        onSettled: (_data, error) => {\n          onSettledMock(error?.message)\n        },\n      })\n\n      return (\n        <div>\n          <h1>{count}</h1>\n          <button onClick={() => mutate({ count: ++count })}>mutate</button>\n        </div>\n      )\n    }\n\n    const { getByRole } = renderWithClient(queryClient, <Page />)\n\n    expect(getByRole('heading').textContent).toBe('0')\n\n    fireEvent.click(getByRole('button', { name: /mutate/i }))\n    fireEvent.click(getByRole('button', { name: /mutate/i }))\n    fireEvent.click(getByRole('button', { name: /mutate/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(getByRole('heading').textContent).toBe('3')\n    expect(onErrorMock).toHaveBeenCalledTimes(3)\n    expect(onErrorMock).toHaveBeenCalledWith(\n      'Expected mock error. All is well! 1',\n    )\n    expect(onErrorMock).toHaveBeenCalledWith(\n      'Expected mock error. All is well! 2',\n    )\n    expect(onErrorMock).toHaveBeenCalledWith(\n      'Expected mock error. All is well! 3',\n    )\n\n    expect(onSettledMock).toHaveBeenCalledTimes(3)\n    expect(onSettledMock).toHaveBeenCalledWith(\n      'Expected mock error. All is well! 1',\n    )\n    expect(onSettledMock).toHaveBeenCalledWith(\n      'Expected mock error. All is well! 2',\n    )\n    expect(onSettledMock).toHaveBeenCalledWith(\n      'Expected mock error. All is well! 3',\n    )\n  })\n\n  it('should be able to override the useMutation success callbacks', async () => {\n    const callbacks: Array<string> = []\n\n    function Page() {\n      const { mutateAsync } = useMutation({\n        mutationFn: (text: string) => Promise.resolve(text),\n        onSuccess: () => {\n          callbacks.push('useMutation.onSuccess')\n          return Promise.resolve()\n        },\n        onSettled: () => {\n          callbacks.push('useMutation.onSettled')\n          return Promise.resolve()\n        },\n      })\n\n      React.useEffect(() => {\n        setActTimeout(async () => {\n          try {\n            const result = await mutateAsync('todo', {\n              onSuccess: () => {\n                callbacks.push('mutateAsync.onSuccess')\n                return Promise.resolve()\n              },\n              onSettled: () => {\n                callbacks.push('mutateAsync.onSettled')\n                return Promise.resolve()\n              },\n            })\n            callbacks.push(`mutateAsync.result:${result}`)\n          } catch {}\n        }, 10)\n      }, [mutateAsync])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(callbacks).toEqual([\n      'useMutation.onSuccess',\n      'useMutation.onSettled',\n      'mutateAsync.onSuccess',\n      'mutateAsync.onSettled',\n      'mutateAsync.result:todo',\n    ])\n  })\n\n  it('should be able to override the error callbacks when using mutateAsync', async () => {\n    const callbacks: Array<string> = []\n\n    function Page() {\n      const { mutateAsync } = useMutation({\n        mutationFn: async (_text: string) => Promise.reject(new Error('oops')),\n        onError: () => {\n          callbacks.push('useMutation.onError')\n          return Promise.resolve()\n        },\n        onSettled: () => {\n          callbacks.push('useMutation.onSettled')\n          return Promise.resolve()\n        },\n      })\n\n      React.useEffect(() => {\n        setActTimeout(async () => {\n          try {\n            await mutateAsync('todo', {\n              onError: () => {\n                callbacks.push('mutateAsync.onError')\n                return Promise.resolve()\n              },\n              onSettled: () => {\n                callbacks.push('mutateAsync.onSettled')\n                return Promise.resolve()\n              },\n            })\n          } catch (error) {\n            callbacks.push(`mutateAsync.error:${(error as Error).message}`)\n          }\n        }, 10)\n      }, [mutateAsync])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(callbacks).toEqual([\n      'useMutation.onError',\n      'useMutation.onSettled',\n      'mutateAsync.onError',\n      'mutateAsync.onSettled',\n      'mutateAsync.error:oops',\n    ])\n  })\n\n  it('should be able to use mutation defaults', async () => {\n    const key = queryKey()\n\n    queryClient.setMutationDefaults(key, {\n      mutationFn: async (text: string) => {\n        await sleep(10)\n        return text\n      },\n    })\n\n    const states: Array<UseMutationResult<any, any, any, any>> = []\n\n    function Page() {\n      const state = useMutation<string, unknown, string>({ mutationKey: key })\n\n      states.push(state)\n\n      const { mutate } = state\n\n      React.useEffect(() => {\n        setActTimeout(() => {\n          mutate('todo')\n        }, 10)\n      }, [mutate])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(21)\n\n    expect(states.length).toBe(3)\n    expect(states[0]).toMatchObject({ data: undefined, isPending: false })\n    expect(states[1]).toMatchObject({ data: undefined, isPending: true })\n    expect(states[2]).toMatchObject({ data: 'todo', isPending: false })\n  })\n\n  it('should be able to retry a failed mutation', async () => {\n    let count = 0\n\n    function Page() {\n      const { mutate } = useMutation({\n        mutationFn: (_text: string) => {\n          count++\n          return Promise.reject(new Error('oops'))\n        },\n        retry: 1,\n        retryDelay: 5,\n      })\n\n      React.useEffect(() => {\n        setActTimeout(() => {\n          mutate('todo')\n        }, 10)\n      }, [mutate])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(15)\n\n    expect(count).toBe(2)\n  })\n\n  it('should not retry mutations while offline', async () => {\n    const onlineMock = mockOnlineManagerIsOnline(false)\n\n    let count = 0\n\n    function Page() {\n      const mutation = useMutation({\n        mutationFn: (_text: string) => {\n          count++\n          return Promise.reject(new Error('oops'))\n        },\n        retry: 1,\n        retryDelay: 5,\n      })\n\n      return (\n        <div>\n          <button onClick={() => mutation.mutate('todo')}>mutate</button>\n          <div>\n            error:{' '}\n            {mutation.error instanceof Error ? mutation.error.message : 'null'},\n            status: {mutation.status}, isPaused: {String(mutation.isPaused)}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(\n      rendered.getByText('error: null, status: idle, isPaused: false'),\n    ).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(\n      rendered.getByText('error: null, status: pending, isPaused: true'),\n    ).toBeInTheDocument()\n\n    expect(count).toBe(0)\n\n    onlineMock.mockReturnValue(true)\n    queryClient.getMutationCache().resumePausedMutations()\n\n    await vi.advanceTimersByTimeAsync(6)\n    expect(\n      rendered.getByText('error: oops, status: error, isPaused: false'),\n    ).toBeInTheDocument()\n\n    expect(count).toBe(2)\n    onlineMock.mockRestore()\n  })\n\n  it('should call onMutate even if paused', async () => {\n    const onlineMock = mockOnlineManagerIsOnline(false)\n    const onMutate = vi.fn()\n    let count = 0\n\n    function Page() {\n      const mutation = useMutation({\n        mutationFn: async (_text: string) => {\n          count++\n          await sleep(10)\n          return count\n        },\n        onMutate,\n      })\n\n      return (\n        <div>\n          <button onClick={() => mutation.mutate('todo')}>mutate</button>\n          <div>\n            data: {mutation.data ?? 'null'}, status: {mutation.status},\n            isPaused: {String(mutation.isPaused)}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(\n      rendered.getByText('data: null, status: idle, isPaused: false'),\n    ).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(\n      rendered.getByText('data: null, status: pending, isPaused: true'),\n    ).toBeInTheDocument()\n\n    expect(onMutate).toHaveBeenCalledTimes(1)\n    expect(onMutate).toHaveBeenCalledWith('todo', {\n      client: queryClient,\n      meta: undefined,\n      mutationKey: undefined,\n    })\n\n    onlineMock.mockReturnValue(true)\n    queryClient.getMutationCache().resumePausedMutations()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(\n      rendered.getByText('data: 1, status: success, isPaused: false'),\n    ).toBeInTheDocument()\n\n    expect(onMutate).toHaveBeenCalledTimes(1)\n    expect(count).toBe(1)\n\n    onlineMock.mockRestore()\n  })\n\n  it('should optimistically go to paused state if offline', async () => {\n    const onlineMock = mockOnlineManagerIsOnline(false)\n    let count = 0\n    const states: Array<string> = []\n\n    function Page() {\n      const mutation = useMutation({\n        mutationFn: async (_text: string) => {\n          count++\n          await sleep(10)\n          return count\n        },\n      })\n\n      states.push(`${mutation.status}, ${mutation.isPaused}`)\n\n      return (\n        <div>\n          <button onClick={() => mutation.mutate('todo')}>mutate</button>\n          <div>\n            data: {mutation.data ?? 'null'}, status: {mutation.status},\n            isPaused: {String(mutation.isPaused)}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(\n      rendered.getByText('data: null, status: idle, isPaused: false'),\n    ).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(\n      rendered.getByText('data: null, status: pending, isPaused: true'),\n    ).toBeInTheDocument()\n\n    // no intermediate 'pending, false' state is expected because we don't start mutating!\n    expect(states[0]).toBe('idle, false')\n    expect(states[1]).toBe('pending, true')\n\n    onlineMock.mockReturnValue(true)\n    queryClient.getMutationCache().resumePausedMutations()\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(\n      rendered.getByText('data: 1, status: success, isPaused: false'),\n    ).toBeInTheDocument()\n\n    onlineMock.mockRestore()\n  })\n\n  it('should be able to retry a mutation when online', async () => {\n    const onlineMock = mockOnlineManagerIsOnline(false)\n    const key = queryKey()\n\n    let count = 0\n\n    function Page() {\n      const state = useMutation({\n        mutationKey: key,\n        mutationFn: async (_text: string) => {\n          await sleep(10)\n          count++\n          return count > 1\n            ? Promise.resolve(`data${count}`)\n            : Promise.reject(new Error('oops'))\n        },\n        retry: 1,\n        retryDelay: 5,\n        networkMode: 'offlineFirst',\n      })\n\n      return (\n        <div>\n          <button onClick={() => state.mutate('todo')}>mutate</button>\n          <div>status: {state.status}</div>\n          <div>isPaused: {String(state.isPaused)}</div>\n          <div>data: {state.data ?? 'null'}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('status: idle')).toBeInTheDocument()\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(16)\n    expect(rendered.getByText('isPaused: true')).toBeInTheDocument()\n\n    expect(\n      queryClient.getMutationCache().findAll({ mutationKey: key }).length,\n    ).toBe(1)\n    expect(\n      queryClient.getMutationCache().findAll({ mutationKey: key })[0]?.state,\n    ).toMatchObject({\n      status: 'pending',\n      isPaused: true,\n      failureCount: 1,\n      failureReason: new Error('oops'),\n    })\n\n    onlineMock.mockReturnValue(true)\n    queryClient.getMutationCache().resumePausedMutations()\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: data2')).toBeInTheDocument()\n\n    expect(\n      queryClient.getMutationCache().findAll({ mutationKey: key })[0]?.state,\n    ).toMatchObject({\n      status: 'success',\n      isPaused: false,\n      failureCount: 0,\n      failureReason: null,\n      data: 'data2',\n    })\n\n    onlineMock.mockRestore()\n  })\n\n  // eslint-disable-next-line vitest/expect-expect\n  it('should not change state if unmounted', () => {\n    function Mutates() {\n      const { mutate } = useMutation({ mutationFn: () => sleep(10) })\n      return <button onClick={() => mutate()}>mutate</button>\n    }\n    function Page() {\n      const [mounted, setMounted] = React.useState(true)\n      return (\n        <div>\n          <button onClick={() => setMounted(false)}>unmount</button>\n          {mounted && <Mutates />}\n        </div>\n      )\n    }\n\n    const { getByText } = renderWithClient(queryClient, <Page />)\n    fireEvent.click(getByText('mutate'))\n    fireEvent.click(getByText('unmount'))\n  })\n\n  it('should be able to throw an error when throwOnError is set to true', async () => {\n    const err = new Error('Expected mock error. All is well!')\n    err.stack = ''\n\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    function Page() {\n      const { mutate } = useMutation<string, Error>({\n        mutationFn: () => {\n          return Promise.reject(err)\n        },\n        throwOnError: true,\n      })\n\n      return (\n        <div>\n          <button onClick={() => mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    const { getByText, queryByText } = renderWithClient(\n      queryClient,\n      <ErrorBoundary\n        fallbackRender={() => (\n          <div>\n            <span>error</span>\n          </div>\n        )}\n      >\n        <Page />\n      </ErrorBoundary>,\n    )\n\n    fireEvent.click(getByText('mutate'))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(queryByText('error')).not.toBeNull()\n\n    expect(consoleMock.mock.calls[0]?.[1]).toBe(err)\n\n    consoleMock.mockRestore()\n  })\n\n  it('should be able to throw an error when throwOnError is a function that returns true', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    let boundary = false\n    function Page() {\n      const { mutate, error } = useMutation<string>({\n        mutationFn: () => {\n          const err = new Error('mock error')\n          err.stack = ''\n          return Promise.reject(err)\n        },\n        throwOnError: () => {\n          return boundary\n        },\n      })\n\n      return (\n        <div>\n          <button onClick={() => mutate()}>mutate</button>\n          {error && error.message}\n        </div>\n      )\n    }\n\n    const { getByText, queryByText } = renderWithClient(\n      queryClient,\n      <ErrorBoundary\n        fallbackRender={() => (\n          <div>\n            <span>error boundary</span>\n          </div>\n        )}\n      >\n        <Page />\n      </ErrorBoundary>,\n    )\n\n    // first error goes to component\n    fireEvent.click(getByText('mutate'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(queryByText('mock error')).not.toBeNull()\n\n    // second error goes to boundary\n    boundary = true\n    fireEvent.click(getByText('mutate'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(queryByText('error boundary')).not.toBeNull()\n    consoleMock.mockRestore()\n  })\n\n  it('should pass meta to mutation', async () => {\n    const errorMock = vi.fn()\n    const successMock = vi.fn()\n\n    const queryClientMutationMeta = new QueryClient({\n      mutationCache: new MutationCache({\n        onSuccess: (_, __, ___, mutation) => {\n          successMock(mutation.meta?.metaSuccessMessage)\n        },\n        onError: (_, __, ___, mutation) => {\n          errorMock(mutation.meta?.metaErrorMessage)\n        },\n      }),\n    })\n\n    const metaSuccessMessage = 'mutation succeeded'\n    const metaErrorMessage = 'mutation failed'\n\n    function Page() {\n      const { mutate: succeed, isSuccess } = useMutation({\n        mutationFn: () => Promise.resolve(''),\n        meta: { metaSuccessMessage },\n      })\n      const { mutate: error, isError } = useMutation({\n        mutationFn: () => {\n          return Promise.reject(new Error(''))\n        },\n        meta: { metaErrorMessage },\n      })\n\n      return (\n        <div>\n          <button onClick={() => succeed()}>succeed</button>\n          <button onClick={() => error()}>error</button>\n          {isSuccess && <div>successTest</div>}\n          {isError && <div>errorTest</div>}\n        </div>\n      )\n    }\n\n    const { getByText, queryByText } = renderWithClient(\n      queryClientMutationMeta,\n      <Page />,\n    )\n\n    fireEvent.click(getByText('succeed'))\n    fireEvent.click(getByText('error'))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(queryByText('successTest')).not.toBeNull()\n    expect(queryByText('errorTest')).not.toBeNull()\n\n    expect(successMock).toHaveBeenCalledTimes(1)\n    expect(successMock).toHaveBeenCalledWith(metaSuccessMessage)\n    expect(errorMock).toHaveBeenCalledTimes(1)\n    expect(errorMock).toHaveBeenCalledWith(metaErrorMessage)\n  })\n\n  it('should call cache callbacks when unmounted', async () => {\n    const onSuccess = vi.fn()\n    const onSuccessMutate = vi.fn()\n    const onSettled = vi.fn()\n    const onSettledMutate = vi.fn()\n    const mutationKey = queryKey()\n    let count = 0\n\n    function Page() {\n      const [show, setShow] = React.useState(true)\n      return (\n        <div>\n          <button onClick={() => setShow(false)}>hide</button>\n          {show && <Component />}\n        </div>\n      )\n    }\n\n    function Component() {\n      const mutation = useMutation({\n        mutationFn: async (_text: string) => {\n          count++\n          await sleep(10)\n          return count\n        },\n        mutationKey,\n        gcTime: 0,\n        onSuccess,\n        onSettled,\n      })\n\n      return (\n        <div>\n          <button\n            onClick={() =>\n              mutation.mutate('todo', {\n                onSuccess: onSuccessMutate,\n                onSettled: onSettledMutate,\n              })\n            }\n          >\n            mutate\n          </button>\n          <div>\n            data: {mutation.data ?? 'null'}, status: {mutation.status},\n            isPaused: {String(mutation.isPaused)}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(\n      rendered.getByText('data: null, status: idle, isPaused: false'),\n    ).toBeInTheDocument()\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /hide/i }))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(\n      queryClient.getMutationCache().findAll({ mutationKey }),\n    ).toHaveLength(0)\n\n    expect(count).toBe(1)\n\n    expect(onSuccess).toHaveBeenCalledTimes(1)\n    expect(onSettled).toHaveBeenCalledTimes(1)\n    expect(onSuccessMutate).toHaveBeenCalledTimes(0)\n    expect(onSettledMutate).toHaveBeenCalledTimes(0)\n  })\n\n  it('should call mutate callbacks only for the last observer', async () => {\n    const onSuccess = vi.fn()\n    const onSuccessMutate = vi.fn()\n    const onSettled = vi.fn()\n    const onSettledMutate = vi.fn()\n    let count = 0\n\n    function Page() {\n      const mutation = useMutation({\n        mutationFn: async (text: string) => {\n          count++\n          const result = `result-${text}`\n          await sleep(10)\n          return result\n        },\n        onSuccess,\n        onSettled,\n      })\n\n      return (\n        <div>\n          <button\n            onClick={() =>\n              mutation.mutate('todo1', {\n                onSuccess: onSuccessMutate,\n                onSettled: onSettledMutate,\n              })\n            }\n          >\n            mutate1\n          </button>\n          <button\n            onClick={() =>\n              mutation.mutate('todo2', {\n                onSuccess: onSuccessMutate,\n                onSettled: onSettledMutate,\n              })\n            }\n          >\n            mutate2\n          </button>\n          <div>\n            data: {mutation.data ?? 'null'}, status: {mutation.status}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('data: null, status: idle')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(\n      rendered.getByText('data: result-todo2, status: success'),\n    ).toBeInTheDocument()\n\n    expect(count).toBe(2)\n\n    expect(onSuccess).toHaveBeenCalledTimes(2)\n    expect(onSuccess).toHaveBeenNthCalledWith(\n      1,\n      'result-todo1',\n      'todo1',\n      undefined,\n      {\n        client: queryClient,\n        meta: undefined,\n        mutationKey: undefined,\n      },\n    )\n    expect(onSuccess).toHaveBeenNthCalledWith(\n      2,\n      'result-todo2',\n      'todo2',\n      undefined,\n      {\n        client: queryClient,\n        meta: undefined,\n        mutationKey: undefined,\n      },\n    )\n    expect(onSettled).toHaveBeenCalledTimes(2)\n    expect(onSuccessMutate).toHaveBeenCalledTimes(1)\n    expect(onSuccessMutate).toHaveBeenCalledWith(\n      'result-todo2',\n      'todo2',\n      undefined,\n      {\n        client: queryClient,\n        meta: undefined,\n        mutationKey: undefined,\n      },\n    )\n    expect(onSettledMutate).toHaveBeenCalledTimes(1)\n    expect(onSettledMutate).toHaveBeenCalledWith(\n      'result-todo2',\n      null,\n      'todo2',\n      undefined,\n      {\n        client: queryClient,\n        meta: undefined,\n        mutationKey: undefined,\n      },\n    )\n  })\n\n  it('should go to error state if onSuccess callback errors', async () => {\n    const error = new Error('error from onSuccess')\n    const onError = vi.fn()\n\n    function Page() {\n      const mutation = useMutation({\n        mutationFn: async (_text: string) => {\n          await sleep(10)\n          return 'result'\n        },\n        onSuccess: () => Promise.reject(error),\n        onError,\n      })\n\n      return (\n        <div>\n          <button onClick={() => mutation.mutate('todo')}>mutate</button>\n          <div>status: {mutation.status}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('status: idle')).toBeInTheDocument()\n\n    rendered.getByRole('button', { name: /mutate/i }).click()\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('status: error')).toBeInTheDocument()\n\n    expect(onError).toHaveBeenCalledWith(error, 'todo', undefined, {\n      client: queryClient,\n      meta: undefined,\n      mutationKey: undefined,\n    })\n  })\n\n  it('should go to error state if onError callback errors', async ({\n    onTestFinished,\n  }) => {\n    const unhandledRejectionFn = vi.fn()\n    process.on('unhandledRejection', (error) => unhandledRejectionFn(error))\n    onTestFinished(() => {\n      process.off('unhandledRejection', unhandledRejectionFn)\n    })\n\n    const error = new Error('error from onError')\n    const mutateFnError = new Error('mutateFnError')\n\n    function Page() {\n      const mutation = useMutation({\n        mutationFn: async (_text: string) => {\n          await sleep(10)\n          throw mutateFnError\n        },\n        onError: () => Promise.reject(error),\n      })\n\n      return (\n        <div>\n          <button onClick={() => mutation.mutate('todo')}>mutate</button>\n          <div>\n            error:{' '}\n            {mutation.error instanceof Error ? mutation.error.message : 'null'},\n            status: {mutation.status}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('error: null, status: idle')).toBeInTheDocument()\n\n    rendered.getByRole('button', { name: /mutate/i }).click()\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(\n      rendered.getByText('error: mutateFnError, status: error'),\n    ).toBeInTheDocument()\n  })\n\n  it('should go to error state if onSettled callback errors', async ({\n    onTestFinished,\n  }) => {\n    const unhandledRejectionFn = vi.fn()\n    process.on('unhandledRejection', (error) => unhandledRejectionFn(error))\n    onTestFinished(() => {\n      process.off('unhandledRejection', unhandledRejectionFn)\n    })\n\n    const error = new Error('error from onSettled')\n    const mutateFnError = new Error('mutateFnError')\n    const onError = vi.fn()\n\n    function Page() {\n      const mutation = useMutation({\n        mutationFn: async (_text: string) => {\n          await sleep(10)\n          throw mutateFnError\n        },\n        onSettled: () => Promise.reject(error),\n        onError,\n      })\n\n      return (\n        <div>\n          <button onClick={() => mutation.mutate('todo')}>mutate</button>\n          <div>\n            error:{' '}\n            {mutation.error instanceof Error ? mutation.error.message : 'null'},\n            status: {mutation.status}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('error: null, status: idle')).toBeInTheDocument()\n\n    rendered.getByRole('button', { name: /mutate/i }).click()\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(\n      rendered.getByText('error: mutateFnError, status: error'),\n    ).toBeInTheDocument()\n    expect(onError).toHaveBeenCalledWith(mutateFnError, 'todo', undefined, {\n      client: queryClient,\n      meta: undefined,\n      mutationKey: undefined,\n    })\n  })\n\n  it('should use provided custom queryClient', async () => {\n    function Page() {\n      const mutation = useMutation(\n        {\n          mutationFn: async (text: string) => {\n            return Promise.resolve(text)\n          },\n        },\n        queryClient,\n      )\n\n      return (\n        <div>\n          <button onClick={() => mutation.mutate('custom client')}>\n            mutate\n          </button>\n          <div>\n            data: {mutation.data ?? 'null'}, status: {mutation.status}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = render(<Page></Page>)\n\n    expect(rendered.getByText('data: null, status: idle')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(\n      rendered.getByText('data: custom client, status: success'),\n    ).toBeInTheDocument()\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/useMutationState.test-d.tsx",
    "content": "import { describe, expectTypeOf, it } from 'vitest'\nimport { useMutationState } from '../useMutationState'\nimport type { MutationState, MutationStatus } from '@tanstack/query-core'\n\ndescribe('useMutationState', () => {\n  it('should default to QueryState', () => {\n    const result = useMutationState({\n      filters: { status: 'pending' },\n    })\n\n    expectTypeOf(result).toEqualTypeOf<\n      Array<MutationState<unknown, Error, unknown, unknown>>\n    >()\n  })\n  it('should infer with select', () => {\n    const result = useMutationState({\n      filters: { status: 'pending' },\n      select: (mutation) => mutation.state.status,\n    })\n\n    expectTypeOf(result).toEqualTypeOf<Array<MutationStatus>>()\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/useMutationState.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { fireEvent, render } from '@testing-library/react'\nimport * as React from 'react'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { QueryClient, useIsMutating, useMutation, useMutationState } from '..'\nimport { renderWithClient } from './utils'\n\ndescribe('useIsMutating', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should return the number of fetching mutations', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n\n    function IsMutating() {\n      const isMutating = useIsMutating()\n\n      isMutatingArray.push(isMutating)\n\n      return null\n    }\n\n    function Mutations() {\n      const { mutate: mutate1 } = useMutation({\n        mutationKey: ['mutation1'],\n        mutationFn: () => sleep(50).then(() => 'data'),\n      })\n      const { mutate: mutate2 } = useMutation({\n        mutationKey: ['mutation2'],\n        mutationFn: () => sleep(10).then(() => 'data'),\n      })\n\n      return (\n        <div>\n          <button onClick={() => mutate1()}>mutate1</button>\n          <button onClick={() => mutate2()}>mutate2</button>\n        </div>\n      )\n    }\n\n    function Page() {\n      return (\n        <div>\n          <IsMutating />\n          <Mutations />\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    await vi.advanceTimersByTimeAsync(10)\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n\n    // we don't really care if this yields\n    // [ +0, 1, 2, +0 ]\n    // or\n    // [ +0, 1, 2, 1, +0 ]\n    // our batching strategy might yield different results\n\n    await vi.advanceTimersByTimeAsync(41)\n    expect(isMutatingArray[0]).toEqual(0)\n    expect(isMutatingArray[1]).toEqual(1)\n    expect(isMutatingArray[2]).toEqual(2)\n    expect(isMutatingArray[3]).toEqual(1)\n    expect(isMutatingArray[4]).toEqual(0)\n\n    expect(isMutatingArray).toEqual([0, 1, 2, 1, 0])\n  })\n\n  it('should filter correctly by mutationKey', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n\n    function IsMutating() {\n      const isMutating = useIsMutating({ mutationKey: ['mutation1'] })\n      isMutatingArray.push(isMutating)\n      return null\n    }\n\n    function Page() {\n      const { mutate: mutate1 } = useMutation({\n        mutationKey: ['mutation1'],\n        mutationFn: () => sleep(100).then(() => 'data'),\n      })\n      const { mutate: mutate2 } = useMutation({\n        mutationKey: ['mutation2'],\n        mutationFn: () => sleep(100).then(() => 'data'),\n      })\n\n      React.useEffect(() => {\n        mutate1()\n        mutate2()\n      }, [mutate1, mutate2])\n\n      return <IsMutating />\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(101)\n    expect(isMutatingArray).toEqual([0, 1, 0])\n  })\n\n  it('should filter correctly by predicate', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n\n    function IsMutating() {\n      const isMutating = useIsMutating({\n        predicate: (mutation) =>\n          mutation.options.mutationKey?.[0] === 'mutation1',\n      })\n      isMutatingArray.push(isMutating)\n      return null\n    }\n\n    function Page() {\n      const { mutate: mutate1 } = useMutation({\n        mutationKey: ['mutation1'],\n        mutationFn: () => sleep(100).then(() => 'data'),\n      })\n      const { mutate: mutate2 } = useMutation({\n        mutationKey: ['mutation2'],\n        mutationFn: () => sleep(100).then(() => 'data'),\n      })\n\n      React.useEffect(() => {\n        mutate1()\n        mutate2()\n      }, [mutate1, mutate2])\n\n      return <IsMutating />\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(101)\n    expect(isMutatingArray).toEqual([0, 1, 0])\n  })\n\n  it('should use provided custom queryClient', async () => {\n    const queryClient = new QueryClient()\n\n    function Page() {\n      const isMutating = useIsMutating({}, queryClient)\n      const { mutate } = useMutation(\n        {\n          mutationKey: ['mutation1'],\n          mutationFn: () => sleep(10).then(() => 'data'),\n        },\n        queryClient,\n      )\n\n      React.useEffect(() => {\n        mutate()\n      }, [mutate])\n\n      return (\n        <div>\n          <div>mutating: {isMutating}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(<Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('mutating: 1')).toBeInTheDocument()\n  })\n})\n\ndescribe('useMutationState', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should return variables after calling mutate', async () => {\n    const queryClient = new QueryClient()\n    const variables: Array<Array<unknown>> = []\n    const mutationKey = ['mutation']\n\n    function Variables() {\n      variables.push(\n        useMutationState({\n          filters: { mutationKey, status: 'pending' },\n          select: (mutation) => mutation.state.variables,\n        }),\n      )\n\n      return null\n    }\n\n    function Mutate() {\n      const { mutate, data } = useMutation({\n        mutationKey,\n        mutationFn: (input: number) => sleep(150).then(() => 'data' + input),\n      })\n\n      return (\n        <div>\n          data: {data ?? 'null'}\n          <button onClick={() => mutate(1)}>mutate</button>\n        </div>\n      )\n    }\n\n    function Page() {\n      return (\n        <div>\n          <Variables />\n          <Mutate />\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('data: null')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(151)\n    expect(rendered.getByText('data: data1')).toBeInTheDocument()\n\n    expect(variables).toEqual([[], [1], []])\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/usePrefetchInfiniteQuery.test-d.tsx",
    "content": "import { assertType, describe, expectTypeOf, it } from 'vitest'\nimport { usePrefetchInfiniteQuery } from '..'\n\ndescribe('usePrefetchInfiniteQuery', () => {\n  it('should return nothing', () => {\n    const result = usePrefetchInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n      initialPageParam: 1,\n      getNextPageParam: () => 1,\n    })\n\n    expectTypeOf(result).toEqualTypeOf<void>()\n  })\n\n  it('should require initialPageParam and getNextPageParam', () => {\n    assertType(\n      // @ts-expect-error TS2345\n      usePrefetchInfiniteQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n      }),\n    )\n  })\n\n  it('should not allow refetchInterval, enabled or throwOnError options', () => {\n    assertType(\n      usePrefetchInfiniteQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        initialPageParam: 1,\n        getNextPageParam: () => 1,\n        // @ts-expect-error TS2353\n        refetchInterval: 1000,\n      }),\n    )\n\n    assertType(\n      usePrefetchInfiniteQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        initialPageParam: 1,\n        getNextPageParam: () => 1,\n        // @ts-expect-error TS2353\n        enabled: true,\n      }),\n    )\n\n    assertType(\n      usePrefetchInfiniteQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        initialPageParam: 1,\n        getNextPageParam: () => 1,\n        // @ts-expect-error TS2353\n        throwOnError: true,\n      }),\n    )\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/usePrefetchInfiniteQuery.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport React from 'react'\nimport { act, fireEvent } from '@testing-library/react'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport {\n  QueryCache,\n  QueryClient,\n  usePrefetchInfiniteQuery,\n  useSuspenseInfiniteQuery,\n} from '..'\nimport { renderWithClient } from './utils'\nimport type { InfiniteData, UseSuspenseInfiniteQueryOptions } from '..'\nimport type { Mock } from 'vitest'\n\nconst createFallback = () =>\n  vi.fn().mockImplementation(() => <div>Loading...</div>)\n\nconst generateInfiniteQueryOptions = (\n  data: Array<{ data: string; currentPage: number; totalPages: number }>,\n) => {\n  let currentPage = 0\n\n  return {\n    queryFn: vi\n      .fn<(...args: Array<any>) => Promise<(typeof data)[number]>>()\n      .mockImplementation(async () => {\n        const currentPageData = data[currentPage]\n        if (!currentPageData) {\n          throw new Error('No data defined for page ' + currentPage)\n        }\n\n        await sleep(10)\n        currentPage++\n\n        return currentPageData\n      }),\n    initialPageParam: 1,\n    getNextPageParam: (lastPage: (typeof data)[number]) =>\n      lastPage.currentPage === lastPage.totalPages\n        ? undefined\n        : lastPage.currentPage + 1,\n  }\n}\n\ndescribe('usePrefetchInfiniteQuery', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  const queryCache = new QueryCache()\n  const queryClient = new QueryClient({ queryCache })\n\n  function Suspended<T = unknown>(props: {\n    queryOpts: UseSuspenseInfiniteQueryOptions<\n      T,\n      Error,\n      InfiniteData<T>,\n      Array<string>,\n      any\n    >\n    renderPage: (page: T) => React.JSX.Element\n  }) {\n    const state = useSuspenseInfiniteQuery(props.queryOpts)\n\n    return (\n      <div>\n        {state.data.pages.map((page, index) => (\n          <div key={index}>{props.renderPage(page)}</div>\n        ))}\n        <button onClick={() => state.fetchNextPage()}>Next Page</button>\n      </div>\n    )\n  }\n\n  it('should prefetch an infinite query if query state does not exist', async () => {\n    const Fallback = createFallback()\n    const data = [\n      { data: 'Do you fetch on render?', currentPage: 1, totalPages: 3 },\n      { data: 'Or do you render as you fetch?', currentPage: 2, totalPages: 3 },\n      {\n        data: 'Either way, Tanstack Query helps you!',\n        currentPage: 3,\n        totalPages: 3,\n      },\n    ]\n\n    const queryOpts = {\n      queryKey: queryKey(),\n      ...generateInfiniteQueryOptions(data),\n    }\n\n    function App() {\n      usePrefetchInfiniteQuery({ ...queryOpts, pages: data.length })\n\n      return (\n        <React.Suspense fallback={<Fallback />}>\n          <Suspended\n            queryOpts={queryOpts}\n            renderPage={(page) => <div>data: {page.data}</div>}\n          />\n        </React.Suspense>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    await act(() => vi.advanceTimersByTimeAsync(30))\n    rendered.getByText('data: Do you fetch on render?')\n    fireEvent.click(rendered.getByText('Next Page'))\n    expect(\n      rendered.getByText('data: Or do you render as you fetch?'),\n    ).toBeInTheDocument()\n    fireEvent.click(rendered.getByText('Next Page'))\n    expect(\n      rendered.getByText('data: Either way, Tanstack Query helps you!'),\n    ).toBeInTheDocument()\n    expect(Fallback).toHaveBeenCalledTimes(1)\n    expect(queryOpts.queryFn).toHaveBeenCalledTimes(3)\n  })\n\n  it('should not display fallback if the query cache is already populated', async () => {\n    const Fallback = createFallback()\n    const queryOpts = {\n      queryKey: queryKey(),\n      ...generateInfiniteQueryOptions([\n        { data: 'Prefetch rocks!', currentPage: 1, totalPages: 3 },\n        { data: 'No waterfalls, boy!', currentPage: 2, totalPages: 3 },\n        { data: 'Tanstack Query #ftw', currentPage: 3, totalPages: 3 },\n      ]),\n    }\n\n    queryClient.prefetchInfiniteQuery({ ...queryOpts, pages: 3 })\n    await vi.advanceTimersByTimeAsync(30)\n    ;(queryOpts.queryFn as Mock).mockClear()\n\n    function App() {\n      usePrefetchInfiniteQuery(queryOpts)\n\n      return (\n        <React.Suspense fallback={<Fallback />}>\n          <Suspended\n            queryOpts={queryOpts}\n            renderPage={(page) => <div>data: {page.data}</div>}\n          />\n        </React.Suspense>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    expect(rendered.getByText('data: Prefetch rocks!')).toBeInTheDocument()\n    fireEvent.click(rendered.getByText('Next Page'))\n    expect(rendered.getByText('data: No waterfalls, boy!')).toBeInTheDocument()\n    fireEvent.click(rendered.getByText('Next Page'))\n    expect(rendered.getByText('data: Tanstack Query #ftw')).toBeInTheDocument()\n    expect(queryOpts.queryFn).not.toHaveBeenCalled()\n    expect(Fallback).not.toHaveBeenCalled()\n  })\n\n  it('should not create an endless loop when using inside a suspense boundary', async () => {\n    const queryOpts = {\n      queryKey: queryKey(),\n      ...generateInfiniteQueryOptions([\n        { data: 'Infinite Page 1', currentPage: 1, totalPages: 3 },\n        { data: 'Infinite Page 2', currentPage: 1, totalPages: 3 },\n        { data: 'Infinite Page 3', currentPage: 1, totalPages: 3 },\n      ]),\n    }\n\n    function Prefetch({ children }: { children: React.ReactNode }) {\n      usePrefetchInfiniteQuery(queryOpts)\n      return <>{children}</>\n    }\n\n    function App() {\n      return (\n        <React.Suspense>\n          <Prefetch>\n            <Suspended\n              queryOpts={queryOpts}\n              renderPage={(page) => <div>data: {page.data}</div>}\n            />\n          </Prefetch>\n        </React.Suspense>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    rendered.getByText('data: Infinite Page 1')\n    fireEvent.click(rendered.getByText('Next Page'))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: Infinite Page 2')).toBeInTheDocument()\n    fireEvent.click(rendered.getByText('Next Page'))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: Infinite Page 3')).toBeInTheDocument()\n    expect(queryOpts.queryFn).toHaveBeenCalledTimes(3)\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/usePrefetchQuery.test-d.tsx",
    "content": "import { assertType, describe, expectTypeOf, it } from 'vitest'\nimport { skipToken, usePrefetchQuery } from '..'\n\ndescribe('usePrefetchQuery', () => {\n  it('should return nothing', () => {\n    const result = usePrefetchQuery({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    expectTypeOf(result).toEqualTypeOf<void>()\n  })\n\n  it('should not allow refetchInterval, enabled or throwOnError options', () => {\n    assertType(\n      usePrefetchQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        // @ts-expect-error TS2345\n        refetchInterval: 1000,\n      }),\n    )\n\n    assertType(\n      usePrefetchQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        // @ts-expect-error TS2345\n        enabled: true,\n      }),\n    )\n\n    assertType(\n      usePrefetchQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        // @ts-expect-error TS2345\n        throwOnError: true,\n      }),\n    )\n  })\n\n  it('should not allow skipToken in queryFn', () => {\n    assertType(\n      usePrefetchQuery({\n        queryKey: ['key'],\n        // @ts-expect-error\n        queryFn: skipToken,\n      }),\n    )\n    assertType(\n      usePrefetchQuery({\n        queryKey: ['key'],\n        // @ts-expect-error\n        queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),\n      }),\n    )\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/usePrefetchQuery.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport React from 'react'\nimport { act, fireEvent } from '@testing-library/react'\nimport { ErrorBoundary } from 'react-error-boundary'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport {\n  QueryCache,\n  QueryClient,\n  usePrefetchQuery,\n  useQueryErrorResetBoundary,\n  useSuspenseQuery,\n} from '..'\nimport { renderWithClient } from './utils'\n\nimport type { UseSuspenseQueryOptions } from '..'\n\nconst generateQueryFn = (data: string) =>\n  vi\n    .fn<(...args: Array<any>) => Promise<string>>()\n    .mockImplementation(async () => {\n      await sleep(10)\n\n      return data\n    })\n\ndescribe('usePrefetchQuery', () => {\n  const queryCache = new QueryCache()\n  const queryClient = new QueryClient({ queryCache })\n\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  function Suspended<TData = unknown>(props: {\n    queryOpts: UseSuspenseQueryOptions<TData, Error, TData, Array<string>>\n    children?: React.ReactNode\n  }) {\n    const state = useSuspenseQuery(props.queryOpts)\n\n    return (\n      <div>\n        <div>data: {String(state.data)}</div>\n        {props.children}\n      </div>\n    )\n  }\n\n  it('should prefetch query if query state does not exist', async () => {\n    const queryOpts = {\n      queryKey: queryKey(),\n      queryFn: generateQueryFn('prefetchQuery'),\n    }\n\n    const componentQueryOpts = {\n      ...queryOpts,\n      queryFn: generateQueryFn('useSuspenseQuery'),\n    }\n\n    function App() {\n      usePrefetchQuery(queryOpts)\n\n      return (\n        <React.Suspense fallback=\"Loading...\">\n          <Suspended queryOpts={componentQueryOpts} />\n        </React.Suspense>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data: prefetchQuery')).toBeInTheDocument()\n    expect(queryOpts.queryFn).toHaveBeenCalledTimes(1)\n  })\n\n  it('should not prefetch query if query state exists', async () => {\n    const queryOpts = {\n      queryKey: queryKey(),\n      queryFn: generateQueryFn('The usePrefetchQuery hook is smart!'),\n    }\n\n    function App() {\n      usePrefetchQuery(queryOpts)\n\n      return (\n        <React.Suspense fallback=\"Loading...\">\n          <Suspended queryOpts={queryOpts} />\n        </React.Suspense>\n      )\n    }\n\n    queryClient.fetchQuery(queryOpts)\n    await vi.advanceTimersByTimeAsync(10)\n    queryOpts.queryFn.mockClear()\n    const rendered = renderWithClient(queryClient, <App />)\n\n    expect(rendered.queryByText('fetching: true')).not.toBeInTheDocument()\n    expect(\n      rendered.getByText('data: The usePrefetchQuery hook is smart!'),\n    ).toBeInTheDocument()\n    expect(queryOpts.queryFn).not.toHaveBeenCalled()\n  })\n\n  it('should let errors fall through and not refetch failed queries', async () => {\n    const consoleMock = vi.spyOn(console, 'error')\n    consoleMock.mockImplementation(() => undefined)\n    const queryFn = generateQueryFn('Not an error')\n\n    const queryOpts = {\n      queryKey: queryKey(),\n      queryFn,\n    }\n\n    queryFn.mockImplementationOnce(async () => {\n      await sleep(10)\n\n      throw new Error('Oops! Server error!')\n    })\n\n    function App() {\n      usePrefetchQuery(queryOpts)\n\n      return (\n        <ErrorBoundary fallbackRender={() => <div>Oops!</div>}>\n          <React.Suspense fallback=\"Loading...\">\n            <Suspended queryOpts={queryOpts} />\n          </React.Suspense>\n        </ErrorBoundary>\n      )\n    }\n\n    queryClient.prefetchQuery(queryOpts)\n    await vi.advanceTimersByTimeAsync(10)\n    queryFn.mockClear()\n    const rendered = renderWithClient(queryClient, <App />)\n\n    expect(rendered.getByText('Oops!')).toBeInTheDocument()\n    expect(rendered.queryByText('data: Not an error')).not.toBeInTheDocument()\n    expect(queryOpts.queryFn).not.toHaveBeenCalled()\n\n    consoleMock.mockRestore()\n  })\n\n  it('should not create an endless loop when using inside a suspense boundary', async () => {\n    const queryFn = generateQueryFn('prefetchedQuery')\n\n    const queryOpts = {\n      queryKey: queryKey(),\n      queryFn,\n    }\n\n    function Prefetch({ children }: { children: React.ReactNode }) {\n      usePrefetchQuery(queryOpts)\n      return <>{children}</>\n    }\n\n    function App() {\n      return (\n        <React.Suspense>\n          <Prefetch>\n            <Suspended queryOpts={queryOpts} />\n          </Prefetch>\n        </React.Suspense>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data: prefetchedQuery')).toBeInTheDocument()\n    expect(queryOpts.queryFn).toHaveBeenCalledTimes(1)\n  })\n\n  it('should be able to recover from errors and try fetching again', async () => {\n    const consoleMock = vi.spyOn(console, 'error')\n    consoleMock.mockImplementation(() => undefined)\n    const queryFn = generateQueryFn('This is fine :dog: :fire:')\n\n    const queryOpts = {\n      queryKey: queryKey(),\n      queryFn,\n    }\n\n    queryFn.mockImplementationOnce(async () => {\n      await sleep(10)\n\n      throw new Error('Oops! Server error!')\n    })\n\n    function App() {\n      const { reset } = useQueryErrorResetBoundary()\n      usePrefetchQuery(queryOpts)\n\n      return (\n        <ErrorBoundary\n          onReset={reset}\n          fallbackRender={({ resetErrorBoundary }) => (\n            <div>\n              <div>Oops!</div>\n              <button onClick={resetErrorBoundary}>Try again</button>\n            </div>\n          )}\n        >\n          <React.Suspense fallback=\"Loading...\">\n            <Suspended queryOpts={queryOpts} />\n          </React.Suspense>\n        </ErrorBoundary>\n      )\n    }\n\n    queryClient.prefetchQuery(queryOpts)\n    await vi.advanceTimersByTimeAsync(10)\n    queryFn.mockClear()\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    expect(rendered.getByText('Oops!')).toBeInTheDocument()\n    fireEvent.click(rendered.getByText('Try again'))\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(\n      rendered.getByText('data: This is fine :dog: :fire:'),\n    ).toBeInTheDocument()\n    expect(queryOpts.queryFn).toHaveBeenCalledTimes(1)\n    consoleMock.mockRestore()\n  })\n\n  it('should not create a suspense waterfall if prefetch is fired', async () => {\n    const firstQueryOpts = {\n      queryKey: queryKey(),\n      queryFn: generateQueryFn('Prefetch is nice!'),\n    }\n\n    const secondQueryOpts = {\n      queryKey: queryKey(),\n      queryFn: generateQueryFn('Prefetch is really nice!!'),\n    }\n\n    const thirdQueryOpts = {\n      queryKey: queryKey(),\n      queryFn: generateQueryFn('Prefetch does not create waterfalls!!'),\n    }\n\n    const Fallback = vi.fn().mockImplementation(() => <div>Loading...</div>)\n\n    function App() {\n      usePrefetchQuery(firstQueryOpts)\n      usePrefetchQuery(secondQueryOpts)\n      usePrefetchQuery(thirdQueryOpts)\n\n      return (\n        <React.Suspense fallback={<Fallback />}>\n          <Suspended queryOpts={firstQueryOpts}>\n            <Suspended queryOpts={secondQueryOpts}>\n              <Suspended queryOpts={thirdQueryOpts} />\n            </Suspended>\n          </Suspended>\n        </React.Suspense>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n    expect(\n      queryClient.getQueryState(firstQueryOpts.queryKey)?.fetchStatus,\n    ).toBe('fetching')\n    expect(\n      queryClient.getQueryState(secondQueryOpts.queryKey)?.fetchStatus,\n    ).toBe('fetching')\n    expect(\n      queryClient.getQueryState(thirdQueryOpts.queryKey)?.fetchStatus,\n    ).toBe('fetching')\n    expect(rendered.getByText('Loading...')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data: Prefetch is nice!')).toBeInTheDocument()\n    expect(\n      rendered.getByText('data: Prefetch is really nice!!'),\n    ).toBeInTheDocument()\n    expect(\n      rendered.getByText('data: Prefetch does not create waterfalls!!'),\n    ).toBeInTheDocument()\n    expect(Fallback).toHaveBeenCalledTimes(1)\n    expect(firstQueryOpts.queryFn).toHaveBeenCalledTimes(1)\n    expect(secondQueryOpts.queryFn).toHaveBeenCalledTimes(1)\n    expect(thirdQueryOpts.queryFn).toHaveBeenCalledTimes(1)\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/useQueries.test-d.tsx",
    "content": "import { describe, expectTypeOf, it } from 'vitest'\nimport { skipToken } from '..'\nimport { useQueries } from '../useQueries'\nimport { queryOptions } from '../queryOptions'\nimport type { OmitKeyof } from '..'\nimport type { UseQueryOptions, UseQueryResult } from '../types'\n\ndescribe('UseQueries config object overload', () => {\n  it('TData should always be defined when initialData is provided as an object', () => {\n    const query1 = {\n      queryKey: ['key1'],\n      queryFn: () => {\n        return {\n          wow: true,\n        }\n      },\n      initialData: {\n        wow: false,\n      },\n    }\n\n    const query2 = {\n      queryKey: ['key2'],\n      queryFn: () => 'Query Data',\n      initialData: 'initial data',\n    }\n\n    const query3 = {\n      queryKey: ['key2'],\n      queryFn: () => 'Query Data',\n    }\n\n    const queryResults = useQueries({ queries: [query1, query2, query3] })\n\n    const query1Data = queryResults[0].data\n    const query2Data = queryResults[1].data\n    const query3Data = queryResults[2].data\n\n    expectTypeOf(query1Data).toEqualTypeOf<{ wow: boolean }>()\n    expectTypeOf(query2Data).toEqualTypeOf<string>()\n    expectTypeOf(query3Data).toEqualTypeOf<string | undefined>()\n  })\n\n  it('TData should be defined when passed through queryOptions', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => {\n        return {\n          wow: true,\n        }\n      },\n      initialData: {\n        wow: true,\n      },\n    })\n    const queryResults = useQueries({ queries: [options] })\n\n    const data = queryResults[0].data\n\n    expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n  })\n\n  it('should be possible to define a different TData than TQueryFnData using select with queryOptions spread into useQuery', () => {\n    const query1 = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(1),\n      select: (data) => data > 1,\n    })\n\n    const query2 = {\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(1),\n      select: (data: number) => data > 1,\n    }\n\n    const queryResults = useQueries({ queries: [query1, query2] })\n    const query1Data = queryResults[0].data\n    const query2Data = queryResults[1].data\n\n    expectTypeOf(query1Data).toEqualTypeOf<boolean | undefined>()\n    expectTypeOf(query2Data).toEqualTypeOf<boolean | undefined>()\n  })\n\n  it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => {\n    const queryResults = useQueries({\n      queries: [\n        {\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n          initialData: () => undefined as { wow: boolean } | undefined,\n        },\n      ],\n    })\n\n    const data = queryResults[0].data\n\n    expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()\n  })\n\n  describe('custom hook', () => {\n    it('should allow custom hooks using UseQueryOptions', () => {\n      type Data = string\n\n      const useCustomQueries = (\n        options?: OmitKeyof<UseQueryOptions<Data>, 'queryKey' | 'queryFn'>,\n      ) => {\n        return useQueries({\n          queries: [\n            {\n              ...options,\n              queryKey: ['todos-key'],\n              queryFn: () => Promise.resolve('data'),\n            },\n          ],\n        })\n      }\n\n      const queryResults = useCustomQueries()\n      const data = queryResults[0].data\n\n      expectTypeOf(data).toEqualTypeOf<Data | undefined>()\n    })\n  })\n\n  it('TData should have correct type when conditional skipToken is passed', () => {\n    const queryResults = useQueries({\n      queries: [\n        {\n          queryKey: ['withSkipToken'],\n          queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),\n        },\n      ],\n    })\n\n    const firstResult = queryResults[0]\n\n    expectTypeOf(firstResult).toEqualTypeOf<UseQueryResult<number, Error>>()\n    expectTypeOf(firstResult.data).toEqualTypeOf<number | undefined>()\n  })\n\n  it('should return correct data for dynamic queries with mixed result types', () => {\n    const Queries1 = {\n      get: () =>\n        queryOptions({\n          queryKey: ['key1'],\n          queryFn: () => Promise.resolve(1),\n        }),\n    }\n    const Queries2 = {\n      get: () =>\n        queryOptions({\n          queryKey: ['key2'],\n          queryFn: () => Promise.resolve(true),\n        }),\n    }\n\n    const queries1List = [1, 2, 3].map(() => ({ ...Queries1.get() }))\n    const result = useQueries({\n      queries: [...queries1List, { ...Queries2.get() }],\n    })\n\n    expectTypeOf(result).toEqualTypeOf<\n      [...Array<UseQueryResult<number, Error>>, UseQueryResult<boolean, Error>]\n    >()\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/useQueries.test.tsx",
    "content": "import {\n  afterEach,\n  beforeEach,\n  describe,\n  expect,\n  expectTypeOf,\n  it,\n  vi,\n} from 'vitest'\nimport { fireEvent, render } from '@testing-library/react'\nimport * as React from 'react'\nimport { ErrorBoundary } from 'react-error-boundary'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport {\n  IsRestoringProvider,\n  QueryCache,\n  QueryClient,\n  queryOptions,\n  skipToken,\n  useQueries,\n} from '..'\nimport { renderWithClient } from './utils'\nimport type {\n  QueryFunction,\n  QueryKey,\n  QueryObserverResult,\n  UseQueryOptions,\n  UseQueryResult,\n} from '..'\nimport type { QueryFunctionContext } from '@tanstack/query-core'\n\ndescribe('useQueries', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  const queryCache = new QueryCache()\n  const queryClient = new QueryClient({ queryCache })\n\n  it('should return the correct states', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const results: Array<Array<UseQueryResult>> = []\n\n    function Page() {\n      const result = useQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: async () => {\n              await sleep(10)\n              return 1\n            },\n          },\n          {\n            queryKey: key2,\n            queryFn: async () => {\n              await sleep(200)\n              return 2\n            },\n          },\n        ],\n      })\n      results.push(result)\n\n      return (\n        <div>\n          <div>\n            data1: {String(result[0].data ?? 'null')}, data2:{' '}\n            {String(result[1].data ?? 'null')}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(201)\n    expect(rendered.getByText('data1: 1, data2: 2')).toBeInTheDocument()\n\n    expect(results.length).toBe(3)\n    expect(results[0]).toMatchObject([{ data: undefined }, { data: undefined }])\n    expect(results[1]).toMatchObject([{ data: 1 }, { data: undefined }])\n    expect(results[2]).toMatchObject([{ data: 1 }, { data: 2 }])\n  })\n\n  it('should track results', async () => {\n    const key1 = queryKey()\n    const results: Array<Array<UseQueryResult>> = []\n    let count = 0\n\n    function Page() {\n      const result = useQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: async () => {\n              await sleep(10)\n              count++\n              return count\n            },\n          },\n        ],\n      })\n      results.push(result)\n\n      return (\n        <div>\n          <div>data: {String(result[0].data ?? 'null')} </div>\n          <button onClick={() => result[0].refetch()}>refetch</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n\n    expect(results.length).toBe(2)\n    expect(results[0]).toMatchObject([{ data: undefined }])\n    expect(results[1]).toMatchObject([{ data: 1 }])\n\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 2')).toBeInTheDocument()\n\n    // only one render for data update, no render for isFetching transition\n    expect(results.length).toBe(3)\n\n    expect(results[2]).toMatchObject([{ data: 2 }])\n  })\n\n  it('handles type parameter - tuple of tuples', () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const key3 = queryKey()\n\n    // @ts-expect-error (Page component is not rendered)\n    function Page() {\n      const result1 = useQueries<\n        [[number], [string], [Array<string>, boolean]]\n      >({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 1,\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n          },\n          {\n            queryKey: key3,\n            queryFn: () => ['string[]'],\n          },\n        ],\n      })\n      expectTypeOf(result1[0]).toEqualTypeOf<UseQueryResult<number, unknown>>()\n      expectTypeOf(result1[1]).toEqualTypeOf<UseQueryResult<string, unknown>>()\n      expectTypeOf(result1[2]).toEqualTypeOf<\n        UseQueryResult<Array<string>, boolean>\n      >()\n      expectTypeOf(result1[0].data).toEqualTypeOf<number | undefined>()\n      expectTypeOf(result1[1].data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(result1[2].data).toEqualTypeOf<Array<string> | undefined>()\n      expectTypeOf(result1[2].error).toEqualTypeOf<boolean | null>()\n\n      // TData (3rd element) takes precedence over TQueryFnData (1st element)\n      const result2 = useQueries<\n        [[string, unknown, string], [string, unknown, number]]\n      >({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return a.toLowerCase()\n            },\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return parseInt(a)\n            },\n          },\n        ],\n      })\n      expectTypeOf(result2[0]).toEqualTypeOf<UseQueryResult<string, unknown>>()\n      expectTypeOf(result2[1]).toEqualTypeOf<UseQueryResult<number, unknown>>()\n      expectTypeOf(result2[0].data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(result2[1].data).toEqualTypeOf<number | undefined>()\n\n      // types should be enforced\n      useQueries<[[string, unknown, string], [string, boolean, number]]>({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return a.toLowerCase()\n            },\n            placeholderData: 'string',\n            // @ts-expect-error (initialData: string)\n            initialData: 123,\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return parseInt(a)\n            },\n            placeholderData: 'string',\n            // @ts-expect-error (initialData: string)\n            initialData: 123,\n          },\n        ],\n      })\n\n      // field names should be enforced\n      useQueries<[[string]]>({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n            // @ts-expect-error (invalidField)\n            someInvalidField: [],\n          },\n        ],\n      })\n    }\n  })\n\n  it('handles type parameter - tuple of objects', () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const key3 = queryKey()\n\n    // @ts-expect-error (Page component is not rendered)\n    function Page() {\n      const result1 = useQueries<\n        [\n          { queryFnData: number },\n          { queryFnData: string },\n          { queryFnData: Array<string>; error: boolean },\n        ]\n      >({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 1,\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n          },\n          {\n            queryKey: key3,\n            queryFn: () => ['string[]'],\n          },\n        ],\n      })\n      expectTypeOf(result1[0]).toEqualTypeOf<UseQueryResult<number, unknown>>()\n      expectTypeOf(result1[1]).toEqualTypeOf<UseQueryResult<string, unknown>>()\n      expectTypeOf(result1[2]).toEqualTypeOf<\n        UseQueryResult<Array<string>, boolean>\n      >()\n      expectTypeOf(result1[0].data).toEqualTypeOf<number | undefined>()\n      expectTypeOf(result1[1].data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(result1[2].data).toEqualTypeOf<Array<string> | undefined>()\n      expectTypeOf(result1[2].error).toEqualTypeOf<boolean | null>()\n\n      // TData (data prop) takes precedence over TQueryFnData (queryFnData prop)\n      const result2 = useQueries<\n        [\n          { queryFnData: string; data: string },\n          { queryFnData: string; data: number },\n        ]\n      >({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return a.toLowerCase()\n            },\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return parseInt(a)\n            },\n          },\n        ],\n      })\n      expectTypeOf(result2[0]).toEqualTypeOf<UseQueryResult<string, unknown>>()\n      expectTypeOf(result2[1]).toEqualTypeOf<UseQueryResult<number, unknown>>()\n      expectTypeOf(result2[0].data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(result2[1].data).toEqualTypeOf<number | undefined>()\n\n      // can pass only TData (data prop) although TQueryFnData will be left unknown\n      const result3 = useQueries<[{ data: string }, { data: number }]>({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<unknown>()\n              return a as string\n            },\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<unknown>()\n              return a as number\n            },\n          },\n        ],\n      })\n      expectTypeOf(result3[0]).toEqualTypeOf<UseQueryResult<string, unknown>>()\n      expectTypeOf(result3[1]).toEqualTypeOf<UseQueryResult<number, unknown>>()\n      expectTypeOf(result3[0].data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(result3[1].data).toEqualTypeOf<number | undefined>()\n\n      // types should be enforced\n      useQueries<\n        [\n          { queryFnData: string; data: string },\n          { queryFnData: string; data: number; error: boolean },\n        ]\n      >({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return a.toLowerCase()\n            },\n            placeholderData: 'string',\n            // @ts-expect-error (initialData: string)\n            initialData: 123,\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return parseInt(a)\n            },\n            placeholderData: 'string',\n            // @ts-expect-error (initialData: string)\n            initialData: 123,\n          },\n        ],\n      })\n\n      // field names should be enforced\n      useQueries<[{ queryFnData: string }]>({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n            // @ts-expect-error (invalidField)\n            someInvalidField: [],\n          },\n        ],\n      })\n    }\n  })\n\n  it('correctly returns types when passing through queryOptions', () => {\n    // @ts-expect-error (Page component is not rendered)\n    function Page() {\n      // data and results types are correct when using queryOptions\n      const result4 = useQueries({\n        queries: [\n          queryOptions({\n            queryKey: ['key1'],\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return a.toLowerCase()\n            },\n          }),\n          queryOptions({\n            queryKey: ['key2'],\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return parseInt(a)\n            },\n          }),\n        ],\n      })\n      expectTypeOf(result4[0]).toEqualTypeOf<UseQueryResult<string, Error>>()\n      expectTypeOf(result4[1]).toEqualTypeOf<UseQueryResult<number, Error>>()\n      expectTypeOf(result4[0].data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(result4[1].data).toEqualTypeOf<number | undefined>()\n    }\n  })\n\n  it('handles array literal without type parameter to infer result type', () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const key3 = queryKey()\n    const key4 = queryKey()\n    const key5 = queryKey()\n\n    type BizError = { code: number }\n    const throwOnError = (_error: BizError) => true\n\n    // @ts-expect-error (Page component is not rendered)\n    function Page() {\n      // Array.map preserves TQueryFnData\n      const result1 = useQueries({\n        queries: Array(50).map((_, i) => ({\n          queryKey: ['key', i] as const,\n          queryFn: () => i + 10,\n        })),\n      })\n      expectTypeOf(result1).toEqualTypeOf<\n        Array<UseQueryResult<number, Error>>\n      >()\n      if (result1[0]) {\n        expectTypeOf(result1[0].data).toEqualTypeOf<number | undefined>()\n      }\n\n      // Array.map preserves TError\n      const result1_err = useQueries({\n        queries: Array(50).map((_, i) => ({\n          queryKey: ['key', i] as const,\n          queryFn: () => i + 10,\n          throwOnError,\n        })),\n      })\n      expectTypeOf(result1_err).toEqualTypeOf<\n        Array<UseQueryResult<number, BizError>>\n      >()\n      if (result1_err[0]) {\n        expectTypeOf(result1_err[0].data).toEqualTypeOf<number | undefined>()\n        expectTypeOf(result1_err[0].error).toEqualTypeOf<BizError | null>()\n      }\n\n      // Array.map preserves TData\n      const result2 = useQueries({\n        queries: Array(50).map((_, i) => ({\n          queryKey: ['key', i] as const,\n          queryFn: () => i + 10,\n          select: (data: number) => data.toString(),\n        })),\n      })\n      expectTypeOf(result2).toEqualTypeOf<\n        Array<UseQueryResult<string, Error>>\n      >()\n\n      const result2_err = useQueries({\n        queries: Array(50).map((_, i) => ({\n          queryKey: ['key', i] as const,\n          queryFn: () => i + 10,\n          select: (data: number) => data.toString(),\n          throwOnError,\n        })),\n      })\n      expectTypeOf(result2_err).toEqualTypeOf<\n        Array<UseQueryResult<string, BizError>>\n      >()\n\n      const result3 = useQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 1,\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n          },\n          {\n            queryKey: key3,\n            queryFn: () => ['string[]'],\n            select: () => 123,\n          },\n          {\n            queryKey: key5,\n            queryFn: () => 'string',\n            throwOnError,\n          },\n        ],\n      })\n      expectTypeOf(result3[0]).toEqualTypeOf<UseQueryResult<number, Error>>()\n      expectTypeOf(result3[1]).toEqualTypeOf<UseQueryResult<string, Error>>()\n      expectTypeOf(result3[2]).toEqualTypeOf<UseQueryResult<number, Error>>()\n      expectTypeOf(result3[0].data).toEqualTypeOf<number | undefined>()\n      expectTypeOf(result3[1].data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(result3[3].data).toEqualTypeOf<string | undefined>()\n      // select takes precedence over queryFn\n      expectTypeOf(result3[2].data).toEqualTypeOf<number | undefined>()\n      // infer TError from throwOnError\n      expectTypeOf(result3[3].error).toEqualTypeOf<BizError | null>()\n\n      // initialData/placeholderData are enforced\n      useQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n            placeholderData: 'string',\n            // @ts-expect-error (initialData: string)\n            initialData: 123,\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 123,\n            // @ts-expect-error (placeholderData: number)\n            placeholderData: 'string',\n            initialData: 123,\n          },\n        ],\n      })\n\n      // select and throwOnError params are \"indirectly\" enforced\n      useQueries({\n        queries: [\n          // unfortunately TS will not suggest the type for you\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n          },\n          // however you can add a type to the callback\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n          },\n          // the type you do pass is enforced\n          {\n            queryKey: key3,\n            queryFn: () => 'string',\n          },\n          {\n            queryKey: key4,\n            queryFn: () => 'string',\n            select: (a: string) => parseInt(a),\n          },\n          {\n            queryKey: key5,\n            queryFn: () => 'string',\n            throwOnError,\n          },\n        ],\n      })\n\n      // callbacks are also indirectly enforced with Array.map\n      useQueries({\n        queries: Array(50).map((_, i) => ({\n          queryKey: ['key', i] as const,\n          queryFn: () => i + 10,\n          select: (data: number) => data.toString(),\n        })),\n      })\n      useQueries({\n        queries: Array(50).map((_, i) => ({\n          queryKey: ['key', i] as const,\n          queryFn: () => i + 10,\n          select: (data: number) => data.toString(),\n        })),\n      })\n\n      // results inference works when all the handlers are defined\n      const result4 = useQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n          },\n          {\n            queryKey: key4,\n            queryFn: () => 'string',\n            select: (a: string) => parseInt(a),\n          },\n          {\n            queryKey: key5,\n            queryFn: () => 'string',\n            select: (a: string) => parseInt(a),\n            throwOnError,\n          },\n        ],\n      })\n      expectTypeOf(result4[0]).toEqualTypeOf<UseQueryResult<string, Error>>()\n      expectTypeOf(result4[1]).toEqualTypeOf<UseQueryResult<string, Error>>()\n      expectTypeOf(result4[2]).toEqualTypeOf<UseQueryResult<number, Error>>()\n      expectTypeOf(result4[3]).toEqualTypeOf<UseQueryResult<number, BizError>>()\n\n      // handles when queryFn returns a Promise\n      const result5 = useQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => Promise.resolve('string'),\n          },\n        ],\n      })\n      expectTypeOf(result5[0]).toEqualTypeOf<UseQueryResult<string, Error>>()\n\n      // Array as const does not throw error\n      const result6 = useQueries({\n        queries: [\n          {\n            queryKey: ['key1'],\n            queryFn: () => 'string',\n          },\n          {\n            queryKey: ['key1'],\n            queryFn: () => 123,\n          },\n          {\n            queryKey: key5,\n            queryFn: () => 'string',\n            throwOnError,\n          },\n        ],\n      } as const)\n      expectTypeOf(result6[0]).toEqualTypeOf<UseQueryResult<string, Error>>()\n      expectTypeOf(result6[1]).toEqualTypeOf<UseQueryResult<number, Error>>()\n      expectTypeOf(result6[2]).toEqualTypeOf<UseQueryResult<string, BizError>>()\n\n      // field names should be enforced - array literal\n      useQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n            // @ts-expect-error (invalidField)\n            someInvalidField: [],\n          },\n        ],\n      })\n\n      // field names should be enforced - Array.map() result\n      useQueries({\n        // @ts-expect-error (invalidField)\n        queries: Array(10).map(() => ({\n          someInvalidField: '',\n        })),\n      })\n\n      // field names should be enforced - array literal\n      useQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n            // @ts-expect-error (invalidField)\n            someInvalidField: [],\n          },\n        ],\n      })\n\n      // supports queryFn using fetch() to return Promise<any> - Array.map() result\n      useQueries({\n        queries: Array(50).map((_, i) => ({\n          queryKey: ['key', i] as const,\n          queryFn: () =>\n            fetch('return Promise<any>').then((resp) => resp.json()),\n        })),\n      })\n\n      // supports queryFn using fetch() to return Promise<any> - array literal\n      useQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () =>\n              fetch('return Promise<any>').then((resp) => resp.json()),\n          },\n        ],\n      })\n    }\n  })\n\n  it('handles strongly typed queryFn factories and useQueries wrappers', () => {\n    // QueryKey + queryFn factory\n    type QueryKeyA = ['queryA']\n    const getQueryKeyA = (): QueryKeyA => ['queryA']\n    type GetQueryFunctionA = () => QueryFunction<number, QueryKeyA>\n    const getQueryFunctionA: GetQueryFunctionA = () => () => {\n      return Promise.resolve(1)\n    }\n    type SelectorA = (data: number) => [number, string]\n    const getSelectorA = (): SelectorA => (data) => [data, data.toString()]\n\n    type QueryKeyB = ['queryB', string]\n    const getQueryKeyB = (id: string): QueryKeyB => ['queryB', id]\n    type GetQueryFunctionB = () => QueryFunction<string, QueryKeyB>\n    const getQueryFunctionB: GetQueryFunctionB = () => () => {\n      return Promise.resolve('1')\n    }\n    type SelectorB = (data: string) => [string, number]\n    const getSelectorB = (): SelectorB => (data) => [data, +data]\n\n    // Wrapper with strongly typed array-parameter\n    function useWrappedQueries<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey extends QueryKey,\n    >(queries: Array<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>>) {\n      return useQueries({\n        queries: queries.map(\n          // no need to type the mapped query\n          (query) => {\n            const { queryFn: fn, queryKey: key } = query\n            expectTypeOf(fn).toEqualTypeOf<\n              | typeof skipToken\n              | QueryFunction<TQueryFnData, TQueryKey, never>\n              | undefined\n            >()\n            return {\n              queryKey: key,\n              queryFn:\n                fn && fn !== skipToken\n                  ? (ctx: QueryFunctionContext<TQueryKey>) => {\n                      // eslint-disable-next-line vitest/valid-expect\n                      expectTypeOf<TQueryKey>(ctx.queryKey)\n                      return fn.call({}, ctx)\n                    }\n                  : undefined,\n            }\n          },\n        ),\n      })\n    }\n\n    // @ts-expect-error (Page component is not rendered)\n    function Page() {\n      const result = useQueries({\n        queries: [\n          {\n            queryKey: getQueryKeyA(),\n            queryFn: getQueryFunctionA(),\n          },\n          {\n            queryKey: getQueryKeyB('id'),\n            queryFn: getQueryFunctionB(),\n          },\n        ],\n      })\n      expectTypeOf(result[0]).toEqualTypeOf<UseQueryResult<number, Error>>()\n      expectTypeOf(result[1]).toEqualTypeOf<UseQueryResult<string, Error>>()\n\n      const withSelector = useQueries({\n        queries: [\n          {\n            queryKey: getQueryKeyA(),\n            queryFn: getQueryFunctionA(),\n            select: getSelectorA(),\n          },\n          {\n            queryKey: getQueryKeyB('id'),\n            queryFn: getQueryFunctionB(),\n            select: getSelectorB(),\n          },\n        ],\n      })\n      expectTypeOf(withSelector[0]).toEqualTypeOf<\n        UseQueryResult<[number, string], Error>\n      >()\n      expectTypeOf(withSelector[1]).toEqualTypeOf<\n        UseQueryResult<[string, number], Error>\n      >()\n\n      const withWrappedQueries = useWrappedQueries(\n        Array(10).map(() => ({\n          queryKey: getQueryKeyA(),\n          queryFn: getQueryFunctionA(),\n          select: getSelectorA(),\n        })),\n      )\n\n      expectTypeOf(withWrappedQueries).toEqualTypeOf<\n        Array<UseQueryResult<number, Error>>\n      >()\n    }\n  })\n\n  it(\"should throw error if in one of queries' queryFn throws and throwOnError is in use\", async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const key3 = queryKey()\n    const key4 = queryKey()\n\n    function Page() {\n      useQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () =>\n              Promise.reject(\n                new Error(\n                  'this should not throw because throwOnError is not set',\n                ),\n              ),\n          },\n          {\n            queryKey: key2,\n            queryFn: () => Promise.reject(new Error('single query error')),\n            throwOnError: true,\n            retry: false,\n          },\n          {\n            queryKey: key3,\n            queryFn: () => Promise.resolve(2),\n          },\n          {\n            queryKey: key4,\n            queryFn: async () =>\n              Promise.reject(\n                new Error('this should not throw because query#2 already did'),\n              ),\n            throwOnError: true,\n            retry: false,\n          },\n        ],\n      })\n\n      return null\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <ErrorBoundary\n        fallbackRender={({ error }) => (\n          <div>\n            <div>error boundary</div>\n            <div>{error.message}</div>\n          </div>\n        )}\n      >\n        <Page />\n      </ErrorBoundary>,\n    )\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n    expect(rendered.getByText('single query error')).toBeInTheDocument()\n    consoleMock.mockRestore()\n  })\n\n  it(\"should throw error if in one of queries' queryFn throws and throwOnError function resolves to true\", async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const key3 = queryKey()\n    const key4 = queryKey()\n\n    function Page() {\n      useQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () =>\n              Promise.reject(\n                new Error(\n                  'this should not throw because throwOnError function resolves to false',\n                ),\n              ),\n            throwOnError: () => false,\n            retry: false,\n          },\n          {\n            queryKey: key2,\n            queryFn: () => Promise.resolve(2),\n          },\n          {\n            queryKey: key3,\n            queryFn: () => Promise.reject(new Error('single query error')),\n            throwOnError: () => true,\n            retry: false,\n          },\n          {\n            queryKey: key4,\n            queryFn: async () =>\n              Promise.reject(\n                new Error('this should not throw because query#3 already did'),\n              ),\n            throwOnError: true,\n            retry: false,\n          },\n        ],\n      })\n\n      return null\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <ErrorBoundary\n        fallbackRender={({ error }) => (\n          <div>\n            <div>error boundary</div>\n            <div>{error.message}</div>\n          </div>\n        )}\n      >\n        <Page />\n      </ErrorBoundary>,\n    )\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n    expect(rendered.getByText('single query error')).toBeInTheDocument()\n    consoleMock.mockRestore()\n  })\n\n  it('should use provided custom queryClient', async () => {\n    const key = queryKey()\n    const queryFn = async () => {\n      return Promise.resolve('custom client')\n    }\n\n    function Page() {\n      const queries = useQueries(\n        {\n          queries: [\n            {\n              queryKey: key,\n              queryFn,\n            },\n          ],\n        },\n        queryClient,\n      )\n\n      return <div>data: {queries[0].data}</div>\n    }\n\n    const rendered = render(<Page></Page>)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('data: custom client')).toBeInTheDocument()\n  })\n\n  it('should combine queries', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    function Page() {\n      const queries = useQueries(\n        {\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: () => Promise.resolve('first result'),\n            },\n            {\n              queryKey: key2,\n              queryFn: () => Promise.resolve('second result'),\n            },\n          ],\n          combine: (results) => {\n            return {\n              combined: true,\n              res: results.map((res) => res.data).join(','),\n            }\n          },\n        },\n        queryClient,\n      )\n\n      return (\n        <div>\n          <div>\n            data: {String(queries.combined)} {queries.res}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = render(<Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(\n      rendered.getByText('data: true first result,second result'),\n    ).toBeInTheDocument()\n  })\n\n  it('should not return new instances when called without queries', async () => {\n    const key = queryKey()\n    const ids: Array<number> = []\n    let resultChanged = 0\n\n    function Page() {\n      const [count, setCount] = React.useState(0)\n      const result = useQueries({\n        queries: ids.map((id) => {\n          return {\n            queryKey: [key, id],\n            queryFn: () => {\n              return () => {\n                return Promise.resolve({\n                  id,\n                  content: { value: Math.random() },\n                })\n              }\n            },\n          }\n        }),\n        combine: () => ({ empty: 'object' }),\n      })\n\n      React.useEffect(() => {\n        resultChanged++\n      }, [result])\n\n      return (\n        <div>\n          <div>count: {count}</div>\n          <div>data: {JSON.stringify(result)}</div>\n          <button onClick={() => setCount((c) => c + 1)}>inc</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('data: {\"empty\":\"object\"}')).toBeInTheDocument()\n    expect(rendered.getByText('count: 0')).toBeInTheDocument()\n\n    expect(resultChanged).toBe(1)\n\n    fireEvent.click(rendered.getByRole('button', { name: /inc/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('count: 1')).toBeInTheDocument()\n    // there should be no further effect calls because the returned object is structurally shared\n    expect(resultChanged).toBe(1)\n  })\n\n  it('should not have infinite render loops with empty queries (#6645)', () => {\n    let renderCount = 0\n\n    function Page() {\n      const result = useQueries({\n        queries: [],\n      })\n\n      React.useEffect(() => {\n        renderCount++\n      })\n\n      return <div>data: {JSON.stringify(result)}</div>\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    expect(renderCount).toBe(1)\n  })\n\n  it('should only call combine with query results', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    function Page() {\n      const result = useQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: async () => {\n              await sleep(5)\n              return Promise.resolve('query1')\n            },\n          },\n          {\n            queryKey: key2,\n            queryFn: async () => {\n              await sleep(20)\n              return Promise.resolve('query2')\n            },\n          },\n        ],\n        combine: ([query1, query2]) => {\n          return {\n            data: { query1: query1.data, query2: query2.data },\n          }\n        },\n      })\n\n      return <div>data: {JSON.stringify(result)}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(21)\n    expect(\n      rendered.getByText(\n        'data: {\"data\":{\"query1\":\"query1\",\"query2\":\"query2\"}}',\n      ),\n    ).toBeInTheDocument()\n  })\n\n  it('should track property access through combine function', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    let count = 0\n    const results: Array<unknown> = []\n\n    function Page() {\n      const queries = useQueries(\n        {\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: async () => {\n                await sleep(5)\n                return Promise.resolve('first result ' + count)\n              },\n            },\n            {\n              queryKey: key2,\n              queryFn: async () => {\n                await sleep(50)\n                return Promise.resolve('second result ' + count)\n              },\n            },\n          ],\n          combine: (queryResults) => {\n            return {\n              combined: true,\n              refetch: () => queryResults.forEach((res) => res.refetch()),\n              res: queryResults\n                .flatMap((res) => (res.data ? [res.data] : []))\n                .join(','),\n            }\n          },\n        },\n        queryClient,\n      )\n\n      results.push(queries)\n\n      return (\n        <div>\n          <div>\n            data: {String(queries.combined)} {queries.res}\n          </div>\n          <button onClick={() => queries.refetch()}>refetch</button>\n        </div>\n      )\n    }\n\n    const rendered = render(<Page />)\n\n    await vi.advanceTimersByTimeAsync(51)\n    expect(\n      rendered.getByText('data: true first result 0,second result 0'),\n    ).toBeInTheDocument()\n\n    expect(results.length).toBe(3)\n\n    expect(results[0]).toStrictEqual({\n      combined: true,\n      refetch: expect.any(Function),\n      res: '',\n    })\n\n    expect(results[1]).toStrictEqual({\n      combined: true,\n      refetch: expect.any(Function),\n      res: 'first result 0',\n    })\n\n    expect(results[2]).toStrictEqual({\n      combined: true,\n      refetch: expect.any(Function),\n      res: 'first result 0,second result 0',\n    })\n\n    count++\n\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n\n    await vi.advanceTimersByTimeAsync(51)\n    expect(\n      rendered.getByText('data: true first result 1,second result 1'),\n    ).toBeInTheDocument()\n\n    const length = results.length\n\n    expect([4, 5, 6]).toContain(results.length)\n\n    expect(results[results.length - 1]).toStrictEqual({\n      combined: true,\n      refetch: expect.any(Function),\n      res: 'first result 1,second result 1',\n    })\n\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n\n    await vi.advanceTimersByTimeAsync(100)\n    // no further re-render because data didn't change\n    expect(results.length).toBe(length)\n  })\n\n  it('should synchronously track properties of all observer even if a property (isLoading) is only accessed on one observer (#7000)', async () => {\n    const key = queryKey()\n    const ids = [1, 2]\n\n    function Page() {\n      const { isLoading } = useQueries({\n        queries: ids.map((id) => ({\n          queryKey: [key, id],\n          queryFn: () =>\n            sleep(10).then(() => {\n              if (id === 2) throw new Error('FAILURE')\n              return { id, title: `Post ${id}` }\n            }),\n          retry: false,\n        })),\n        combine: (results) => {\n          // this tracks data on all observers\n          void results.forEach((result) => result.data)\n          return {\n            // .some aborts early, so `isLoading` might not be accessed (and thus tracked) on all observers\n            // leading to missing re-renders\n            isLoading: results.some((result) => result.isLoading),\n          }\n        },\n      })\n\n      return (\n        <div>\n          <p>Loading Status: {isLoading ? 'Loading...' : 'Loaded'}</p>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('Loading Status: Loading...')).toBeInTheDocument()\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Loading Status: Loaded')).toBeInTheDocument()\n  })\n\n  it('should not have stale closures with combine (#6648)', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const [count, setCount] = React.useState(0)\n      const queries = useQueries(\n        {\n          queries: [\n            {\n              queryKey: key,\n              queryFn: () => Promise.resolve('result'),\n            },\n          ],\n          combine: (results) => {\n            return {\n              count,\n              res: results.map((res) => res.data).join(','),\n            }\n          },\n        },\n        queryClient,\n      )\n\n      return (\n        <div>\n          <div>\n            data: {String(queries.count)} {queries.res}\n          </div>\n          <button onClick={() => setCount((c) => c + 1)}>inc</button>\n        </div>\n      )\n    }\n\n    const rendered = render(<Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('data: 0 result')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /inc/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('data: 1 result')).toBeInTheDocument()\n  })\n\n  it('should optimize combine if it is a stable reference', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    const client = new QueryClient()\n\n    const spy = vi.fn()\n    let value = 0\n\n    function Page() {\n      const [state, setState] = React.useState(0)\n      const queries = useQueries(\n        {\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: async () => {\n                await sleep(10)\n                return 'first result:' + value\n              },\n            },\n            {\n              queryKey: key2,\n              queryFn: async () => {\n                await sleep(20)\n                return 'second result:' + value\n              },\n            },\n          ],\n          combine: React.useCallback((results: Array<QueryObserverResult>) => {\n            const result = {\n              combined: true,\n              res: results.map((res) => res.data).join(','),\n            }\n            spy(result)\n            return result\n          }, []),\n        },\n        client,\n      )\n\n      return (\n        <div>\n          <div>\n            data: {String(queries.combined)} {queries.res}\n          </div>\n          <button onClick={() => setState(state + 1)}>rerender</button>\n        </div>\n      )\n    }\n\n    const rendered = render(<Page />)\n\n    await vi.advanceTimersByTimeAsync(21)\n    expect(\n      rendered.getByText('data: true first result:0,second result:0'),\n    ).toBeInTheDocument()\n\n    // both pending, one pending, both resolved\n    expect(spy).toHaveBeenCalledTimes(3)\n\n    client.refetchQueries()\n\n    await vi.advanceTimersByTimeAsync(21)\n    // no increase because result hasn't changed\n    expect(spy).toHaveBeenCalledTimes(3)\n\n    fireEvent.click(rendered.getByRole('button', { name: /rerender/i }))\n\n    // one extra call due to recomputing the combined result on rerender\n    expect(spy).toHaveBeenCalledTimes(4)\n\n    value = 1\n\n    client.refetchQueries()\n\n    await vi.advanceTimersByTimeAsync(21)\n    expect(\n      rendered.getByText('data: true first result:1,second result:1'),\n    ).toBeInTheDocument()\n\n    // refetch with new values triggers: both pending -> one pending -> both resolved\n    expect(spy).toHaveBeenCalledTimes(7)\n  })\n\n  it('should re-run combine if the functional reference changes', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    const client = new QueryClient()\n\n    const spy = vi.fn()\n\n    function Page() {\n      const [state, setState] = React.useState(0)\n      const queries = useQueries(\n        {\n          queries: [\n            {\n              queryKey: [key1],\n              queryFn: async () => {\n                await sleep(10)\n                return 'first result'\n              },\n            },\n            {\n              queryKey: [key2],\n              queryFn: async () => {\n                await sleep(20)\n                return 'second result'\n              },\n            },\n          ],\n          combine: React.useCallback(\n            (results: Array<QueryObserverResult>) => {\n              const result = {\n                combined: true,\n                state,\n                res: results.map((res) => res.data).join(','),\n              }\n              spy(result)\n              return result\n            },\n            [state],\n          ),\n        },\n        client,\n      )\n\n      return (\n        <div>\n          <div>\n            data: {String(queries.state)} {queries.res}\n          </div>\n          <button onClick={() => setState(state + 1)}>rerender</button>\n        </div>\n      )\n    }\n\n    const rendered = render(<Page />)\n\n    await vi.advanceTimersByTimeAsync(21)\n    expect(\n      rendered.getByText('data: 0 first result,second result'),\n    ).toBeInTheDocument()\n\n    // both pending, one pending, both resolved\n    expect(spy).toHaveBeenCalledTimes(3)\n\n    fireEvent.click(rendered.getByRole('button', { name: /rerender/i }))\n\n    // state changed, re-run combine\n    expect(spy).toHaveBeenCalledTimes(4)\n  })\n\n  it('should not re-render if combine returns a stable reference', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    const client = new QueryClient()\n\n    const queryFns: Array<string> = []\n    let renders = 0\n\n    function Page() {\n      const data = useQueries(\n        {\n          queries: [\n            {\n              queryKey: [key1],\n              queryFn: async () => {\n                await sleep(10)\n                queryFns.push('first result')\n                return 'first result'\n              },\n            },\n            {\n              queryKey: [key2],\n              queryFn: async () => {\n                await sleep(20)\n                queryFns.push('second result')\n                return 'second result'\n              },\n            },\n          ],\n          combine: () => 'foo',\n        },\n        client,\n      )\n\n      renders++\n\n      return (\n        <div>\n          <div>data: {data}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(<Page />)\n\n    await vi.advanceTimersByTimeAsync(21)\n    expect(rendered.getByText('data: foo')).toBeInTheDocument()\n\n    expect(queryFns).toEqual(['first result', 'second result'])\n\n    expect(renders).toBe(1)\n  })\n\n  it('should re-render once combine returns a different reference', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const key3 = queryKey()\n\n    const client = new QueryClient()\n\n    let renders = 0\n\n    function Page() {\n      const data = useQueries(\n        {\n          queries: [\n            {\n              queryKey: [key1],\n              queryFn: async () => {\n                await sleep(10)\n                return 'first result'\n              },\n            },\n            {\n              queryKey: [key2],\n              queryFn: async () => {\n                await sleep(15)\n                return 'second result'\n              },\n            },\n            {\n              queryKey: [key3],\n              queryFn: async () => {\n                await sleep(20)\n                return 'third result'\n              },\n            },\n          ],\n          combine: (results) => {\n            const isPending = results.some((res) => res.isPending)\n\n            return isPending ? 'pending' : 'foo'\n          },\n        },\n        client,\n      )\n\n      renders++\n\n      return (\n        <div>\n          <div>data: {data}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(<Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('data: pending')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(21)\n    expect(rendered.getByText('data: foo')).toBeInTheDocument()\n\n    // one with pending, one with foo\n    expect(renders).toBe(2)\n  })\n\n  it('should track properties correctly with combine', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const key3 = queryKey()\n\n    const client = new QueryClient()\n\n    function Page() {\n      const data = useQueries(\n        {\n          queries: [\n            {\n              queryKey: [key1],\n              queryFn: async () => {\n                await sleep(10)\n                return 'first result'\n              },\n            },\n            {\n              queryKey: [key2],\n              queryFn: async () => {\n                await sleep(15)\n                return 'second result'\n              },\n            },\n            {\n              queryKey: [key3],\n              queryFn: async () => {\n                await sleep(20)\n                return 'third result'\n              },\n            },\n          ],\n          combine: (results) => {\n            if (results.find((r) => r.isPending)) {\n              return 'pending'\n            }\n            return results.map((r) => r.data).join(', ')\n          },\n        },\n        client,\n      )\n\n      return (\n        <div>\n          <div>data: {data}</div>\n          <button\n            onClick={() => {\n              client.setQueryData([key1], 'first result updated')\n            }}\n          >\n            update\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = render(<Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('data: pending')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(21)\n    expect(\n      rendered.getByText('data: first result, second result, third result'),\n    ).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /update/i }))\n\n    await vi.advanceTimersByTimeAsync(21)\n    expect(\n      rendered.getByText(\n        'data: first result updated, second result, third result',\n      ),\n    ).toBeInTheDocument()\n  })\n\n  it('should not re-run stable combine on unrelated re-render', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    const client = new QueryClient()\n\n    const spy = vi.fn()\n\n    function Page() {\n      const [unrelatedState, setUnrelatedState] = React.useState(0)\n\n      const queries = useQueries(\n        {\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: async () => {\n                await sleep(10)\n                return 'first result'\n              },\n            },\n            {\n              queryKey: key2,\n              queryFn: async () => {\n                await sleep(20)\n                return 'second result'\n              },\n            },\n          ],\n          combine: React.useCallback((results: Array<QueryObserverResult>) => {\n            const result = {\n              combined: true,\n              res: results.map((res) => res.data).join(','),\n            }\n            spy(result)\n            return result\n          }, []),\n        },\n        client,\n      )\n\n      return (\n        <div>\n          <div>\n            data: {String(queries.combined)} {queries.res}\n          </div>\n          <div>unrelated: {unrelatedState}</div>\n          <button onClick={() => setUnrelatedState((s) => s + 1)}>\n            increment\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = render(<Page />)\n\n    await vi.advanceTimersByTimeAsync(21)\n    expect(\n      rendered.getByText('data: true first result,second result'),\n    ).toBeInTheDocument()\n\n    // initial renders: both pending, one pending, both resolved\n    expect(spy).toHaveBeenCalledTimes(3)\n\n    fireEvent.click(rendered.getByRole('button', { name: /increment/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(rendered.getByText('unrelated: 1')).toBeInTheDocument()\n\n    // combine should NOT re-run for unrelated re-render with stable reference\n    expect(spy).toHaveBeenCalledTimes(3)\n\n    fireEvent.click(rendered.getByRole('button', { name: /increment/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(rendered.getByText('unrelated: 2')).toBeInTheDocument()\n\n    // still no extra calls to combine\n    expect(spy).toHaveBeenCalledTimes(3)\n  })\n\n  it('should not cause infinite re-renders when removing last query', async () => {\n    let renderCount = 0\n\n    function Page() {\n      const [queries, setQueries] = React.useState([\n        {\n          queryKey: ['query1'],\n          queryFn: () => 'data1',\n        },\n        {\n          queryKey: ['query2'],\n          queryFn: () => 'data2',\n        },\n      ])\n      renderCount++\n\n      const result = useQueries({ queries })\n\n      return (\n        <div>\n          <div data-testid=\"render-count\">renders: {renderCount}</div>\n          <div data-testid=\"query-count\">queries: {result.length}</div>\n          <button\n            onClick={() => {\n              setQueries([\n                {\n                  queryKey: ['query1'],\n                  queryFn: () => 'data1',\n                },\n              ])\n            }}\n          >\n            remove last\n          </button>\n          <button\n            onClick={() => {\n              setQueries([\n                {\n                  queryKey: ['query2'],\n                  queryFn: () => 'data2',\n                },\n              ])\n            }}\n          >\n            remove first\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    renderCount = 0\n\n    fireEvent.click(rendered.getByRole('button', { name: /remove last/i }))\n    await vi.advanceTimersByTimeAsync(100)\n\n    expect(renderCount).toBeLessThan(10)\n    expect(rendered.getByTestId('query-count').textContent).toBe('queries: 1')\n\n    renderCount = 0\n\n    fireEvent.click(rendered.getByRole('button', { name: /remove first/i }))\n    await vi.advanceTimersByTimeAsync(100)\n\n    expect(renderCount).toBeLessThan(10)\n    expect(rendered.getByTestId('query-count').textContent).toBe('queries: 1')\n  })\n\n  it('should return correct results when queries count changes with stable combine reference', async () => {\n    const combine = (results: Array<QueryObserverResult>) => results\n\n    const results: Array<{ n: number; length: number }> = []\n\n    function Page() {\n      const [n, setN] = React.useState(0)\n\n      const queries = useQueries(\n        {\n          queries: [...Array(n).keys()].map((i) => ({\n            queryKey: ['dynamic', i],\n            queryFn: () => i,\n          })),\n          combine,\n        },\n        queryClient,\n      )\n\n      results.push({ n, length: queries.length })\n\n      return (\n        <div>\n          <span data-testid=\"n\">{n}</span>\n          <span data-testid=\"length\">{queries.length}</span>\n          <button onClick={() => setN(n + 1)}>Increase</button>\n        </div>\n      )\n    }\n\n    const rendered = render(<Page />)\n\n    expect(rendered.getByTestId('n').textContent).toBe('0')\n    expect(rendered.getByTestId('length').textContent).toBe('0')\n\n    fireEvent.click(rendered.getByRole('button', { name: /increase/i }))\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(rendered.getByTestId('n').textContent).toBe('1')\n    expect(rendered.getByTestId('length').textContent).toBe('1')\n\n    fireEvent.click(rendered.getByRole('button', { name: /increase/i }))\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(rendered.getByTestId('n').textContent).toBe('2')\n    expect(rendered.getByTestId('length').textContent).toBe('2')\n\n    results.forEach((result) => {\n      expect(result.length).toBe(result.n)\n    })\n  })\n\n  it('should not fetch for the duration of the restoring period when isRestoring is true', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const queryFn1 = vi.fn(() => sleep(10).then(() => 'data1'))\n    const queryFn2 = vi.fn(() => sleep(10).then(() => 'data2'))\n\n    function Page() {\n      const results = useQueries({\n        queries: [\n          { queryKey: key1, queryFn: queryFn1 },\n          { queryKey: key2, queryFn: queryFn2 },\n        ],\n      })\n\n      return (\n        <div>\n          <div data-testid=\"status1\">{results[0]?.status}</div>\n          <div data-testid=\"status2\">{results[1]?.status}</div>\n          <div data-testid=\"fetchStatus1\">{results[0]?.fetchStatus}</div>\n          <div data-testid=\"fetchStatus2\">{results[1]?.fetchStatus}</div>\n          <div data-testid=\"data1\">{results[0]?.data ?? 'undefined'}</div>\n          <div data-testid=\"data2\">{results[1]?.data ?? 'undefined'}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <IsRestoringProvider value={true}>\n        <Page />\n      </IsRestoringProvider>,\n    )\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(rendered.getByTestId('status1')).toHaveTextContent('pending')\n    expect(rendered.getByTestId('status2')).toHaveTextContent('pending')\n    expect(rendered.getByTestId('fetchStatus1')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('fetchStatus2')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('data1')).toHaveTextContent('undefined')\n    expect(rendered.getByTestId('data2')).toHaveTextContent('undefined')\n    expect(queryFn1).toHaveBeenCalledTimes(0)\n    expect(queryFn2).toHaveBeenCalledTimes(0)\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(rendered.getByTestId('status1')).toHaveTextContent('pending')\n    expect(rendered.getByTestId('status2')).toHaveTextContent('pending')\n    expect(rendered.getByTestId('fetchStatus1')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('fetchStatus2')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('data1')).toHaveTextContent('undefined')\n    expect(rendered.getByTestId('data2')).toHaveTextContent('undefined')\n    expect(queryFn1).toHaveBeenCalledTimes(0)\n    expect(queryFn2).toHaveBeenCalledTimes(0)\n  })\n\n  it('should not fetch queries with different durations for the duration of the restoring period when isRestoring is true', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const queryFn1 = vi.fn(() => sleep(10).then(() => 'data1'))\n    const queryFn2 = vi.fn(() => sleep(20).then(() => 'data2'))\n\n    function Page() {\n      const results = useQueries({\n        queries: [\n          { queryKey: key1, queryFn: queryFn1 },\n          { queryKey: key2, queryFn: queryFn2 },\n        ],\n      })\n\n      return (\n        <div>\n          <div data-testid=\"status1\">{results[0]?.status}</div>\n          <div data-testid=\"status2\">{results[1]?.status}</div>\n          <div data-testid=\"fetchStatus1\">{results[0]?.fetchStatus}</div>\n          <div data-testid=\"fetchStatus2\">{results[1]?.fetchStatus}</div>\n          <div data-testid=\"data1\">{results[0]?.data ?? 'undefined'}</div>\n          <div data-testid=\"data2\">{results[1]?.data ?? 'undefined'}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <IsRestoringProvider value={true}>\n        <Page />\n      </IsRestoringProvider>,\n    )\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(rendered.getByTestId('status1')).toHaveTextContent('pending')\n    expect(rendered.getByTestId('status2')).toHaveTextContent('pending')\n    expect(rendered.getByTestId('fetchStatus1')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('fetchStatus2')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('data1')).toHaveTextContent('undefined')\n    expect(rendered.getByTestId('data2')).toHaveTextContent('undefined')\n    expect(queryFn1).toHaveBeenCalledTimes(0)\n    expect(queryFn2).toHaveBeenCalledTimes(0)\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(rendered.getByTestId('status1')).toHaveTextContent('pending')\n    expect(rendered.getByTestId('status2')).toHaveTextContent('pending')\n    expect(rendered.getByTestId('fetchStatus1')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('fetchStatus2')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('data1')).toHaveTextContent('undefined')\n    expect(rendered.getByTestId('data2')).toHaveTextContent('undefined')\n    expect(queryFn1).toHaveBeenCalledTimes(0)\n    expect(queryFn2).toHaveBeenCalledTimes(0)\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(rendered.getByTestId('status1')).toHaveTextContent('pending')\n    expect(rendered.getByTestId('status2')).toHaveTextContent('pending')\n    expect(rendered.getByTestId('fetchStatus1')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('fetchStatus2')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('data1')).toHaveTextContent('undefined')\n    expect(rendered.getByTestId('data2')).toHaveTextContent('undefined')\n    expect(queryFn1).toHaveBeenCalledTimes(0)\n    expect(queryFn2).toHaveBeenCalledTimes(0)\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/useQuery.promise.test.tsx",
    "content": "import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'\nimport * as React from 'react'\nimport { ErrorBoundary } from 'react-error-boundary'\nimport {\n  createRenderStream,\n  useTrackRenders,\n} from '@testing-library/react-render-stream'\nimport { queryKey } from '@tanstack/query-test-utils'\nimport { waitFor } from '@testing-library/react'\nimport {\n  QueryClient,\n  QueryClientProvider,\n  QueryErrorResetBoundary,\n  keepPreviousData,\n  useInfiniteQuery,\n  useQuery,\n} from '..'\nimport { QueryCache } from '../index'\n\ndescribe('useQuery().promise', { timeout: 10_000 }, () => {\n  const queryCache = new QueryCache()\n  const queryClient = new QueryClient({\n    queryCache,\n  })\n\n  beforeAll(() => {\n    vi.useFakeTimers({\n      shouldAdvanceTime: true,\n      toFake: ['setTimeout', 'clearTimeout', 'setInterval', 'clearInterval'],\n    })\n    queryClient.setDefaultOptions({\n      queries: { experimental_prefetchInRender: true },\n    })\n  })\n\n  afterAll(() => {\n    vi.useRealTimers()\n    queryClient.setDefaultOptions({\n      queries: { experimental_prefetchInRender: false },\n    })\n  })\n\n  it('should work with a basic test', async () => {\n    const key = queryKey()\n\n    const renderStream = createRenderStream({ snapshotDOM: true })\n\n    function MyComponent(props: { promise: Promise<string> }) {\n      const data = React.use(props.promise)\n      useTrackRenders()\n      return <>{data}</>\n    }\n\n    function Loading() {\n      useTrackRenders()\n      return <>loading..</>\n    }\n\n    function Page() {\n      useTrackRenders()\n      const query = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await vi.advanceTimersByTimeAsync(1)\n          return 'test'\n        },\n      })\n\n      return (\n        <React.Suspense fallback={<Loading />}>\n          <div>\n            <MyComponent promise={query.promise} />\n          </div>\n          <div>status:{query.status}</div>\n        </React.Suspense>\n      )\n    }\n\n    await renderStream.render(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('loading..')\n      expect(renderedComponents).toEqual([Page, Loading])\n    }\n\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('test')\n      expect(renderedComponents).toEqual([Page, MyComponent])\n    }\n  })\n\n  it('colocate suspense and promise', async () => {\n    const key = queryKey()\n    let callCount = 0\n\n    const renderStream = createRenderStream({ snapshotDOM: true })\n\n    function MyComponent() {\n      useTrackRenders()\n      const query = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          callCount++\n          await vi.advanceTimersByTimeAsync(1)\n          return 'test'\n        },\n        staleTime: 1000,\n      })\n      const data = React.use(query.promise)\n\n      return <>{data}</>\n    }\n\n    function Loading() {\n      useTrackRenders()\n      return <>loading..</>\n    }\n    function Page() {\n      useTrackRenders()\n      return (\n        <React.Suspense fallback={<Loading />}>\n          <MyComponent />\n        </React.Suspense>\n      )\n    }\n\n    await renderStream.render(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('loading..')\n      expect(renderedComponents).toEqual([Page, Loading])\n    }\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('test')\n      expect(renderedComponents).toEqual([MyComponent])\n    }\n\n    expect(callCount).toBe(1)\n  })\n\n  it('parallel queries', async () => {\n    const key = queryKey()\n    const renderStream = createRenderStream({ snapshotDOM: true })\n    let callCount = 0\n\n    function MyComponent() {\n      useTrackRenders()\n      const query = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          callCount++\n          await vi.advanceTimersByTimeAsync(1)\n          return 'test'\n        },\n        staleTime: 1000,\n      })\n      const data = React.use(query.promise)\n\n      return <>{data}</>\n    }\n\n    function Loading() {\n      useTrackRenders()\n      return <>loading..</>\n    }\n    function Page() {\n      useTrackRenders()\n      return (\n        <>\n          <React.Suspense fallback={<Loading />}>\n            <MyComponent />\n            <MyComponent />\n            <MyComponent />\n          </React.Suspense>\n          <React.Suspense fallback={null}>\n            <MyComponent />\n            <MyComponent />\n          </React.Suspense>\n        </>\n      )\n    }\n\n    await renderStream.render(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('loading..')\n      expect(renderedComponents).toEqual([Page, Loading])\n    }\n\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('testtesttesttesttest')\n      expect(renderedComponents).toEqual([\n        MyComponent,\n        MyComponent,\n        MyComponent,\n        MyComponent,\n        MyComponent,\n      ])\n    }\n\n    expect(callCount).toBe(1)\n  })\n\n  it('should work with initial data', async () => {\n    const key = queryKey()\n    const renderStream = createRenderStream({ snapshotDOM: true })\n\n    function MyComponent(props: { promise: Promise<string> }) {\n      useTrackRenders()\n      const data = React.use(props.promise)\n\n      return <>{data}</>\n    }\n    function Loading() {\n      useTrackRenders()\n\n      return <>loading..</>\n    }\n    function Page() {\n      useTrackRenders()\n      const query = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await vi.advanceTimersByTimeAsync(1)\n          return 'test'\n        },\n        initialData: 'initial',\n      })\n\n      return (\n        <React.Suspense fallback={<Loading />}>\n          <MyComponent promise={query.promise} />\n        </React.Suspense>\n      )\n    }\n\n    await renderStream.render(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('initial')\n      expect(renderedComponents).toEqual([Page, MyComponent])\n    }\n\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('test')\n      expect(renderedComponents).toEqual([Page, MyComponent])\n    }\n  })\n\n  it('should not fetch with initial data and staleTime', async () => {\n    const key = queryKey()\n    const renderStream = createRenderStream({ snapshotDOM: true })\n    const queryFn = vi.fn().mockImplementation(async () => {\n      await vi.advanceTimersByTimeAsync(1)\n      return 'test'\n    })\n\n    function MyComponent(props: { promise: Promise<string> }) {\n      useTrackRenders()\n      const data = React.use(props.promise)\n\n      return <>{data}</>\n    }\n    function Loading() {\n      useTrackRenders()\n      return <>loading..</>\n    }\n    function Page() {\n      useTrackRenders()\n      const query = useQuery({\n        queryKey: key,\n        queryFn,\n        initialData: 'initial',\n        staleTime: 1000,\n      })\n\n      return (\n        <React.Suspense fallback={<Loading />}>\n          <MyComponent promise={query.promise} />\n        </React.Suspense>\n      )\n    }\n\n    await renderStream.render(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('initial')\n      expect(renderedComponents).toEqual([Page, MyComponent])\n    }\n\n    // should not call queryFn because of staleTime + initialData combo\n    expect(queryFn).toHaveBeenCalledTimes(0)\n  })\n\n  it('should work with static placeholderData', async () => {\n    const key = queryKey()\n    const renderStream = createRenderStream({ snapshotDOM: true })\n\n    function MyComponent(props: { promise: Promise<string> }) {\n      useTrackRenders()\n      const data = React.use(props.promise)\n\n      return <>{data}</>\n    }\n    function Loading() {\n      useTrackRenders()\n\n      return <>loading..</>\n    }\n    function Page() {\n      const query = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await vi.advanceTimersByTimeAsync(1)\n          return 'test'\n        },\n        placeholderData: 'placeholder',\n      })\n      useTrackRenders()\n\n      return (\n        <React.Suspense fallback={<Loading />}>\n          <MyComponent promise={query.promise} />\n        </React.Suspense>\n      )\n    }\n\n    await renderStream.render(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('placeholder')\n      expect(renderedComponents).toEqual([Page, MyComponent])\n    }\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('test')\n      expect(renderedComponents).toEqual([Page, MyComponent])\n    }\n  })\n\n  it('should work with placeholderData: keepPreviousData', async () => {\n    const key = queryKey()\n    const renderStream = createRenderStream({ snapshotDOM: true })\n\n    function MyComponent(props: { promise: Promise<string> }) {\n      useTrackRenders()\n      const data = React.use(props.promise)\n\n      return <>{data}</>\n    }\n    function Loading() {\n      useTrackRenders()\n\n      return <>loading..</>\n    }\n    function Page() {\n      useTrackRenders()\n      const [count, setCount] = React.useState(0)\n      const query = useQuery({\n        queryKey: [...key, count],\n        queryFn: async () => {\n          await vi.advanceTimersByTimeAsync(1)\n          return 'test-' + count\n        },\n        placeholderData: keepPreviousData,\n      })\n\n      return (\n        <div>\n          <React.Suspense fallback={<Loading />}>\n            <MyComponent promise={query.promise} />\n          </React.Suspense>\n          <button onClick={() => setCount((c) => c + 1)}>increment</button>\n        </div>\n      )\n    }\n\n    const rendered = await renderStream.render(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('loading..')\n      expect(renderedComponents).toEqual([Page, Loading])\n    }\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('test-0')\n      expect(renderedComponents).toEqual([Page, MyComponent])\n    }\n\n    rendered.getByRole('button', { name: 'increment' }).click()\n\n    // re-render because of the increment\n    {\n      const { renderedComponents } = await renderStream.takeRender()\n      expect(renderedComponents).toEqual([Page, MyComponent])\n    }\n\n    // re-render with new data, no loading between\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('test-1')\n      // no more suspense boundary rendering\n      expect(renderedComponents).toEqual([Page, MyComponent])\n    }\n  })\n\n  it('should be possible to select a part of the data with select', async () => {\n    const key = queryKey()\n    const renderStream = createRenderStream({ snapshotDOM: true })\n\n    function MyComponent(props: { promise: Promise<string> }) {\n      useTrackRenders()\n      const data = React.use(props.promise)\n      return <>{data}</>\n    }\n\n    function Loading() {\n      useTrackRenders()\n      return <>loading..</>\n    }\n\n    function Page() {\n      const query = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await vi.advanceTimersByTimeAsync(1)\n          return { name: 'test' }\n        },\n        select: (data) => data.name,\n      })\n\n      useTrackRenders()\n      return (\n        <React.Suspense fallback={<Loading />}>\n          <MyComponent promise={query.promise} />\n        </React.Suspense>\n      )\n    }\n\n    await renderStream.render(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('loading..')\n      expect(renderedComponents).toEqual([Page, Loading])\n    }\n\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('test')\n      expect(renderedComponents).toEqual([Page, MyComponent])\n    }\n  })\n\n  it('should throw error if the promise fails', async () => {\n    const renderStream = createRenderStream({ snapshotDOM: true })\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n\n    const key = queryKey()\n    function MyComponent(props: { promise: Promise<string> }) {\n      const data = React.use(props.promise)\n\n      return <>{data}</>\n    }\n\n    function Loading() {\n      return <>loading..</>\n    }\n\n    let queryCount = 0\n    function Page() {\n      const query = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await vi.advanceTimersByTimeAsync(1)\n          if (++queryCount > 1) {\n            // second time this query mounts, it should not throw\n            return 'data'\n          }\n          throw new Error('Error test')\n        },\n        retry: false,\n      })\n\n      return (\n        <React.Suspense fallback={<Loading />}>\n          <MyComponent promise={query.promise} />\n        </React.Suspense>\n      )\n    }\n\n    const rendered = await renderStream.render(\n      <QueryClientProvider client={queryClient}>\n        <QueryErrorResetBoundary>\n          {({ reset }) => (\n            <ErrorBoundary\n              onReset={reset}\n              fallbackRender={({ resetErrorBoundary }) => (\n                <div>\n                  <div>error boundary</div>\n                  <button\n                    onClick={() => {\n                      resetErrorBoundary()\n                    }}\n                  >\n                    resetErrorBoundary\n                  </button>\n                </div>\n              )}\n            >\n              <Page />\n            </ErrorBoundary>\n          )}\n        </QueryErrorResetBoundary>\n      </QueryClientProvider>,\n    )\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('loading..')\n    }\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('error boundary')\n    }\n\n    consoleMock.mockRestore()\n\n    rendered.getByText('resetErrorBoundary').click()\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('loading..')\n    }\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('data')\n    }\n\n    expect(queryCount).toBe(2)\n  })\n\n  it('should throw error if the promise fails (colocate suspense and promise)', async () => {\n    const renderStream = createRenderStream({ snapshotDOM: true })\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n\n    const key = queryKey()\n\n    function MyComponent() {\n      const query = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await vi.advanceTimersByTimeAsync(1)\n          throw new Error('Error test')\n        },\n        retry: false,\n      })\n      const data = React.use(query.promise)\n\n      return <>{data}</>\n    }\n\n    function Page() {\n      return (\n        <React.Suspense fallback=\"loading..\">\n          <MyComponent />\n        </React.Suspense>\n      )\n    }\n\n    await renderStream.render(\n      <QueryClientProvider client={queryClient}>\n        <ErrorBoundary fallbackRender={() => <div>error boundary</div>}>\n          <Page />\n        </ErrorBoundary>\n      </QueryClientProvider>,\n    )\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      expect(withinDOM().getByText('loading..')).toBeInTheDocument()\n    }\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      expect(withinDOM().getByText('error boundary')).toBeInTheDocument()\n    }\n\n    consoleMock.mockRestore()\n  })\n\n  it('should recreate promise with data changes', async () => {\n    const key = queryKey()\n    const renderStream = createRenderStream({ snapshotDOM: true })\n\n    function MyComponent(props: { promise: Promise<string> }) {\n      useTrackRenders()\n      const data = React.use(props.promise)\n\n      return <>{data}</>\n    }\n\n    function Loading() {\n      useTrackRenders()\n      return <>loading..</>\n    }\n    function Page() {\n      const query = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await vi.advanceTimersByTimeAsync(1)\n          return 'test1'\n        },\n      })\n\n      useTrackRenders()\n      return (\n        <React.Suspense fallback={<Loading />}>\n          <MyComponent promise={query.promise} />\n        </React.Suspense>\n      )\n    }\n\n    await renderStream.render(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('loading..')\n      expect(renderedComponents).toEqual([Page, Loading])\n    }\n\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('test1')\n      expect(renderedComponents).toEqual([Page, MyComponent])\n    }\n\n    queryClient.setQueryData(key, 'test2')\n\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('test2')\n      expect(renderedComponents).toEqual([Page, MyComponent])\n    }\n  })\n\n  it('should dedupe when re-fetched with queryClient.fetchQuery while suspending', async () => {\n    const key = queryKey()\n    const renderStream = createRenderStream({ snapshotDOM: true })\n    const queryFn = vi.fn().mockImplementation(async () => {\n      await vi.advanceTimersByTimeAsync(10)\n      return 'test'\n    })\n\n    const options = {\n      queryKey: key,\n      queryFn,\n    }\n\n    function MyComponent(props: { promise: Promise<string> }) {\n      const data = React.use(props.promise)\n\n      return <>{data}</>\n    }\n\n    function Loading() {\n      return <>loading..</>\n    }\n    function Page() {\n      const query = useQuery(options)\n\n      return (\n        <div>\n          <React.Suspense fallback={<Loading />}>\n            <MyComponent promise={query.promise} />\n          </React.Suspense>\n          <button onClick={() => queryClient.fetchQuery(options)}>fetch</button>\n        </div>\n      )\n    }\n\n    const rendered = await renderStream.render(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('loading..')\n    }\n\n    rendered.getByText('fetch').click()\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('test')\n    }\n\n    expect(queryFn).toHaveBeenCalledOnce()\n  })\n\n  it('should dedupe when re-fetched with refetchQueries while suspending', async () => {\n    const key = queryKey()\n    let count = 0\n    const renderStream = createRenderStream({ snapshotDOM: true })\n    const queryFn = vi.fn().mockImplementation(async () => {\n      await vi.advanceTimersByTimeAsync(10)\n      return 'test' + count++\n    })\n\n    const options = {\n      queryKey: key,\n      queryFn,\n    }\n\n    function MyComponent(props: { promise: Promise<string> }) {\n      const data = React.use(props.promise)\n\n      return <>{data}</>\n    }\n\n    function Loading() {\n      return <>loading..</>\n    }\n    function Page() {\n      const query = useQuery(options)\n\n      return (\n        <div>\n          <React.Suspense fallback={<Loading />}>\n            <MyComponent promise={query.promise} />\n          </React.Suspense>\n          <button onClick={() => queryClient.refetchQueries(options)}>\n            refetch\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = await renderStream.render(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('loading..')\n    }\n\n    rendered.getByText('refetch').click()\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('test0')\n    }\n\n    expect(queryFn).toHaveBeenCalledOnce()\n  })\n\n  it.skip('should stay pending when canceled with cancelQueries while suspending until refetched', async () => {\n    const renderStream = createRenderStream({ snapshotDOM: true })\n    const key = queryKey()\n    let count = 0\n    const queryFn = vi.fn().mockImplementation(async () => {\n      await vi.advanceTimersByTimeAsync(10)\n      return 'test' + count++\n    })\n\n    const options = {\n      queryKey: key,\n      queryFn,\n    }\n\n    function MyComponent(props: { promise: Promise<string> }) {\n      const data = React.use(props.promise)\n\n      return <>{data}</>\n    }\n\n    function Loading() {\n      return <>loading..</>\n    }\n    function Page() {\n      const query = useQuery(options)\n\n      return (\n        <div>\n          <React.Suspense fallback={<Loading />}>\n            <MyComponent promise={query.promise} />\n          </React.Suspense>\n          <button onClick={() => queryClient.cancelQueries(options)}>\n            cancel\n          </button>\n          <button\n            onClick={() => queryClient.setQueryData<string>(key, 'hello')}\n          >\n            fetch\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = await renderStream.render(\n      <QueryClientProvider client={queryClient}>\n        <ErrorBoundary fallbackRender={() => <>error boundary</>}>\n          <Page />\n        </ErrorBoundary>\n      </QueryClientProvider>,\n    )\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('loading..')\n    }\n\n    rendered.getByText('cancel').click()\n\n    await vi.waitFor(() => {\n      const state = queryClient.getQueryState(key)\n      expect(state).toMatchObject({\n        status: 'pending',\n        fetchStatus: 'idle',\n      })\n    })\n\n    expect(queryFn).toHaveBeenCalledOnce()\n\n    rendered.getByText('fetch').click()\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('hello')\n    }\n  })\n\n  it('should resolve to previous data when canceled with cancelQueries while suspending', async () => {\n    const renderStream = createRenderStream({ snapshotDOM: true })\n    const key = queryKey()\n    const queryFn = vi.fn().mockImplementation(async () => {\n      await vi.advanceTimersByTimeAsync(10)\n      return 'test'\n    })\n\n    const options = {\n      queryKey: key,\n      queryFn,\n    }\n\n    function MyComponent(props: { promise: Promise<string> }) {\n      const data = React.use(props.promise)\n\n      return <>{data}</>\n    }\n\n    function Loading() {\n      return <>loading..</>\n    }\n    function Page() {\n      const query = useQuery(options)\n\n      return (\n        <div>\n          <React.Suspense fallback={<Loading />}>\n            <MyComponent promise={query.promise} />\n          </React.Suspense>\n          <button onClick={() => queryClient.cancelQueries(options)}>\n            cancel\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = await renderStream.render(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('loading..')\n    }\n\n    queryClient.setQueryData(key, 'initial')\n\n    rendered.getByText('cancel').click()\n\n    await vi.waitFor(() => {\n      const state = queryClient.getQueryState(key)\n      expect(state?.data).toBe('initial')\n    })\n\n    expect(queryFn).toHaveBeenCalledTimes(1)\n  })\n\n  it('should suspend when not enabled', async () => {\n    const renderStream = createRenderStream({ snapshotDOM: true })\n    const key = queryKey()\n\n    const options = (count: number) => ({\n      queryKey: [...key, count],\n      queryFn: async () => {\n        await vi.advanceTimersByTimeAsync(10)\n        return 'test' + count\n      },\n    })\n\n    function MyComponent(props: { promise: Promise<string> }) {\n      const data = React.use(props.promise)\n\n      return <>{data}</>\n    }\n\n    function Loading() {\n      return <>loading..</>\n    }\n    function Page() {\n      const [count, setCount] = React.useState(0)\n      const query = useQuery({ ...options(count), enabled: count > 0 })\n\n      return (\n        <div>\n          <React.Suspense fallback={<Loading />}>\n            <MyComponent promise={query.promise} />\n          </React.Suspense>\n          <button onClick={() => setCount(1)}>enable</button>\n        </div>\n      )\n    }\n\n    const rendered = await renderStream.render(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      expect(withinDOM().getByText('loading..')).toBeInTheDocument()\n    }\n\n    rendered.getByText('enable').click()\n\n    // loading re-render with enabled\n    await renderStream.takeRender()\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      expect(withinDOM().getByText('test1')).toBeInTheDocument()\n    }\n  })\n\n  it('should show correct data when read from cache only (staleTime)', async () => {\n    const key = queryKey()\n    const renderStream = createRenderStream({ snapshotDOM: true })\n    queryClient.setQueryData(key, 'initial')\n\n    const queryFn = vi.fn().mockImplementation(async () => {\n      await vi.advanceTimersByTimeAsync(1)\n      return 'test'\n    })\n\n    function MyComponent(props: { promise: Promise<string> }) {\n      const data = React.use(props.promise)\n\n      return <>{data}</>\n    }\n\n    function Loading() {\n      return <>loading..</>\n    }\n    function Page() {\n      const query = useQuery({\n        queryKey: key,\n        queryFn,\n        staleTime: Infinity,\n      })\n\n      return (\n        <React.Suspense fallback={<Loading />}>\n          <MyComponent promise={query.promise} />\n        </React.Suspense>\n      )\n    }\n\n    await renderStream.render(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('initial')\n    }\n\n    expect(queryFn).toHaveBeenCalledTimes(0)\n  })\n\n  it('should show correct data when switching between cache entries without re-fetches', async () => {\n    const key = queryKey()\n    const renderStream = createRenderStream({ snapshotDOM: true })\n\n    function MyComponent(props: { promise: Promise<string> }) {\n      useTrackRenders()\n      const data = React.use(props.promise)\n\n      return <>{data}</>\n    }\n\n    function Loading() {\n      useTrackRenders()\n      return <>loading..</>\n    }\n    function Page() {\n      useTrackRenders()\n      const [count, setCount] = React.useState(0)\n      const query = useQuery({\n        queryKey: [key, count],\n        queryFn: async () => {\n          await vi.advanceTimersByTimeAsync(10)\n          return 'test' + count\n        },\n        staleTime: Infinity,\n      })\n\n      return (\n        <div>\n          <React.Suspense fallback={<Loading />}>\n            <MyComponent promise={query.promise} />\n          </React.Suspense>\n          <button onClick={() => setCount(count + 1)}>inc</button>\n          <button onClick={() => setCount(count - 1)}>dec</button>\n        </div>\n      )\n    }\n\n    const rendered = await renderStream.render(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('loading..')\n      expect(renderedComponents).toEqual([Page, Loading])\n    }\n\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('test0')\n      expect(renderedComponents).toEqual([Page, MyComponent])\n    }\n\n    rendered.getByText('inc').click()\n\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('loading..')\n      expect(renderedComponents).toEqual([Page, Loading])\n    }\n\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('test1')\n      expect(renderedComponents).toEqual([Page, MyComponent])\n    }\n\n    rendered.getByText('dec').click()\n\n    {\n      const { renderedComponents, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('test0')\n      expect(renderedComponents).toEqual([Page, MyComponent])\n    }\n  })\n\n  it('should not resolve with intermediate data when keys are switched', async () => {\n    const key = queryKey()\n    const renderStream = createRenderStream<{ data: string }>({\n      snapshotDOM: true,\n    })\n\n    function MyComponent(props: { promise: Promise<string> }) {\n      const data = React.use(props.promise)\n\n      renderStream.replaceSnapshot({ data })\n\n      return <>{data}</>\n    }\n\n    function Loading() {\n      return <>loading..</>\n    }\n    function Page() {\n      const [count, setCount] = React.useState(0)\n      const query = useQuery({\n        queryKey: [key, count],\n        queryFn: async () => {\n          await vi.advanceTimersByTimeAsync(10)\n          return 'test' + count\n        },\n        staleTime: Infinity,\n      })\n\n      return (\n        <div>\n          <React.Suspense fallback={<Loading />}>\n            <MyComponent promise={query.promise} />\n          </React.Suspense>\n          <button onClick={() => setCount(count + 1)}>inc</button>\n        </div>\n      )\n    }\n\n    const rendered = await renderStream.render(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('loading..')\n    }\n\n    {\n      const { snapshot, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('test0')\n      expect(snapshot).toMatchObject({ data: 'test0' })\n    }\n\n    rendered.getByText('inc').click()\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('loading..')\n    }\n\n    rendered.getByText('inc').click()\n    await renderStream.takeRender()\n\n    rendered.getByText('inc').click()\n    await renderStream.takeRender()\n\n    {\n      const { snapshot, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('test3')\n      expect(snapshot).toMatchObject({ data: 'test3' })\n    }\n  })\n\n  it('should not resolve with intermediate data when keys are switched (with background updates)', async () => {\n    const key = queryKey()\n    const renderStream = createRenderStream<{ data: string }>({\n      snapshotDOM: true,\n    })\n    let modifier = ''\n\n    function MyComponent(props: { promise: Promise<string> }) {\n      const data = React.use(props.promise)\n\n      renderStream.replaceSnapshot({ data })\n\n      return <>{data}</>\n    }\n\n    function Loading() {\n      return <>loading..</>\n    }\n    function Page() {\n      const [count, setCount] = React.useState(0)\n      const query = useQuery({\n        queryKey: [key, count],\n        queryFn: async () => {\n          await vi.advanceTimersByTimeAsync(10)\n          return 'test' + count + modifier\n        },\n      })\n\n      return (\n        <div>\n          <React.Suspense fallback={<Loading />}>\n            <MyComponent promise={query.promise} />\n          </React.Suspense>\n          <button onClick={() => setCount(count + 1)}>inc</button>\n          <button onClick={() => setCount(count - 1)}>dec</button>\n        </div>\n      )\n    }\n\n    const rendered = await renderStream.render(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('loading..')\n    }\n\n    {\n      const { snapshot, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('test0')\n      expect(snapshot).toMatchObject({ data: 'test0' })\n    }\n\n    rendered.getByText('inc').click()\n    {\n      const { snapshot } = await renderStream.takeRender()\n      expect(snapshot).toMatchObject({ data: 'test0' })\n    }\n\n    rendered.getByText('inc').click()\n    {\n      const { snapshot } = await renderStream.takeRender()\n      expect(snapshot).toMatchObject({ data: 'test0' })\n    }\n\n    rendered.getByText('inc').click()\n\n    {\n      const { snapshot, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('loading..')\n      expect(snapshot).toMatchObject({ data: 'test0' })\n    }\n\n    {\n      const { snapshot, withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('test3')\n      expect(snapshot).toMatchObject({ data: 'test3' })\n    }\n\n    modifier = 'new'\n\n    rendered.getByText('dec').click()\n    {\n      const { snapshot } = await renderStream.takeRender()\n      expect(snapshot).toMatchObject({ data: 'test3' })\n    }\n\n    rendered.getByText('dec').click()\n    {\n      const { snapshot } = await renderStream.takeRender()\n      expect(snapshot).toMatchObject({ data: 'test3' })\n    }\n\n    rendered.getByText('dec').click()\n    {\n      const { snapshot } = await renderStream.takeRender()\n      expect(snapshot).toMatchObject({ data: 'test0' })\n    }\n\n    await waitFor(() => rendered.getByText('test0new'))\n  })\n\n  it('should not suspend indefinitely with multiple, nested observers)', async () => {\n    const key = queryKey()\n    const renderStream = createRenderStream({ snapshotDOM: true })\n\n    function MyComponent({ input }: { input: string }) {\n      const query = useTheQuery(input)\n      const data = React.use(query.promise)\n\n      return <>{data}</>\n    }\n\n    function useTheQuery(input: string) {\n      return useQuery({\n        staleTime: Infinity,\n        queryKey: [key, input],\n        queryFn: async () => {\n          await vi.advanceTimersByTimeAsync(1)\n          return input + ' response'\n        },\n      })\n    }\n\n    function Page() {\n      const [input, setInput] = React.useState('defaultInput')\n      useTheQuery(input)\n\n      return (\n        <div>\n          <button onClick={() => setInput('someInput')}>setInput</button>\n          <React.Suspense fallback=\"loading..\">\n            <MyComponent input={input} />\n          </React.Suspense>\n        </div>\n      )\n    }\n\n    const rendered = await renderStream.render(\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>,\n    )\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('loading..')\n    }\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('defaultInput response')\n    }\n\n    expect(\n      queryClient.getQueryCache().find({ queryKey: [key, 'defaultInput'] })!\n        .observers.length,\n    ).toBe(2)\n\n    rendered.getByText('setInput').click()\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('loading..')\n    }\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      withinDOM().getByText('someInput response')\n    }\n\n    expect(\n      queryClient.getQueryCache().find({ queryKey: [key, 'defaultInput'] })!\n        .observers.length,\n    ).toBe(0)\n\n    expect(\n      queryClient.getQueryCache().find({ queryKey: [key, 'someInput'] })!\n        .observers.length,\n    ).toBe(2)\n  })\n\n  it('should implicitly observe data when promise is used', async () => {\n    const key = queryKey()\n\n    const renderStream = createRenderStream({ snapshotDOM: true })\n\n    function Page() {\n      useTrackRenders()\n      const query = useInfiniteQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await vi.advanceTimersByTimeAsync(1)\n          return { nextCursor: 1, data: 'test' }\n        },\n        initialPageParam: 0,\n        getNextPageParam: (lastPage) => lastPage.nextCursor,\n      })\n\n      React.use(query.promise)\n\n      const hasNextPage = query.hasNextPage\n\n      return (\n        <div>\n          <div>hasNextPage: {String(hasNextPage)}</div>\n        </div>\n      )\n    }\n\n    await renderStream.render(\n      <QueryClientProvider client={queryClient}>\n        <React.Suspense fallback=\"loading..\">\n          <Page />\n        </React.Suspense>\n      </QueryClientProvider>,\n    )\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      expect(withinDOM().getByText('loading..')).toBeInTheDocument()\n    }\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      expect(withinDOM().getByText('hasNextPage: true')).toBeInTheDocument()\n    }\n  })\n\n  it('should not throw to error boundary for refetch errors in infinite queries', async () => {\n    const key = queryKey()\n    const renderStream = createRenderStream({ snapshotDOM: true })\n\n    function Page() {\n      const query = useInfiniteQuery({\n        queryKey: key,\n        queryFn: async ({ pageParam = 0 }) => {\n          await vi.advanceTimersByTimeAsync(1)\n          if (pageParam === 0) {\n            return { nextCursor: 1, data: 'page-1' }\n          }\n          throw new Error('page error')\n        },\n        initialPageParam: 0,\n        getNextPageParam: (lastPage) => lastPage.nextCursor,\n        retry: false,\n      })\n\n      const data = React.use(query.promise)\n\n      return (\n        <div>\n          <div>pages:{data.pages.length}</div>\n          <div>isError:{String(query.isError)}</div>\n          <div>isFetchNextPageError:{String(query.isFetchNextPageError)}</div>\n          <button onClick={() => query.fetchNextPage()}>fetchNext</button>\n        </div>\n      )\n    }\n\n    const rendered = await renderStream.render(\n      <QueryClientProvider client={queryClient}>\n        <ErrorBoundary fallbackRender={() => <div>error boundary</div>}>\n          <React.Suspense fallback=\"loading..\">\n            <Page />\n          </React.Suspense>\n        </ErrorBoundary>\n      </QueryClientProvider>,\n    )\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      expect(withinDOM().getByText('loading..')).toBeInTheDocument()\n    }\n\n    {\n      const { withinDOM } = await renderStream.takeRender()\n      expect(withinDOM().getByText('pages:1')).toBeInTheDocument()\n      expect(withinDOM().getByText('isError:false')).toBeInTheDocument()\n      expect(\n        withinDOM().getByText('isFetchNextPageError:false'),\n      ).toBeInTheDocument()\n    }\n\n    rendered.getByText('fetchNext').click()\n    await vi.advanceTimersByTimeAsync(1)\n\n    await waitFor(() => {\n      expect(\n        rendered.getByText('isFetchNextPageError:true'),\n      ).toBeInTheDocument()\n    })\n\n    expect(rendered.queryByText('error boundary')).toBeNull()\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/useQuery.test-d.tsx",
    "content": "import { describe, expectTypeOf, it } from 'vitest'\nimport { queryKey } from '@tanstack/query-test-utils'\nimport { useQuery } from '../useQuery'\nimport { queryOptions } from '../queryOptions'\nimport type { OmitKeyof, QueryFunction, UseQueryOptions } from '..'\n\ndescribe('useQuery', () => {\n  const key = queryKey()\n\n  // unspecified query function should default to unknown\n  const noQueryFn = useQuery({ queryKey: key })\n  expectTypeOf(noQueryFn.data).toEqualTypeOf<unknown>()\n  expectTypeOf(noQueryFn.error).toEqualTypeOf<Error | null>()\n\n  // it should infer the result type from the query function\n  const fromQueryFn = useQuery({ queryKey: key, queryFn: () => 'test' })\n  expectTypeOf(fromQueryFn.data).toEqualTypeOf<string | undefined>()\n  expectTypeOf(fromQueryFn.error).toEqualTypeOf<Error | null>()\n  expectTypeOf(fromQueryFn.promise).toEqualTypeOf<Promise<string>>()\n\n  // it should be possible to specify the result type\n  const withResult = useQuery<string>({\n    queryKey: key,\n    queryFn: () => 'test',\n  })\n  expectTypeOf(withResult.data).toEqualTypeOf<string | undefined>()\n  expectTypeOf(withResult.error).toEqualTypeOf<Error | null>()\n\n  // it should be possible to specify the error type\n  const withError = useQuery<string, Error>({\n    queryKey: key,\n    queryFn: () => 'test',\n  })\n  expectTypeOf(withError.data).toEqualTypeOf<string | undefined>()\n  expectTypeOf(withError.error).toEqualTypeOf<Error | null>()\n\n  // it should provide the result type in the configuration\n  useQuery({\n    queryKey: [key],\n    queryFn: () => Promise.resolve(true),\n  })\n\n  // it should be possible to specify a union type as result type\n  const unionTypeSync = useQuery({\n    queryKey: key,\n    queryFn: () => (Math.random() > 0.5 ? ('a' as const) : ('b' as const)),\n  })\n  expectTypeOf(unionTypeSync.data).toEqualTypeOf<'a' | 'b' | undefined>()\n  const unionTypeAsync = useQuery<'a' | 'b'>({\n    queryKey: key,\n    queryFn: () => Promise.resolve(Math.random() > 0.5 ? 'a' : 'b'),\n  })\n  expectTypeOf(unionTypeAsync.data).toEqualTypeOf<'a' | 'b' | undefined>()\n\n  // should error when the query function result does not match with the specified type\n  // @ts-expect-error\n  useQuery<number>({ queryKey: key, queryFn: () => 'test' })\n\n  // it should infer the result type from a generic query function\n  function queryFn<T = string>(): Promise<T> {\n    return Promise.resolve({} as T)\n  }\n\n  const fromGenericQueryFn = useQuery({\n    queryKey: key,\n    queryFn: () => queryFn(),\n  })\n  expectTypeOf(fromGenericQueryFn.data).toEqualTypeOf<string | undefined>()\n  expectTypeOf(fromGenericQueryFn.error).toEqualTypeOf<Error | null>()\n\n  const fromGenericOptionsQueryFn = useQuery({\n    queryKey: key,\n    queryFn: () => queryFn(),\n  })\n  expectTypeOf(fromGenericOptionsQueryFn.data).toEqualTypeOf<\n    string | undefined\n  >()\n  expectTypeOf(fromGenericOptionsQueryFn.error).toEqualTypeOf<Error | null>()\n\n  type MyData = number\n  type MyQueryKey = readonly ['my-data', number]\n\n  const getMyDataArrayKey: QueryFunction<MyData, MyQueryKey> = ({\n    queryKey: [, n],\n  }) => {\n    return Promise.resolve(n + 42)\n  }\n\n  useQuery({\n    queryKey: ['my-data', 100],\n    queryFn: getMyDataArrayKey,\n  })\n\n  const getMyDataStringKey: QueryFunction<MyData, ['1']> = (context) => {\n    expectTypeOf(context.queryKey).toEqualTypeOf<['1']>()\n    return Promise.resolve(Number(context.queryKey[0]) + 42)\n  }\n\n  useQuery({\n    queryKey: ['1'],\n    queryFn: getMyDataStringKey,\n  })\n\n  // it should handle query-functions that return Promise<any>\n  useQuery({\n    queryKey: key,\n    queryFn: () => fetch('return Promise<any>').then((resp) => resp.json()),\n  })\n\n  // handles wrapped queries with custom fetcher passed as inline queryFn\n  const useWrappedQuery = <\n    TQueryKey extends [string, Record<string, unknown>?],\n    TQueryFnData,\n    TError,\n    TData = TQueryFnData,\n  >(\n    qk: TQueryKey,\n    fetcher: (\n      obj: TQueryKey[1],\n      token: string,\n      // return type must be wrapped with TQueryFnReturn\n    ) => Promise<TQueryFnData>,\n    options?: OmitKeyof<\n      UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n      'queryKey' | 'queryFn' | 'initialData'\n    >,\n  ) =>\n    useQuery({\n      queryKey: qk,\n      queryFn: () => fetcher(qk[1], 'token'),\n      ...options,\n    })\n  const testQuery = useWrappedQuery([''], () => Promise.resolve('1'))\n  expectTypeOf(testQuery.data).toEqualTypeOf<string | undefined>()\n\n  // handles wrapped queries with custom fetcher passed directly to useQuery\n  const useWrappedFuncStyleQuery = <\n    TQueryKey extends [string, Record<string, unknown>?],\n    TQueryFnData,\n    TError,\n    TData = TQueryFnData,\n  >(\n    qk: TQueryKey,\n    fetcher: () => Promise<TQueryFnData>,\n    options?: OmitKeyof<\n      UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n      'queryKey' | 'queryFn' | 'initialData'\n    >,\n  ) => useQuery({ queryKey: qk, queryFn: fetcher, ...options })\n  const testFuncStyle = useWrappedFuncStyleQuery([''], () =>\n    Promise.resolve(true),\n  )\n  expectTypeOf(testFuncStyle.data).toEqualTypeOf<boolean | undefined>()\n\n  it('should return the correct states for a successful query', () => {\n    const state = useQuery<string, Error>({\n      queryKey: key,\n      queryFn: () => Promise.resolve('test'),\n    })\n\n    if (state.isPending) {\n      expectTypeOf(state.data).toEqualTypeOf<undefined>()\n      expectTypeOf(state.error).toEqualTypeOf<null>()\n      return <span>pending</span>\n    }\n\n    if (state.isLoadingError) {\n      expectTypeOf(state.data).toEqualTypeOf<undefined>()\n      expectTypeOf(state.error).toEqualTypeOf<Error>()\n      return <span>{state.error.message}</span>\n    }\n\n    expectTypeOf(state.data).toEqualTypeOf<string>()\n    expectTypeOf(state.error).toEqualTypeOf<Error | null>()\n    return <span>{state.data}</span>\n  })\n\n  describe('initialData', () => {\n    describe('Config object overload', () => {\n      it('TData should always be defined when initialData is provided as an object', () => {\n        const { data } = useQuery({\n          queryKey: ['key'],\n          queryFn: () => ({ wow: true }),\n          initialData: { wow: true },\n        })\n\n        expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n      })\n\n      it('TData should be defined when passed through queryOptions', () => {\n        const options = queryOptions({\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n          initialData: {\n            wow: true,\n          },\n        })\n        const { data } = useQuery(options)\n\n        expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n      })\n\n      it('should be possible to define a different TData than TQueryFnData using select with queryOptions spread into useQuery', () => {\n        const options = queryOptions({\n          queryKey: ['key'],\n          queryFn: () => Promise.resolve(1),\n        })\n\n        const query = useQuery({\n          ...options,\n          select: (data) => data > 1,\n        })\n\n        expectTypeOf(query.data).toEqualTypeOf<boolean | undefined>()\n      })\n\n      it('TData should always be defined when initialData is provided as a function which ALWAYS returns the data', () => {\n        const { data } = useQuery({\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n          initialData: () => ({\n            wow: true,\n          }),\n        })\n\n        expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n      })\n\n      it('TData should have undefined in the union when initialData is NOT provided', () => {\n        const { data } = useQuery({\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n        })\n\n        expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()\n      })\n\n      it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => {\n        const { data } = useQuery({\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n          initialData: () => undefined as { wow: boolean } | undefined,\n        })\n\n        expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()\n      })\n\n      it('TData should be narrowed after an isSuccess check when initialData is provided as a function which can return undefined', () => {\n        const { data, isSuccess } = useQuery({\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n          initialData: () => undefined as { wow: boolean } | undefined,\n        })\n\n        if (isSuccess) {\n          expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n        }\n      })\n\n      // eslint-disable-next-line vitest/expect-expect\n      it('TData should depend from only arguments, not the result', () => {\n        // @ts-expect-error\n        const result: UseQueryResult<{ wow: string }> = useQuery({\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n          initialData: () => undefined as { wow: boolean } | undefined,\n        })\n\n        void result\n      })\n\n      it('data should not have undefined when initialData is provided', () => {\n        const { data } = useQuery({\n          queryKey: ['query-key'],\n          initialData: 42,\n        })\n\n        expectTypeOf(data).toEqualTypeOf<number>()\n      })\n    })\n\n    describe('custom hook', () => {\n      it('should allow custom hooks using UseQueryOptions', () => {\n        type Data = string\n\n        const useCustomQuery = (\n          options?: OmitKeyof<UseQueryOptions<Data>, 'queryKey' | 'queryFn'>,\n        ) => {\n          return useQuery({\n            ...options,\n            queryKey: ['todos-key'],\n            queryFn: () => Promise.resolve('data'),\n          })\n        }\n\n        const { data } = useCustomQuery()\n\n        expectTypeOf(data).toEqualTypeOf<Data | undefined>()\n      })\n    })\n\n    describe('structuralSharing', () => {\n      it('should be able to use structuralSharing with unknown types', () => {\n        // https://github.com/TanStack/query/issues/6525#issuecomment-1938411343\n        useQuery({\n          queryKey: ['key'],\n          queryFn: () => 5,\n          structuralSharing: (oldData, newData) => {\n            expectTypeOf(oldData).toBeUnknown()\n            expectTypeOf(newData).toBeUnknown()\n            return newData\n          },\n        })\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/useQuery.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, test, vi } from 'vitest'\nimport { act, fireEvent, render } from '@testing-library/react'\nimport * as React from 'react'\nimport { ErrorBoundary } from 'react-error-boundary'\nimport {\n  mockVisibilityState,\n  queryKey,\n  sleep,\n} from '@tanstack/query-test-utils'\nimport {\n  IsRestoringProvider,\n  QueryCache,\n  QueryClient,\n  dehydrate,\n  hydrate,\n  keepPreviousData,\n  skipToken,\n  useQuery,\n} from '..'\nimport {\n  Blink,\n  mockOnlineManagerIsOnline,\n  renderWithClient,\n  setActTimeout,\n} from './utils'\nimport type { DefinedUseQueryResult, QueryFunction, UseQueryResult } from '..'\nimport type { Mock } from 'vitest'\n\ndescribe('useQuery', () => {\n  let queryCache: QueryCache\n  let queryClient: QueryClient\n\n  beforeEach(() => {\n    queryCache = new QueryCache()\n    queryClient = new QueryClient({\n      queryCache,\n    })\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/105\n  it('should allow to set default data value', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const { data = 'default' } = useQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'test'),\n      })\n\n      return (\n        <div>\n          <h1>{data}</h1>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('default')).toBeInTheDocument()\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('test')).toBeInTheDocument()\n  })\n\n  it('should return the correct states for a successful query', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery<string, Error>({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return 'test'\n        },\n      })\n\n      states.push(state)\n\n      if (state.isPending) {\n        return <span>pending</span>\n      }\n\n      if (state.isLoadingError) {\n        return <span>{state.error.message}</span>\n      }\n\n      return <span>{state.data}</span>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('test')\n\n    expect(states.length).toEqual(2)\n\n    expect(states[0]).toEqual({\n      data: undefined,\n      dataUpdatedAt: 0,\n      error: null,\n      errorUpdatedAt: 0,\n      failureCount: 0,\n      failureReason: null,\n      errorUpdateCount: 0,\n      isError: false,\n      isFetched: false,\n      isFetchedAfterMount: false,\n      isFetching: true,\n      isPaused: false,\n      isPending: true,\n      isInitialLoading: true,\n      isLoading: true,\n      isLoadingError: false,\n      isPlaceholderData: false,\n      isRefetchError: false,\n      isRefetching: false,\n      isStale: true,\n      isSuccess: false,\n      isEnabled: true,\n      refetch: expect.any(Function),\n      status: 'pending',\n      fetchStatus: 'fetching',\n      promise: expect.any(Promise),\n    })\n\n    expect(states[1]).toEqual({\n      data: 'test',\n      dataUpdatedAt: expect.any(Number),\n      error: null,\n      errorUpdatedAt: 0,\n      failureCount: 0,\n      failureReason: null,\n      errorUpdateCount: 0,\n      isError: false,\n      isFetched: true,\n      isFetchedAfterMount: true,\n      isFetching: false,\n      isPaused: false,\n      isPending: false,\n      isInitialLoading: false,\n      isLoading: false,\n      isLoadingError: false,\n      isPlaceholderData: false,\n      isRefetchError: false,\n      isRefetching: false,\n      isStale: true,\n      isSuccess: true,\n      isEnabled: true,\n      refetch: expect.any(Function),\n      status: 'success',\n      fetchStatus: 'idle',\n      promise: expect.any(Promise),\n    })\n\n    expect(states[0]!.promise).toEqual(states[1]!.promise)\n  })\n\n  it('should return the correct states for an unsuccessful query', async () => {\n    const key = queryKey()\n\n    const states: Array<UseQueryResult> = []\n    let index = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => Promise.reject(new Error(`rejected #${++index}`)),\n\n        retry: 1,\n        retryDelay: 1,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <h1>Status: {state.status}</h1>\n          <div>Failure Count: {state.failureCount}</div>\n          <div>Failure Reason: {state.failureReason?.message}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(2)\n    rendered.getByText('Status: error')\n\n    expect(states[0]).toEqual({\n      data: undefined,\n      dataUpdatedAt: 0,\n      error: null,\n      errorUpdatedAt: 0,\n      failureCount: 0,\n      failureReason: null,\n      errorUpdateCount: 0,\n      isError: false,\n      isFetched: false,\n      isFetchedAfterMount: false,\n      isFetching: true,\n      isPaused: false,\n      isPending: true,\n      isInitialLoading: true,\n      isLoading: true,\n      isLoadingError: false,\n      isPlaceholderData: false,\n      isRefetchError: false,\n      isRefetching: false,\n      isStale: true,\n      isSuccess: false,\n      isEnabled: true,\n      refetch: expect.any(Function),\n      status: 'pending',\n      fetchStatus: 'fetching',\n      promise: expect.any(Promise),\n    })\n\n    expect(states[1]).toEqual({\n      data: undefined,\n      dataUpdatedAt: 0,\n      error: null,\n      errorUpdatedAt: 0,\n      failureCount: 1,\n      failureReason: new Error('rejected #1'),\n      errorUpdateCount: 0,\n      isError: false,\n      isFetched: false,\n      isFetchedAfterMount: false,\n      isFetching: true,\n      isPaused: false,\n      isPending: true,\n      isInitialLoading: true,\n      isLoading: true,\n      isLoadingError: false,\n      isPlaceholderData: false,\n      isRefetchError: false,\n      isRefetching: false,\n      isStale: true,\n      isSuccess: false,\n      isEnabled: true,\n      refetch: expect.any(Function),\n      status: 'pending',\n      fetchStatus: 'fetching',\n      promise: expect.any(Promise),\n    })\n\n    expect(states[2]).toEqual({\n      data: undefined,\n      dataUpdatedAt: 0,\n      error: new Error('rejected #2'),\n      errorUpdatedAt: expect.any(Number),\n      failureCount: 2,\n      failureReason: new Error('rejected #2'),\n      errorUpdateCount: 1,\n      isError: true,\n      isFetched: true,\n      isFetchedAfterMount: true,\n      isFetching: false,\n      isPaused: false,\n      isPending: false,\n      isInitialLoading: false,\n      isLoading: false,\n      isLoadingError: true,\n      isPlaceholderData: false,\n      isRefetchError: false,\n      isRefetching: false,\n      isStale: true,\n      isSuccess: false,\n      isEnabled: true,\n      refetch: expect.any(Function),\n      status: 'error',\n      fetchStatus: 'idle',\n      promise: expect.any(Promise),\n    })\n\n    expect(states[0]!.promise).toEqual(states[1]!.promise)\n    expect(states[1]!.promise).toEqual(states[2]!.promise)\n  })\n\n  it('should set isFetchedAfterMount to true after a query has been fetched', async () => {\n    const key = queryKey()\n\n    await queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => 'prefetched',\n    })\n\n    function Page() {\n      const result = useQuery({ queryKey: key, queryFn: () => 'new data' })\n\n      return (\n        <>\n          <div>data: {result.data}</div>\n          <div>isFetched: {result.isFetched ? 'true' : 'false'}</div>\n          <div>\n            isFetchedAfterMount: {result.isFetchedAfterMount ? 'true' : 'false'}\n          </div>\n        </>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('data: prefetched')).toBeInTheDocument()\n    expect(rendered.getByText('isFetched: true')).toBeInTheDocument()\n    expect(rendered.getByText('isFetchedAfterMount: false')).toBeInTheDocument()\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('data: new data')).toBeInTheDocument()\n    expect(rendered.getByText('isFetched: true')).toBeInTheDocument()\n    expect(rendered.getByText('isFetchedAfterMount: true')).toBeInTheDocument()\n  })\n\n  it('should not cancel an ongoing fetch when refetch is called with cancelRefetch=false if we have data already', async () => {\n    const key = queryKey()\n    let fetchCount = 0\n\n    function Page() {\n      const { refetch } = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          fetchCount++\n          await sleep(10)\n          return 'data'\n        },\n        enabled: false,\n        initialData: 'initialData',\n      })\n\n      React.useEffect(() => {\n        setActTimeout(() => {\n          refetch()\n        }, 5)\n        setActTimeout(() => {\n          refetch({ cancelRefetch: false })\n        }, 5)\n      }, [refetch])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(15)\n    // first refetch only, second refetch is ignored\n    expect(fetchCount).toBe(1)\n  })\n\n  it('should cancel an ongoing fetch when refetch is called (cancelRefetch=true) if we have data already', async () => {\n    const key = queryKey()\n    let fetchCount = 0\n\n    function Page() {\n      const { refetch } = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          fetchCount++\n          await sleep(10)\n          return 'data'\n        },\n        enabled: false,\n        initialData: 'initialData',\n      })\n\n      React.useEffect(() => {\n        setActTimeout(() => {\n          refetch()\n        }, 5)\n        setActTimeout(() => {\n          refetch()\n        }, 5)\n      }, [refetch])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(15)\n    // first refetch (gets cancelled) and second refetch\n    expect(fetchCount).toBe(2)\n  })\n\n  it('should not cancel an ongoing fetch when refetch is called (cancelRefetch=true) if we do not have data yet', async () => {\n    const key = queryKey()\n    let fetchCount = 0\n\n    function Page() {\n      const { refetch } = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          fetchCount++\n          await sleep(10)\n          return 'data'\n        },\n        enabled: false,\n      })\n\n      React.useEffect(() => {\n        setActTimeout(() => {\n          refetch()\n        }, 5)\n        setActTimeout(() => {\n          refetch()\n        }, 5)\n      }, [refetch])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(15)\n    // first refetch will not get cancelled, second one gets skipped\n    expect(fetchCount).toBe(1)\n  })\n\n  it('should be able to watch a query without providing a query function', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    queryClient.setQueryDefaults(key, { queryFn: () => 'data' })\n\n    function Page() {\n      const state = useQuery<string>({ queryKey: key })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined })\n    expect(states[1]).toMatchObject({ data: 'data' })\n  })\n\n  it('should pick up a query when re-mounting with gcTime 0', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const [toggle, setToggle] = React.useState(false)\n\n      return (\n        <div>\n          <button onClick={() => setToggle(true)}>toggle</button>\n          {toggle ? (\n            <Component key=\"2\" value=\"2\" />\n          ) : (\n            <Component key=\"1\" value=\"1\" />\n          )}\n        </div>\n      )\n    }\n\n    function Component({ value }: { value: string }) {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return 'data: ' + value\n        },\n\n        gcTime: 0,\n        notifyOnChangeProps: 'all',\n      })\n      states.push(state)\n      return (\n        <div>\n          <div>{state.data}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 1')\n\n    fireEvent.click(rendered.getByRole('button', { name: /toggle/i }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 2')\n\n    expect(states.length).toBe(4)\n    // First load\n    expect(states[0]).toMatchObject({\n      isPending: true,\n      isSuccess: false,\n      isFetching: true,\n    })\n    // First success\n    expect(states[1]).toMatchObject({\n      isPending: false,\n      isSuccess: true,\n      isFetching: false,\n    })\n    // Switch, goes to fetching\n    expect(states[2]).toMatchObject({\n      isPending: false,\n      isSuccess: true,\n      isFetching: true,\n    })\n    // Second success\n    expect(states[3]).toMatchObject({\n      isPending: false,\n      isSuccess: true,\n      isFetching: false,\n    })\n  })\n\n  it('should not get into an infinite loop when removing a query with gcTime 0 and rerendering', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const [, rerender] = React.useState({})\n\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(5)\n          return 'data'\n        },\n\n        gcTime: 0,\n        notifyOnChangeProps: ['isPending', 'isSuccess', 'data'],\n      })\n\n      states.push(state)\n\n      return (\n        <>\n          <div>{state.data}</div>\n\n          <button\n            onClick={() => {\n              queryClient.removeQueries({ queryKey: key })\n              rerender({})\n            }}\n          >\n            remove\n          </button>\n        </>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('data')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'remove' }))\n\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('data')\n\n    expect(states.length).toBe(4)\n    // First load\n    expect(states[0]).toMatchObject({\n      isPending: true,\n      isSuccess: false,\n      data: undefined,\n    })\n    // First success\n    expect(states[1]).toMatchObject({\n      isPending: false,\n      isSuccess: true,\n      data: 'data',\n    })\n    // Remove\n    expect(states[2]).toMatchObject({\n      isPending: true,\n      isSuccess: false,\n      data: undefined,\n    })\n    // Second success\n    expect(states[3]).toMatchObject({\n      isPending: false,\n      isSuccess: true,\n      data: 'data',\n    })\n  })\n\n  it('should fetch when refetchOnMount is false and nothing has been fetched yet', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => 'test',\n        refetchOnMount: false,\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined })\n    expect(states[1]).toMatchObject({ data: 'test' })\n  })\n\n  it('should not fetch when refetchOnMount is false and data has been fetched already', () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    queryClient.setQueryData(key, 'prefetched')\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => 'test',\n        refetchOnMount: false,\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    expect(states.length).toBe(1)\n    expect(states[0]).toMatchObject({ data: 'prefetched' })\n  })\n\n  it('should be able to select a part of the data with select', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => ({ name: 'test' }),\n        select: (data) => data.name,\n      })\n      states.push(state)\n\n      return <div>{state.data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('test')\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined })\n    expect(states[1]).toMatchObject({ data: 'test' })\n  })\n\n  it('should be able to select a part of the data with select in object syntax', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => ({ name: 'test' }),\n        select: (data) => data.name,\n      })\n      states.push(state)\n\n      return <div>{state.data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('test')\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined })\n    expect(states[1]).toMatchObject({ data: 'test' })\n  })\n\n  it('should throw an error when a selector throws', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n    const error = new Error('Select Error')\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => ({ name: 'test' }),\n        select: () => {\n          throw error\n        },\n      })\n      states.push(state)\n\n      return <div>{state.status}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('error')\n\n    expect(states.length).toBe(2)\n\n    expect(states[0]).toMatchObject({ status: 'pending', data: undefined })\n    expect(states[1]).toMatchObject({ status: 'error', error })\n  })\n\n  it('should not re-run a stable select when it re-renders if selector throws an error', async () => {\n    const key = queryKey()\n    const error = new Error('Select Error')\n    let runs = 0\n\n    function Page() {\n      const [, rerender] = React.useReducer(() => ({}), {})\n      const state = useQuery<string, Error>({\n        queryKey: key,\n        queryFn: () => (runs === 0 ? 'test' : 'test2'),\n\n        select: React.useCallback(() => {\n          runs++\n          throw error\n        }, []),\n      })\n      return (\n        <div>\n          <div>error: {state.error?.message}</div>\n          <button onClick={rerender}>rerender</button>\n          <button onClick={() => state.refetch()}>refetch</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('error: Select Error')\n    expect(runs).toEqual(1)\n    fireEvent.click(rendered.getByRole('button', { name: 'rerender' }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(runs).toEqual(1)\n    fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(runs).toEqual(2)\n  })\n\n  it('should track properties and only re-render when a tracked property changes', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          return 'test' + count\n        },\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <h1>{state.data ?? null}</h1>\n          <button onClick={() => state.refetch()}>refetch</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('test1')\n\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('test2')\n\n    expect(states.length).toBe(3)\n    expect(states[0]).toMatchObject({ data: undefined })\n    expect(states[1]).toMatchObject({ data: 'test1' })\n    expect(states[2]).toMatchObject({ data: 'test2' })\n  })\n\n  it('should always re-render if we are tracking props but not using any', async () => {\n    const key = queryKey()\n    let renderCount = 0\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery({ queryKey: key, queryFn: () => 'test' })\n\n      states.push(state)\n\n      React.useEffect(() => {\n        renderCount++\n      }, [state])\n\n      return (\n        <div>\n          <h1>hello</h1>\n        </div>\n      )\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(renderCount).toBe(2)\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined })\n    expect(states[1]).toMatchObject({ data: 'test' })\n  })\n\n  it('should be able to remove a query', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const [, rerender] = React.useState({})\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => ++count,\n        notifyOnChangeProps: 'all',\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <button onClick={() => queryClient.removeQueries({ queryKey: key })}>\n            remove\n          </button>\n          <button onClick={() => rerender({})}>rerender</button>\n          data: {state.data ?? 'null'}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('data: 1')\n    fireEvent.click(rendered.getByRole('button', { name: /remove/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    fireEvent.click(rendered.getByRole('button', { name: /rerender/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('data: 2')\n\n    expect(states.length).toBe(4)\n    // Initial\n    expect(states[0]).toMatchObject({ status: 'pending', data: undefined })\n    // Fetched\n    expect(states[1]).toMatchObject({ status: 'success', data: 1 })\n    // Remove + Hook state update, batched\n    expect(states[2]).toMatchObject({ status: 'pending', data: undefined })\n    // Fetched\n    expect(states[3]).toMatchObject({ status: 'success', data: 2 })\n  })\n\n  it('should create a new query when refetching a removed query', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return ++count\n        },\n        notifyOnChangeProps: 'all',\n      })\n\n      states.push(state)\n\n      const { refetch } = state\n\n      return (\n        <div>\n          <button onClick={() => queryClient.removeQueries({ queryKey: key })}>\n            remove\n          </button>\n          <button onClick={() => refetch()}>refetch</button>\n          data: {state.data ?? 'null'}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 1')\n    fireEvent.click(rendered.getByRole('button', { name: /remove/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 2')\n\n    expect(states.length).toBe(4)\n    // Initial\n    expect(states[0]).toMatchObject({ data: undefined, dataUpdatedAt: 0 })\n    // Fetched\n    expect(states[1]).toMatchObject({ data: 1 })\n    // Switch\n    expect(states[2]).toMatchObject({ data: undefined, dataUpdatedAt: 0 })\n    // Fetched\n    expect(states[3]).toMatchObject({ data: 2 })\n  })\n\n  it('should share equal data structures between query results', async () => {\n    const key = queryKey()\n\n    const result1 = [\n      { id: '1', done: false },\n      { id: '2', done: false },\n    ]\n\n    const result2 = [\n      { id: '1', done: false },\n      { id: '2', done: true },\n    ]\n\n    const states: Array<UseQueryResult<typeof result1>> = []\n\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          return count === 1 ? result1 : result2\n        },\n        notifyOnChangeProps: 'all',\n      })\n\n      states.push(state)\n\n      const { refetch } = state\n\n      return (\n        <div>\n          <button onClick={() => refetch()}>refetch</button>\n          data: {String(state.data?.[1]?.done)}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: false')\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: true')\n\n    expect(states.length).toBe(4)\n\n    const todos = states[2]?.data\n    const todo1 = todos?.[0]\n    const todo2 = todos?.[1]\n\n    const newTodos = states[3]?.data\n    const newTodo1 = newTodos?.[0]\n    const newTodo2 = newTodos?.[1]\n\n    expect(todos).toEqual(result1)\n    expect(newTodos).toEqual(result2)\n    expect(newTodos).not.toBe(todos)\n    expect(newTodo1).toBe(todo1)\n    expect(newTodo2).not.toBe(todo2)\n\n    return null\n  })\n\n  it('should use query function from hook when the existing query does not have a query function', async () => {\n    const key = queryKey()\n\n    queryClient.setQueryData(key, 'set')\n\n    function Page() {\n      const result = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return 'fetched'\n        },\n\n        initialData: 'initial',\n        staleTime: Infinity,\n      })\n\n      return (\n        <div>\n          <div>isFetching: {result.isFetching}</div>\n          <button onClick={() => queryClient.refetchQueries({ queryKey: key })}>\n            refetch\n          </button>\n          data: {result.data}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: set')).toBeInTheDocument()\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: fetched')).toBeInTheDocument()\n  })\n\n  it('should update query stale state and refetch when invalidated with invalidateQueries', async () => {\n    const key = queryKey()\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          return count\n        },\n        staleTime: Infinity,\n      })\n\n      return (\n        <div>\n          <button\n            onClick={() => queryClient.invalidateQueries({ queryKey: key })}\n          >\n            invalidate\n          </button>\n          data: {state.data}, isStale: {String(state.isStale)}, isFetching:{' '}\n          {String(state.isFetching)}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(\n      rendered.getByText('data: 1, isStale: false, isFetching: false'),\n    ).toBeInTheDocument()\n    fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(\n      rendered.getByText('data: 1, isStale: true, isFetching: true'),\n    ).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(\n      rendered.getByText('data: 2, isStale: false, isFetching: false'),\n    ).toBeInTheDocument()\n  })\n\n  it('should not update disabled query when refetching with refetchQueries', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          return count\n        },\n        enabled: false,\n      })\n\n      states.push(state)\n\n      React.useEffect(() => {\n        setActTimeout(() => {\n          queryClient.refetchQueries({ queryKey: key })\n        }, 20)\n      }, [])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(31)\n\n    expect(states.length).toBe(1)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: false,\n      isSuccess: false,\n      isStale: false,\n    })\n  })\n\n  it('should not refetch disabled query when invalidated with invalidateQueries', () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          return count\n        },\n        enabled: false,\n      })\n\n      states.push(state)\n\n      React.useEffect(() => {\n        setActTimeout(() => {\n          queryClient.invalidateQueries({ queryKey: key })\n        }, 10)\n      }, [])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    expect(states.length).toBe(1)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: false,\n      isSuccess: false,\n      isStale: false,\n    })\n  })\n\n  it('should not fetch when switching to a disabled query', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n\n    function Page() {\n      const [count, setCount] = React.useState(0)\n\n      const state = useQuery({\n        queryKey: [key, count],\n        queryFn: async () => {\n          await sleep(5)\n          return count\n        },\n        enabled: count === 0,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <button onClick={() => setCount(1)}>increment</button>\n          <div>data: {state.data ?? 'undefined'}</div>\n          <div>count: {count}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('data: 0')\n\n    fireEvent.click(rendered.getByRole('button', { name: /increment/i }))\n\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('count: 1')\n    rendered.getByText('data: undefined')\n\n    expect(states.length).toBe(3)\n\n    // Fetch query\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isSuccess: false,\n    })\n    // Fetched query\n    expect(states[1]).toMatchObject({\n      data: 0,\n      isFetching: false,\n      isSuccess: true,\n    })\n    // Switch to disabled query\n    expect(states[2]).toMatchObject({\n      data: undefined,\n      isFetching: false,\n      isSuccess: false,\n    })\n  })\n\n  it('should keep the previous data when placeholderData is set', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n\n    function Page() {\n      const [count, setCount] = React.useState(0)\n\n      const state = useQuery({\n        queryKey: [key, count],\n        queryFn: async () => {\n          await sleep(10)\n          return count\n        },\n        placeholderData: keepPreviousData,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <div>data: {state.data}</div>\n          <button onClick={() => setCount(1)}>setCount</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 0')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 1')\n\n    // Initial\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isSuccess: false,\n      isPlaceholderData: false,\n    })\n    // Fetched\n    expect(states[1]).toMatchObject({\n      data: 0,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Set state\n    expect(states[2]).toMatchObject({\n      data: 0,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // New data\n    expect(states[3]).toMatchObject({\n      data: 1,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n  })\n\n  it('should keep the previous data when placeholderData is set and select fn transform is used', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n\n    function Page() {\n      const [count, setCount] = React.useState(0)\n\n      const state = useQuery({\n        queryKey: [key, count],\n        queryFn: async () => {\n          await sleep(10)\n          return {\n            count,\n          }\n        },\n        select(data) {\n          return data.count\n        },\n        placeholderData: keepPreviousData,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <div>data: {state.data}</div>\n          <button onClick={() => setCount(1)}>setCount</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 0')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 1')\n\n    // Initial\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isSuccess: false,\n      isPlaceholderData: false,\n    })\n    // Fetched\n    expect(states[1]).toMatchObject({\n      data: 0,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Set state\n    expect(states[2]).toMatchObject({\n      data: 0,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // New data\n    expect(states[3]).toMatchObject({\n      data: 1,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n  })\n\n  it('should keep the previous queryKey (from prevQuery) between multiple pending queries when placeholderData is set and select fn transform is used', async () => {\n    const keys: Array<ReadonlyArray<unknown> | null> = []\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n\n    function Page() {\n      const [count, setCount] = React.useState(0)\n\n      const state = useQuery({\n        queryKey: [key, count],\n        queryFn: async () => {\n          await sleep(10)\n          return {\n            count,\n          }\n        },\n        select(data) {\n          return data.count\n        },\n        placeholderData: (prevData, prevQuery) => {\n          if (prevQuery) {\n            keys.push(prevQuery.queryKey)\n          }\n          return prevData\n        },\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <div>data: {state.data}</div>\n          <button onClick={() => setCount((prev) => prev + 1)}>setCount</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 0')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))\n    fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))\n    fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 3')\n\n    const allPreviousKeysAreTheFirstQueryKey = keys.every(\n      (k) => JSON.stringify(k) === JSON.stringify([key, 0]),\n    )\n\n    expect(allPreviousKeysAreTheFirstQueryKey).toBe(true)\n  })\n\n  it('should show placeholderData between multiple pending queries when select fn transform is used', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n\n    function Page() {\n      const [count, setCount] = React.useState(0)\n\n      const state = useQuery({\n        queryKey: [key, count],\n        queryFn: async () => {\n          await sleep(10)\n          return {\n            count,\n          }\n        },\n        select(data) {\n          return data.count\n        },\n        placeholderData: keepPreviousData,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <div>data: {state.data}</div>\n          <button onClick={() => setCount((prev) => prev + 1)}>setCount</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 0')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))\n    fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))\n    fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 3')\n    // Initial\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isSuccess: false,\n      isPlaceholderData: false,\n    })\n    // Fetched\n    expect(states[1]).toMatchObject({\n      data: 0,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Set state -> count = 1\n    expect(states[2]).toMatchObject({\n      data: 0,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // Set state -> count = 2\n    expect(states[3]).toMatchObject({\n      data: 0,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // Set state -> count = 3\n    expect(states[4]).toMatchObject({\n      data: 0,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // New data\n    expect(states[5]).toMatchObject({\n      data: 3,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n  })\n\n  it('should transition to error state when placeholderData is set', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n\n    function Page({ count }: { count: number }) {\n      const state = useQuery<number, Error>({\n        queryKey: [key, count],\n        queryFn: async () => {\n          await sleep(10)\n          if (count === 2) {\n            throw new Error('Error test')\n          }\n          return Promise.resolve(count)\n        },\n        retry: false,\n        placeholderData: keepPreviousData,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <h1>data: {state.data}</h1>\n          <h2>error: {state.error?.message}</h2>\n          <p>placeholder data: {state.isPlaceholderData}</p>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page count={0} />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 0')\n    rendered.rerender(<Page count={1} />)\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 1')\n    rendered.rerender(<Page count={2} />)\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('error: Error test')\n\n    expect(states.length).toBe(6)\n    // Initial\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      status: 'pending',\n      error: null,\n      isPlaceholderData: false,\n    })\n    // Fetched\n    expect(states[1]).toMatchObject({\n      data: 0,\n      isFetching: false,\n      status: 'success',\n      error: null,\n      isPlaceholderData: false,\n    })\n    // rerender Page 1\n    expect(states[2]).toMatchObject({\n      data: 0,\n      isFetching: true,\n      status: 'success',\n      error: null,\n      isPlaceholderData: true,\n    })\n    // New data\n    expect(states[3]).toMatchObject({\n      data: 1,\n      isFetching: false,\n      status: 'success',\n      error: null,\n      isPlaceholderData: false,\n    })\n    // rerender Page 2\n    expect(states[4]).toMatchObject({\n      data: 1,\n      isFetching: true,\n      status: 'success',\n      error: null,\n      isPlaceholderData: true,\n    })\n    // Error\n    expect(states[5]).toMatchObject({\n      data: undefined,\n      isFetching: false,\n      status: 'error',\n      isPlaceholderData: false,\n    })\n    expect(states[5]!.error).toHaveProperty('message', 'Error test')\n  })\n\n  it('should not show initial data from next query if placeholderData is set', async () => {\n    const key = queryKey()\n    const states: Array<DefinedUseQueryResult<number>> = []\n\n    function Page() {\n      const [count, setCount] = React.useState(0)\n\n      const state = useQuery({\n        queryKey: [key, count],\n        queryFn: async () => {\n          await sleep(10)\n          return count\n        },\n        initialData: 99,\n        placeholderData: keepPreviousData,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <h1>\n            data: {state.data}, count: {count}, isFetching:{' '}\n            {String(state.isFetching)}\n          </h1>\n          <button onClick={() => setCount(1)}>inc</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 0, count: 0, isFetching: false')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'inc' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 1, count: 1, isFetching: false')\n\n    expect(states.length).toBe(4)\n\n    // Initial\n    expect(states[0]).toMatchObject({\n      data: 99,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Fetched\n    expect(states[1]).toMatchObject({\n      data: 0,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Set state\n    expect(states[2]).toMatchObject({\n      data: 99,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // New data\n    expect(states[3]).toMatchObject({\n      data: 1,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n  })\n\n  it('should keep the previous data on disabled query when placeholderData is set', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n\n    function Page() {\n      const [count, setCount] = React.useState(0)\n\n      const state = useQuery({\n        queryKey: [key, count],\n        queryFn: async () => {\n          await sleep(10)\n          return count\n        },\n        enabled: false,\n        placeholderData: keepPreviousData,\n        notifyOnChangeProps: 'all',\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <button onClick={() => state.refetch()}>refetch</button>\n          <button onClick={() => setCount(1)}>setCount</button>\n          <div>data: {state.data ?? 'undefined'}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    rendered.getByText('data: undefined')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 0')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 0')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 1')\n\n    expect(states.length).toBe(6)\n\n    // Disabled query\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: false,\n      isSuccess: false,\n      isPlaceholderData: false,\n    })\n    // Fetching query\n    expect(states[1]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isSuccess: false,\n      isPlaceholderData: false,\n    })\n    // Fetched query\n    expect(states[2]).toMatchObject({\n      data: 0,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Set state\n    expect(states[3]).toMatchObject({\n      data: 0,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // Fetching new query\n    expect(states[4]).toMatchObject({\n      data: 0,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // Fetched new query\n    expect(states[5]).toMatchObject({\n      data: 1,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n  })\n\n  it('should keep the previous data on disabled query when placeholderData is set and switching query key multiple times', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n\n    queryClient.setQueryData([key, 10], 10)\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    function Page() {\n      const [count, setCount] = React.useState(10)\n\n      const state = useQuery({\n        queryKey: [key, count],\n        queryFn: async () => {\n          await sleep(10)\n          return count\n        },\n        enabled: false,\n        placeholderData: keepPreviousData,\n        notifyOnChangeProps: 'all',\n      })\n\n      states.push(state)\n\n      const { refetch } = state\n\n      React.useEffect(() => {\n        setActTimeout(() => {\n          setCount(11)\n        }, 20)\n        setActTimeout(() => {\n          setCount(12)\n        }, 30)\n        setActTimeout(() => {\n          refetch()\n        }, 40)\n      }, [refetch])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(51)\n\n    expect(states.length).toBe(5)\n\n    // Disabled query\n    expect(states[0]).toMatchObject({\n      data: 10,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Set state\n    expect(states[1]).toMatchObject({\n      data: 10,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // State update\n    expect(states[2]).toMatchObject({\n      data: 10,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // Refetch\n    expect(states[3]).toMatchObject({\n      data: 10,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // Refetch done\n    expect(states[4]).toMatchObject({\n      data: 12,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n  })\n\n  it('should use the correct query function when components use different configurations', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n\n    function FirstComponent() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return 1\n        },\n        notifyOnChangeProps: 'all',\n      })\n      const refetch = state.refetch\n\n      states.push(state)\n\n      return (\n        <div>\n          <button onClick={() => refetch()}>refetch</button>\n          data: {state.data}\n        </div>\n      )\n    }\n\n    function SecondComponent() {\n      useQuery({ queryKey: key, queryFn: () => 2, notifyOnChangeProps: 'all' })\n      return null\n    }\n\n    function Page() {\n      return (\n        <>\n          <FirstComponent />\n          <SecondComponent />\n        </>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 1')\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(states.length).toBe(4)\n\n    expect(states[0]).toMatchObject({\n      data: undefined,\n    })\n    expect(states[1]).toMatchObject({\n      data: 1,\n    })\n    expect(states[2]).toMatchObject({\n      data: 1,\n    })\n    // This state should be 1 instead of 2\n    expect(states[3]).toMatchObject({\n      data: 1,\n    })\n  })\n\n  it('should be able to set different stale times for a query', async () => {\n    const key = queryKey()\n    const states1: Array<UseQueryResult<string>> = []\n    const states2: Array<UseQueryResult<string>> = []\n\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: async () => {\n        await sleep(10)\n        return 'prefetch'\n      },\n    })\n\n    await vi.advanceTimersByTimeAsync(20)\n\n    function FirstComponent() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return 'one'\n        },\n\n        staleTime: 100,\n      })\n      states1.push(state)\n      return null\n    }\n\n    function SecondComponent() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return 'two'\n        },\n\n        staleTime: 10,\n      })\n      states2.push(state)\n      return null\n    }\n\n    function Page() {\n      return (\n        <>\n          <FirstComponent />\n          <SecondComponent />\n        </>\n      )\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(200)\n\n    expect(states1.length).toBe(4)\n    expect(states2.length).toBe(3)\n\n    expect(states1).toMatchObject([\n      // First render\n      {\n        data: 'prefetch',\n        isStale: false,\n      },\n      // Second useQuery started fetching\n      {\n        data: 'prefetch',\n        isStale: false,\n      },\n      // Second useQuery data came in\n      {\n        data: 'two',\n        isStale: false,\n      },\n      // Data became stale after 100ms\n      {\n        data: 'two',\n        isStale: true,\n      },\n    ])\n\n    expect(states2).toMatchObject([\n      // First render, data is stale and starts fetching\n      {\n        data: 'prefetch',\n        isStale: true,\n      },\n      // Second useQuery data came in\n      {\n        data: 'two',\n        isStale: false,\n      },\n      // Data became stale after 5ms\n      {\n        data: 'two',\n        isStale: true,\n      },\n    ])\n  })\n\n  it('should re-render when a query becomes stale', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => 'test',\n        staleTime: 50,\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(100)\n\n    expect(states.length).toBe(3)\n    expect(states[0]).toMatchObject({ isStale: true })\n    expect(states[1]).toMatchObject({ isStale: false })\n    expect(states[2]).toMatchObject({ isStale: true })\n  })\n\n  it('should re-render disabled observers when other observers trigger a query (#8741)', async () => {\n    const key = queryKey()\n\n    const useUserInfoQuery = ({\n      id,\n      enabled,\n    }: {\n      id: number | null\n      enabled: boolean\n    }) => {\n      return useQuery({\n        queryKey: [key, id],\n        queryFn: async () => {\n          await sleep(10)\n          return { id, name: 'John' }\n        },\n        enabled: !!id && enabled,\n      })\n    }\n\n    const Page = () => {\n      const [id, setId] = React.useState<number | null>(null)\n\n      const searchQuery = useUserInfoQuery({ id, enabled: false })\n\n      return (\n        <>\n          <div>User fetching status is {searchQuery.fetchStatus}</div>\n          <UserInfo id={id} />\n          <button onClick={() => setId(42)}>\n            Set ID and trigger user load\n          </button>\n        </>\n      )\n    }\n\n    function UserInfo({ id }: { id: number | null }) {\n      const searchQuery = useUserInfoQuery({ id, enabled: true })\n\n      return <div>UserInfo data is {JSON.stringify(searchQuery.data)} </div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    rendered.getByText('User fetching status is idle')\n\n    fireEvent.click(rendered.getByRole('button', { name: /set id/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(\n      rendered.getByText('User fetching status is fetching'),\n    ).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(\n      rendered.getByText('UserInfo data is {\"id\":42,\"name\":\"John\"}'),\n    ).toBeInTheDocument()\n\n    expect(\n      rendered.getByText('User fetching status is idle'),\n    ).toBeInTheDocument()\n  })\n\n  describe('notifyOnChangeProps', () => {\n    it('should not re-render when it should only re-render only data change and the selected data did not change', async () => {\n      const key = queryKey()\n      const states: Array<UseQueryResult<string>> = []\n\n      function Page() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: () => ({ name: 'test' }),\n          select: (data) => data.name,\n          notifyOnChangeProps: ['data'],\n        })\n\n        states.push(state)\n\n        return (\n          <div>\n            <div>{state.data}</div>\n            <button onClick={() => state.refetch()}>refetch</button>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      await vi.advanceTimersByTimeAsync(0)\n      rendered.getByText('test')\n\n      fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))\n\n      await vi.advanceTimersByTimeAsync(0)\n      rendered.getByText('test')\n\n      expect(states[0]).toMatchObject({ data: undefined })\n      expect(states[1]).toMatchObject({ data: 'test' })\n\n      // make sure no additional renders happen\n      await vi.advanceTimersByTimeAsync(50)\n      expect(states.length).toBe(2)\n    })\n    it('should not re-render when it should only re-render on data changes and the data did not change', async () => {\n      const key = queryKey()\n      const states: Array<UseQueryResult<string>> = []\n\n      function Page() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: async () => {\n            await sleep(5)\n            return 'test'\n          },\n\n          notifyOnChangeProps: ['data'],\n        })\n\n        states.push(state)\n\n        return (\n          <>\n            <button\n              onClick={async () => {\n                await state.refetch()\n              }}\n            >\n              refetch\n            </button>\n\n            <div>{state.data}</div>\n          </>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      await vi.advanceTimersByTimeAsync(6)\n      rendered.getByText('test')\n\n      fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))\n\n      // sleep is required to make sure no additional renders happen after click\n      await vi.advanceTimersByTimeAsync(20)\n\n      expect(states.length).toBe(2)\n      expect(states[0]).toMatchObject({\n        data: undefined,\n        status: 'pending',\n        isFetching: true,\n      })\n      expect(states[1]).toMatchObject({\n        data: 'test',\n        status: 'success',\n        isFetching: false,\n      })\n    })\n\n    // See https://github.com/TanStack/query/discussions/5588\n    describe('function', () => {\n      it('should not re-render when it should only re-render on data changes and the data did not change', async () => {\n        const key = queryKey()\n        const states: Array<UseQueryResult<string>> = []\n\n        function Page() {\n          const state = useQuery({\n            queryKey: key,\n            queryFn: async () => {\n              await sleep(5)\n              return 'test'\n            },\n            notifyOnChangeProps: () => ['data'],\n          })\n\n          states.push(state)\n\n          return (\n            <>\n              <button\n                onClick={async () => {\n                  await state.refetch()\n                }}\n              >\n                refetch\n              </button>\n\n              <div>{state.data}</div>\n            </>\n          )\n        }\n\n        const rendered = renderWithClient(queryClient, <Page />)\n\n        await vi.advanceTimersByTimeAsync(6)\n        rendered.getByText('test')\n\n        fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))\n\n        await vi.advanceTimersByTimeAsync(20)\n\n        expect(states.length).toBe(2)\n        expect(states[0]).toMatchObject({\n          data: undefined,\n          status: 'pending',\n          isFetching: true,\n        })\n        expect(states[1]).toMatchObject({\n          data: 'test',\n          status: 'success',\n          isFetching: false,\n        })\n      })\n\n      it('should not re-render when change props are not actively being tracked', async () => {\n        const key = queryKey()\n        const states: Array<UseQueryResult<string>> = []\n\n        function Page() {\n          const fetchCounterRef = React.useRef(0)\n          const trackChangesRef = React.useRef(true)\n\n          const notifyOnChangeProps = React.useCallback(() => {\n            return trackChangesRef.current ? 'all' : []\n          }, [])\n\n          const state = useQuery({\n            queryKey: key,\n            queryFn: async () => {\n              await sleep(5)\n              fetchCounterRef.current++\n              return `fetch counter: ${fetchCounterRef.current}`\n            },\n            notifyOnChangeProps,\n          })\n\n          states.push(state)\n\n          return (\n            <>\n              <button\n                onClick={async () => {\n                  await state.refetch()\n                }}\n              >\n                refetch\n              </button>\n              <button\n                onClick={() => {\n                  trackChangesRef.current = true\n                }}\n              >\n                enableTracking\n              </button>\n              <button\n                onClick={() => {\n                  trackChangesRef.current = false\n                }}\n              >\n                disableTracking\n              </button>\n\n              <div>{state.data}</div>\n            </>\n          )\n        }\n\n        const rendered = renderWithClient(queryClient, <Page />)\n        await vi.advanceTimersByTimeAsync(6)\n        rendered.getByText('fetch counter: 1')\n\n        expect(states.length).toBe(2)\n        expect(states[0]).toMatchObject({\n          data: undefined,\n          isFetching: true,\n          status: 'pending',\n        })\n        expect(states[1]).toMatchObject({\n          data: 'fetch counter: 1',\n          status: 'success',\n          isFetching: false,\n        })\n\n        // disable tracking and refetch to check for re-renders\n        fireEvent.click(\n          rendered.getByRole('button', { name: 'disableTracking' }),\n        )\n        fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))\n\n        await vi.advanceTimersByTimeAsync(20)\n        // still expect to only have two re-renders from the initial fetch\n        expect(states.length).toBe(2)\n\n        // enable tracking and refetch to check for re-renders\n        fireEvent.click(\n          rendered.getByRole('button', { name: 'enableTracking' }),\n        )\n        fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))\n\n        await vi.advanceTimersByTimeAsync(6)\n        rendered.getByText('fetch counter: 3')\n        await vi.advanceTimersByTimeAsync(20)\n\n        expect(states.length).toBe(4)\n        expect(states[2]).toMatchObject({\n          data: 'fetch counter: 2',\n          status: 'success',\n          isFetching: true,\n        })\n        expect(states[3]).toMatchObject({\n          data: 'fetch counter: 3',\n          status: 'success',\n          isFetching: false,\n        })\n      })\n    })\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/137\n  it('should not override initial data in dependent queries', () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    function Page() {\n      const first = useQuery({\n        queryKey: key1,\n        queryFn: () => 'data',\n        enabled: false,\n        initialData: 'init',\n      })\n\n      const second = useQuery({\n        queryKey: key2,\n        queryFn: () => 'data',\n        enabled: false,\n        initialData: 'init',\n      })\n\n      return (\n        <div>\n          <h2>First Data: {first.data}</h2>\n          <h2>Second Data: {second.data}</h2>\n          <div>First Status: {first.status}</div>\n          <div>Second Status: {second.status}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('First Data: init')).toBeInTheDocument()\n    expect(rendered.getByText('Second Data: init')).toBeInTheDocument()\n    expect(rendered.getByText('First Status: success')).toBeInTheDocument()\n    expect(rendered.getByText('Second Status: success')).toBeInTheDocument()\n  })\n\n  it('should update query options', () => {\n    const key = queryKey()\n\n    const queryFn = async () => {\n      await sleep(10)\n      return 'data1'\n    }\n\n    function Page() {\n      useQuery({ queryKey: key, queryFn, retryDelay: 10 })\n      useQuery({ queryKey: key, queryFn, retryDelay: 20 })\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    expect(queryCache.find({ queryKey: key })!.options.retryDelay).toBe(20)\n  })\n\n  it('should batch re-renders', async () => {\n    const key = queryKey()\n\n    let renders = 0\n\n    const queryFn = async () => {\n      await sleep(15)\n      return 'data'\n    }\n\n    function Page() {\n      const query1 = useQuery({ queryKey: key, queryFn })\n      const query2 = useQuery({ queryKey: key, queryFn })\n      renders++\n\n      return (\n        <div>\n          {query1.data} {query2.data}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(16)\n    rendered.getByText('data data')\n\n    // Should be 2 instead of 3\n    expect(renders).toBe(2)\n  })\n\n  it('should render latest data even if react has discarded certain renders', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const [, setNewState] = React.useState('state')\n      const state = useQuery({ queryKey: key, queryFn: () => 'data' })\n      React.useEffect(() => {\n        setActTimeout(() => {\n          queryClient.setQueryData(key, 'new')\n          // Update with same state to make react discard the next render\n          setNewState('state')\n        }, 10)\n      }, [])\n      return <div>{state.data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('new')).toBeInTheDocument()\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/170\n  it('should start with status pending, fetchStatus idle if enabled is false', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    function Page() {\n      const first = useQuery({\n        queryKey: key1,\n        queryFn: async () => {\n          await sleep(10)\n          return 'data'\n        },\n        enabled: false,\n      })\n      const second = useQuery({\n        queryKey: key2,\n        queryFn: async () => {\n          await sleep(10)\n          return 'data'\n        },\n      })\n\n      return (\n        <div>\n          <div>\n            First Status: {first.status}, {first.fetchStatus}\n          </div>\n          <div>\n            Second Status: {second.status}, {second.fetchStatus}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    // use \"act\" to wait for state update and prevent console warning\n\n    expect(\n      rendered.getByText('First Status: pending, idle'),\n    ).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(0)\n    expect(\n      rendered.getByText('Second Status: pending, fetching'),\n    ).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(\n      rendered.getByText('Second Status: success, idle'),\n    ).toBeInTheDocument()\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/144\n  it('should be in \"pending\" state by default', () => {\n    const key = queryKey()\n\n    function Page() {\n      const { status } = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return 'test'\n        },\n      })\n\n      return <div>status: {status}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('status: pending')).toBeInTheDocument()\n  })\n\n  it('should not refetch query on focus when `enabled` is set to `false`', async () => {\n    const key = queryKey()\n    const queryFn = vi\n      .fn<(...args: Array<unknown>) => string>()\n      .mockReturnValue('data')\n\n    function Page() {\n      const { data = 'default' } = useQuery({\n        queryKey: key,\n        queryFn,\n        enabled: false,\n      })\n\n      return (\n        <div>\n          <h1>{data}</h1>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('default')\n\n    act(() => {\n      window.dispatchEvent(new Event('visibilitychange'))\n    })\n\n    expect(queryFn).not.toHaveBeenCalled()\n  })\n\n  it('should not refetch stale query on focus when `refetchOnWindowFocus` is set to `false`', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => count++,\n        staleTime: 0,\n        refetchOnWindowFocus: false,\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    act(() => {\n      window.dispatchEvent(new Event('visibilitychange'))\n    })\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined, isFetching: true })\n    expect(states[1]).toMatchObject({ data: 0, isFetching: false })\n  })\n\n  it('should not refetch stale query on focus when `refetchOnWindowFocus` is set to a function that returns `false`', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => count++,\n        staleTime: 0,\n        refetchOnWindowFocus: () => false,\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    act(() => {\n      window.dispatchEvent(new Event('visibilitychange'))\n    })\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined, isFetching: true })\n    expect(states[1]).toMatchObject({ data: 0, isFetching: false })\n  })\n\n  it('should not refetch fresh query on focus when `refetchOnWindowFocus` is set to `true`', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => count++,\n        staleTime: Infinity,\n        refetchOnWindowFocus: true,\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    act(() => {\n      window.dispatchEvent(new Event('visibilitychange'))\n    })\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined, isFetching: true })\n    expect(states[1]).toMatchObject({ data: 0, isFetching: false })\n  })\n\n  it('should refetch fresh query on focus when `refetchOnWindowFocus` is set to `always`', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return count++\n        },\n\n        staleTime: Infinity,\n        refetchOnWindowFocus: 'always',\n      })\n      states.push(state)\n      return (\n        <div>\n          <div>\n            data: {state.data}, isFetching: {String(state.isFetching)}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 0, isFetching: false')).toBeInTheDocument()\n\n    act(() => {\n      window.dispatchEvent(new Event('visibilitychange'))\n    })\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 1, isFetching: false')).toBeInTheDocument()\n  })\n\n  it('should calculate focus behavior for `refetchOnWindowFocus` depending on function', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return count++\n        },\n\n        staleTime: 0,\n        retry: 0,\n        refetchOnWindowFocus: (query) => (query.state.data || 0) < 1,\n      })\n      states.push(state)\n      return <div>data: {String(state.data)}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 0')\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined, isFetching: true })\n    expect(states[1]).toMatchObject({ data: 0, isFetching: false })\n\n    act(() => {\n      window.dispatchEvent(new Event('visibilitychange'))\n    })\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 1')\n\n    // refetch should happen\n    expect(states.length).toBe(4)\n\n    expect(states[2]).toMatchObject({ data: 0, isFetching: true })\n    expect(states[3]).toMatchObject({ data: 1, isFetching: false })\n\n    act(() => {\n      window.dispatchEvent(new Event('visibilitychange'))\n    })\n\n    await vi.advanceTimersByTimeAsync(20)\n\n    // no more refetch now\n    expect(states.length).toBe(4)\n  })\n\n  it('should refetch fresh query when refetchOnMount is set to always', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    await queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => 'prefetched',\n    })\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => 'data',\n        refetchOnMount: 'always',\n        staleTime: Infinity,\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: 'prefetched',\n      isStale: false,\n      isFetching: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: 'data',\n      isStale: false,\n      isFetching: false,\n    })\n  })\n\n  it('should refetch stale query when refetchOnMount is set to true', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    await queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => 'prefetched',\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => 'data',\n        refetchOnMount: true,\n        staleTime: 0,\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: 'prefetched',\n      isStale: true,\n      isFetching: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: 'data',\n      isStale: true,\n      isFetching: false,\n    })\n  })\n\n  it('should set status to error if queryFn throws', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    function Page() {\n      const { status, error } = useQuery({\n        queryKey: key,\n        queryFn: () => {\n          return Promise.reject(new Error('Error test'))\n        },\n        retry: false,\n      })\n\n      return (\n        <div>\n          <h1>{status}</h1>\n          <h2>{error?.message}</h2>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('error')).toBeInTheDocument()\n    expect(rendered.getByText('Error test')).toBeInTheDocument()\n    consoleMock.mockRestore()\n  })\n\n  it('should throw error if queryFn throws and throwOnError is in use', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    function Page() {\n      const { status, error } = useQuery<unknown, string>({\n        queryKey: key,\n        queryFn: () => Promise.reject(new Error('Error test')),\n        retry: false,\n        throwOnError: true,\n      })\n\n      return (\n        <div>\n          <h1>{status}</h1>\n          <h2>{error}</h2>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <ErrorBoundary fallbackRender={() => <div>error boundary</div>}>\n        <Page />\n      </ErrorBoundary>,\n    )\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n    consoleMock.mockRestore()\n  })\n\n  it('should update with data if we observe no properties and throwOnError', async () => {\n    const key = queryKey()\n\n    let result: UseQueryResult<string> | undefined\n\n    function Page() {\n      const query = useQuery({\n        queryKey: key,\n        queryFn: () => Promise.resolve('data'),\n        throwOnError: true,\n      })\n\n      React.useEffect(() => {\n        result = query\n      })\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(queryClient.isFetching()).toBe(0)\n\n    expect(result?.data).toBe('data')\n  })\n\n  it('should set status to error instead of throwing when error should not be thrown', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const { status, error } = useQuery({\n        queryKey: key,\n        queryFn: () => Promise.reject(new Error('Local Error')),\n\n        retry: false,\n        throwOnError: (err) => err.message !== 'Local Error',\n      })\n\n      return (\n        <div>\n          <h1>{status}</h1>\n          <h2>{error?.message}</h2>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <ErrorBoundary fallbackRender={() => <div>error boundary</div>}>\n        <Page />\n      </ErrorBoundary>,\n    )\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('error')).toBeInTheDocument()\n    expect(rendered.getByText('Local Error')).toBeInTheDocument()\n  })\n\n  it('should throw error instead of setting status when error should be thrown', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n\n    const key = queryKey()\n\n    function Page() {\n      const { status, error } = useQuery<unknown, Error>({\n        queryKey: key,\n        queryFn: () => Promise.reject(new Error('Remote Error')),\n\n        retry: false,\n        throwOnError: (err) => err.message !== 'Local Error',\n      })\n\n      return (\n        <div>\n          <h1>{status}</h1>\n          <h2>{error?.message ?? ''}</h2>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <ErrorBoundary\n        fallbackRender={({ error }) => (\n          <div>\n            <div>error boundary</div>\n            <div>{error?.message}</div>\n          </div>\n        )}\n      >\n        <Page />\n      </ErrorBoundary>,\n    )\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n    expect(rendered.getByText('Remote Error')).toBeInTheDocument()\n    consoleMock.mockRestore()\n  })\n\n  it('should continue retries when observers unmount and remount while waiting for a retry (#3031)', async () => {\n    const key = queryKey()\n    let count = 0\n\n    function Page() {\n      const result = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          count++\n          await sleep(10)\n          return Promise.reject(new Error('some error'))\n        },\n\n        retry: 2,\n        retryDelay: 100,\n      })\n\n      return (\n        <div>\n          <div>error: {result.error?.message ?? 'null'}</div>\n          <div>failureCount: {result.failureCount}</div>\n          <div>failureReason: {result.failureReason?.message}</div>\n        </div>\n      )\n    }\n\n    function App() {\n      const [show, toggle] = React.useReducer((x) => !x, true)\n\n      return (\n        <div>\n          <button onClick={toggle}>{show ? 'hide' : 'show'}</button>\n          {show && <Page />}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('failureCount: 1')).toBeInTheDocument()\n    expect(rendered.getByText('failureReason: some error')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(90)\n    fireEvent.click(rendered.getByRole('button', { name: /hide/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByRole('button', { name: /show/i })).toBeInTheDocument()\n    fireEvent.click(rendered.getByRole('button', { name: /show/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    await vi.advanceTimersByTimeAsync(110)\n    await vi.advanceTimersByTimeAsync(110)\n    expect(rendered.getByText('error: some error')).toBeInTheDocument()\n\n    expect(count).toBe(4)\n  })\n\n  it('should restart when observers unmount and remount while waiting for a retry when query was cancelled in between (#3031)', async () => {\n    const key = queryKey()\n    let count = 0\n\n    function Page() {\n      const result = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          count++\n          await sleep(10)\n          return Promise.reject(new Error('some error'))\n        },\n\n        retry: 2,\n        retryDelay: 100,\n      })\n\n      return (\n        <div>\n          <div>error: {result.error?.message ?? 'null'}</div>\n          <div>failureCount: {result.failureCount}</div>\n          <div>failureReason: {result.failureReason?.message}</div>\n        </div>\n      )\n    }\n\n    function App() {\n      const [show, toggle] = React.useReducer((x) => !x, true)\n\n      return (\n        <div>\n          <button onClick={toggle}>{show ? 'hide' : 'show'}</button>\n          <button onClick={() => queryClient.cancelQueries({ queryKey: key })}>\n            cancel\n          </button>\n          {show && <Page />}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('failureCount: 1')).toBeInTheDocument()\n    expect(rendered.getByText('failureReason: some error')).toBeInTheDocument()\n    fireEvent.click(rendered.getByRole('button', { name: /hide/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /cancel/i }))\n    expect(rendered.getByRole('button', { name: /show/i })).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(1)\n    fireEvent.click(rendered.getByRole('button', { name: /show/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    await vi.advanceTimersByTimeAsync(110)\n    await vi.advanceTimersByTimeAsync(110)\n    expect(rendered.getByText('error: some error')).toBeInTheDocument()\n\n    // initial fetch (1), which will be cancelled, followed by new mount(2) + 2 retries = 4\n    expect(count).toBe(4)\n  })\n\n  it('should always fetch if refetchOnMount is set to always', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    await queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => 'prefetched',\n    })\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => 'data',\n        refetchOnMount: 'always',\n        staleTime: 50,\n      })\n      states.push(state)\n      return (\n        <div>\n          <div>data: {state.data ?? 'null'}</div>\n          <div>isFetching: {state.isFetching}</div>\n          <div>isStale: {state.isStale}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('data: data')\n    await vi.advanceTimersByTimeAsync(52)\n    expect(states.length).toBe(3)\n\n    expect(states[0]).toMatchObject({\n      data: 'prefetched',\n      isStale: false,\n      isFetching: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: 'data',\n      isStale: false,\n      isFetching: false,\n    })\n    expect(states[2]).toMatchObject({\n      data: 'data',\n      isStale: true,\n      isFetching: false,\n    })\n  })\n\n  it('should fetch if initial data is set', async () => {\n    const key = queryKey()\n    const states: Array<DefinedUseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => 'data',\n        initialData: 'initial',\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(states.length).toBe(2)\n\n    expect(states[0]).toMatchObject({\n      data: 'initial',\n      isStale: true,\n      isFetching: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: 'data',\n      isStale: true,\n      isFetching: false,\n    })\n  })\n\n  it('should not fetch if initial data is set with a stale time', async () => {\n    const key = queryKey()\n    const states: Array<DefinedUseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => 'data',\n        staleTime: 50,\n        initialData: 'initial',\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(52)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: 'initial',\n      isStale: false,\n      isFetching: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: 'initial',\n      isStale: true,\n      isFetching: false,\n    })\n  })\n\n  it('should fetch if initial data updated at is older than stale time', async () => {\n    const key = queryKey()\n    const states: Array<DefinedUseQueryResult<string>> = []\n\n    const oneSecondAgo = Date.now() - 1000\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => 'data',\n        staleTime: 50,\n        initialData: 'initial',\n        initialDataUpdatedAt: oneSecondAgo,\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(52)\n\n    expect(states.length).toBe(3)\n    expect(states[0]).toMatchObject({\n      data: 'initial',\n      isStale: true,\n      isFetching: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: 'data',\n      isStale: false,\n      isFetching: false,\n    })\n    expect(states[2]).toMatchObject({\n      data: 'data',\n      isStale: true,\n      isFetching: false,\n    })\n  })\n\n  it('should fetch if \"initial data updated at\" is exactly 0', async () => {\n    const key = queryKey()\n    const states: Array<DefinedUseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => 'data',\n        staleTime: 10 * 1000, // 10 seconds\n        initialData: 'initial',\n        initialDataUpdatedAt: 0,\n      })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: 'initial',\n      isStale: true,\n      isFetching: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: 'data',\n      isStale: false,\n      isFetching: false,\n    })\n  })\n\n  it('should keep initial data when the query key changes', async () => {\n    const key = queryKey()\n    const states: Array<DefinedUseQueryResult<{ count: number }>> = []\n\n    function Page() {\n      const [count, setCount] = React.useState(0)\n      const state = useQuery({\n        queryKey: [key, count],\n        queryFn: () => ({ count: 10 }),\n        staleTime: Infinity,\n        initialData: () => ({ count }),\n      })\n      states.push(state)\n\n      React.useEffect(() => {\n        setActTimeout(() => {\n          setCount(1)\n        }, 10)\n      }, [])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(states.length).toBe(2)\n    // Initial\n    expect(states[0]).toMatchObject({ data: { count: 0 } })\n    // Set state\n    expect(states[1]).toMatchObject({ data: { count: 1 } })\n  })\n\n  it('should retry specified number of times', async () => {\n    const key = queryKey()\n\n    const queryFn = vi.fn<(...args: Array<unknown>) => unknown>()\n    queryFn.mockImplementation(() => {\n      return Promise.reject(new Error('Error test Barrett'))\n    })\n\n    function Page() {\n      const { status, failureCount, failureReason } = useQuery({\n        queryKey: key,\n        queryFn,\n        retry: 1,\n        retryDelay: 1,\n      })\n\n      return (\n        <div>\n          <h1>{status}</h1>\n          <h2>Failed {failureCount} times</h2>\n          <h2>Failed because {failureReason?.message}</h2>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    rendered.getByText('pending')\n    await vi.advanceTimersByTimeAsync(2)\n    rendered.getByText('error')\n\n    // query should fail `retry + 1` times, since first time isn't a \"retry\"\n    rendered.getByText('Failed 2 times')\n    rendered.getByText('Failed because Error test Barrett')\n\n    expect(queryFn).toHaveBeenCalledTimes(2)\n  })\n\n  it('should not retry if retry function `false`', async () => {\n    const key = queryKey()\n\n    const queryFn = vi.fn<(...args: Array<unknown>) => unknown>()\n\n    queryFn.mockImplementationOnce(() => {\n      return Promise.reject(new Error('Error test Tanner'))\n    })\n\n    queryFn.mockImplementation(() => {\n      return Promise.reject(new Error('NoRetry'))\n    })\n\n    function Page() {\n      const { status, failureCount, failureReason, error } = useQuery({\n        queryKey: key,\n        queryFn,\n        retryDelay: 1,\n        retry: (_failureCount, err) => err.message !== 'NoRetry',\n      })\n\n      return (\n        <div>\n          <h1>{status}</h1>\n          <h2>Failed {failureCount} times</h2>\n          <h2>Failed because {failureReason?.message}</h2>\n          <h2>{error?.message}</h2>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    rendered.getByText('pending')\n    await vi.advanceTimersByTimeAsync(2)\n    rendered.getByText('error')\n\n    rendered.getByText('Failed 2 times')\n    rendered.getByText('Failed because NoRetry')\n\n    rendered.getByText('NoRetry')\n\n    expect(queryFn).toHaveBeenCalledTimes(2)\n  })\n\n  it('should extract retryDelay from error', async () => {\n    const key = queryKey()\n\n    type DelayError = { delay: number }\n\n    const queryFn = vi.fn<(...args: Array<unknown>) => unknown>()\n    queryFn.mockImplementation(() => {\n      return Promise.reject({ delay: 50 })\n    })\n\n    function Page() {\n      const { status, failureCount, failureReason } = useQuery({\n        queryKey: key,\n        queryFn,\n        retry: 1,\n        retryDelay: (_, error: DelayError) => error.delay,\n      })\n\n      return (\n        <div>\n          <h1>{status}</h1>\n          <h2>Failed {failureCount} times</h2>\n          <h2>Failed because DelayError: {failureReason?.delay}ms</h2>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(queryFn).toHaveBeenCalledTimes(1)\n\n    rendered.getByText('Failed because DelayError: 50ms')\n    await vi.advanceTimersByTimeAsync(51)\n    rendered.getByText('Failed 2 times')\n\n    expect(queryFn).toHaveBeenCalledTimes(2)\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/160\n  it('should continue retry after focus regain', async () => {\n    const key = queryKey()\n\n    // make page unfocused\n    const visibilityMock = mockVisibilityState('hidden')\n\n    let count = 0\n\n    function Page() {\n      const query = useQuery<unknown, string>({\n        queryKey: key,\n        queryFn: () => {\n          count++\n          return Promise.reject<unknown>(`fetching error ${count}`)\n        },\n        retry: 3,\n        retryDelay: 1,\n      })\n\n      return (\n        <div>\n          <div>error {String(query.error)}</div>\n          <div>status {query.status}</div>\n          <div>failureCount {query.failureCount}</div>\n          <div>failureReason {query.failureReason}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    // The query should display the first error result\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('failureCount 1')).toBeInTheDocument()\n    expect(\n      rendered.getByText('failureReason fetching error 1'),\n    ).toBeInTheDocument()\n    expect(rendered.getByText('status pending')).toBeInTheDocument()\n    expect(rendered.getByText('error null')).toBeInTheDocument()\n\n    // Check if the query really paused\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('failureCount 1')).toBeInTheDocument()\n    expect(\n      rendered.getByText('failureReason fetching error 1'),\n    ).toBeInTheDocument()\n\n    act(() => {\n      // reset visibilityState to original value\n      visibilityMock.mockRestore()\n      window.dispatchEvent(new Event('visibilitychange'))\n    })\n\n    // Wait for the final result\n    await vi.advanceTimersByTimeAsync(4)\n    expect(rendered.getByText('failureCount 4')).toBeInTheDocument()\n    expect(\n      rendered.getByText('failureReason fetching error 4'),\n    ).toBeInTheDocument()\n    expect(rendered.getByText('status error')).toBeInTheDocument()\n    expect(rendered.getByText('error fetching error 4')).toBeInTheDocument()\n\n    // Check if the query really stopped\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('failureCount 4')).toBeInTheDocument()\n    expect(\n      rendered.getByText('failureReason fetching error 4'),\n    ).toBeInTheDocument()\n  })\n\n  it('should fetch on mount when a query was already created with setQueryData', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    queryClient.setQueryData(key, 'prefetched')\n\n    function Page() {\n      const state = useQuery({ queryKey: key, queryFn: () => 'data' })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(states.length).toBe(2)\n    expect(states).toMatchObject([\n      {\n        data: 'prefetched',\n        isFetching: true,\n        isStale: true,\n      },\n      {\n        data: 'data',\n        isFetching: false,\n        isStale: true,\n      },\n    ])\n  })\n\n  it('should refetch after focus regain', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    // make page unfocused\n    const visibilityMock = mockVisibilityState('hidden')\n\n    // set data in cache to check if the hook query fn is actually called\n    queryClient.setQueryData(key, 'prefetched')\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return 'data'\n        },\n      })\n      states.push(state)\n      return (\n        <div>\n          {state.data}, {state.isStale}, {state.isFetching}\n        </div>\n      )\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(states.length).toBe(2)\n\n    act(() => {\n      // reset visibilityState to original value\n      visibilityMock.mockRestore()\n      window.dispatchEvent(new Event('visibilitychange'))\n    })\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(states.length).toBe(4)\n\n    expect(states).toMatchObject([\n      {\n        data: 'prefetched',\n        isFetching: true,\n        isStale: true,\n      },\n      {\n        data: 'data',\n        isFetching: false,\n        isStale: true,\n      },\n      {\n        data: 'data',\n        isFetching: true,\n        isStale: true,\n      },\n      {\n        data: 'data',\n        isFetching: false,\n        isStale: true,\n      },\n    ])\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/195\n  it('should refetch if stale after a prefetch', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    const queryFn = vi.fn<(...args: Array<unknown>) => string>()\n    queryFn.mockImplementation(() => 'data')\n\n    const prefetchQueryFn = vi.fn<(...args: Array<unknown>) => string>()\n    prefetchQueryFn.mockImplementation(() => 'not yet...')\n\n    await queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: prefetchQueryFn,\n      staleTime: 10,\n    })\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    function Page() {\n      const state = useQuery({ queryKey: key, queryFn })\n      states.push(state)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(states.length).toBe(2)\n\n    expect(prefetchQueryFn).toHaveBeenCalledTimes(1)\n    expect(queryFn).toHaveBeenCalledTimes(1)\n  })\n\n  it('should not refetch if not stale after a prefetch', async () => {\n    const key = queryKey()\n\n    const queryFn = vi.fn<(...args: Array<unknown>) => string>()\n    queryFn.mockImplementation(() => 'data')\n\n    const prefetchQueryFn =\n      vi.fn<(...args: Array<unknown>) => Promise<string>>()\n    prefetchQueryFn.mockImplementation(async () => {\n      await sleep(10)\n      return 'not yet...'\n    })\n\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: prefetchQueryFn,\n      staleTime: 1000,\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    function Page() {\n      useQuery({ queryKey: key, queryFn, staleTime: 1000 })\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(prefetchQueryFn).toHaveBeenCalledTimes(1)\n    expect(queryFn).toHaveBeenCalledTimes(0)\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/190\n  it('should reset failureCount on successful fetch', async () => {\n    const key = queryKey()\n\n    let counter = 0\n\n    function Page() {\n      const query = useQuery({\n        queryKey: key,\n        queryFn: () => {\n          if (counter < 2) {\n            counter++\n            return Promise.reject(new Error('error'))\n          } else {\n            return Promise.resolve('data')\n          }\n        },\n        retryDelay: 10,\n      })\n\n      return (\n        <div>\n          <div>failureCount {query.failureCount}</div>\n          <div>failureReason {query.failureReason?.message ?? 'null'}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('failureCount 2')).toBeInTheDocument()\n    expect(rendered.getByText('failureReason error')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('failureCount 0')).toBeInTheDocument()\n    expect(rendered.getByText('failureReason null')).toBeInTheDocument()\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/199\n  it('should use prefetched data for dependent query', async () => {\n    const key = queryKey()\n    let count = 0\n\n    function Page() {\n      const [enabled, setEnabled] = React.useState(false)\n      const [isPrefetched, setPrefetched] = React.useState(false)\n\n      const query = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          count++\n          await sleep(10)\n          return count\n        },\n\n        enabled,\n      })\n\n      React.useEffect(() => {\n        async function prefetch() {\n          await queryClient.prefetchQuery({\n            queryKey: key,\n            queryFn: () => Promise.resolve('prefetched data'),\n          })\n          act(() => setPrefetched(true))\n        }\n\n        prefetch()\n      }, [])\n\n      return (\n        <div>\n          {isPrefetched && <div>isPrefetched</div>}\n          <button onClick={() => setEnabled(true)}>setKey</button>\n          <div>data: {query.data}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('isPrefetched')).toBeInTheDocument()\n    fireEvent.click(rendered.getByText('setKey'))\n    expect(rendered.getByText('data: prefetched data')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n    expect(count).toBe(1)\n  })\n\n  it('should support dependent queries via the enable config option', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const [shouldFetch, setShouldFetch] = React.useState(false)\n\n      const query = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return 'data'\n        },\n        enabled: shouldFetch,\n      })\n\n      return (\n        <div>\n          <div>FetchStatus: {query.fetchStatus}</div>\n          <h2>Data: {query.data || 'no data'}</h2>\n          {shouldFetch ? null : (\n            <button onClick={() => setShouldFetch(true)}>fetch</button>\n          )}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('FetchStatus: idle')).toBeInTheDocument()\n    expect(rendered.getByText('Data: no data')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('fetch'))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('FetchStatus: fetching')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('FetchStatus: idle')).toBeInTheDocument()\n    expect(rendered.getByText('Data: data')).toBeInTheDocument()\n  })\n\n  it('should mark query as fetching, when using initialData', async () => {\n    const key = queryKey()\n    const results: Array<DefinedUseQueryResult<string>> = []\n\n    function Page() {\n      const result = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return 'serverData'\n        },\n        initialData: 'initialData',\n      })\n      results.push(result)\n      return <div>data: {result.data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    rendered.getByText('data: initialData')\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: serverData')\n\n    expect(results.length).toBe(2)\n    expect(results[0]).toMatchObject({ data: 'initialData', isFetching: true })\n    expect(results[1]).toMatchObject({ data: 'serverData', isFetching: false })\n  })\n\n  it('should initialize state properly, when initialData is falsy', async () => {\n    const key = queryKey()\n    const results: Array<DefinedUseQueryResult<number>> = []\n\n    function Page() {\n      const result = useQuery({\n        queryKey: key,\n        queryFn: () => 1,\n        initialData: 0,\n      })\n      results.push(result)\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(results.length).toBe(2)\n    expect(results[0]).toMatchObject({ data: 0, isFetching: true })\n    expect(results[1]).toMatchObject({ data: 1, isFetching: false })\n  })\n\n  it('should show the correct data when switching keys with initialData, placeholderData & staleTime', async () => {\n    const key = queryKey()\n\n    const ALL_TODOS = [\n      { name: 'todo A', priority: 'high' },\n      { name: 'todo B', priority: 'medium' },\n    ]\n\n    const initialTodos = ALL_TODOS\n\n    function Page() {\n      const [filter, setFilter] = React.useState('')\n      const { data: todos } = useQuery({\n        queryKey: [...key, filter],\n        queryFn: () => {\n          return Promise.resolve(\n            ALL_TODOS.filter((todo) =>\n              filter ? todo.priority === filter : true,\n            ),\n          )\n        },\n        initialData() {\n          return filter === '' ? initialTodos : undefined\n        },\n        placeholderData: keepPreviousData,\n        staleTime: 5000,\n      })\n\n      return (\n        <div>\n          Current Todos, filter: {filter || 'all'}\n          <hr />\n          <button onClick={() => setFilter('')}>All</button>\n          <button onClick={() => setFilter('high')}>High</button>\n          <ul>\n            {(todos ?? []).map((todo) => (\n              <li key={todo.name}>\n                {todo.name} - {todo.priority}\n              </li>\n            ))}\n          </ul>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('Current Todos, filter: all')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /high/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(\n      rendered.getByText('Current Todos, filter: high'),\n    ).toBeInTheDocument()\n    fireEvent.click(rendered.getByRole('button', { name: /all/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('todo B - medium')).toBeInTheDocument()\n  })\n\n  // // See https://github.com/tannerlinsley/react-query/issues/214\n  it('data should persist when enabled is changed to false', async () => {\n    const key = queryKey()\n    const results: Array<DefinedUseQueryResult<string>> = []\n\n    function Page() {\n      const [shouldFetch, setShouldFetch] = React.useState(true)\n\n      const result = useQuery({\n        queryKey: key,\n        queryFn: () => 'fetched data',\n        enabled: shouldFetch,\n        initialData: shouldFetch ? 'initial' : 'initial falsy',\n      })\n\n      results.push(result)\n\n      return (\n        <div>\n          <div>{result.data}</div>\n          <div>{shouldFetch ? 'enabled' : 'disabled'}</div>\n          <button\n            onClick={() => {\n              setShouldFetch(false)\n            }}\n          >\n            enable\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('fetched data')).toBeInTheDocument()\n    expect(rendered.getByText('enabled')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /enable/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('fetched data')).toBeInTheDocument()\n    expect(rendered.getByText('disabled')).toBeInTheDocument()\n\n    expect(results.length).toBe(3)\n    expect(results[0]).toMatchObject({ data: 'initial', isStale: true })\n    expect(results[1]).toMatchObject({ data: 'fetched data', isStale: true })\n    // disabled observers are not stale\n    expect(results[2]).toMatchObject({ data: 'fetched data', isStale: false })\n  })\n\n  it('should support enabled:false in query object syntax', () => {\n    const key = queryKey()\n    const queryFn = vi.fn<(...args: Array<unknown>) => string>()\n    queryFn.mockImplementation(() => 'data')\n\n    function Page() {\n      const { fetchStatus } = useQuery({\n        queryKey: key,\n        queryFn,\n        enabled: false,\n      })\n      return <div>fetchStatus: {fetchStatus}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(queryFn).not.toHaveBeenCalled()\n    expect(queryCache.find({ queryKey: key })).not.toBeUndefined()\n    expect(rendered.getByText('fetchStatus: idle')).toBeInTheDocument()\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/360\n  test('should init to status:pending, fetchStatus:idle when enabled is false', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const query = useQuery({\n        queryKey: key,\n        queryFn: () => 'data',\n        enabled: false,\n      })\n\n      return (\n        <div>\n          <div>\n            status: {query.status}, {query.fetchStatus}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('status: pending, idle')).toBeInTheDocument()\n  })\n\n  test('should not schedule garbage collection, if gcTimeout is set to `Infinity`', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const query = useQuery({\n        queryKey: key,\n        queryFn: () => 'fetched data',\n        gcTime: Infinity,\n      })\n      return <div>{query.data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('fetched data')\n    const setTimeoutSpy = vi.spyOn(globalThis.window, 'setTimeout')\n\n    rendered.unmount()\n\n    expect(setTimeoutSpy).not.toHaveBeenCalled()\n  })\n\n  test('should schedule garbage collection, if gcTimeout is not set to infinity', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const query = useQuery({\n        queryKey: key,\n        queryFn: () => 'fetched data',\n        gcTime: 1000 * 60 * 10, // 10 Minutes\n      })\n      return <div>{query.data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('fetched data')\n\n    const setTimeoutSpy = vi.spyOn(globalThis.window, 'setTimeout')\n\n    rendered.unmount()\n\n    expect(setTimeoutSpy).toHaveBeenLastCalledWith(\n      expect.any(Function),\n      1000 * 60 * 10,\n    )\n  })\n\n  it('should not cause memo churn when data does not change', async () => {\n    const key = queryKey()\n    const queryFn = vi\n      .fn<(...args: Array<unknown>) => string>()\n      .mockReturnValue('data')\n    const memoFn = vi.fn()\n\n    function Page() {\n      const result = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return (\n            queryFn() || {\n              data: {\n                nested: true,\n              },\n            }\n          )\n        },\n      })\n\n      React.useMemo(() => {\n        memoFn()\n        return result.data\n      }, [result.data])\n\n      return (\n        <div>\n          <div>status {result.status}</div>\n          <div>isFetching {result.isFetching ? 'true' : 'false'}</div>\n          <button onClick={() => result.refetch()}>refetch</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('status pending')\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('status success')\n    fireEvent.click(rendered.getByText('refetch'))\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('isFetching true')\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('isFetching false')\n    expect(queryFn).toHaveBeenCalledTimes(2)\n    expect(memoFn).toHaveBeenCalledTimes(2)\n  })\n\n  it('should update data upon interval changes', async () => {\n    const key = queryKey()\n    let count = 0\n\n    function Page() {\n      const [int, setInt] = React.useState(200)\n      const { data } = useQuery({\n        queryKey: key,\n        queryFn: () => count++,\n        refetchInterval: int,\n      })\n\n      React.useEffect(() => {\n        if (data === 2) {\n          setInt(0)\n        }\n      }, [data])\n\n      return <div>count: {data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    // mount\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('count: 0')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(201)\n    expect(rendered.getByText('count: 1')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(201)\n    expect(rendered.getByText('count: 2')).toBeInTheDocument()\n  })\n\n  it('should refetch in an interval depending on function result', async () => {\n    const key = queryKey()\n    let count = 0\n    const states: Array<UseQueryResult<number>> = []\n\n    function Page() {\n      const queryInfo = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return count++\n        },\n        refetchInterval: ({ state: { data = 0 } }) => (data < 2 ? 10 : false),\n      })\n\n      states.push(queryInfo)\n\n      return (\n        <div>\n          <h1>count: {queryInfo.data}</h1>\n          <h2>status: {queryInfo.status}</h2>\n          <h2>data: {queryInfo.data}</h2>\n          <h2>refetch: {queryInfo.isRefetching}</h2>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(51)\n    rendered.getByText('count: 2')\n\n    expect(states.length).toEqual(6)\n\n    expect(states).toMatchObject([\n      {\n        status: 'pending',\n        isFetching: true,\n        data: undefined,\n      },\n      {\n        status: 'success',\n        isFetching: false,\n        data: 0,\n      },\n      {\n        status: 'success',\n        isFetching: true,\n        data: 0,\n      },\n      {\n        status: 'success',\n        isFetching: false,\n        data: 1,\n      },\n      {\n        status: 'success',\n        isFetching: true,\n        data: 1,\n      },\n      {\n        status: 'success',\n        isFetching: false,\n        data: 2,\n      },\n    ])\n  })\n\n  it('should not interval fetch with a refetchInterval of 0', async () => {\n    const key = queryKey()\n    const queryFn = vi.fn(() => 1)\n\n    function Page() {\n      const queryInfo = useQuery({\n        queryKey: key,\n        queryFn,\n        refetchInterval: 0,\n      })\n\n      return <div>count: {queryInfo.data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('count: 1')\n\n    await vi.advanceTimersByTimeAsync(10) // extra sleep to make sure we're not re-fetching\n\n    expect(queryFn).toHaveBeenCalledTimes(1)\n  })\n\n  it('should accept an empty string as query key', async () => {\n    function Page() {\n      const result = useQuery({\n        queryKey: [''],\n        queryFn: (ctx) => ctx.queryKey,\n      })\n      return <>{JSON.stringify(result.data)}</>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('')).toBeInTheDocument()\n  })\n\n  it('should accept an object as query key', async () => {\n    function Page() {\n      const result = useQuery({\n        queryKey: [{ a: 'a' }],\n        queryFn: (ctx) => ctx.queryKey,\n      })\n      return <>{JSON.stringify(result.data)}</>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('[{\"a\":\"a\"}]')).toBeInTheDocument()\n  })\n\n  it('should refetch if any query instance becomes enabled', async () => {\n    const key = queryKey()\n\n    const queryFn = vi\n      .fn<(...args: Array<unknown>) => string>()\n      .mockReturnValue('data')\n\n    function Disabled() {\n      useQuery({ queryKey: key, queryFn, enabled: false })\n      return null\n    }\n\n    function Page() {\n      const [enabled, setEnabled] = React.useState(false)\n      const result = useQuery({ queryKey: key, queryFn, enabled })\n      return (\n        <>\n          <Disabled />\n          <div>{result.data}</div>\n          <button onClick={() => setEnabled(true)}>enable</button>\n        </>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n    expect(queryFn).toHaveBeenCalledTimes(0)\n    fireEvent.click(rendered.getByText('enable'))\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('data')\n    expect(queryFn).toHaveBeenCalledTimes(1)\n  })\n\n  it('should use placeholder data while the query loads', async () => {\n    const key1 = queryKey()\n\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key1,\n        queryFn: () => 'data',\n        placeholderData: 'placeholder',\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <h2>Data: {state.data}</h2>\n          <div>Status: {state.status}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('Data: data')\n\n    expect(states).toMatchObject([\n      {\n        isSuccess: true,\n        isPlaceholderData: true,\n        data: 'placeholder',\n      },\n      {\n        isSuccess: true,\n        isPlaceholderData: false,\n        data: 'data',\n      },\n    ])\n  })\n\n  it('should use placeholder data even for disabled queries', async () => {\n    const key1 = queryKey()\n\n    const states: Array<{ state: UseQueryResult<string>; count: number }> = []\n\n    function Page() {\n      const [count, setCount] = React.useState(0)\n\n      const state = useQuery({\n        queryKey: key1,\n        queryFn: () => 'data',\n        placeholderData: 'placeholder',\n        enabled: count === 0,\n      })\n\n      states.push({ state, count })\n\n      React.useEffect(() => {\n        setCount(1)\n      }, [])\n\n      return (\n        <div>\n          <h2>Data: {state.data}</h2>\n          <div>Status: {state.status}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('Data: data')\n\n    expect(states).toMatchObject([\n      {\n        state: {\n          isSuccess: true,\n          isPlaceholderData: true,\n          data: 'placeholder',\n        },\n        count: 0,\n      },\n      {\n        state: {\n          isSuccess: true,\n          isPlaceholderData: true,\n          data: 'placeholder',\n        },\n        count: 1,\n      },\n      {\n        state: {\n          isSuccess: true,\n          isPlaceholderData: false,\n          data: 'data',\n        },\n        count: 1,\n      },\n    ])\n  })\n\n  it('placeholder data should run through select', async () => {\n    const key1 = queryKey()\n\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key1,\n        queryFn: () => 1,\n        placeholderData: 23,\n        select: (data) => String(data * 2),\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <h2>Data: {state.data}</h2>\n          <div>Status: {state.status}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('Data: 2')\n\n    expect(states).toMatchObject([\n      {\n        isSuccess: true,\n        isPlaceholderData: true,\n        data: '46',\n      },\n      {\n        isSuccess: true,\n        isPlaceholderData: false,\n        data: '2',\n      },\n    ])\n  })\n\n  it('placeholder data function result should run through select', async () => {\n    const key1 = queryKey()\n\n    const states: Array<UseQueryResult<string>> = []\n    let placeholderFunctionRunCount = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key1,\n        queryFn: () => 1,\n        placeholderData: () => {\n          placeholderFunctionRunCount++\n          return 23\n        },\n        select: (data) => String(data * 2),\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <h2>Data: {state.data}</h2>\n          <div>Status: {state.status}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('Data: 2')\n\n    rendered.rerender(<Page />)\n\n    expect(states).toMatchObject([\n      {\n        isSuccess: true,\n        isPlaceholderData: true,\n        data: '46',\n      },\n      {\n        isSuccess: true,\n        isPlaceholderData: false,\n        data: '2',\n      },\n      {\n        isSuccess: true,\n        isPlaceholderData: false,\n        data: '2',\n      },\n    ])\n\n    expect(placeholderFunctionRunCount).toEqual(1)\n  })\n\n  it('select should only run when dependencies change if memoized', async () => {\n    const key1 = queryKey()\n\n    let selectRun = 0\n\n    function Page() {\n      const [count, inc] = React.useReducer((prev) => prev + 1, 2)\n\n      const state = useQuery({\n        queryKey: key1,\n        queryFn: async () => {\n          await sleep(10)\n          return 0\n        },\n        select: React.useCallback(\n          (data: number) => {\n            selectRun++\n            return `selected ${data + count}`\n          },\n          [count],\n        ),\n        placeholderData: 99,\n      })\n\n      return (\n        <div>\n          <h2>Data: {state.data}</h2>\n          <button onClick={inc}>inc: {count}</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n    rendered.getByText('Data: selected 101') // 99 + 2\n    expect(selectRun).toBe(1)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('Data: selected 2') // 0 + 2\n    expect(selectRun).toBe(2)\n\n    fireEvent.click(rendered.getByRole('button', { name: /inc/i }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('Data: selected 3') // 0 + 3\n    expect(selectRun).toBe(3)\n  })\n\n  it('select should always return the correct state', async () => {\n    const key1 = queryKey()\n\n    function Page() {\n      const [count, inc] = React.useReducer((prev) => prev + 1, 2)\n      const [forceValue, forceUpdate] = React.useReducer((prev) => prev + 1, 1)\n\n      const state = useQuery({\n        queryKey: key1,\n        queryFn: async () => {\n          await sleep(10)\n          return 0\n        },\n\n        select: React.useCallback(\n          (data: number) => {\n            return `selected ${data + count}`\n          },\n          [count],\n        ),\n        placeholderData: 99,\n      })\n\n      return (\n        <div>\n          <h2>Data: {state.data}</h2>\n          <h2>forceValue: {forceValue}</h2>\n          <button onClick={inc}>inc: {count}</button>\n          <button onClick={forceUpdate}>forceUpdate</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('Data: selected 101')).toBeInTheDocument() // 99 + 2\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Data: selected 2')).toBeInTheDocument() // 0 + 2\n\n    fireEvent.click(rendered.getByRole('button', { name: /inc/i }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Data: selected 3')).toBeInTheDocument() // 0 + 3\n\n    fireEvent.click(rendered.getByRole('button', { name: /forceUpdate/i }))\n\n    expect(rendered.getByText('forceValue: 2')).toBeInTheDocument()\n    // data should still be 3 after an independent re-render\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Data: selected 3')).toBeInTheDocument()\n  })\n\n  it('select should structurally share data', async () => {\n    const key1 = queryKey()\n    const states: Array<Array<number>> = []\n\n    function Page() {\n      const [forceValue, forceUpdate] = React.useReducer((prev) => prev + 1, 1)\n\n      const state = useQuery({\n        queryKey: key1,\n        queryFn: async () => {\n          await sleep(10)\n          return [1, 2]\n        },\n\n        select: (res) => res.map((x) => x + 1),\n      })\n\n      React.useEffect(() => {\n        if (state.data) {\n          states.push(state.data)\n        }\n      }, [state.data])\n\n      return (\n        <div>\n          <h2>Data: {JSON.stringify(state.data)}</h2>\n          <h2>forceValue: {forceValue}</h2>\n          <button onClick={forceUpdate}>forceUpdate</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('Data: [2,3]')\n    expect(states).toHaveLength(1)\n\n    fireEvent.click(rendered.getByRole('button', { name: /forceUpdate/i }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('forceValue: 2')\n    rendered.getByText('Data: [2,3]')\n\n    // effect should not be triggered again due to structural sharing\n    expect(states).toHaveLength(1)\n  })\n\n  it('should cancel the query function when there are no more subscriptions', async () => {\n    const key = queryKey()\n    let cancelFn: Mock = vi.fn()\n\n    const queryFn = ({ signal }: { signal?: AbortSignal }) => {\n      const promise = new Promise<string>((resolve, reject) => {\n        cancelFn = vi.fn(() => reject('Cancelled'))\n        signal?.addEventListener('abort', cancelFn)\n        sleep(20).then(() => resolve('OK'))\n      })\n\n      return promise\n    }\n\n    function Page() {\n      const state = useQuery({ queryKey: key, queryFn })\n      return (\n        <div>\n          <h1>Status: {state.status}</h1>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <Blink duration={5}>\n        <Page />\n      </Blink>,\n    )\n\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('off')\n\n    expect(cancelFn).toHaveBeenCalled()\n  })\n\n  it('should cancel the query if the signal was consumed and there are no more subscriptions', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    const queryFn: QueryFunction<string, [typeof key, number]> = async (\n      ctx,\n    ) => {\n      const [, limit] = ctx.queryKey\n      const value = limit % 2 && ctx.signal ? 'abort' : `data ${limit}`\n      await sleep(25)\n      return value\n    }\n\n    function Page(props: { limit: number }) {\n      const state = useQuery({ queryKey: [key, props.limit], queryFn })\n      // eslint-disable-next-line react-hooks/immutability\n      states[props.limit] = state\n      return (\n        <div>\n          <h1>Status: {state.status}</h1>\n          <h1>data: {state.data}</h1>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <Blink duration={5}>\n        <Page limit={0} />\n        <Page limit={1} />\n        <Page limit={2} />\n        <Page limit={3} />\n      </Blink>,\n    )\n\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('off')\n    await vi.advanceTimersByTimeAsync(20)\n\n    expect(states).toHaveLength(4)\n\n    expect(queryCache.find({ queryKey: [key, 0] })?.state).toMatchObject({\n      data: 'data 0',\n      status: 'success',\n      dataUpdateCount: 1,\n    })\n\n    expect(queryCache.find({ queryKey: [key, 1] })?.state).toMatchObject({\n      data: undefined,\n      status: 'pending',\n      fetchStatus: 'idle',\n    })\n\n    expect(queryCache.find({ queryKey: [key, 2] })?.state).toMatchObject({\n      data: 'data 2',\n      status: 'success',\n      dataUpdateCount: 1,\n    })\n\n    expect(queryCache.find({ queryKey: [key, 3] })?.state).toMatchObject({\n      data: undefined,\n      status: 'pending',\n      fetchStatus: 'idle',\n    })\n  })\n\n  it('should refetch when quickly switching to a failed query', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    const queryFn = async () => {\n      await sleep(50)\n      return 'OK'\n    }\n\n    function Page() {\n      const [id, setId] = React.useState(1)\n      const [hasChanged, setHasChanged] = React.useState(false)\n\n      const state = useQuery({ queryKey: [key, id], queryFn })\n\n      states.push(state)\n\n      React.useEffect(() => {\n        setId((prevId) => (prevId === 1 ? 2 : 1))\n        setHasChanged(true)\n      }, [hasChanged])\n\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(51)\n    expect(states.length).toBe(4)\n    // Load query 1\n    expect(states[0]).toMatchObject({\n      status: 'pending',\n      error: null,\n    })\n    // Load query 2\n    expect(states[1]).toMatchObject({\n      status: 'pending',\n      error: null,\n    })\n    // Load query 1\n    expect(states[2]).toMatchObject({\n      status: 'pending',\n      error: null,\n    })\n    // Loaded query 1\n    expect(states[3]).toMatchObject({\n      status: 'success',\n      error: null,\n    })\n  })\n\n  it('should update query state and refetch when reset with resetQueries', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          return count\n        },\n        staleTime: Infinity,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <button onClick={() => queryClient.resetQueries({ queryKey: key })}>\n            reset\n          </button>\n          <div>data: {state.data ?? 'null'}</div>\n          <div>isFetching: {state.isFetching}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 1')\n    fireEvent.click(rendered.getByRole('button', { name: /reset/i }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(states.length).toBe(4)\n    rendered.getByText('data: 2')\n\n    expect(count).toBe(2)\n\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isPending: true,\n      isFetching: true,\n      isSuccess: false,\n      isStale: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: 1,\n      isPending: false,\n      isFetching: false,\n      isSuccess: true,\n      isStale: false,\n    })\n    expect(states[2]).toMatchObject({\n      data: undefined,\n      isPending: true,\n      isFetching: true,\n      isSuccess: false,\n      isStale: true,\n    })\n    expect(states[3]).toMatchObject({\n      data: 2,\n      isPending: false,\n      isFetching: false,\n      isSuccess: true,\n      isStale: false,\n    })\n  })\n\n  it('should update query state and not refetch when resetting a disabled query with resetQueries', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          return count\n        },\n        staleTime: Infinity,\n        enabled: false,\n        notifyOnChangeProps: 'all',\n      })\n\n      states.push(state)\n\n      const { refetch } = state\n\n      return (\n        <div>\n          <button onClick={() => refetch()}>refetch</button>\n          <button onClick={() => queryClient.resetQueries({ queryKey: key })}>\n            reset\n          </button>\n          <div>data: {state.data ?? 'null'}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    rendered.getByText('data: null')\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 1')\n    fireEvent.click(rendered.getByRole('button', { name: /reset/i }))\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('data: null')\n    expect(states.length).toBe(4)\n\n    expect(count).toBe(1)\n\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isPending: true,\n      isFetching: false,\n      isSuccess: false,\n      isStale: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: undefined,\n      isPending: true,\n      isFetching: true,\n      isSuccess: false,\n      isStale: false,\n    })\n    expect(states[2]).toMatchObject({\n      data: 1,\n      isPending: false,\n      isFetching: false,\n      isSuccess: true,\n      isStale: false,\n    })\n    expect(states[3]).toMatchObject({\n      data: undefined,\n      isPending: true,\n      isFetching: false,\n      isSuccess: false,\n      isStale: false,\n    })\n  })\n\n  it('should only call the query hash function once each render', async () => {\n    const key = queryKey()\n\n    let hashes = 0\n    let renders = 0\n\n    function queryKeyHashFn(x: any) {\n      hashes++\n      return JSON.stringify(x)\n    }\n\n    function Page() {\n      React.useEffect(() => {\n        renders++\n      })\n\n      useQuery({ queryKey: key, queryFn: () => 'test', queryKeyHashFn })\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(renders).toBe(hashes)\n  })\n\n  it('should hash query keys that contain bigints given a supported query hash function', async () => {\n    const key = [queryKey(), 1n]\n\n    function queryKeyHashFn(x: any) {\n      return JSON.stringify(x, (_, value) => {\n        if (typeof value === 'bigint') return value.toString()\n        return value\n      })\n    }\n\n    function Page() {\n      useQuery({ queryKey: key, queryFn: () => 'test', queryKeyHashFn })\n      return null\n    }\n\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    const query = queryClient.getQueryCache().get(queryKeyHashFn(key))\n    expect(query?.state.data).toBe('test')\n  })\n\n  it('should refetch when changed enabled to true in error state', async () => {\n    const queryFn = vi.fn<(...args: Array<unknown>) => unknown>()\n    queryFn.mockImplementation(async () => {\n      await sleep(10)\n      return Promise.reject(new Error('Suspense Error Bingo'))\n    })\n\n    function Page({ enabled }: { enabled: boolean }) {\n      const { error, isPending } = useQuery({\n        queryKey: ['key'],\n        queryFn,\n        enabled,\n        retry: false,\n        retryOnMount: false,\n        refetchOnMount: false,\n        refetchOnWindowFocus: false,\n      })\n\n      if (isPending) {\n        return <div>status: pending</div>\n      }\n      if (error instanceof Error) {\n        return <div>error</div>\n      }\n      return <div>rendered</div>\n    }\n\n    function App() {\n      const [enabled, toggle] = React.useReducer((x) => !x, true)\n\n      return (\n        <div>\n          <Page enabled={enabled} />\n          <button aria-label=\"retry\" onClick={toggle}>\n            retry {enabled}\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    // initial state check\n    rendered.getByText('status: pending')\n\n    // // render error state component\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('error')\n    expect(queryFn).toBeCalledTimes(1)\n\n    // change to enabled to false\n    fireEvent.click(rendered.getByLabelText('retry'))\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('error')\n    expect(queryFn).toBeCalledTimes(1)\n\n    // // change to enabled to true\n    fireEvent.click(rendered.getByLabelText('retry'))\n    expect(queryFn).toBeCalledTimes(2)\n  })\n\n  it('should refetch when query key changed when previous status is error', async () => {\n    function Page({ id }: { id: number }) {\n      const { error, isPending } = useQuery({\n        queryKey: [id],\n        queryFn: async () => {\n          await sleep(10)\n          if (id % 2 === 1) {\n            return Promise.reject(new Error('Error'))\n          } else {\n            return 'data'\n          }\n        },\n        retry: false,\n        retryOnMount: false,\n        refetchOnMount: false,\n        refetchOnWindowFocus: false,\n      })\n\n      if (isPending) {\n        return <div>status: pending</div>\n      }\n      if (error instanceof Error) {\n        return <div>error</div>\n      }\n      return <div>rendered</div>\n    }\n\n    function App() {\n      const [id, changeId] = React.useReducer((x) => x + 1, 1)\n\n      return (\n        <div>\n          <Page id={id} />\n          <button aria-label=\"change\" onClick={changeId}>\n            change {id}\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    // initial state check\n    expect(rendered.getByText('status: pending')).toBeInTheDocument()\n\n    // render error state component\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('error')).toBeInTheDocument()\n\n    // change to unmount query\n    fireEvent.click(rendered.getByLabelText('change'))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n\n    // change to mount new query\n    fireEvent.click(rendered.getByLabelText('change'))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('error')).toBeInTheDocument()\n  })\n\n  it('should refetch when query key changed when switching between erroneous queries', async () => {\n    function Page({ id }: { id: boolean }) {\n      const { error, isFetching } = useQuery({\n        queryKey: [id],\n        queryFn: async () => {\n          await sleep(10)\n          return Promise.reject<unknown>(new Error('Error'))\n        },\n        retry: false,\n        retryOnMount: false,\n        refetchOnMount: false,\n        refetchOnWindowFocus: false,\n      })\n\n      if (isFetching) {\n        return <div>status: fetching</div>\n      }\n      if (error instanceof Error) {\n        return <div>error</div>\n      }\n      return <div>rendered</div>\n    }\n\n    function App() {\n      const [value, toggle] = React.useReducer((x) => !x, true)\n\n      return (\n        <div>\n          <Page id={value} />\n          <button aria-label=\"change\" onClick={toggle}>\n            change {value}\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    // initial state check\n    expect(rendered.getByText('status: fetching')).toBeInTheDocument()\n\n    // render error state component\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('error')).toBeInTheDocument()\n\n    // change to mount second query\n    fireEvent.click(rendered.getByLabelText('change'))\n    expect(rendered.getByText('status: fetching')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('error')).toBeInTheDocument()\n\n    // change to mount first query again\n    fireEvent.click(rendered.getByLabelText('change'))\n    expect(rendered.getByText('status: fetching')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('error')).toBeInTheDocument()\n  })\n\n  it('should have no error in pending state when refetching after error occurred', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    const error = new Error('oops')\n\n    let count = 0\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          if (count === 0) {\n            count++\n            throw error\n          }\n          return 5\n        },\n        retry: false,\n      })\n\n      states.push(state)\n\n      if (state.isPending) {\n        return <div>status: pending</div>\n      }\n      if (state.error instanceof Error) {\n        return (\n          <div>\n            <div>error</div>\n            <button onClick={() => state.refetch()}>refetch</button>\n          </div>\n        )\n      }\n      return <div>data: {state.data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('error')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 5')\n\n    expect(states.length).toBe(4)\n\n    expect(states[0]).toMatchObject({\n      status: 'pending',\n      data: undefined,\n      error: null,\n    })\n\n    expect(states[1]).toMatchObject({\n      status: 'error',\n      data: undefined,\n      error,\n    })\n\n    expect(states[2]).toMatchObject({\n      status: 'pending',\n      data: undefined,\n      error: null,\n    })\n\n    expect(states[3]).toMatchObject({\n      status: 'success',\n      data: 5,\n      error: null,\n    })\n  })\n\n  describe('networkMode online', () => {\n    it('online queries should not start fetching if you are offline', async () => {\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const key = queryKey()\n      const states: Array<any> = []\n\n      function Page() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: async () => {\n            await sleep(10)\n            return 'data'\n          },\n        })\n\n        React.useEffect(() => {\n          states.push(state.fetchStatus)\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, isPaused: {String(state.isPaused)}\n            </div>\n            <div>data: {state.data}</div>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      rendered.getByText('status: pending, isPaused: true')\n\n      onlineMock.mockReturnValue(true)\n      queryClient.getQueryCache().onOnline()\n\n      await vi.advanceTimersByTimeAsync(11)\n      rendered.getByText('status: success, isPaused: false')\n      expect(rendered.getByText('data: data')).toBeInTheDocument()\n\n      expect(states).toEqual(['paused', 'fetching', 'idle'])\n      onlineMock.mockRestore()\n    })\n\n    it('online queries should not refetch if you are offline', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery<string, string>({\n          queryKey: key,\n          queryFn: async () => {\n            count++\n            await sleep(10)\n            return 'data' + count\n          },\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus},\n              failureCount: {state.failureCount}\n            </div>\n            <div>failureReason: {state.failureReason ?? 'null'}</div>\n            <div>data: {state.data}</div>\n            <button\n              onClick={() => queryClient.invalidateQueries({ queryKey: key })}\n            >\n              invalidate\n            </button>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      await vi.advanceTimersByTimeAsync(11)\n      rendered.getByText('data: data1')\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))\n\n      await vi.advanceTimersByTimeAsync(11)\n      rendered.getByText(\n        'status: success, fetchStatus: paused, failureCount: 0',\n      )\n      rendered.getByText('failureReason: null')\n\n      onlineMock.mockReturnValue(true)\n      queryClient.getQueryCache().onOnline()\n\n      await vi.advanceTimersByTimeAsync(0)\n      rendered.getByText(\n        'status: success, fetchStatus: fetching, failureCount: 0',\n      )\n      rendered.getByText('failureReason: null')\n      await vi.advanceTimersByTimeAsync(11)\n      rendered.getByText('status: success, fetchStatus: idle, failureCount: 0')\n      rendered.getByText('failureReason: null')\n\n      expect(rendered.getByText('data: data2')).toBeInTheDocument()\n\n      onlineMock.mockRestore()\n    })\n\n    it('online queries should not refetch if you are offline and refocus', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: async () => {\n            count++\n            await sleep(10)\n            return 'data' + count\n          },\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus}\n            </div>\n            <div>data: {state.data}</div>\n            <button\n              onClick={() => queryClient.invalidateQueries({ queryKey: key })}\n            >\n              invalidate\n            </button>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      await vi.advanceTimersByTimeAsync(11)\n      rendered.getByText('data: data1')\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n      fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))\n\n      await vi.advanceTimersByTimeAsync(0)\n      rendered.getByText('status: success, fetchStatus: paused')\n\n      window.dispatchEvent(new Event('visibilitychange'))\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(rendered.queryByText('data: data2')).not.toBeInTheDocument()\n      expect(count).toBe(1)\n      onlineMock.mockRestore()\n    })\n\n    it('online queries should not refetch while already paused', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: async () => {\n            count++\n            await sleep(10)\n            return 'data' + count\n          },\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus}\n            </div>\n            <div>data: {state.data}</div>\n            <button\n              onClick={() => queryClient.invalidateQueries({ queryKey: key })}\n            >\n              invalidate\n            </button>\n          </div>\n        )\n      }\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      await vi.advanceTimersByTimeAsync(0)\n      rendered.getByText('status: pending, fetchStatus: paused')\n\n      fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))\n\n      await vi.advanceTimersByTimeAsync(11)\n      // invalidation should not trigger a refetch\n      rendered.getByText('status: pending, fetchStatus: paused')\n\n      expect(count).toBe(0)\n      onlineMock.mockRestore()\n    })\n\n    it('online queries should not refetch while already paused if data is in the cache', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: async () => {\n            count++\n            await sleep(10)\n            return 'data' + count\n          },\n          initialData: 'initial',\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus}\n            </div>\n            <div>data: {state.data}</div>\n            <button\n              onClick={() => queryClient.invalidateQueries({ queryKey: key })}\n            >\n              invalidate\n            </button>\n          </div>\n        )\n      }\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      rendered.getByText('status: success, fetchStatus: paused')\n      expect(rendered.getByText('data: initial')).toBeInTheDocument()\n\n      fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))\n\n      await vi.advanceTimersByTimeAsync(11)\n\n      // invalidation should not trigger a refetch\n      rendered.getByText('status: success, fetchStatus: paused')\n\n      expect(count).toBe(0)\n      onlineMock.mockRestore()\n    })\n\n    it('online queries should not get stuck in fetching state when pausing multiple times', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: async () => {\n            count++\n            await sleep(10)\n            return 'data' + count\n          },\n          initialData: 'initial',\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus}\n            </div>\n            <div>data: {state.data}</div>\n            <button\n              onClick={() => queryClient.invalidateQueries({ queryKey: key })}\n            >\n              invalidate\n            </button>\n          </div>\n        )\n      }\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      rendered.getByText('status: success, fetchStatus: paused')\n      expect(rendered.getByText('data: initial')).toBeInTheDocument()\n\n      // triggers one pause\n      fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))\n\n      await vi.advanceTimersByTimeAsync(11)\n      rendered.getByText('status: success, fetchStatus: paused')\n\n      // triggers a second pause\n      act(() => {\n        window.dispatchEvent(new Event('visibilitychange'))\n      })\n\n      onlineMock.mockReturnValue(true)\n      queryClient.getQueryCache().onOnline()\n\n      await vi.advanceTimersByTimeAsync(11)\n      rendered.getByText('status: success, fetchStatus: idle')\n      expect(rendered.getByText('data: data1')).toBeInTheDocument()\n\n      expect(count).toBe(1)\n\n      onlineMock.mockRestore()\n    })\n\n    it('online queries should pause retries if you are offline', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery<unknown, Error>({\n          queryKey: key,\n          queryFn: async (): Promise<unknown> => {\n            count++\n            await sleep(10)\n            throw new Error('failed' + count)\n          },\n          retry: 2,\n          retryDelay: 10,\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus},\n              failureCount: {state.failureCount}\n            </div>\n            <div>failureReason: {state.failureReason?.message ?? 'null'}</div>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      rendered.getByText(/status: pending, fetchStatus: fetching/i)\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      await vi.advanceTimersByTimeAsync(31)\n\n      rendered.getByText(\n        'status: pending, fetchStatus: paused, failureCount: 1',\n      )\n      rendered.getByText('failureReason: failed1')\n\n      expect(count).toBe(1)\n\n      onlineMock.mockReturnValue(true)\n      queryClient.getQueryCache().onOnline()\n\n      await vi.advanceTimersByTimeAsync(31)\n      rendered.getByText('status: error, fetchStatus: idle, failureCount: 3')\n      rendered.getByText('failureReason: failed3')\n\n      expect(count).toBe(3)\n\n      onlineMock.mockRestore()\n    })\n\n    it('online queries should not fetch if paused initial load and we go online after unmount', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Component() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: async ({ signal: _signal }) => {\n            count++\n            await sleep(10)\n            return `signal${count}`\n          },\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus}\n            </div>\n            <div>data: {state.data}</div>\n          </div>\n        )\n      }\n\n      function Page() {\n        const [show, setShow] = React.useState(true)\n\n        return (\n          <div>\n            {show && <Component />}\n            <button onClick={() => setShow(false)}>hide</button>\n          </div>\n        )\n      }\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      rendered.getByText('status: pending, fetchStatus: paused')\n\n      fireEvent.click(rendered.getByRole('button', { name: /hide/i }))\n\n      onlineMock.mockReturnValue(true)\n      queryClient.getQueryCache().onOnline()\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(queryClient.getQueryState(key)).toMatchObject({\n        fetchStatus: 'idle',\n        status: 'pending',\n      })\n\n      expect(count).toBe(0)\n\n      onlineMock.mockRestore()\n    })\n\n    it('online queries should re-fetch if paused and we go online even if already unmounted (because not cancelled)', async () => {\n      const key = queryKey()\n      let count = 0\n\n      queryClient.setQueryData(key, 'initial')\n\n      function Component() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: async () => {\n            count++\n            await sleep(10)\n            return 'data' + count\n          },\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus}\n            </div>\n            <div>data: {state.data}</div>\n          </div>\n        )\n      }\n\n      function Page() {\n        const [show, setShow] = React.useState(true)\n\n        return (\n          <div>\n            {show && <Component />}\n            <button onClick={() => setShow(false)}>hide</button>\n          </div>\n        )\n      }\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      rendered.getByText('status: success, fetchStatus: paused')\n\n      fireEvent.click(rendered.getByRole('button', { name: /hide/i }))\n\n      onlineMock.mockReturnValue(true)\n      queryClient.getQueryCache().onOnline()\n\n      await vi.advanceTimersByTimeAsync(11)\n      expect(queryClient.getQueryState(key)).toMatchObject({\n        fetchStatus: 'idle',\n        status: 'success',\n      })\n\n      // give it a bit more time to make sure queryFn is not called again\n      expect(count).toBe(1)\n\n      onlineMock.mockRestore()\n    })\n\n    it('online queries should not fetch if paused and we go online when cancelled and no refetchOnReconnect', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: async () => {\n            count++\n            await sleep(10)\n            return 'data' + count\n          },\n          refetchOnReconnect: false,\n        })\n\n        return (\n          <div>\n            <button\n              onClick={() => queryClient.cancelQueries({ queryKey: key })}\n            >\n              cancel\n            </button>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus}\n            </div>\n            <div>data: {state.data}</div>\n          </div>\n        )\n      }\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      rendered.getByText('status: pending, fetchStatus: paused')\n\n      fireEvent.click(rendered.getByRole('button', { name: /cancel/i }))\n\n      await vi.advanceTimersByTimeAsync(11)\n      rendered.getByText('status: pending, fetchStatus: idle')\n\n      expect(count).toBe(0)\n\n      onlineMock.mockReturnValue(true)\n      queryClient.getQueryCache().onOnline()\n\n      await vi.advanceTimersByTimeAsync(11)\n\n      rendered.getByText('status: pending, fetchStatus: idle')\n\n      expect(count).toBe(0)\n\n      onlineMock.mockRestore()\n    })\n\n    it('online queries should fetch if paused and we go online even if already unmounted when refetch was not cancelled', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Component() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: async () => {\n            count++\n            return `data${count}`\n          },\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus}\n            </div>\n            <div>data: {state.data}</div>\n          </div>\n        )\n      }\n\n      function Page() {\n        const [show, setShow] = React.useState(true)\n\n        return (\n          <div>\n            {show && <Component />}\n            <button onClick={() => setShow(false)}>hide</button>\n            <button\n              onClick={() => queryClient.invalidateQueries({ queryKey: key })}\n            >\n              invalidate\n            </button>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      await vi.advanceTimersByTimeAsync(11)\n      rendered.getByText('status: success, fetchStatus: idle')\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))\n\n      await vi.advanceTimersByTimeAsync(0)\n      rendered.getByText('status: success, fetchStatus: paused')\n\n      fireEvent.click(rendered.getByRole('button', { name: /hide/i }))\n\n      onlineMock.mockReturnValue(true)\n      queryClient.getQueryCache().onOnline()\n\n      await vi.advanceTimersByTimeAsync(11)\n\n      expect(queryClient.getQueryState(key)).toMatchObject({\n        fetchStatus: 'idle',\n        status: 'success',\n      })\n\n      expect(count).toBe(2)\n\n      onlineMock.mockRestore()\n    })\n  })\n\n  describe('networkMode always', () => {\n    it('always queries should start fetching even if you are offline', async () => {\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: async () => {\n            count++\n            await sleep(10)\n            return 'data ' + count\n          },\n          networkMode: 'always',\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, isPaused: {String(state.isPaused)}\n            </div>\n            <div>data: {state.data}</div>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      await vi.advanceTimersByTimeAsync(11)\n      rendered.getByText('status: success, isPaused: false')\n      expect(rendered.getByText('data: data 1')).toBeInTheDocument()\n\n      onlineMock.mockRestore()\n    })\n\n    it('always queries should not pause retries', async () => {\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery({\n          queryKey: key,\n          queryFn: async (): Promise<unknown> => {\n            count++\n            await sleep(10)\n            throw new Error('error ' + count)\n          },\n          networkMode: 'always',\n          retry: 1,\n          retryDelay: 5,\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, isPaused: {String(state.isPaused)}\n            </div>\n            <div>\n              error: {state.error instanceof Error && state.error.message}\n            </div>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      await vi.advanceTimersByTimeAsync(26)\n      rendered.getByText('status: error, isPaused: false')\n      expect(rendered.getByText('error: error 2')).toBeInTheDocument()\n\n      expect(count).toBe(2)\n\n      onlineMock.mockRestore()\n    })\n  })\n\n  describe('networkMode offlineFirst', () => {\n    it('offlineFirst queries should start fetching if you are offline, but pause retries', async () => {\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery<unknown, Error>({\n          queryKey: key,\n          queryFn: async (): Promise<unknown> => {\n            count++\n            await sleep(10)\n            throw new Error('failed' + count)\n          },\n          retry: 2,\n          retryDelay: 1,\n          networkMode: 'offlineFirst',\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus},\n              failureCount: {state.failureCount}\n            </div>\n            <div>failureReason: {state.failureReason?.message ?? 'null'}</div>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      await vi.advanceTimersByTimeAsync(12)\n      rendered.getByText(\n        'status: pending, fetchStatus: paused, failureCount: 1',\n      )\n      rendered.getByText('failureReason: failed1')\n\n      expect(count).toBe(1)\n\n      onlineMock.mockReturnValue(true)\n      queryClient.getQueryCache().onOnline()\n\n      await vi.advanceTimersByTimeAsync(22)\n      rendered.getByText('status: error, fetchStatus: idle, failureCount: 3')\n      rendered.getByText('failureReason: failed3')\n\n      expect(count).toBe(3)\n      onlineMock.mockRestore()\n    })\n  })\n\n  describe('subscribed', () => {\n    it('should be able to toggle subscribed', async () => {\n      const key = queryKey()\n      const queryFn = vi.fn(() => Promise.resolve('data'))\n\n      function Page() {\n        const [subscribed, setSubscribed] = React.useState(true)\n        const { data } = useQuery({\n          queryKey: key,\n          queryFn,\n          subscribed,\n        })\n        return (\n          <div>\n            <span>data: {data}</span>\n            <button onClick={() => setSubscribed(!subscribed)}>toggle</button>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n      await vi.advanceTimersByTimeAsync(0)\n      rendered.getByText('data: data')\n\n      expect(\n        queryClient.getQueryCache().find({ queryKey: key })!.observers.length,\n      ).toBe(1)\n\n      fireEvent.click(rendered.getByRole('button', { name: 'toggle' }))\n\n      expect(\n        queryClient.getQueryCache().find({ queryKey: key })!.observers.length,\n      ).toBe(0)\n\n      expect(queryFn).toHaveBeenCalledTimes(1)\n\n      fireEvent.click(rendered.getByRole('button', { name: 'toggle' }))\n\n      // background refetch when we re-subscribe\n      await vi.advanceTimersByTimeAsync(0)\n      expect(queryFn).toHaveBeenCalledTimes(2)\n      expect(\n        queryClient.getQueryCache().find({ queryKey: key })!.observers.length,\n      ).toBe(1)\n    })\n\n    it('should not be attached to the query when subscribed is false', async () => {\n      const key = queryKey()\n      const queryFn = vi.fn(() => Promise.resolve('data'))\n\n      function Page() {\n        const { data } = useQuery({\n          queryKey: key,\n          queryFn,\n          subscribed: false,\n        })\n        return (\n          <div>\n            <span>data: {data}</span>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      await vi.advanceTimersByTimeAsync(0)\n      rendered.getByText('data:')\n\n      expect(\n        queryClient.getQueryCache().find({ queryKey: key })!.observers.length,\n      ).toBe(0)\n\n      expect(queryFn).toHaveBeenCalledTimes(0)\n    })\n\n    it('should not re-render when data is added to the cache when subscribed is false', async () => {\n      const key = queryKey()\n      let renders = 0\n\n      function Page() {\n        const { data } = useQuery({\n          queryKey: key,\n          queryFn: () => Promise.resolve('data'),\n          subscribed: false,\n        })\n        renders++\n        return (\n          <div>\n            <span>{data ? 'has data' + data : 'no data'}</span>\n            <button\n              onClick={() => queryClient.setQueryData<string>(key, 'new data')}\n            >\n              set data\n            </button>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <Page />)\n\n      await vi.advanceTimersByTimeAsync(0)\n      rendered.getByText('no data')\n\n      fireEvent.click(rendered.getByRole('button', { name: 'set data' }))\n\n      await vi.advanceTimersByTimeAsync(0)\n      rendered.getByText('no data')\n\n      expect(renders).toBe(1)\n    })\n  })\n\n  it('should have status=error on mount when a query has failed', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<unknown>> = []\n    const error = new Error('oops')\n\n    const queryFn = (): Promise<unknown> => {\n      return Promise.reject(error)\n    }\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn,\n        retry: false,\n        retryOnMount: false,\n      })\n\n      states.push(state)\n\n      return <></>\n    }\n\n    await queryClient.prefetchQuery({ queryKey: key, queryFn })\n    renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(states).toHaveLength(1)\n\n    expect(states[0]).toMatchObject({\n      status: 'error',\n      error,\n    })\n  })\n\n  it('setQueryData - should respect updatedAt', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const state = useQuery({ queryKey: key, queryFn: () => 'data' })\n      return (\n        <div>\n          <div>data: {state.data}</div>\n          <div>dataUpdatedAt: {state.dataUpdatedAt}</div>\n          <button\n            onClick={() => {\n              queryClient.setQueryData(key, 'newData', {\n                updatedAt: 100,\n              })\n            }}\n          >\n            setQueryData\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('data: data')\n    fireEvent.click(rendered.getByRole('button', { name: /setQueryData/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('data: newData')\n    expect(rendered.getByText('dataUpdatedAt: 100')).toBeInTheDocument()\n  })\n\n  it('errorUpdateCount should increased on each fetch failure', async () => {\n    const key = queryKey()\n    const error = new Error('oops')\n\n    function Page() {\n      const { refetch, errorUpdateCount } = useQuery({\n        queryKey: key,\n        queryFn: (): Promise<unknown> => {\n          return Promise.reject(error)\n        },\n        retry: false,\n      })\n      return (\n        <div>\n          <button onClick={() => refetch()}>refetch</button>\n          <span>data: {errorUpdateCount}</span>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    const fetchBtn = rendered.getByRole('button', { name: 'refetch' })\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n    fireEvent.click(fetchBtn)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('data: 2')).toBeInTheDocument()\n    fireEvent.click(fetchBtn)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('data: 3')).toBeInTheDocument()\n  })\n\n  it('should use provided custom queryClient', async () => {\n    const key = queryKey()\n    const queryFn = async () => {\n      return Promise.resolve('custom client')\n    }\n\n    function Page() {\n      const { data } = useQuery(\n        {\n          queryKey: key,\n          queryFn,\n        },\n        queryClient,\n      )\n\n      return <div>data: {data}</div>\n    }\n\n    const rendered = render(<Page></Page>)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('data: custom client')).toBeInTheDocument()\n  })\n\n  it('should be notified of updates between create and subscribe', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const { data, status } = useQuery({\n        enabled: false,\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return 5\n        },\n      })\n\n      const mounted = React.useRef<boolean>(null)\n      // this simulates a synchronous update between the time the query is created\n      // and the time it is subscribed to that could be missed otherwise\n      if (mounted.current === null) {\n        mounted.current = true\n        queryClient.setQueryData(key, 1)\n      }\n\n      return (\n        <div>\n          <span>status: {status}</span>\n          <span>data: {data}</span>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('status: success')).toBeInTheDocument()\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n  })\n  it('should reuse same data object reference when queryKey changes back to some cached data', async () => {\n    const key = queryKey()\n    const spy = vi.fn()\n\n    async function fetchNumber(id: number) {\n      await sleep(5)\n      return { numbers: { current: { id } } }\n    }\n\n    function Test() {\n      const [id, setId] = React.useState(1)\n\n      const { data } = useQuery({\n        select: selector,\n        queryKey: [key, 'user', id],\n        queryFn: () => fetchNumber(id),\n      })\n\n      React.useEffect(() => {\n        spy(data)\n      }, [data])\n\n      return (\n        <div>\n          <button name=\"1\" onClick={() => setId(1)}>\n            1\n          </button>\n          <button name=\"2\" onClick={() => setId(2)}>\n            2\n          </button>\n          <span>Rendered Id: {data?.id}</span>\n        </div>\n      )\n    }\n\n    function selector(data: any) {\n      return data.numbers.current\n    }\n\n    const rendered = renderWithClient(queryClient, <Test />)\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    spy.mockClear()\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('Rendered Id: 1')\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    spy.mockClear()\n    fireEvent.click(rendered.getByRole('button', { name: /2/ }))\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('Rendered Id: 2')\n    expect(spy).toHaveBeenCalledTimes(2) // called with undefined because id changed\n\n    spy.mockClear()\n    fireEvent.click(rendered.getByRole('button', { name: /1/ }))\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('Rendered Id: 1')\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    spy.mockClear()\n    fireEvent.click(rendered.getByRole('button', { name: /2/ }))\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('Rendered Id: 2')\n    expect(spy).toHaveBeenCalledTimes(1)\n  })\n\n  it('should reuse same data object reference when queryKey changes and placeholderData is present', async () => {\n    const key = queryKey()\n    const spy = vi.fn()\n\n    async function fetchNumber(id: number) {\n      await sleep(5)\n      return { numbers: { current: { id } } }\n    }\n\n    function Test() {\n      const [id, setId] = React.useState(1)\n\n      const { data } = useQuery({\n        select: selector,\n        queryKey: [key, 'user', id],\n        queryFn: () => fetchNumber(id),\n        placeholderData: { numbers: { current: { id: 99 } } },\n      })\n\n      React.useEffect(() => {\n        spy(data)\n      }, [data])\n\n      return (\n        <div>\n          <button name=\"1\" onClick={() => setId(1)}>\n            1\n          </button>\n          <button name=\"2\" onClick={() => setId(2)}>\n            2\n          </button>\n          <span>Rendered Id: {data?.id}</span>\n        </div>\n      )\n    }\n\n    function selector(data: any) {\n      return data.numbers.current\n    }\n\n    const rendered = renderWithClient(queryClient, <Test />)\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    spy.mockClear()\n    rendered.getByText('Rendered Id: 99')\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('Rendered Id: 1')\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    spy.mockClear()\n    fireEvent.click(rendered.getByRole('button', { name: /2/ }))\n    rendered.getByText('Rendered Id: 99')\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('Rendered Id: 2')\n    expect(spy).toHaveBeenCalledTimes(2) // called with undefined because id changed\n\n    spy.mockClear()\n    fireEvent.click(rendered.getByRole('button', { name: /1/ }))\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('Rendered Id: 1')\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    spy.mockClear()\n    fireEvent.click(rendered.getByRole('button', { name: /2/ }))\n    await vi.advanceTimersByTimeAsync(6)\n    rendered.getByText('Rendered Id: 2')\n    expect(spy).toHaveBeenCalledTimes(1)\n  })\n\n  it('should not cause an infinite render loop when using unstable callback ref', async () => {\n    const key = queryKey()\n\n    function Test() {\n      const [_, setRef] = React.useState<HTMLDivElement | null>()\n\n      const { data } = useQuery({\n        queryKey: [key],\n        queryFn: async () => {\n          await sleep(5)\n          return 'Works'\n        },\n      })\n\n      return <div ref={(value) => setRef(value)}>{data}</div>\n    }\n\n    const rendered = renderWithClient(queryClient, <Test />)\n\n    await vi.advanceTimersByTimeAsync(6)\n    expect(rendered.getByText('Works')).toBeInTheDocument()\n  })\n\n  it('should keep the previous data when placeholderData is set and cache is used', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number | undefined>> = []\n    const steps = [0, 1, 0, 2]\n\n    function Page() {\n      const [count, setCount] = React.useState(0)\n\n      const state = useQuery({\n        staleTime: Infinity,\n        queryKey: [key, steps[count]],\n        queryFn: async () => {\n          await sleep(10)\n          return steps[count]\n        },\n        placeholderData: keepPreviousData,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <div>data: {state.data}</div>\n          <button onClick={() => setCount((c) => c + 1)}>setCount</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 0')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 1')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 0')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: 2')\n\n    // Initial\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isSuccess: false,\n      isPlaceholderData: false,\n    })\n    // Fetched\n    expect(states[1]).toMatchObject({\n      data: 0,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Set state\n    expect(states[2]).toMatchObject({\n      data: 0,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // New data\n    expect(states[3]).toMatchObject({\n      data: 1,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Set state with existing data\n    expect(states[4]).toMatchObject({\n      data: 0,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Set state where the placeholder value should come from cache request\n    expect(states[5]).toMatchObject({\n      data: 0,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // New data\n    expect(states[6]).toMatchObject({\n      data: 2,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n  })\n\n  // For Project without TS, when migrating from v4 to v5, make sure invalid calls due to bad parameters are tracked.\n  it('should throw in case of bad arguments to enhance DevX', () => {\n    // Mock console error to avoid noise when test is run\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n\n    const key = queryKey()\n    const queryFn = () => 'data'\n\n    function Page() {\n      // Invalid call on purpose\n      // @ts-expect-error\n      useQuery(key, { queryFn })\n      return <div>Does not matter</div>\n    }\n\n    expect(() => render(<Page />)).toThrow('Bad argument type')\n    consoleMock.mockRestore()\n  })\n\n  it('should respect skipToken and refetch when skipToken is taken away', async () => {\n    const key = queryKey()\n\n    function Page({ enabled }: { enabled: boolean }) {\n      const { data, status } = useQuery({\n        queryKey: [key],\n        queryFn: enabled\n          ? async () => {\n              await sleep(10)\n\n              return Promise.resolve('data')\n            }\n          : skipToken,\n        retry: false,\n        retryOnMount: false,\n        refetchOnMount: false,\n        refetchOnWindowFocus: false,\n      })\n\n      return (\n        <div>\n          <div>status: {status}</div>\n          <div>data: {String(data)}</div>\n        </div>\n      )\n    }\n\n    function App() {\n      const [enabled, toggle] = React.useReducer((x) => !x, false)\n\n      return (\n        <div>\n          <Page enabled={enabled} />\n          <button onClick={toggle}>enable</button>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    expect(rendered.getByText('status: pending')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: 'enable' }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('status: success')).toBeInTheDocument()\n    expect(rendered.getByText('data: data')).toBeInTheDocument()\n  })\n\n  it('should allow enabled: true and queryFn: skipToken', () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    function App() {\n      const query = useQuery({\n        queryKey: key,\n        queryFn: skipToken,\n        enabled: true,\n      })\n\n      return (\n        <div>\n          <div>\n            status: {query.status}, fetchStatus: {query.fetchStatus}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    rendered.getByText('status: pending, fetchStatus: idle')\n\n    // no warnings expected about skipToken / missing queryFn\n    expect(consoleMock).toHaveBeenCalledTimes(0)\n    consoleMock.mockRestore()\n  })\n\n  it('should return correct optimistic result when fetching after error', async () => {\n    const key = queryKey()\n    const error = new Error('oh no')\n\n    const results: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const query = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return Promise.reject(error)\n        },\n        retry: false,\n        notifyOnChangeProps: 'all',\n      })\n\n      results.push(query)\n\n      return (\n        <div>\n          <div>\n            status: {query.status}, {query.fetchStatus}\n          </div>\n          <div>error: {query.error?.message}</div>\n        </div>\n      )\n    }\n\n    function App() {\n      const [enabled, setEnabled] = React.useState(true)\n\n      return (\n        <div>\n          <button onClick={() => setEnabled(!enabled)}>toggle</button>\n          {enabled && <Page />}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('status: error, idle')\n\n    fireEvent.click(rendered.getByRole('button', { name: 'toggle' }))\n    fireEvent.click(rendered.getByRole('button', { name: 'toggle' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('status: error, idle')\n\n    expect(results).toHaveLength(4)\n\n    // initial fetch\n    expect(results[0]).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'fetching',\n      error: null,\n      errorUpdatedAt: 0,\n      errorUpdateCount: 0,\n      isLoading: true,\n      failureCount: 0,\n      failureReason: null,\n    })\n\n    // error state\n    expect(results[1]).toMatchObject({\n      status: 'error',\n      fetchStatus: 'idle',\n      error,\n      errorUpdateCount: 1,\n      isLoading: false,\n      failureCount: 1,\n      failureReason: error,\n    })\n    expect(results[1]?.errorUpdatedAt).toBeGreaterThan(0)\n\n    // refetch, optimistic state, no errors anymore\n    expect(results[2]).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'fetching',\n      error: null,\n      errorUpdateCount: 1,\n      isLoading: true,\n      failureCount: 0,\n      failureReason: null,\n    })\n    expect(results[2]?.errorUpdatedAt).toBeGreaterThan(0)\n\n    // final state\n    expect(results[3]).toMatchObject({\n      status: 'error',\n      fetchStatus: 'idle',\n      error: error,\n      errorUpdateCount: 2,\n      isLoading: false,\n      failureCount: 1,\n      failureReason: error,\n    })\n    expect(results[3]?.errorUpdatedAt).toBeGreaterThan(0)\n  })\n\n  it('should pick up an initialPromise', async () => {\n    const key = queryKey()\n\n    const serverQueryClient = new QueryClient({\n      defaultOptions: { dehydrate: { shouldDehydrateQuery: () => true } },\n    })\n\n    void serverQueryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: async () => {\n        await sleep(10)\n        return Promise.resolve('server')\n      },\n    })\n\n    const dehydrated = dehydrate(serverQueryClient)\n\n    let count = 0\n\n    function Page() {\n      const query = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          count++\n          await sleep(10)\n          return Promise.resolve('client')\n        },\n      })\n\n      return (\n        <div>\n          <div>data: {query.data}</div>\n          <button onClick={() => query.refetch()}>refetch</button>\n        </div>\n      )\n    }\n\n    const clientQueryClient = new QueryClient()\n    hydrate(clientQueryClient, dehydrated)\n\n    const rendered = renderWithClient(clientQueryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: server')\n    expect(count).toBe(0)\n\n    fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('data: client')\n    expect(count).toBe(1)\n  })\n\n  it('should retry failed initialPromise on the client', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    const serverQueryClient = new QueryClient({\n      defaultOptions: {\n        dehydrate: { shouldDehydrateQuery: () => true },\n      },\n    })\n\n    void serverQueryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: async () => {\n        await sleep(10)\n        return Promise.reject(new Error('server error'))\n      },\n    })\n\n    const dehydrated = dehydrate(serverQueryClient)\n\n    let count = 0\n\n    function Page() {\n      const query = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          count++\n          await sleep(10)\n          return Promise.resolve('client')\n        },\n      })\n\n      return (\n        <div>\n          <div>failure: {query.failureReason?.message}</div>\n          <div>data: {query.data}</div>\n        </div>\n      )\n    }\n\n    const clientQueryClient = new QueryClient({\n      defaultOptions: { hydrate: { queries: { retry: 1, retryDelay: 10 } } },\n    })\n    hydrate(clientQueryClient, dehydrated)\n\n    const rendered = renderWithClient(clientQueryClient, <Page />)\n\n    await vi.advanceTimersByTimeAsync(11)\n    rendered.getByText('failure: redacted')\n    await vi.advanceTimersByTimeAsync(21)\n    rendered.getByText('data: client')\n    expect(count).toBe(1)\n\n    const query = clientQueryClient.getQueryCache().find({ queryKey: key })\n\n    expect(consoleMock).toHaveBeenCalledTimes(1)\n    expect(consoleMock).toHaveBeenCalledWith(\n      `A query that was dehydrated as pending ended up rejecting. [${query?.queryHash}]: Error: server error; The error will be redacted in production builds`,\n    )\n\n    consoleMock.mockRestore()\n  })\n\n  it('should console.error when there is no queryFn', () => {\n    const consoleErrorMock = vi.spyOn(console, 'error')\n    const key = queryKey()\n\n    function Example() {\n      useQuery({ queryKey: key })\n      return <></>\n    }\n\n    renderWithClient(queryClient, <Example />)\n\n    expect(consoleErrorMock).toHaveBeenCalledTimes(1)\n    expect(consoleErrorMock).toHaveBeenCalledWith(\n      `[${queryClient.getQueryCache().find({ queryKey: key })?.queryHash}]: No queryFn was passed as an option, and no default queryFn was found. The queryFn parameter is only optional when using a default queryFn. More info here: https://tanstack.com/query/latest/docs/framework/react/guides/default-query-function`,\n    )\n\n    consoleErrorMock.mockRestore()\n  })\n\n  it('should retry on mount when throwOnError returns false', async () => {\n    const key = queryKey()\n    let fetchCount = 0\n    const queryFn = vi.fn().mockImplementation(() => {\n      fetchCount++\n      console.log(`Fetching... (attempt ${fetchCount})`)\n      return Promise.reject(new Error('Simulated 500 error'))\n    })\n\n    function Component() {\n      const { status, error } = useQuery({\n        queryKey: key,\n        queryFn,\n        throwOnError: () => false,\n        retryOnMount: true,\n        staleTime: Infinity,\n        retry: false,\n      })\n\n      return (\n        <div>\n          <div data-testid=\"status\">{status}</div>\n          {error && <div data-testid=\"error\">{error.message}</div>}\n        </div>\n      )\n    }\n\n    const rendered1 = renderWithClient(queryClient, <Component />)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered1.getByTestId('status')).toHaveTextContent('error')\n    expect(rendered1.getByTestId('error')).toHaveTextContent(\n      'Simulated 500 error',\n    )\n    expect(fetchCount).toBe(1)\n    rendered1.unmount()\n\n    const initialFetchCount = fetchCount\n\n    const rendered2 = renderWithClient(queryClient, <Component />)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered2.getByTestId('status')).toHaveTextContent('error')\n\n    expect(fetchCount).toBe(initialFetchCount + 1)\n    expect(queryFn).toHaveBeenCalledTimes(2)\n  })\n\n  it('should not retry on mount when throwOnError function returns true', async () => {\n    const key = queryKey()\n    let fetchCount = 0\n    const queryFn = vi.fn().mockImplementation(() => {\n      fetchCount++\n      console.log(`Fetching... (attempt ${fetchCount})`)\n      return Promise.reject(new Error('Simulated 500 error'))\n    })\n\n    function Component() {\n      const { status, error } = useQuery({\n        queryKey: key,\n        queryFn,\n        throwOnError: () => true,\n        retryOnMount: true,\n        staleTime: Infinity,\n        retry: false,\n      })\n\n      return (\n        <div>\n          <div data-testid=\"status\">{status}</div>\n          {error && <div data-testid=\"error\">{error.message}</div>}\n        </div>\n      )\n    }\n\n    const rendered1 = renderWithClient(\n      queryClient,\n      <ErrorBoundary\n        fallbackRender={({ error }) => (\n          <div>\n            <div data-testid=\"status\">error</div>\n            <div data-testid=\"error\">{error?.message}</div>\n          </div>\n        )}\n      >\n        <Component />\n      </ErrorBoundary>,\n    )\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered1.getByTestId('status')).toHaveTextContent('error')\n    expect(rendered1.getByTestId('error')).toHaveTextContent(\n      'Simulated 500 error',\n    )\n    expect(fetchCount).toBe(1)\n\n    rendered1.unmount()\n\n    const initialFetchCount = fetchCount\n\n    const rendered2 = renderWithClient(\n      queryClient,\n      <ErrorBoundary\n        fallbackRender={({ error }) => (\n          <div>\n            <div data-testid=\"status\">error</div>\n            <div data-testid=\"error\">{error?.message}</div>\n          </div>\n        )}\n      >\n        <Component />\n      </ErrorBoundary>,\n    )\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered2.getByTestId('status')).toHaveTextContent('error')\n\n    // Should not retry because throwOnError returns true\n    expect(fetchCount).toBe(initialFetchCount)\n    expect(queryFn).toHaveBeenCalledTimes(1)\n  })\n\n  it('should handle throwOnError function based on actual error state', async () => {\n    const key = queryKey()\n    let fetchCount = 0\n    const queryFn = vi.fn().mockImplementation(() => {\n      fetchCount++\n      console.log(`Fetching... (attempt ${fetchCount})`)\n      return Promise.reject(new Error('Simulated 500 error'))\n    })\n\n    function Component() {\n      const { status, error } = useQuery({\n        queryKey: key,\n        queryFn,\n        throwOnError: (error) => error.message.includes('404'),\n        retryOnMount: true,\n        staleTime: Infinity,\n        retry: false,\n      })\n\n      return (\n        <div>\n          <div data-testid=\"status\">{status}</div>\n          {error && <div data-testid=\"error\">{error.message}</div>}\n        </div>\n      )\n    }\n\n    const rendered1 = renderWithClient(queryClient, <Component />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered1.getByTestId('status')).toHaveTextContent('error')\n    expect(rendered1.getByTestId('error')).toHaveTextContent(\n      'Simulated 500 error',\n    )\n    expect(fetchCount).toBe(1)\n\n    rendered1.unmount()\n\n    const initialFetchCount = fetchCount\n\n    const rendered2 = renderWithClient(queryClient, <Component />)\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered2.getByTestId('status')).toHaveTextContent('error')\n\n    // Should retry because throwOnError returns false (500 error doesn't include '404')\n    expect(fetchCount).toBe(initialFetchCount + 1)\n    expect(queryFn).toHaveBeenCalledTimes(2)\n  })\n\n  it('should not fetch for the duration of the restoring period when isRestoring is true', async () => {\n    const key = queryKey()\n    const queryFn = vi\n      .fn()\n      .mockImplementation(() => sleep(10).then(() => 'data'))\n\n    function Page() {\n      const result = useQuery({\n        queryKey: key,\n        queryFn,\n      })\n\n      return (\n        <div>\n          <div data-testid=\"status\">{result.status}</div>\n          <div data-testid=\"fetchStatus\">{result.fetchStatus}</div>\n          <div data-testid=\"data\">{result.data ?? 'undefined'}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <IsRestoringProvider value={true}>\n        <Page />\n      </IsRestoringProvider>,\n    )\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(rendered.getByTestId('status')).toHaveTextContent('pending')\n    expect(rendered.getByTestId('fetchStatus')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('data')).toHaveTextContent('undefined')\n    expect(queryFn).toHaveBeenCalledTimes(0)\n\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(rendered.getByTestId('status')).toHaveTextContent('pending')\n    expect(rendered.getByTestId('fetchStatus')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('data')).toHaveTextContent('undefined')\n    expect(queryFn).toHaveBeenCalledTimes(0)\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/useSuspenseInfiniteQuery.test-d.tsx",
    "content": "import { assertType, describe, expectTypeOf, it } from 'vitest'\nimport { skipToken } from '@tanstack/query-core'\nimport { useSuspenseInfiniteQuery } from '../useSuspenseInfiniteQuery'\nimport type { InfiniteData } from '@tanstack/query-core'\n\ndescribe('useSuspenseInfiniteQuery', () => {\n  it('should always have data defined', () => {\n    const { data } = useSuspenseInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n      initialPageParam: 1,\n      getNextPageParam: () => 1,\n    })\n\n    expectTypeOf(data).toEqualTypeOf<InfiniteData<number, unknown>>()\n  })\n\n  it('should not allow skipToken in queryFn', () => {\n    assertType(\n      useSuspenseInfiniteQuery({\n        queryKey: ['key'],\n        // @ts-expect-error\n        queryFn: skipToken,\n      }),\n    )\n\n    assertType(\n      useSuspenseInfiniteQuery({\n        queryKey: ['key'],\n        // @ts-expect-error\n        queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),\n      }),\n    )\n  })\n\n  it('should not have pending status', () => {\n    const { status } = useSuspenseInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n      initialPageParam: 1,\n      getNextPageParam: () => 1,\n    })\n\n    expectTypeOf(status).toEqualTypeOf<'error' | 'success'>()\n  })\n\n  it('should not allow placeholderData, enabled or throwOnError props', () => {\n    assertType(\n      useSuspenseInfiniteQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        initialPageParam: 1,\n        getNextPageParam: () => 1,\n        // @ts-expect-error TS2345\n        placeholderData: 5,\n        enabled: true,\n      }),\n    )\n\n    assertType(\n      useSuspenseInfiniteQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        initialPageParam: 1,\n        getNextPageParam: () => 1,\n        // @ts-expect-error TS2345\n        enabled: true,\n      }),\n    )\n\n    assertType(\n      useSuspenseInfiniteQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        initialPageParam: 1,\n        getNextPageParam: () => 1,\n        // @ts-expect-error TS2345\n        throwOnError: true,\n      }),\n    )\n  })\n\n  it('should not return isPlaceholderData', () => {\n    const query = useSuspenseInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n      initialPageParam: 1,\n      getNextPageParam: () => 1,\n    })\n\n    expectTypeOf(query).not.toHaveProperty('isPlaceholderData')\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/useSuspenseInfiniteQuery.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { act, fireEvent } from '@testing-library/react'\nimport * as React from 'react'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport {\n  QueryCache,\n  QueryClient,\n  skipToken,\n  useSuspenseInfiniteQuery,\n} from '..'\nimport { renderWithClient } from './utils'\nimport type { InfiniteData, UseSuspenseInfiniteQueryResult } from '..'\n\ndescribe('useSuspenseInfiniteQuery', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  const queryCache = new QueryCache()\n  const queryClient = new QueryClient({ queryCache })\n\n  it('should return the correct states for a successful infinite query', async () => {\n    const key = queryKey()\n    const states: Array<UseSuspenseInfiniteQueryResult<InfiniteData<number>>> =\n      []\n\n    function Page() {\n      const [multiplier, setMultiplier] = React.useState(1)\n      const state = useSuspenseInfiniteQuery({\n        queryKey: [`${key}_${multiplier}`],\n        queryFn: ({ pageParam }) =>\n          sleep(10).then(() => pageParam * multiplier),\n        initialPageParam: 1,\n        getNextPageParam: (lastPage) => lastPage + 1,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <button onClick={() => setMultiplier(2)}>next</button>\n          data: {state.data?.pages.join(',')}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <React.Suspense fallback=\"loading\">\n        <Page />\n      </React.Suspense>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n\n    expect(states.length).toBe(1)\n    expect(states[0]).toMatchObject({\n      data: { pages: [1], pageParams: [1] },\n      status: 'success',\n    })\n\n    fireEvent.click(rendered.getByText('next'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data: 2')).toBeInTheDocument()\n\n    expect(states.length).toBe(2)\n    expect(states[1]).toMatchObject({\n      data: { pages: [2], pageParams: [1] },\n      status: 'success',\n    })\n  })\n\n  it('should log an error when skipToken is passed as queryFn', () => {\n    const consoleErrorSpy = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => {})\n    const key = queryKey()\n\n    function Page() {\n      useSuspenseInfiniteQuery({\n        queryKey: key,\n        initialPageParam: 1,\n        getNextPageParam: () => 1,\n        // @ts-expect-error\n        // eslint-disable-next-line react-hooks/purity\n        queryFn: Math.random() >= 0 ? skipToken : () => Promise.resolve(5),\n      })\n\n      return null\n    }\n\n    function App() {\n      return (\n        <React.Suspense fallback=\"Loading...\">\n          <Page />\n        </React.Suspense>\n      )\n    }\n\n    renderWithClient(queryClient, <App />)\n\n    expect(consoleErrorSpy).toHaveBeenCalledWith(\n      'skipToken is not allowed for useSuspenseInfiniteQuery',\n    )\n    consoleErrorSpy.mockRestore()\n  })\n\n  it('should log an error when skipToken is used in development environment', () => {\n    const envCopy = process.env.NODE_ENV\n    process.env.NODE_ENV = 'development'\n\n    const consoleErrorSpy = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    function Page() {\n      useSuspenseInfiniteQuery({\n        queryKey: key,\n        queryFn: skipToken as any,\n        initialPageParam: 1,\n        getNextPageParam: () => 1,\n      })\n\n      return null\n    }\n\n    renderWithClient(\n      queryClient,\n      <React.Suspense fallback=\"Loading...\">\n        <Page />\n      </React.Suspense>,\n    )\n\n    expect(consoleErrorSpy).toHaveBeenCalledWith(\n      'skipToken is not allowed for useSuspenseInfiniteQuery',\n    )\n\n    consoleErrorSpy.mockRestore()\n    process.env.NODE_ENV = envCopy\n  })\n\n  it('should not log an error when skipToken is used in production environment', () => {\n    const envCopy = process.env.NODE_ENV\n    process.env.NODE_ENV = 'production'\n\n    const consoleErrorSpy = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    function Page() {\n      useSuspenseInfiniteQuery({\n        queryKey: key,\n        queryFn: skipToken as any,\n        initialPageParam: 1,\n        getNextPageParam: () => 1,\n      })\n\n      return null\n    }\n\n    renderWithClient(\n      queryClient,\n      <React.Suspense fallback=\"Loading...\">\n        <Page />\n      </React.Suspense>,\n    )\n\n    expect(consoleErrorSpy).not.toHaveBeenCalled()\n\n    consoleErrorSpy.mockRestore()\n    process.env.NODE_ENV = envCopy\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/useSuspenseQueries.test-d.tsx",
    "content": "import { assertType, describe, expectTypeOf, it } from 'vitest'\nimport { skipToken, useSuspenseQueries } from '..'\nimport { queryOptions } from '../queryOptions'\nimport type { OmitKeyof } from '..'\nimport type { UseQueryOptions, UseSuspenseQueryResult } from '../types'\n\ndescribe('UseSuspenseQueries config object overload', () => {\n  it('TData should always be defined', () => {\n    const query1 = {\n      queryKey: ['key1'],\n      queryFn: () => {\n        return {\n          wow: true,\n        }\n      },\n      initialData: {\n        wow: false,\n      },\n    }\n\n    const query2 = {\n      queryKey: ['key2'],\n      queryFn: () => 'Query Data',\n    }\n\n    const queryResults = useSuspenseQueries({ queries: [query1, query2] })\n\n    const query1Data = queryResults[0].data\n    const query2Data = queryResults[1].data\n\n    expectTypeOf(query1Data).toEqualTypeOf<{ wow: boolean }>()\n    expectTypeOf(query2Data).toEqualTypeOf<string>()\n  })\n\n  it('TData should be defined when passed through queryOptions', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => {\n        return {\n          wow: true,\n        }\n      },\n    })\n    const queryResults = useSuspenseQueries({ queries: [options] })\n\n    const data = queryResults[0].data\n\n    expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n  })\n\n  it('should be possible to define a different TData than TQueryFnData using select with queryOptions spread into useQuery', () => {\n    const query1 = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(1),\n      select: (data) => data > 1,\n    })\n\n    const query2 = {\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(1),\n      select: (data: number) => data > 1,\n    }\n\n    const queryResults = useSuspenseQueries({ queries: [query1, query2] })\n    const query1Data = queryResults[0].data\n    const query2Data = queryResults[1].data\n\n    expectTypeOf(query1Data).toEqualTypeOf<boolean>()\n    expectTypeOf(query2Data).toEqualTypeOf<boolean>()\n  })\n\n  it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => {\n    const queryResults = useSuspenseQueries({\n      queries: [\n        {\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n          initialData: () => undefined as { wow: boolean } | undefined,\n        },\n      ],\n    })\n\n    const data = queryResults[0].data\n\n    expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n  })\n\n  it('should not allow skipToken in queryFn', () => {\n    assertType(\n      useSuspenseQueries({\n        queries: [\n          {\n            queryKey: ['key'],\n            // @ts-expect-error\n            queryFn: skipToken,\n          },\n        ],\n      }),\n    )\n\n    assertType(\n      useSuspenseQueries({\n        queries: [\n          {\n            queryKey: ['key'],\n            // @ts-expect-error\n            queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),\n          },\n        ],\n      }),\n    )\n  })\n\n  it('TData should have correct type when conditional skipToken is passed', () => {\n    const queryResults = useSuspenseQueries({\n      queries: [\n        {\n          queryKey: ['withSkipToken'],\n          // @ts-expect-error\n          queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),\n        },\n      ],\n    })\n\n    const firstResult = queryResults[0]\n\n    expectTypeOf(firstResult).toEqualTypeOf<\n      UseSuspenseQueryResult<number, Error>\n    >()\n    expectTypeOf(firstResult.data).toEqualTypeOf<number>()\n  })\n\n  describe('custom hook', () => {\n    it('should allow custom hooks using UseQueryOptions', () => {\n      type Data = string\n\n      const useCustomQueries = (\n        options?: OmitKeyof<UseQueryOptions<Data>, 'queryKey' | 'queryFn'>,\n      ) => {\n        return useSuspenseQueries({\n          queries: [\n            {\n              ...options,\n              queryKey: ['todos-key'],\n              queryFn: () => Promise.resolve('data'),\n            },\n          ],\n        })\n      }\n\n      const queryResults = useCustomQueries()\n      const data = queryResults[0].data\n\n      expectTypeOf(data).toEqualTypeOf<Data>()\n    })\n  })\n\n  it('should return correct data for dynamic queries with mixed result types', () => {\n    const Queries1 = {\n      get: () =>\n        queryOptions({\n          queryKey: ['key1'],\n          queryFn: () => Promise.resolve(1),\n        }),\n    }\n    const Queries2 = {\n      get: () =>\n        queryOptions({\n          queryKey: ['key2'],\n          queryFn: () => Promise.resolve(true),\n        }),\n    }\n\n    const queries1List = [1, 2, 3].map(() => ({ ...Queries1.get() }))\n    const result = useSuspenseQueries({\n      queries: [\n        ...queries1List,\n        {\n          ...Queries2.get(),\n          select(data: boolean) {\n            return data\n          },\n        },\n      ],\n    })\n\n    expectTypeOf(result).toEqualTypeOf<\n      [\n        ...Array<UseSuspenseQueryResult<number, Error>>,\n        UseSuspenseQueryResult<boolean, Error>,\n      ]\n    >()\n  })\n\n  it('queryOptions with initialData works on useSuspenseQueries', () => {\n    const query1 = queryOptions({\n      queryKey: ['key1'],\n      queryFn: () => 'Query Data',\n      initialData: 'initial data',\n    })\n\n    const queryResults = useSuspenseQueries({ queries: [query1] })\n    const query1Data = queryResults[0].data\n\n    expectTypeOf(query1Data).toEqualTypeOf<string>()\n  })\n\n  it('queryOptions with skipToken in queryFn should not work on useSuspenseQueries', () => {\n    assertType(\n      useSuspenseQueries({\n        queries: [\n          // @ts-expect-error\n          queryOptions({\n            queryKey: ['key1'],\n            queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),\n          }),\n        ],\n      }),\n    )\n\n    assertType(\n      useSuspenseQueries({\n        queries: [\n          // @ts-expect-error\n          queryOptions({\n            queryKey: ['key1'],\n            queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),\n            initialData: 5,\n          }),\n        ],\n      }),\n    )\n  })\n\n  it('should not show type error when using rest queryOptions', () => {\n    assertType(\n      useSuspenseQueries({\n        queries: [\n          {\n            ...queryOptions({\n              queryKey: ['key1'],\n              queryFn: () => 'Query Data',\n            }),\n            select(data: string) {\n              return data\n            },\n          },\n        ],\n      }),\n    )\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/useSuspenseQueries.test.tsx",
    "content": "import {\n  afterAll,\n  afterEach,\n  beforeAll,\n  beforeEach,\n  describe,\n  expect,\n  it,\n  vi,\n} from 'vitest'\nimport { act, fireEvent, render } from '@testing-library/react'\nimport * as React from 'react'\nimport { ErrorBoundary } from 'react-error-boundary'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport {\n  QueryClient,\n  skipToken,\n  useSuspenseQueries,\n  useSuspenseQuery,\n} from '..'\nimport { renderWithClient } from './utils'\nimport type { UseSuspenseQueryOptions } from '..'\n\ntype NumberQueryOptions = UseSuspenseQueryOptions<number>\n\nconst QUERY_DURATION = 1000\n\nconst createQuery: (id: number) => NumberQueryOptions = (id) => ({\n  queryKey: [id],\n  queryFn: () => sleep(QUERY_DURATION).then(() => id),\n})\nconst resolveQueries = () => vi.advanceTimersByTimeAsync(QUERY_DURATION)\n\nconst queryClient = new QueryClient()\n\ndescribe('useSuspenseQueries', () => {\n  const onSuspend = vi.fn()\n  const onQueriesResolution = vi.fn()\n\n  beforeAll(() => {\n    vi.useFakeTimers()\n  })\n\n  afterAll(() => {\n    vi.useRealTimers()\n  })\n\n  afterEach(() => {\n    queryClient.clear()\n    onSuspend.mockClear()\n    onQueriesResolution.mockClear()\n  })\n\n  function SuspenseFallback() {\n    React.useEffect(() => {\n      onSuspend()\n    }, [])\n\n    return <div>loading</div>\n  }\n\n  const withSuspenseWrapper = <T extends object>(Component: React.FC<T>) => {\n    function SuspendedComponent(props: T) {\n      return (\n        <React.Suspense fallback={<SuspenseFallback />}>\n          <Component {...props} />\n        </React.Suspense>\n      )\n    }\n\n    return SuspendedComponent\n  }\n\n  function QueriesContainer({\n    queries,\n  }: {\n    queries: Array<NumberQueryOptions>\n  }) {\n    const queriesResults = useSuspenseQueries(\n      { queries, combine: (results) => results.map((r) => r.data) },\n      queryClient,\n    )\n\n    React.useEffect(() => {\n      onQueriesResolution(queriesResults)\n    }, [queriesResults])\n\n    return null\n  }\n\n  const TestComponent = withSuspenseWrapper(QueriesContainer)\n\n  it('should suspend on mount', () => {\n    render(<TestComponent queries={[1, 2].map(createQuery)} />)\n\n    expect(onSuspend).toHaveBeenCalledOnce()\n  })\n\n  it('should resolve queries', async () => {\n    render(<TestComponent queries={[1, 2].map(createQuery)} />)\n\n    await act(resolveQueries)\n\n    expect(onQueriesResolution).toHaveBeenCalledTimes(1)\n    expect(onQueriesResolution).toHaveBeenLastCalledWith([1, 2])\n  })\n\n  it('should not suspend on mount if query has been already fetched', () => {\n    const query = createQuery(1)\n\n    queryClient.setQueryData(query.queryKey, query.queryFn)\n\n    render(<TestComponent queries={[query]} />)\n\n    expect(onSuspend).not.toHaveBeenCalled()\n  })\n\n  it('should not break suspense when queries change without resolving', async () => {\n    const initQueries = [1, 2].map(createQuery)\n    const nextQueries = [3, 4, 5, 6].map(createQuery)\n\n    const { rerender } = render(<TestComponent queries={initQueries} />)\n\n    rerender(<TestComponent queries={nextQueries} />)\n\n    await act(resolveQueries)\n\n    expect(onSuspend).toHaveBeenCalledTimes(1)\n    expect(onQueriesResolution).toHaveBeenCalledTimes(1)\n    expect(onQueriesResolution).toHaveBeenLastCalledWith([3, 4, 5, 6])\n  })\n\n  it('should suspend only once per queries change', async () => {\n    const initQueries = [1, 2].map(createQuery)\n    const nextQueries = [3, 4, 5, 6].map(createQuery)\n\n    const { rerender } = render(<TestComponent queries={initQueries} />)\n\n    await act(resolveQueries)\n\n    rerender(<TestComponent queries={nextQueries} />)\n\n    await act(resolveQueries)\n\n    expect(onSuspend).toHaveBeenCalledTimes(2)\n    expect(onQueriesResolution).toHaveBeenCalledTimes(2)\n    expect(onQueriesResolution).toHaveBeenLastCalledWith([3, 4, 5, 6])\n  })\n\n  it('should only call combine after resolving', async () => {\n    const spy = vi.fn()\n    const key = queryKey()\n\n    function Page() {\n      const data = useSuspenseQueries({\n        queries: [1, 2, 3].map((value) => ({\n          queryKey: [...key, { value }],\n          queryFn: () => sleep(value * 10).then(() => ({ value: value * 10 })),\n        })),\n        combine: (result) => {\n          spy(result)\n          return 'data'\n        },\n      })\n\n      return <h1>{data}</h1>\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <React.Suspense fallback=\"loading\">\n        <Page />\n      </React.Suspense>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n\n    expect(spy).not.toHaveBeenCalled()\n\n    await act(() => vi.advanceTimersByTimeAsync(30))\n    expect(rendered.getByText('data')).toBeInTheDocument()\n\n    expect(spy).toHaveBeenCalled()\n  })\n\n  it('should handle duplicate query keys without infinite loops', async () => {\n    const key = queryKey()\n    const localDuration = 10\n    let renderCount = 0\n\n    function getUserData() {\n      return {\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(localDuration)\n          return { name: 'John Doe', age: 50 }\n        },\n      }\n    }\n\n    function getName() {\n      return {\n        ...getUserData(),\n        select: (data: any) => data.name,\n      }\n    }\n\n    function getAge() {\n      return {\n        ...getUserData(),\n        select: (data: any) => data.age,\n      }\n    }\n\n    function App() {\n      renderCount++\n      const [{ data }, { data: data2 }] = useSuspenseQueries({\n        queries: [getName(), getAge()],\n      })\n\n      React.useEffect(() => {\n        onQueriesResolution({ data, data2 })\n      }, [data, data2])\n\n      return (\n        <div>\n          <h1>Data</h1>\n          {JSON.stringify({ data }, null, 2)}\n          {JSON.stringify({ data2 }, null, 2)}\n        </div>\n      )\n    }\n\n    renderWithClient(\n      queryClient,\n      <React.Suspense fallback={<SuspenseFallback />}>\n        <App />\n      </React.Suspense>,\n    )\n\n    await act(() => vi.advanceTimersByTimeAsync(localDuration))\n\n    expect(onSuspend).toHaveBeenCalledTimes(1)\n    expect(onQueriesResolution).toHaveBeenCalledTimes(1)\n\n    await vi.advanceTimersByTimeAsync(100)\n\n    expect(onQueriesResolution).toHaveBeenCalledTimes(1)\n    expect(onQueriesResolution).toHaveBeenLastCalledWith({\n      data: 'John Doe',\n      data2: 50,\n    })\n\n    // With the infinite loop bug, renderCount would be very high (e.g. > 100)\n    // Without bug, it should be small (initial suspend + resolution = 2-3)\n    expect(renderCount).toBeLessThan(10)\n  })\n})\n\ndescribe('useSuspenseQueries 2', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should suspend all queries in parallel', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const results: Array<string> = []\n\n    function Fallback() {\n      results.push('loading')\n      return <div>loading</div>\n    }\n\n    function Page() {\n      const result = useSuspenseQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () =>\n              sleep(10).then(() => {\n                results.push('1')\n                return '1'\n              }),\n          },\n          {\n            queryKey: key2,\n            queryFn: () =>\n              sleep(20).then(() => {\n                results.push('2')\n                return '2'\n              }),\n          },\n        ],\n      })\n\n      return (\n        <div>\n          <h1>data: {result.map((item) => item.data ?? 'null').join(',')}</h1>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <React.Suspense fallback={<Fallback />}>\n        <Page />\n      </React.Suspense>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(20))\n    expect(rendered.getByText('data: 1,2')).toBeInTheDocument()\n\n    expect(results).toEqual(['loading', '1', '2'])\n  })\n\n  it(\"shouldn't unmount before all promises fetched\", async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const results: Array<string> = []\n    const refs: Array<number> = []\n\n    function Fallback() {\n      results.push('loading')\n      return <div>loading</div>\n    }\n\n    function Page() {\n      // eslint-disable-next-line react-hooks/purity\n      const ref = React.useRef(Math.random())\n      const result = useSuspenseQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () =>\n              sleep(10).then(() => {\n                refs.push(ref.current)\n                results.push('1')\n                return '1'\n              }),\n          },\n          {\n            queryKey: key2,\n            queryFn: () =>\n              sleep(20).then(() => {\n                refs.push(ref.current)\n                results.push('2')\n                return '2'\n              }),\n          },\n        ],\n      })\n\n      return (\n        <div>\n          <h1>data: {result.map((item) => item.data ?? 'null').join(',')}</h1>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <React.Suspense fallback={<Fallback />}>\n        <Page />\n      </React.Suspense>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n\n    await act(() => vi.advanceTimersByTimeAsync(20))\n    expect(rendered.getByText('data: 1,2')).toBeInTheDocument()\n\n    expect(refs.length).toBe(2)\n    expect(refs[0]).toBe(refs[1])\n  })\n\n  // this addresses the following issue:\n  // https://github.com/TanStack/query/issues/6344\n  it('should suspend on offline when query changes, and data should not be undefined', async () => {\n    function Page() {\n      const [id, setId] = React.useState(0)\n\n      const { data } = useSuspenseQuery({\n        queryKey: [id],\n        queryFn: () => sleep(10).then(() => `Data ${id}`),\n      })\n\n      // defensive guard here\n      if (data === undefined) {\n        throw new Error('data cannot be undefined')\n      }\n\n      return (\n        <>\n          <div>{data}</div>\n          <button onClick={() => setId(id + 1)}>fetch</button>\n        </>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <React.Suspense fallback={<div>loading</div>}>\n        <Page />\n      </React.Suspense>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('Data 0')).toBeInTheDocument()\n\n    // go offline\n    document.dispatchEvent(new CustomEvent('offline'))\n\n    fireEvent.click(rendered.getByText('fetch'))\n    expect(rendered.getByText('Data 0')).toBeInTheDocument()\n\n    // go back online\n    document.dispatchEvent(new CustomEvent('online'))\n\n    fireEvent.click(rendered.getByText('fetch'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    // query should resume\n    expect(rendered.getByText('Data 1')).toBeInTheDocument()\n  })\n\n  it('should throw error when queryKey changes and new query fails', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    function Page() {\n      const [fail, setFail] = React.useState(false)\n      const { data } = useSuspenseQuery({\n        queryKey: [key, fail],\n        queryFn: () =>\n          sleep(10).then(() => {\n            if (fail) throw new Error('Suspense Error Bingo')\n            return 'data'\n          }),\n        retry: 0,\n      })\n\n      return (\n        <div>\n          <button onClick={() => setFail(true)}>trigger fail</button>\n          <div>rendered: {data}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <ErrorBoundary fallbackRender={() => <div>error boundary</div>}>\n        <React.Suspense fallback=\"loading\">\n          <Page />\n        </React.Suspense>\n      </ErrorBoundary>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('rendered: data')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('trigger fail'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n\n    expect(consoleMock.mock.calls[0]?.[1]).toStrictEqual(\n      new Error('Suspense Error Bingo'),\n    )\n\n    consoleMock.mockRestore()\n  })\n\n  it('should keep previous data when wrapped in a transition', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const [count, setCount] = React.useState(0)\n      const [isPending, startTransition] = React.useTransition()\n      const { data } = useSuspenseQuery({\n        queryKey: [key, count],\n        queryFn: () => sleep(10).then(() => 'data' + count),\n      })\n\n      return (\n        <div>\n          <button onClick={() => startTransition(() => setCount(count + 1))}>\n            inc\n          </button>\n\n          <div>{isPending ? 'pending' : data}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <React.Suspense fallback=\"loading\">\n        <Page />\n      </React.Suspense>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('inc'))\n    expect(rendered.getByText('pending')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data1')).toBeInTheDocument()\n  })\n\n  it('should not request old data inside transitions (issue #6486)', async () => {\n    const key = queryKey()\n    let queryFnCount = 0\n\n    function App() {\n      const [count, setCount] = React.useState(0)\n\n      return (\n        <div>\n          <button\n            onClick={() => React.startTransition(() => setCount(count + 1))}\n          >\n            inc\n          </button>\n          <React.Suspense fallback=\"loading\">\n            <Page count={count} />\n          </React.Suspense>\n        </div>\n      )\n    }\n\n    function Page({ count }: { count: number }) {\n      const { data } = useSuspenseQuery({\n        queryKey: [key, count],\n        queryFn: () =>\n          sleep(10).then(() => {\n            queryFnCount++\n            return 'data' + count\n          }),\n      })\n\n      return (\n        <div>\n          <div>{String(data)}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n\n      <App />,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('inc'))\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data1')).toBeInTheDocument()\n\n    expect(queryFnCount).toBe(2)\n  })\n\n  it('should still suspense if queryClient has placeholderData config', async () => {\n    const key = queryKey()\n    const queryClientWithPlaceholder = new QueryClient({\n      defaultOptions: {\n        queries: {\n          placeholderData: (previousData: any) => previousData,\n        },\n      },\n    })\n\n    function Page() {\n      const [count, setCount] = React.useState(0)\n      const [isPending, startTransition] = React.useTransition()\n      const { data } = useSuspenseQuery({\n        queryKey: [key, count],\n        queryFn: () => sleep(10).then(() => 'data' + count),\n      })\n\n      return (\n        <div>\n          <button onClick={() => startTransition(() => setCount(count + 1))}>\n            inc\n          </button>\n          <div>{isPending ? 'pending' : data}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClientWithPlaceholder,\n      <React.Suspense fallback=\"loading\">\n        <Page />\n      </React.Suspense>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('inc'))\n    expect(rendered.getByText('pending')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data1')).toBeInTheDocument()\n  })\n\n  it('should show error boundary even with gcTime:0 (#7853)', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n    let count = 0\n\n    function Page() {\n      useSuspenseQuery({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => {\n            count++\n            throw new Error('Query failed')\n          }),\n        gcTime: 0,\n        retry: false,\n      })\n\n      return null\n    }\n\n    function App() {\n      return (\n        <React.Suspense fallback=\"loading\">\n          <ErrorBoundary\n            fallbackRender={() => {\n              return <div>There was an error!</div>\n            }}\n          >\n            <Page />\n          </ErrorBoundary>\n        </React.Suspense>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('There was an error!')).toBeInTheDocument()\n\n    expect(count).toBe(1)\n\n    consoleMock.mockRestore()\n  })\n\n  describe('gc (with fake timers)', () => {\n    beforeAll(() => {\n      vi.useFakeTimers()\n    })\n\n    afterAll(() => {\n      vi.useRealTimers()\n    })\n\n    it('should gc when unmounted while fetching with low gcTime (#8159)', async () => {\n      const key = queryKey()\n\n      function Page() {\n        return (\n          <React.Suspense fallback=\"loading\">\n            <Component />\n          </React.Suspense>\n        )\n      }\n\n      function Component() {\n        const { data } = useSuspenseQuery({\n          queryKey: key,\n          queryFn: () => sleep(3000).then(() => 'data'),\n          gcTime: 1000,\n        })\n\n        return <div>{data}</div>\n      }\n\n      function Page2() {\n        return <div>page2</div>\n      }\n\n      function App() {\n        const [show, setShow] = React.useState(true)\n\n        return (\n          <div>\n            {show ? <Page /> : <Page2 />}\n            <button onClick={() => setShow(false)}>hide</button>\n          </div>\n        )\n      }\n\n      const rendered = renderWithClient(queryClient, <App />)\n\n      expect(rendered.getByText('loading')).toBeInTheDocument()\n\n      fireEvent.click(rendered.getByText('hide'))\n      expect(rendered.getByText('page2')).toBeInTheDocument()\n      // wait for query to be resolved\n      await vi.advanceTimersByTimeAsync(3000)\n      expect(queryClient.getQueryData(key)).toBe('data')\n      // wait for gc\n      await vi.advanceTimersByTimeAsync(1000)\n      expect(queryClient.getQueryData(key)).toBe(undefined)\n    })\n  })\n\n  it('should log an error when skipToken is passed as queryFn', () => {\n    const consoleErrorSpy = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => {})\n    const key = queryKey()\n\n    function Page() {\n      useSuspenseQueries({\n        queries: [\n          {\n            queryKey: key,\n            // @ts-expect-error\n            // eslint-disable-next-line react-hooks/purity\n            queryFn: Math.random() >= 0 ? skipToken : () => Promise.resolve(5),\n          },\n        ],\n      })\n\n      return null\n    }\n\n    function App() {\n      return (\n        <React.Suspense fallback=\"loading\">\n          <Page />\n        </React.Suspense>\n      )\n    }\n\n    renderWithClient(queryClient, <App />)\n\n    expect(consoleErrorSpy).toHaveBeenCalledWith(\n      'skipToken is not allowed for useSuspenseQueries',\n    )\n    consoleErrorSpy.mockRestore()\n  })\n\n  it('should log an error when skipToken is used in development environment', () => {\n    const envCopy = process.env.NODE_ENV\n    process.env.NODE_ENV = 'development'\n\n    const consoleErrorSpy = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    function Page() {\n      useSuspenseQueries({\n        queries: [\n          {\n            queryKey: key,\n            queryFn: skipToken as any,\n          },\n        ],\n      })\n\n      return null\n    }\n\n    renderWithClient(\n      queryClient,\n      <React.Suspense fallback=\"loading\">\n        <Page />\n      </React.Suspense>,\n    )\n\n    expect(consoleErrorSpy).toHaveBeenCalledWith(\n      'skipToken is not allowed for useSuspenseQueries',\n    )\n    consoleErrorSpy.mockRestore()\n    process.env.NODE_ENV = envCopy\n  })\n\n  it('should not log an error when skipToken is used in production environment', () => {\n    const envCopy = process.env.NODE_ENV\n    process.env.NODE_ENV = 'production'\n\n    const consoleErrorSpy = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    function Page() {\n      useSuspenseQueries({\n        queries: [\n          {\n            queryKey: key,\n            queryFn: skipToken as any,\n          },\n        ],\n      })\n\n      return null\n    }\n\n    renderWithClient(\n      queryClient,\n      <React.Suspense fallback=\"loading\">\n        <Page />\n      </React.Suspense>,\n    )\n\n    expect(consoleErrorSpy).not.toHaveBeenCalled()\n    consoleErrorSpy.mockRestore()\n    process.env.NODE_ENV = envCopy\n  })\n\n  it('should only suspend queries that are pending when the slower query already has data', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    queryClient.setQueryData(key1, 'cached')\n\n    function Page() {\n      const [result1, result2] = useSuspenseQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => sleep(2000).then(() => 'data1'),\n          },\n          {\n            queryKey: key2,\n            queryFn: () => sleep(1000).then(() => 'data2'),\n          },\n        ],\n      })\n\n      return (\n        <div>\n          <div>data1: {result1.data}</div>\n          <div>data2: {result2.data}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <React.Suspense fallback={<div>loading</div>}>\n        <Page />\n      </React.Suspense>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n\n    // key2 resolves: suspend lifts, key1 shows cached data, key2 shows fresh data\n    await act(() => vi.advanceTimersByTimeAsync(1000))\n\n    expect(rendered.getByText('data1: cached')).toBeInTheDocument()\n    expect(rendered.getByText('data2: data2')).toBeInTheDocument()\n\n    // key1 stale timer fires, triggering background refetch\n    await vi.advanceTimersByTimeAsync(1000)\n\n    // key1 background refetch completes: key1 updates to fresh data\n    await vi.advanceTimersByTimeAsync(2000)\n\n    expect(rendered.getByText('data1: data1')).toBeInTheDocument()\n    expect(rendered.getByText('data2: data2')).toBeInTheDocument()\n  })\n\n  it('should only suspend queries that are pending when the faster query already has data', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    queryClient.setQueryData(key2, 'cached')\n\n    function Page() {\n      const [result1, result2] = useSuspenseQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => sleep(2000).then(() => 'data1'),\n          },\n          {\n            queryKey: key2,\n            queryFn: () => sleep(1000).then(() => 'data2'),\n          },\n        ],\n      })\n\n      return (\n        <div>\n          <div>data1: {result1.data}</div>\n          <div>data2: {result2.data}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <React.Suspense fallback={<div>loading</div>}>\n        <Page />\n      </React.Suspense>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n\n    // key1 resolves: suspend lifts, key1 shows fresh data, key2 shows cached data\n    await act(() => vi.advanceTimersByTimeAsync(2000))\n\n    expect(rendered.getByText('data1: data1')).toBeInTheDocument()\n    expect(rendered.getByText('data2: cached')).toBeInTheDocument()\n\n    // key2 stale timer fires, triggering background refetch\n    await vi.advanceTimersByTimeAsync(1000)\n\n    // key2 background refetch completes: key2 updates to fresh data\n    await vi.advanceTimersByTimeAsync(1000)\n\n    expect(rendered.getByText('data1: data1')).toBeInTheDocument()\n    expect(rendered.getByText('data2: data2')).toBeInTheDocument()\n  })\n\n  it('should not suspend and not refetch when all queries have fresh cached data', () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    queryClient.setQueryData(key1, 'cached1')\n    queryClient.setQueryData(key2, 'cached2')\n\n    const queryFn1 = vi.fn(() => sleep(20).then(() => 'data1'))\n    const queryFn2 = vi.fn(() => sleep(10).then(() => 'data2'))\n\n    function Page() {\n      const [result1, result2] = useSuspenseQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: queryFn1,\n          },\n          {\n            queryKey: key2,\n            queryFn: queryFn2,\n          },\n        ],\n      })\n\n      return (\n        <div>\n          <div>data1: {result1.data}</div>\n          <div>data2: {result2.data}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <React.Suspense fallback={<div>loading</div>}>\n        <Page />\n      </React.Suspense>,\n    )\n\n    // No suspend, fresh cached data shown immediately\n    expect(rendered.getByText('data1: cached1')).toBeInTheDocument()\n    expect(rendered.getByText('data2: cached2')).toBeInTheDocument()\n\n    // No background refetch because data is still fresh (within staleTime)\n    expect(queryFn1).toHaveBeenCalledTimes(0)\n    expect(queryFn2).toHaveBeenCalledTimes(0)\n  })\n\n  it('should not suspend but refetch when all queries have stale cached data', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    queryClient.setQueryData(key1, 'cached1')\n    queryClient.setQueryData(key2, 'cached2')\n\n    // Advance past staleTime (min 1000ms in suspense) so data becomes stale before mount\n    vi.advanceTimersByTime(1000)\n\n    function Page() {\n      const [result1, result2] = useSuspenseQueries({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => sleep(20).then(() => 'data1'),\n          },\n          {\n            queryKey: key2,\n            queryFn: () => sleep(10).then(() => 'data2'),\n          },\n        ],\n      })\n\n      return (\n        <div>\n          <div>data1: {result1.data}</div>\n          <div>data2: {result2.data}</div>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <React.Suspense fallback={<div>loading</div>}>\n        <Page />\n      </React.Suspense>,\n    )\n\n    // No suspend, stale cached data shown immediately with background refetch started\n    expect(rendered.getByText('data1: cached1')).toBeInTheDocument()\n    expect(rendered.getByText('data2: cached2')).toBeInTheDocument()\n\n    // key2 background refetch completes\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(rendered.getByText('data1: cached1')).toBeInTheDocument()\n    expect(rendered.getByText('data2: data2')).toBeInTheDocument()\n\n    // key1 background refetch completes\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(rendered.getByText('data1: data1')).toBeInTheDocument()\n    expect(rendered.getByText('data2: data2')).toBeInTheDocument()\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/useSuspenseQuery.test-d.tsx",
    "content": "import { assertType, describe, expectTypeOf, it } from 'vitest'\nimport { skipToken } from '@tanstack/query-core'\nimport { useSuspenseQuery } from '../useSuspenseQuery'\n\ndescribe('useSuspenseQuery', () => {\n  it('should always have data defined', () => {\n    const { data } = useSuspenseQuery({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    expectTypeOf(data).toEqualTypeOf<number>()\n  })\n\n  it('should not have pending status', () => {\n    const { status } = useSuspenseQuery({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    expectTypeOf(status).toEqualTypeOf<'error' | 'success'>()\n  })\n\n  it('should not allow skipToken in queryFn', () => {\n    assertType(\n      useSuspenseQuery({\n        queryKey: ['key'],\n        // @ts-expect-error\n        queryFn: skipToken,\n      }),\n    )\n    assertType(\n      useSuspenseQuery({\n        queryKey: ['key'],\n        // @ts-expect-error\n        queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),\n      }),\n    )\n  })\n\n  it('should not allow placeholderData, enabled or throwOnError props', () => {\n    assertType(\n      useSuspenseQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        // @ts-expect-error TS2345\n        placeholderData: 5,\n        enabled: true,\n      }),\n    )\n    assertType(\n      useSuspenseQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        // @ts-expect-error TS2345\n        enabled: true,\n      }),\n    )\n    assertType(\n      useSuspenseQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        // @ts-expect-error TS2345\n        throwOnError: true,\n      }),\n    )\n  })\n\n  it('should not return isPlaceholderData', () => {\n    expectTypeOf(\n      useSuspenseQuery({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n      }),\n    ).not.toHaveProperty('isPlaceholderData')\n  })\n\n  it('should type-narrow the error field', () => {\n    const query = useSuspenseQuery({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    if (query.status === 'error') {\n      expectTypeOf(query.error).toEqualTypeOf<Error>()\n    }\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/useSuspenseQuery.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { act, fireEvent } from '@testing-library/react'\nimport * as React from 'react'\nimport { ErrorBoundary } from 'react-error-boundary'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport {\n  QueryCache,\n  QueryClient,\n  QueryErrorResetBoundary,\n  skipToken,\n  useQueryErrorResetBoundary,\n  useSuspenseInfiniteQuery,\n  useSuspenseQuery,\n} from '..'\nimport { renderWithClient } from './utils'\nimport type {\n  InfiniteData,\n  UseSuspenseInfiniteQueryResult,\n  UseSuspenseQueryResult,\n} from '..'\n\ndescribe('useSuspenseQuery', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  const queryCache = new QueryCache()\n  const queryClient = new QueryClient({ queryCache })\n\n  it('should render the correct amount of times in Suspense mode', async () => {\n    const key = queryKey()\n    const states: Array<UseSuspenseQueryResult<number>> = []\n\n    let count = 0\n    let renders = 0\n\n    function Page() {\n      renders++\n\n      const [stateKey, setStateKey] = React.useState(key)\n\n      const state = useSuspenseQuery({\n        queryKey: stateKey,\n        queryFn: () => sleep(10).then(() => ++count),\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <button aria-label=\"toggle\" onClick={() => setStateKey(queryKey())} />\n          data: {String(state.data)}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <React.Suspense fallback=\"loading\">\n        <Page />\n      </React.Suspense>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByLabelText('toggle'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data: 2')).toBeInTheDocument()\n\n    expect(renders).toBe(6)\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: 1, status: 'success' })\n    expect(states[1]).toMatchObject({ data: 2, status: 'success' })\n  })\n\n  it('should return the correct states for a successful infinite query', async () => {\n    const key = queryKey()\n    const states: Array<UseSuspenseInfiniteQueryResult<InfiniteData<number>>> =\n      []\n\n    function Page() {\n      const [multiplier, setMultiplier] = React.useState(1)\n      const state = useSuspenseInfiniteQuery({\n        queryKey: [`${key}_${multiplier}`],\n        queryFn: ({ pageParam }) =>\n          sleep(10).then(() => pageParam * multiplier),\n        initialPageParam: 1,\n        getNextPageParam: (lastPage) => lastPage + 1,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <button onClick={() => setMultiplier(2)}>next</button>\n          data: {state.data?.pages.join(',')}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <React.Suspense fallback=\"loading\">\n        <Page />\n      </React.Suspense>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n\n    expect(states.length).toBe(1)\n    expect(states[0]).toMatchObject({\n      data: { pages: [1], pageParams: [1] },\n      status: 'success',\n    })\n\n    fireEvent.click(rendered.getByText('next'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data: 2')).toBeInTheDocument()\n\n    expect(states.length).toBe(2)\n    expect(states[1]).toMatchObject({\n      data: { pages: [2], pageParams: [1] },\n      status: 'success',\n    })\n  })\n\n  it('should not call the queryFn twice when used in Suspense mode', async () => {\n    const key = queryKey()\n\n    const queryFn = vi.fn(() => sleep(10).then(() => 'data'))\n\n    function Page() {\n      useSuspenseQuery({ queryKey: [key], queryFn })\n\n      return <>rendered</>\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <React.Suspense fallback=\"loading\">\n        <Page />\n      </React.Suspense>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n\n    expect(queryFn).toHaveBeenCalledTimes(1)\n  })\n\n  it('should remove query instance when component unmounted', async () => {\n    const key = queryKey()\n\n    function Page() {\n      useSuspenseQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'data'),\n      })\n\n      return <>rendered</>\n    }\n\n    function App() {\n      const [show, setShow] = React.useState(false)\n\n      return (\n        <>\n          <React.Suspense fallback=\"loading\">{show && <Page />}</React.Suspense>\n          <button\n            aria-label=\"toggle\"\n            onClick={() => setShow((prev) => !prev)}\n          />\n        </>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    expect(rendered.queryByText('loading')).not.toBeInTheDocument()\n    expect(rendered.queryByText('rendered')).not.toBeInTheDocument()\n    expect(queryCache.find({ queryKey: key })).toBeFalsy()\n\n    fireEvent.click(rendered.getByLabelText('toggle'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n\n    expect(queryCache.find({ queryKey: key })?.getObserversCount()).toBe(1)\n\n    fireEvent.click(rendered.getByLabelText('toggle'))\n    expect(rendered.queryByText('loading')).not.toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.queryByText('rendered')).not.toBeInTheDocument()\n    expect(queryCache.find({ queryKey: key })?.getObserversCount()).toBe(0)\n  })\n\n  // https://github.com/tannerlinsley/react-query/issues/468\n  it('should reset error state if new component instances are mounted', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    let succeed = false\n\n    function Page() {\n      useSuspenseQuery({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => {\n            if (!succeed) throw new Error('Suspense Error Bingo')\n            return 'data'\n          }),\n        retryDelay: 10,\n      })\n\n      return <div>rendered</div>\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <QueryErrorResetBoundary>\n        {({ reset }) => (\n          <ErrorBoundary\n            onReset={reset}\n            fallbackRender={({ resetErrorBoundary }) => (\n              <div>\n                <div>error boundary</div>\n                <button\n                  onClick={() => {\n                    succeed = true\n                    resetErrorBoundary()\n                  }}\n                >\n                  retry\n                </button>\n              </div>\n            )}\n          >\n            <React.Suspense fallback=\"loading\">\n              <Page />\n            </React.Suspense>\n          </ErrorBoundary>\n        )}\n      </QueryErrorResetBoundary>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(70))\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n    expect(rendered.getByText('retry')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('retry'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n\n    expect(consoleMock.mock.calls[0]?.[1]).toStrictEqual(\n      new Error('Suspense Error Bingo'),\n    )\n\n    consoleMock.mockRestore()\n  })\n\n  it('should retry fetch if the reset error boundary has been reset', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    let succeed = false\n\n    function Page() {\n      useSuspenseQuery({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => {\n            if (!succeed) throw new Error('Suspense Error Bingo')\n            return 'data'\n          }),\n        retry: false,\n      })\n      return <div>rendered</div>\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <QueryErrorResetBoundary>\n        {({ reset }) => (\n          <ErrorBoundary\n            onReset={reset}\n            fallbackRender={({ resetErrorBoundary }) => (\n              <div>\n                <div>error boundary</div>\n                <button\n                  onClick={() => {\n                    resetErrorBoundary()\n                  }}\n                >\n                  retry\n                </button>\n              </div>\n            )}\n          >\n            <React.Suspense fallback=\"loading\">\n              <Page />\n            </React.Suspense>\n          </ErrorBoundary>\n        )}\n      </QueryErrorResetBoundary>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n    expect(rendered.getByText('retry')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('retry'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n    expect(rendered.getByText('retry')).toBeInTheDocument()\n\n    succeed = true\n\n    fireEvent.click(rendered.getByText('retry'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n\n    consoleMock.mockRestore()\n  })\n\n  it('should set staleTime when having passed a function', async () => {\n    const key = queryKey()\n    let count = 0\n\n    function Component() {\n      const result = useSuspenseQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => ++count),\n        staleTime: () => 60 * 1000,\n      })\n      return (\n        <div>\n          <span>data: {result.data}</span>\n        </div>\n      )\n    }\n\n    function Page() {\n      return (\n        <React.Suspense fallback=\"loading\">\n          <Component />\n        </React.Suspense>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n\n    expect(\n      typeof queryClient.getQueryCache().find({ queryKey: key })?.observers[0]\n        ?.options.staleTime,\n    ).toBe('function')\n  })\n\n  it('should suspend when switching to a new query', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    function Component(props: { queryKey: Array<string> }) {\n      const result = useSuspenseQuery({\n        queryKey: props.queryKey,\n        queryFn: () => sleep(10).then(() => props.queryKey),\n        retry: false,\n      })\n      return <div>data: {result.data}</div>\n    }\n\n    function Page() {\n      const [key, setKey] = React.useState(key1)\n      return (\n        <div>\n          <button\n            onClick={() => {\n              setKey(key2)\n            }}\n          >\n            switch\n          </button>\n          <React.Suspense fallback=\"loading\">\n            <Component queryKey={key} />\n          </React.Suspense>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <Page />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText(`data: ${key1}`)).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('switch'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText(`data: ${key2}`)).toBeInTheDocument()\n  })\n\n  it('should retry fetch if the reset error boundary has been reset with global hook', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    let succeed = false\n\n    function Page() {\n      useSuspenseQuery({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => {\n            if (!succeed) throw new Error('Suspense Error Bingo')\n            return 'data'\n          }),\n        retry: false,\n      })\n      return <div>rendered</div>\n    }\n\n    function App() {\n      const { reset } = useQueryErrorResetBoundary()\n      return (\n        <ErrorBoundary\n          onReset={reset}\n          fallbackRender={({ resetErrorBoundary }) => (\n            <div>\n              <div>error boundary</div>\n              <button\n                onClick={() => {\n                  resetErrorBoundary()\n                }}\n              >\n                retry\n              </button>\n            </div>\n          )}\n        >\n          <React.Suspense fallback=\"loading\">\n            <Page />\n          </React.Suspense>\n        </ErrorBoundary>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n    expect(rendered.getByText('retry')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('retry'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n    expect(rendered.getByText('retry')).toBeInTheDocument()\n\n    succeed = true\n\n    fireEvent.click(rendered.getByText('retry'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n\n    consoleMock.mockRestore()\n  })\n\n  it('should throw errors to the error boundary by default', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    function Page() {\n      useSuspenseQuery({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => Promise.reject(new Error('Suspense Error a1x'))),\n        retry: false,\n      })\n      return <div>rendered</div>\n    }\n\n    function App() {\n      return (\n        <ErrorBoundary\n          fallbackRender={() => (\n            <div>\n              <div>error boundary</div>\n            </div>\n          )}\n        >\n          <React.Suspense fallback=\"loading\">\n            <Page />\n          </React.Suspense>\n        </ErrorBoundary>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n\n    consoleMock.mockRestore()\n  })\n\n  it('should throw select errors to the error boundary by default', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    function Page() {\n      useSuspenseQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => ({ a: { b: 'c' } })),\n        select: () => {\n          throw new Error('foo')\n        },\n      })\n      return <div>rendered</div>\n    }\n\n    function App() {\n      return (\n        <ErrorBoundary\n          fallbackRender={() => (\n            <div>\n              <div>error boundary</div>\n            </div>\n          )}\n        >\n          <React.Suspense fallback=\"loading\">\n            <Page />\n          </React.Suspense>\n        </ErrorBoundary>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n\n    consoleMock.mockRestore()\n  })\n\n  it('should error caught in error boundary without infinite loop', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    let succeed = true\n\n    function Page() {\n      const [nonce] = React.useState(0)\n      const queryKeys = [`${key}-${succeed}`]\n      const result = useSuspenseQuery({\n        queryKey: queryKeys,\n        queryFn: () =>\n          sleep(10).then(() => {\n            if (!succeed) throw new Error('Suspense Error Bingo')\n            return nonce\n          }),\n        retry: false,\n      })\n      return (\n        <div>\n          <span>rendered</span> <span>{result.data}</span>\n          <button aria-label=\"fail\" onClick={() => queryClient.resetQueries()}>\n            fail\n          </button>\n        </div>\n      )\n    }\n\n    function App() {\n      const { reset } = useQueryErrorResetBoundary()\n      return (\n        <ErrorBoundary\n          onReset={reset}\n          fallbackRender={() => <div>error boundary</div>}\n        >\n          <React.Suspense fallback=\"loading\">\n            <Page />\n          </React.Suspense>\n        </ErrorBoundary>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    // render suspense fallback (loading)\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    // resolve promise -> render Page (rendered)\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n\n    // change query key\n    succeed = false\n\n    // reset query -> and throw error\n    fireEvent.click(rendered.getByLabelText('fail'))\n    // render error boundary fallback (error boundary)\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n\n    expect(consoleMock.mock.calls[0]?.[1]).toStrictEqual(\n      new Error('Suspense Error Bingo'),\n    )\n\n    consoleMock.mockRestore()\n  })\n\n  it('should error caught in error boundary without infinite loop when query keys changed', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    let succeed = true\n\n    function Page() {\n      const [key, rerender] = React.useReducer((x) => x + 1, 0)\n      const queryKeys = [key, succeed]\n\n      const result = useSuspenseQuery({\n        queryKey: queryKeys,\n        queryFn: () =>\n          sleep(10).then(() => {\n            if (!succeed) throw new Error('Suspense Error Bingo')\n            return 'data'\n          }),\n        retry: false,\n      })\n\n      if (result.error) {\n        throw result.error\n      }\n\n      return (\n        <div>\n          <span>rendered</span> <span>{result.data}</span>\n          <button aria-label=\"fail\" onClick={rerender}>\n            fail\n          </button>\n        </div>\n      )\n    }\n\n    function App() {\n      const { reset } = useQueryErrorResetBoundary()\n      return (\n        <ErrorBoundary\n          onReset={reset}\n          fallbackRender={() => <div>error boundary</div>}\n        >\n          <React.Suspense fallback=\"loading\">\n            <Page />\n          </React.Suspense>\n        </ErrorBoundary>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    // render suspense fallback (loading)\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    // resolve promise -> render Page (rendered)\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n\n    // change promise result to error\n    succeed = false\n\n    // change query key\n    fireEvent.click(rendered.getByLabelText('fail'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    // render error boundary fallback (error boundary)\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n\n    expect(consoleMock.mock.calls[0]?.[1]).toStrictEqual(\n      new Error('Suspense Error Bingo'),\n    )\n\n    consoleMock.mockRestore()\n  })\n\n  it('should render the correct amount of times in Suspense mode when gcTime is set to 0', async () => {\n    const key = queryKey()\n    let state: UseSuspenseQueryResult<number, Error | null> | null = null\n\n    let count = 0\n    let renders = 0\n\n    function Page() {\n      renders++\n\n      state = useSuspenseQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => ++count),\n        gcTime: 0,\n      })\n\n      return (\n        <div>\n          <span>rendered</span>\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <React.Suspense fallback=\"loading\">\n        <Page />\n      </React.Suspense>,\n    )\n\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n\n    expect(state).toMatchObject({\n      data: 1,\n      status: 'success',\n    })\n    expect(renders).toBe(3)\n  })\n\n  it('should not throw background errors to the error boundary', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    let succeed = true\n    const key = queryKey()\n\n    function Page() {\n      const result = useSuspenseQuery({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => {\n            if (!succeed) throw new Error('Suspense Error Bingo')\n            return 'data'\n          }),\n        retry: false,\n      })\n\n      return (\n        <div>\n          <span>\n            rendered {result.data} {result.status}\n          </span>\n          <button onClick={() => result.refetch()}>refetch</button>\n        </div>\n      )\n    }\n\n    function App() {\n      const { reset } = useQueryErrorResetBoundary()\n      return (\n        <ErrorBoundary\n          onReset={reset}\n          fallbackRender={() => <div>error boundary</div>}\n        >\n          <React.Suspense fallback=\"loading\">\n            <Page />\n          </React.Suspense>\n        </ErrorBoundary>\n      )\n    }\n\n    const rendered = renderWithClient(queryClient, <App />)\n\n    // render suspense fallback (loading)\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    // resolve promise -> render Page (rendered)\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('rendered data success')).toBeInTheDocument()\n\n    // change promise result to error\n    succeed = false\n\n    // refetch\n    fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))\n    // we are now in error state but still have data to show\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('rendered data error')).toBeInTheDocument()\n\n    consoleMock.mockRestore()\n  })\n\n  it('should still suspense if queryClient has placeholderData config', async () => {\n    const key = queryKey()\n    const queryClientWithPlaceholder = new QueryClient({\n      defaultOptions: {\n        queries: {\n          placeholderData: (previousData: any) => previousData,\n        },\n      },\n    })\n    const states: Array<UseSuspenseQueryResult<number>> = []\n\n    let count = 0\n\n    function Page() {\n      const [stateKey, setStateKey] = React.useState(key)\n\n      const state = useSuspenseQuery({\n        queryKey: stateKey,\n        queryFn: async () => sleep(10).then(() => ++count),\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <button aria-label=\"toggle\" onClick={() => setStateKey(queryKey())} />\n          data: {String(state.data)}\n        </div>\n      )\n    }\n\n    const rendered = renderWithClient(\n      queryClientWithPlaceholder,\n      <React.Suspense fallback=\"loading\">\n        <Page />\n      </React.Suspense>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByLabelText('toggle'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data: 2')).toBeInTheDocument()\n  })\n\n  it('should log an error when skipToken is passed as queryFn', () => {\n    const consoleErrorSpy = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => {})\n    const key = queryKey()\n\n    function Page() {\n      useSuspenseQuery({\n        queryKey: key,\n        // @ts-expect-error\n        // eslint-disable-next-line react-hooks/purity\n        queryFn: Math.random() >= 0 ? skipToken : () => Promise.resolve(5),\n      })\n\n      return null\n    }\n\n    function App() {\n      return (\n        <React.Suspense fallback=\"loading\">\n          <Page />\n        </React.Suspense>\n      )\n    }\n\n    renderWithClient(queryClient, <App />)\n\n    expect(consoleErrorSpy).toHaveBeenCalledWith(\n      'skipToken is not allowed for useSuspenseQuery',\n    )\n    consoleErrorSpy.mockRestore()\n  })\n\n  it('should properly refresh data when refetchInterval is set', async () => {\n    const key = queryKey()\n    let count = 0\n\n    function Page() {\n      const state = useSuspenseQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => ++count),\n        refetchInterval: 10,\n      })\n\n      return <div>count: {state.data}</div>\n    }\n\n    const rendered = renderWithClient(\n      queryClient,\n      <React.Suspense fallback=\"loading\">\n        <Page />\n      </React.Suspense>,\n    )\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('count: 1')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(21)\n    expect(rendered.getByText('count: 2')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(21)\n    expect(rendered.getByText('count: 3')).toBeInTheDocument()\n\n    expect(count).toBeGreaterThanOrEqual(3)\n  })\n\n  it('should log an error when skipToken is used in development environment', () => {\n    const envCopy = process.env.NODE_ENV\n    process.env.NODE_ENV = 'development'\n\n    const consoleErrorSpy = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    function Page() {\n      useSuspenseQuery({\n        queryKey: key,\n        queryFn: skipToken as any,\n      })\n\n      return null\n    }\n\n    renderWithClient(\n      queryClient,\n      <React.Suspense fallback=\"loading\">\n        <Page />\n      </React.Suspense>,\n    )\n\n    expect(consoleErrorSpy).toHaveBeenCalledWith(\n      'skipToken is not allowed for useSuspenseQuery',\n    )\n\n    consoleErrorSpy.mockRestore()\n    process.env.NODE_ENV = envCopy\n  })\n\n  it('should not log an error when skipToken is used in production environment', () => {\n    const envCopy = process.env.NODE_ENV\n    process.env.NODE_ENV = 'production'\n\n    const consoleErrorSpy = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const key = queryKey()\n\n    function Page() {\n      useSuspenseQuery({\n        queryKey: key,\n        queryFn: skipToken as any,\n      })\n\n      return null\n    }\n\n    renderWithClient(\n      queryClient,\n      <React.Suspense fallback=\"loading\">\n        <Page />\n      </React.Suspense>,\n    )\n\n    expect(consoleErrorSpy).not.toHaveBeenCalled()\n\n    consoleErrorSpy.mockRestore()\n    process.env.NODE_ENV = envCopy\n  })\n})\n"
  },
  {
    "path": "packages/react-query/src/__tests__/utils.tsx",
    "content": "import { vi } from 'vitest'\nimport * as React from 'react'\nimport { act, render } from '@testing-library/react'\nimport { environmentManager, isServer } from '@tanstack/query-core'\nimport { QueryClientProvider, onlineManager } from '..'\nimport type { QueryClient } from '..'\nimport type { MockInstance } from 'vitest'\n\nexport function renderWithClient(\n  client: QueryClient,\n  ui: React.ReactElement,\n): ReturnType<typeof render> {\n  const { rerender, ...result } = render(\n    <QueryClientProvider client={client}>{ui}</QueryClientProvider>,\n  )\n  return {\n    ...result,\n    rerender: (rerenderUi: React.ReactElement) =>\n      rerender(\n        <QueryClientProvider client={client}>{rerenderUi}</QueryClientProvider>,\n      ),\n  } as any\n}\n\nexport function Blink({\n  duration,\n  children,\n}: {\n  duration: number\n  children: React.ReactNode\n}) {\n  const [shouldShow, setShouldShow] = React.useState<boolean>(true)\n\n  React.useEffect(() => {\n    setShouldShow(true)\n    const timeout = setActTimeout(() => setShouldShow(false), duration)\n    return () => {\n      clearTimeout(timeout)\n    }\n  }, [duration, children])\n\n  return shouldShow ? <>{children}</> : <>off</>\n}\n\nexport function mockOnlineManagerIsOnline(\n  value: boolean,\n): MockInstance<() => boolean> {\n  return vi.spyOn(onlineManager, 'isOnline').mockReturnValue(value)\n}\n\nexport function setActTimeout(fn: () => void, ms?: number) {\n  return setTimeout(() => {\n    act(() => {\n      fn()\n    })\n  }, ms)\n}\n\nexport function setIsServer(value: boolean) {\n  environmentManager.setIsServer(() => value)\n  return () => {\n    environmentManager.setIsServer(() => isServer)\n  }\n}\n"
  },
  {
    "path": "packages/react-query/src/errorBoundaryUtils.ts",
    "content": "'use client'\nimport * as React from 'react'\nimport { shouldThrowError } from '@tanstack/query-core'\nimport type {\n  DefaultedQueryObserverOptions,\n  Query,\n  QueryKey,\n  QueryObserverResult,\n  ThrowOnError,\n} from '@tanstack/query-core'\nimport type { QueryErrorResetBoundaryValue } from './QueryErrorResetBoundary'\n\nexport const ensurePreventErrorBoundaryRetry = <\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryData,\n  TQueryKey extends QueryKey,\n>(\n  options: DefaultedQueryObserverOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryData,\n    TQueryKey\n  >,\n  errorResetBoundary: QueryErrorResetBoundaryValue,\n  query: Query<TQueryFnData, TError, TQueryData, TQueryKey> | undefined,\n) => {\n  const throwOnError =\n    query?.state.error && typeof options.throwOnError === 'function'\n      ? shouldThrowError(options.throwOnError, [query.state.error, query])\n      : options.throwOnError\n\n  if (\n    options.suspense ||\n    options.experimental_prefetchInRender ||\n    throwOnError\n  ) {\n    // Prevent retrying failed query if the error boundary has not been reset yet\n    if (!errorResetBoundary.isReset()) {\n      options.retryOnMount = false\n    }\n  }\n}\n\nexport const useClearResetErrorBoundary = (\n  errorResetBoundary: QueryErrorResetBoundaryValue,\n) => {\n  React.useEffect(() => {\n    errorResetBoundary.clearReset()\n  }, [errorResetBoundary])\n}\n\nexport const getHasError = <\n  TData,\n  TError,\n  TQueryFnData,\n  TQueryData,\n  TQueryKey extends QueryKey,\n>({\n  result,\n  errorResetBoundary,\n  throwOnError,\n  query,\n  suspense,\n}: {\n  result: QueryObserverResult<TData, TError>\n  errorResetBoundary: QueryErrorResetBoundaryValue\n  throwOnError: ThrowOnError<TQueryFnData, TError, TQueryData, TQueryKey>\n  query: Query<TQueryFnData, TError, TQueryData, TQueryKey> | undefined\n  suspense: boolean | undefined\n}) => {\n  return (\n    result.isError &&\n    !errorResetBoundary.isReset() &&\n    !result.isFetching &&\n    query &&\n    ((suspense && result.data === undefined) ||\n      shouldThrowError(throwOnError, [result.error, query]))\n  )\n}\n"
  },
  {
    "path": "packages/react-query/src/index.ts",
    "content": "/* istanbul ignore file */\n\n// Re-export core\nexport * from '@tanstack/query-core'\n\n// React Query\nexport * from './types'\nexport { useQueries } from './useQueries'\nexport type { QueriesResults, QueriesOptions } from './useQueries'\nexport { useQuery } from './useQuery'\nexport { useSuspenseQuery } from './useSuspenseQuery'\nexport { useSuspenseInfiniteQuery } from './useSuspenseInfiniteQuery'\nexport { useSuspenseQueries } from './useSuspenseQueries'\nexport type {\n  SuspenseQueriesResults,\n  SuspenseQueriesOptions,\n} from './useSuspenseQueries'\nexport { usePrefetchQuery } from './usePrefetchQuery'\nexport { usePrefetchInfiniteQuery } from './usePrefetchInfiniteQuery'\nexport { queryOptions } from './queryOptions'\nexport type {\n  DefinedInitialDataOptions,\n  UndefinedInitialDataOptions,\n  UnusedSkipTokenOptions,\n} from './queryOptions'\nexport { infiniteQueryOptions } from './infiniteQueryOptions'\nexport type {\n  DefinedInitialDataInfiniteOptions,\n  UndefinedInitialDataInfiniteOptions,\n  UnusedSkipTokenInfiniteOptions,\n} from './infiniteQueryOptions'\nexport {\n  QueryClientContext,\n  QueryClientProvider,\n  useQueryClient,\n} from './QueryClientProvider'\nexport type { QueryClientProviderProps } from './QueryClientProvider'\nexport type { QueryErrorResetBoundaryProps } from './QueryErrorResetBoundary'\nexport { HydrationBoundary } from './HydrationBoundary'\nexport type { HydrationBoundaryProps } from './HydrationBoundary'\nexport type {\n  QueryErrorClearResetFunction,\n  QueryErrorIsResetFunction,\n  QueryErrorResetBoundaryFunction,\n  QueryErrorResetFunction,\n} from './QueryErrorResetBoundary'\nexport {\n  QueryErrorResetBoundary,\n  useQueryErrorResetBoundary,\n} from './QueryErrorResetBoundary'\nexport { useIsFetching } from './useIsFetching'\nexport { useIsMutating, useMutationState } from './useMutationState'\nexport { useMutation } from './useMutation'\nexport { mutationOptions } from './mutationOptions'\nexport { useInfiniteQuery } from './useInfiniteQuery'\nexport { useIsRestoring, IsRestoringProvider } from './IsRestoringProvider'\n"
  },
  {
    "path": "packages/react-query/src/infiniteQueryOptions.ts",
    "content": "import type {\n  DataTag,\n  DefaultError,\n  InfiniteData,\n  InitialDataFunction,\n  NonUndefinedGuard,\n  OmitKeyof,\n  QueryKey,\n  SkipToken,\n} from '@tanstack/query-core'\nimport type { UseInfiniteQueryOptions } from './types'\n\nexport type UndefinedInitialDataInfiniteOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> = UseInfiniteQueryOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey,\n  TPageParam\n> & {\n  initialData?:\n    | undefined\n    | NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>\n    | InitialDataFunction<\n        NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>\n      >\n}\n\nexport type UnusedSkipTokenInfiniteOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> = OmitKeyof<\n  UseInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>,\n  'queryFn'\n> & {\n  queryFn?: Exclude<\n    UseInfiniteQueryOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey,\n      TPageParam\n    >['queryFn'],\n    SkipToken | undefined\n  >\n}\n\nexport type DefinedInitialDataInfiniteOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> = UseInfiniteQueryOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey,\n  TPageParam\n> & {\n  initialData:\n    | NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>\n    | (() => NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>)\n    | undefined\n}\n\nexport function infiniteQueryOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: DefinedInitialDataInfiniteOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n): DefinedInitialDataInfiniteOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey,\n  TPageParam\n> & {\n  queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>\n}\n\nexport function infiniteQueryOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: UnusedSkipTokenInfiniteOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n): UnusedSkipTokenInfiniteOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey,\n  TPageParam\n> & {\n  queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>\n}\n\nexport function infiniteQueryOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: UndefinedInitialDataInfiniteOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n): UndefinedInitialDataInfiniteOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey,\n  TPageParam\n> & {\n  queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>\n}\n\nexport function infiniteQueryOptions(options: unknown) {\n  return options\n}\n"
  },
  {
    "path": "packages/react-query/src/mutationOptions.ts",
    "content": "import type { DefaultError, WithRequired } from '@tanstack/query-core'\nimport type { UseMutationOptions } from './types'\n\nexport function mutationOptions<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n>(\n  options: WithRequired<\n    UseMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n    'mutationKey'\n  >,\n): WithRequired<\n  UseMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n  'mutationKey'\n>\nexport function mutationOptions<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n>(\n  options: Omit<\n    UseMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n    'mutationKey'\n  >,\n): Omit<\n  UseMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n  'mutationKey'\n>\nexport function mutationOptions<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n>(\n  options: UseMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n): UseMutationOptions<TData, TError, TVariables, TOnMutateResult> {\n  return options\n}\n"
  },
  {
    "path": "packages/react-query/src/queryOptions.ts",
    "content": "import type {\n  DataTag,\n  DefaultError,\n  InitialDataFunction,\n  NonUndefinedGuard,\n  OmitKeyof,\n  QueryFunction,\n  QueryKey,\n  SkipToken,\n} from '@tanstack/query-core'\nimport type { UseQueryOptions } from './types'\n\nexport type UndefinedInitialDataOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = UseQueryOptions<TQueryFnData, TError, TData, TQueryKey> & {\n  initialData?:\n    | undefined\n    | InitialDataFunction<NonUndefinedGuard<TQueryFnData>>\n    | NonUndefinedGuard<TQueryFnData>\n}\n\nexport type UnusedSkipTokenOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = OmitKeyof<\n  UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  'queryFn'\n> & {\n  queryFn?: Exclude<\n    UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>['queryFn'],\n    SkipToken | undefined\n  >\n}\n\nexport type DefinedInitialDataOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = Omit<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'queryFn'> & {\n  initialData:\n    | NonUndefinedGuard<TQueryFnData>\n    | (() => NonUndefinedGuard<TQueryFnData>)\n  queryFn?: QueryFunction<TQueryFnData, TQueryKey>\n}\n\nexport function queryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,\n): DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> & {\n  queryKey: DataTag<TQueryKey, TQueryFnData, TError>\n}\n\nexport function queryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: UnusedSkipTokenOptions<TQueryFnData, TError, TData, TQueryKey>,\n): UnusedSkipTokenOptions<TQueryFnData, TError, TData, TQueryKey> & {\n  queryKey: DataTag<TQueryKey, TQueryFnData, TError>\n}\n\nexport function queryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,\n): UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> & {\n  queryKey: DataTag<TQueryKey, TQueryFnData, TError>\n}\n\nexport function queryOptions(options: unknown) {\n  return options\n}\n"
  },
  {
    "path": "packages/react-query/src/suspense.ts",
    "content": "import type {\n  DefaultError,\n  DefaultedQueryObserverOptions,\n  Query,\n  QueryKey,\n  QueryObserver,\n  QueryObserverResult,\n} from '@tanstack/query-core'\nimport type { QueryErrorResetBoundaryValue } from './QueryErrorResetBoundary'\n\nexport const defaultThrowOnError = <\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  _error: TError,\n  query: Query<TQueryFnData, TError, TData, TQueryKey>,\n) => query.state.data === undefined\n\nexport const ensureSuspenseTimers = (\n  defaultedOptions: DefaultedQueryObserverOptions<any, any, any, any, any>,\n) => {\n  if (defaultedOptions.suspense) {\n    // Handle staleTime to ensure minimum 1000ms in Suspense mode\n    // This prevents unnecessary refetching when components remount after suspending\n    const MIN_SUSPENSE_TIME_MS = 1000\n\n    const clamp = (value: number | 'static' | undefined) =>\n      value === 'static'\n        ? value\n        : Math.max(value ?? MIN_SUSPENSE_TIME_MS, MIN_SUSPENSE_TIME_MS)\n\n    const originalStaleTime = defaultedOptions.staleTime\n    defaultedOptions.staleTime =\n      typeof originalStaleTime === 'function'\n        ? (...args) => clamp(originalStaleTime(...args))\n        : clamp(originalStaleTime)\n\n    if (typeof defaultedOptions.gcTime === 'number') {\n      defaultedOptions.gcTime = Math.max(\n        defaultedOptions.gcTime,\n        MIN_SUSPENSE_TIME_MS,\n      )\n    }\n  }\n}\n\nexport const willFetch = (\n  result: QueryObserverResult<any, any>,\n  isRestoring: boolean,\n) => result.isLoading && result.isFetching && !isRestoring\n\nexport const shouldSuspend = (\n  defaultedOptions:\n    | DefaultedQueryObserverOptions<any, any, any, any, any>\n    | undefined,\n  result: QueryObserverResult<any, any>,\n) => defaultedOptions?.suspense && result.isPending\n\nexport const fetchOptimistic = <\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryData,\n  TQueryKey extends QueryKey,\n>(\n  defaultedOptions: DefaultedQueryObserverOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryData,\n    TQueryKey\n  >,\n  observer: QueryObserver<TQueryFnData, TError, TData, TQueryData, TQueryKey>,\n  errorResetBoundary: QueryErrorResetBoundaryValue,\n) =>\n  observer.fetchOptimistic(defaultedOptions).catch(() => {\n    errorResetBoundary.clearReset()\n  })\n"
  },
  {
    "path": "packages/react-query/src/types.ts",
    "content": "/* istanbul ignore file */\n\nimport type {\n  DefaultError,\n  DefinedInfiniteQueryObserverResult,\n  DefinedQueryObserverResult,\n  DistributiveOmit,\n  FetchQueryOptions,\n  InfiniteQueryObserverOptions,\n  InfiniteQueryObserverResult,\n  MutateFunction,\n  MutationObserverOptions,\n  MutationObserverResult,\n  OmitKeyof,\n  Override,\n  QueryKey,\n  QueryObserverOptions,\n  QueryObserverResult,\n  SkipToken,\n} from '@tanstack/query-core'\n\nexport type AnyUseBaseQueryOptions = UseBaseQueryOptions<\n  any,\n  any,\n  any,\n  any,\n  any\n>\nexport interface UseBaseQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> extends QueryObserverOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryData,\n  TQueryKey\n> {\n  /**\n   * Set this to `false` to unsubscribe this observer from updates to the query cache.\n   * Defaults to `true`.\n   */\n  subscribed?: boolean\n}\n\nexport interface UsePrefetchQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> extends OmitKeyof<\n  FetchQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  'queryFn'\n> {\n  queryFn?: Exclude<\n    FetchQueryOptions<TQueryFnData, TError, TData, TQueryKey>['queryFn'],\n    SkipToken\n  >\n}\n\nexport type AnyUseQueryOptions = UseQueryOptions<any, any, any, any>\nexport interface UseQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> extends OmitKeyof<\n  UseBaseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>,\n  'suspense'\n> {}\n\nexport type AnyUseSuspenseQueryOptions = UseSuspenseQueryOptions<\n  any,\n  any,\n  any,\n  any\n>\nexport interface UseSuspenseQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> extends OmitKeyof<\n  UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  'queryFn' | 'enabled' | 'throwOnError' | 'placeholderData'\n> {\n  queryFn?: Exclude<\n    UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>['queryFn'],\n    SkipToken\n  >\n}\n\nexport type AnyUseInfiniteQueryOptions = UseInfiniteQueryOptions<\n  any,\n  any,\n  any,\n  any,\n  any\n>\nexport interface UseInfiniteQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> extends OmitKeyof<\n  InfiniteQueryObserverOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n  'suspense'\n> {\n  /**\n   * Set this to `false` to unsubscribe this observer from updates to the query cache.\n   * Defaults to `true`.\n   */\n  subscribed?: boolean\n}\n\nexport type AnyUseSuspenseInfiniteQueryOptions =\n  UseSuspenseInfiniteQueryOptions<any, any, any, any, any>\nexport interface UseSuspenseInfiniteQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> extends OmitKeyof<\n  UseInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>,\n  'queryFn' | 'enabled' | 'throwOnError' | 'placeholderData'\n> {\n  queryFn?: Exclude<\n    UseInfiniteQueryOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey,\n      TPageParam\n    >['queryFn'],\n    SkipToken\n  >\n}\n\nexport type UseBaseQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = QueryObserverResult<TData, TError>\n\nexport type UseQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = UseBaseQueryResult<TData, TError>\n\nexport type UseSuspenseQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = DistributiveOmit<\n  DefinedQueryObserverResult<TData, TError>,\n  'isPlaceholderData' | 'promise'\n>\n\nexport type DefinedUseQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = DefinedQueryObserverResult<TData, TError>\n\nexport type UseInfiniteQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = InfiniteQueryObserverResult<TData, TError>\n\nexport type DefinedUseInfiniteQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = DefinedInfiniteQueryObserverResult<TData, TError>\n\nexport type UseSuspenseInfiniteQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = OmitKeyof<\n  DefinedInfiniteQueryObserverResult<TData, TError>,\n  'isPlaceholderData' | 'promise'\n>\n\nexport type AnyUseMutationOptions = UseMutationOptions<any, any, any, any>\nexport interface UseMutationOptions<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> extends OmitKeyof<\n  MutationObserverOptions<TData, TError, TVariables, TOnMutateResult>,\n  '_defaulted'\n> {}\n\nexport type UseMutateFunction<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> = (\n  ...args: Parameters<\n    MutateFunction<TData, TError, TVariables, TOnMutateResult>\n  >\n) => void\n\nexport type UseMutateAsyncFunction<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> = MutateFunction<TData, TError, TVariables, TOnMutateResult>\n\nexport type UseBaseMutationResult<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = unknown,\n  TOnMutateResult = unknown,\n> = Override<\n  MutationObserverResult<TData, TError, TVariables, TOnMutateResult>,\n  { mutate: UseMutateFunction<TData, TError, TVariables, TOnMutateResult> }\n> & {\n  mutateAsync: UseMutateAsyncFunction<\n    TData,\n    TError,\n    TVariables,\n    TOnMutateResult\n  >\n}\n\nexport type UseMutationResult<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = unknown,\n  TOnMutateResult = unknown,\n> = UseBaseMutationResult<TData, TError, TVariables, TOnMutateResult>\n"
  },
  {
    "path": "packages/react-query/src/useBaseQuery.ts",
    "content": "'use client'\nimport * as React from 'react'\n\nimport { environmentManager, noop, notifyManager } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { useQueryErrorResetBoundary } from './QueryErrorResetBoundary'\nimport {\n  ensurePreventErrorBoundaryRetry,\n  getHasError,\n  useClearResetErrorBoundary,\n} from './errorBoundaryUtils'\nimport { useIsRestoring } from './IsRestoringProvider'\nimport {\n  ensureSuspenseTimers,\n  fetchOptimistic,\n  shouldSuspend,\n  willFetch,\n} from './suspense'\nimport type {\n  QueryClient,\n  QueryKey,\n  QueryObserver,\n  QueryObserverResult,\n} from '@tanstack/query-core'\nimport type { UseBaseQueryOptions } from './types'\n\nexport function useBaseQuery<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryData,\n  TQueryKey extends QueryKey,\n>(\n  options: UseBaseQueryOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryData,\n    TQueryKey\n  >,\n  Observer: typeof QueryObserver,\n  queryClient?: QueryClient,\n): QueryObserverResult<TData, TError> {\n  if (process.env.NODE_ENV !== 'production') {\n    if (typeof options !== 'object' || Array.isArray(options)) {\n      throw new Error(\n        'Bad argument type. Starting with v5, only the \"Object\" form is allowed when calling query related functions. Please use the error stack to find the culprit call. More info here: https://tanstack.com/query/latest/docs/react/guides/migrating-to-v5#supports-a-single-signature-one-object',\n      )\n    }\n  }\n\n  const isRestoring = useIsRestoring()\n  const errorResetBoundary = useQueryErrorResetBoundary()\n  const client = useQueryClient(queryClient)\n  const defaultedOptions = client.defaultQueryOptions(options)\n  ;(client.getDefaultOptions().queries as any)?._experimental_beforeQuery?.(\n    defaultedOptions,\n  )\n\n  const query = client\n    .getQueryCache()\n    .get<\n      TQueryFnData,\n      TError,\n      TQueryData,\n      TQueryKey\n    >(defaultedOptions.queryHash)\n\n  if (process.env.NODE_ENV !== 'production') {\n    if (!defaultedOptions.queryFn) {\n      console.error(\n        `[${defaultedOptions.queryHash}]: No queryFn was passed as an option, and no default queryFn was found. The queryFn parameter is only optional when using a default queryFn. More info here: https://tanstack.com/query/latest/docs/framework/react/guides/default-query-function`,\n      )\n    }\n  }\n\n  // Make sure results are optimistically set in fetching state before subscribing or updating options\n  defaultedOptions._optimisticResults = isRestoring\n    ? 'isRestoring'\n    : 'optimistic'\n\n  ensureSuspenseTimers(defaultedOptions)\n  ensurePreventErrorBoundaryRetry(defaultedOptions, errorResetBoundary, query)\n  useClearResetErrorBoundary(errorResetBoundary)\n\n  // this needs to be invoked before creating the Observer because that can create a cache entry\n  const isNewCacheEntry = !client\n    .getQueryCache()\n    .get(defaultedOptions.queryHash)\n\n  const [observer] = React.useState(\n    () =>\n      new Observer<TQueryFnData, TError, TData, TQueryData, TQueryKey>(\n        client,\n        defaultedOptions,\n      ),\n  )\n\n  // note: this must be called before useSyncExternalStore\n  const result = observer.getOptimisticResult(defaultedOptions)\n\n  const shouldSubscribe = !isRestoring && options.subscribed !== false\n  React.useSyncExternalStore(\n    React.useCallback(\n      (onStoreChange) => {\n        const unsubscribe = shouldSubscribe\n          ? observer.subscribe(notifyManager.batchCalls(onStoreChange))\n          : noop\n\n        // Update result to make sure we did not miss any query updates\n        // between creating the observer and subscribing to it.\n        observer.updateResult()\n\n        return unsubscribe\n      },\n      [observer, shouldSubscribe],\n    ),\n    () => observer.getCurrentResult(),\n    () => observer.getCurrentResult(),\n  )\n\n  React.useEffect(() => {\n    observer.setOptions(defaultedOptions)\n  }, [defaultedOptions, observer])\n\n  // Handle suspense\n  if (shouldSuspend(defaultedOptions, result)) {\n    throw fetchOptimistic(defaultedOptions, observer, errorResetBoundary)\n  }\n\n  // Handle error boundary\n  if (\n    getHasError({\n      result,\n      errorResetBoundary,\n      throwOnError: defaultedOptions.throwOnError,\n      query,\n      suspense: defaultedOptions.suspense,\n    })\n  ) {\n    throw result.error\n  }\n\n  ;(client.getDefaultOptions().queries as any)?._experimental_afterQuery?.(\n    defaultedOptions,\n    result,\n  )\n\n  if (\n    defaultedOptions.experimental_prefetchInRender &&\n    !environmentManager.isServer() &&\n    willFetch(result, isRestoring)\n  ) {\n    const promise = isNewCacheEntry\n      ? // Fetch immediately on render in order to ensure `.promise` is resolved even if the component is unmounted\n        fetchOptimistic(defaultedOptions, observer, errorResetBoundary)\n      : // subscribe to the \"cache promise\" so that we can finalize the currentThenable once data comes in\n        query?.promise\n\n    promise?.catch(noop).finally(() => {\n      // `.updateResult()` will trigger `.#currentThenable` to finalize\n      observer.updateResult()\n    })\n  }\n\n  // Handle result property usage tracking\n  return !defaultedOptions.notifyOnChangeProps\n    ? observer.trackResult(result)\n    : result\n}\n"
  },
  {
    "path": "packages/react-query/src/useInfiniteQuery.ts",
    "content": "'use client'\nimport { InfiniteQueryObserver } from '@tanstack/query-core'\nimport { useBaseQuery } from './useBaseQuery'\nimport type {\n  DefaultError,\n  InfiniteData,\n  QueryClient,\n  QueryKey,\n  QueryObserver,\n} from '@tanstack/query-core'\nimport type {\n  DefinedUseInfiniteQueryResult,\n  UseInfiniteQueryOptions,\n  UseInfiniteQueryResult,\n} from './types'\nimport type {\n  DefinedInitialDataInfiniteOptions,\n  UndefinedInitialDataInfiniteOptions,\n} from './infiniteQueryOptions'\n\nexport function useInfiniteQuery<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: DefinedInitialDataInfiniteOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n  queryClient?: QueryClient,\n): DefinedUseInfiniteQueryResult<TData, TError>\n\nexport function useInfiniteQuery<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: UndefinedInitialDataInfiniteOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n  queryClient?: QueryClient,\n): UseInfiniteQueryResult<TData, TError>\n\nexport function useInfiniteQuery<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: UseInfiniteQueryOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n  queryClient?: QueryClient,\n): UseInfiniteQueryResult<TData, TError>\n\nexport function useInfiniteQuery(\n  options: UseInfiniteQueryOptions,\n  queryClient?: QueryClient,\n) {\n  return useBaseQuery(\n    options,\n    InfiniteQueryObserver as typeof QueryObserver,\n    queryClient,\n  )\n}\n"
  },
  {
    "path": "packages/react-query/src/useIsFetching.ts",
    "content": "'use client'\nimport * as React from 'react'\nimport { notifyManager } from '@tanstack/query-core'\n\nimport { useQueryClient } from './QueryClientProvider'\nimport type { QueryClient, QueryFilters } from '@tanstack/query-core'\n\nexport function useIsFetching(\n  filters?: QueryFilters,\n  queryClient?: QueryClient,\n): number {\n  const client = useQueryClient(queryClient)\n  const queryCache = client.getQueryCache()\n\n  return React.useSyncExternalStore(\n    React.useCallback(\n      (onStoreChange) =>\n        queryCache.subscribe(notifyManager.batchCalls(onStoreChange)),\n      [queryCache],\n    ),\n    () => client.isFetching(filters),\n    () => client.isFetching(filters),\n  )\n}\n"
  },
  {
    "path": "packages/react-query/src/useMutation.ts",
    "content": "'use client'\nimport * as React from 'react'\nimport {\n  MutationObserver,\n  noop,\n  notifyManager,\n  shouldThrowError,\n} from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport type {\n  UseMutateFunction,\n  UseMutationOptions,\n  UseMutationResult,\n} from './types'\nimport type { DefaultError, QueryClient } from '@tanstack/query-core'\n\n// HOOK\n\nexport function useMutation<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n>(\n  options: UseMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n  queryClient?: QueryClient,\n): UseMutationResult<TData, TError, TVariables, TOnMutateResult> {\n  const client = useQueryClient(queryClient)\n\n  const [observer] = React.useState(\n    () =>\n      new MutationObserver<TData, TError, TVariables, TOnMutateResult>(\n        client,\n        options,\n      ),\n  )\n\n  React.useEffect(() => {\n    observer.setOptions(options)\n  }, [observer, options])\n\n  const result = React.useSyncExternalStore(\n    React.useCallback(\n      (onStoreChange) =>\n        observer.subscribe(notifyManager.batchCalls(onStoreChange)),\n      [observer],\n    ),\n    () => observer.getCurrentResult(),\n    () => observer.getCurrentResult(),\n  )\n\n  const mutate = React.useCallback<\n    UseMutateFunction<TData, TError, TVariables, TOnMutateResult>\n  >(\n    (variables, mutateOptions) => {\n      observer.mutate(variables, mutateOptions).catch(noop)\n    },\n    [observer],\n  )\n\n  if (\n    result.error &&\n    shouldThrowError(observer.options.throwOnError, [result.error])\n  ) {\n    throw result.error\n  }\n\n  return { ...result, mutate, mutateAsync: result.mutate }\n}\n"
  },
  {
    "path": "packages/react-query/src/useMutationState.ts",
    "content": "'use client'\nimport * as React from 'react'\n\nimport { notifyManager, replaceEqualDeep } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport type {\n  Mutation,\n  MutationCache,\n  MutationFilters,\n  MutationState,\n  QueryClient,\n} from '@tanstack/query-core'\n\nexport function useIsMutating(\n  filters?: MutationFilters,\n  queryClient?: QueryClient,\n): number {\n  const client = useQueryClient(queryClient)\n  return useMutationState(\n    { filters: { ...filters, status: 'pending' } },\n    client,\n  ).length\n}\n\ntype MutationStateOptions<TResult = MutationState> = {\n  filters?: MutationFilters\n  select?: (mutation: Mutation) => TResult\n}\n\nfunction getResult<TResult = MutationState>(\n  mutationCache: MutationCache,\n  options: MutationStateOptions<TResult>,\n): Array<TResult> {\n  return mutationCache\n    .findAll(options.filters)\n    .map(\n      (mutation): TResult =>\n        (options.select ? options.select(mutation) : mutation.state) as TResult,\n    )\n}\n\nexport function useMutationState<TResult = MutationState>(\n  options: MutationStateOptions<TResult> = {},\n  queryClient?: QueryClient,\n): Array<TResult> {\n  const mutationCache = useQueryClient(queryClient).getMutationCache()\n  const optionsRef = React.useRef(options)\n  const result = React.useRef<Array<TResult>>(null)\n  if (result.current === null) {\n    result.current = getResult(mutationCache, options)\n  }\n\n  React.useEffect(() => {\n    optionsRef.current = options\n  })\n\n  return React.useSyncExternalStore(\n    React.useCallback(\n      (onStoreChange) =>\n        mutationCache.subscribe(() => {\n          const nextResult = replaceEqualDeep(\n            result.current,\n            getResult(mutationCache, optionsRef.current),\n          )\n          if (result.current !== nextResult) {\n            result.current = nextResult\n            notifyManager.schedule(onStoreChange)\n          }\n        }),\n      [mutationCache],\n    ),\n    () => result.current,\n    () => result.current,\n  )!\n}\n"
  },
  {
    "path": "packages/react-query/src/usePrefetchInfiniteQuery.tsx",
    "content": "import { useQueryClient } from './QueryClientProvider'\nimport type {\n  DefaultError,\n  FetchInfiniteQueryOptions,\n  QueryClient,\n  QueryKey,\n} from '@tanstack/query-core'\n\nexport function usePrefetchInfiniteQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: FetchInfiniteQueryOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n  queryClient?: QueryClient,\n) {\n  const client = useQueryClient(queryClient)\n\n  if (!client.getQueryState(options.queryKey)) {\n    client.prefetchInfiniteQuery(options)\n  }\n}\n"
  },
  {
    "path": "packages/react-query/src/usePrefetchQuery.tsx",
    "content": "import { useQueryClient } from './QueryClientProvider'\nimport type { DefaultError, QueryClient, QueryKey } from '@tanstack/query-core'\nimport type { UsePrefetchQueryOptions } from './types'\n\nexport function usePrefetchQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: UsePrefetchQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  queryClient?: QueryClient,\n) {\n  const client = useQueryClient(queryClient)\n\n  if (!client.getQueryState(options.queryKey)) {\n    client.prefetchQuery(options)\n  }\n}\n"
  },
  {
    "path": "packages/react-query/src/useQueries.ts",
    "content": "'use client'\nimport * as React from 'react'\n\nimport {\n  QueriesObserver,\n  QueryObserver,\n  noop,\n  notifyManager,\n} from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { useIsRestoring } from './IsRestoringProvider'\nimport { useQueryErrorResetBoundary } from './QueryErrorResetBoundary'\nimport {\n  ensurePreventErrorBoundaryRetry,\n  getHasError,\n  useClearResetErrorBoundary,\n} from './errorBoundaryUtils'\nimport {\n  ensureSuspenseTimers,\n  fetchOptimistic,\n  shouldSuspend,\n} from './suspense'\nimport type {\n  DefinedUseQueryResult,\n  UseQueryOptions,\n  UseQueryResult,\n} from './types'\nimport type {\n  DefaultError,\n  OmitKeyof,\n  QueriesObserverOptions,\n  QueriesPlaceholderDataFunction,\n  QueryClient,\n  QueryFunction,\n  QueryKey,\n  QueryObserverOptions,\n  ThrowOnError,\n} from '@tanstack/query-core'\n\n// This defines the `UseQueryOptions` that are accepted in `QueriesOptions` & `GetOptions`.\n// `placeholderData` function always gets undefined passed\ntype UseQueryOptionsForUseQueries<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = OmitKeyof<\n  UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  'placeholderData' | 'subscribed'\n> & {\n  placeholderData?: TQueryFnData | QueriesPlaceholderDataFunction<TQueryFnData>\n}\n\n// Avoid TS depth-limit error in case of large array literal\ntype MAXIMUM_DEPTH = 20\n\n// Widen the type of the symbol to enable type inference even if skipToken is not immutable.\ntype SkipTokenForUseQueries = symbol\n\ntype GetUseQueryOptionsForUseQueries<T> =\n  // Part 1: responsible for applying explicit type parameter to function arguments, if object { queryFnData: TQueryFnData, error: TError, data: TData }\n  T extends {\n    queryFnData: infer TQueryFnData\n    error?: infer TError\n    data: infer TData\n  }\n    ? UseQueryOptionsForUseQueries<TQueryFnData, TError, TData>\n    : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n      ? UseQueryOptionsForUseQueries<TQueryFnData, TError>\n      : T extends { data: infer TData; error?: infer TError }\n        ? UseQueryOptionsForUseQueries<unknown, TError, TData>\n        : // Part 2: responsible for applying explicit type parameter to function arguments, if tuple [TQueryFnData, TError, TData]\n          T extends [infer TQueryFnData, infer TError, infer TData]\n          ? UseQueryOptionsForUseQueries<TQueryFnData, TError, TData>\n          : T extends [infer TQueryFnData, infer TError]\n            ? UseQueryOptionsForUseQueries<TQueryFnData, TError>\n            : T extends [infer TQueryFnData]\n              ? UseQueryOptionsForUseQueries<TQueryFnData>\n              : // Part 3: responsible for inferring and enforcing type if no explicit parameter was provided\n                T extends {\n                    queryFn?:\n                      | QueryFunction<infer TQueryFnData, infer TQueryKey>\n                      | SkipTokenForUseQueries\n                    select?: (data: any) => infer TData\n                    throwOnError?: ThrowOnError<any, infer TError, any, any>\n                  }\n                ? UseQueryOptionsForUseQueries<\n                    TQueryFnData,\n                    unknown extends TError ? DefaultError : TError,\n                    unknown extends TData ? TQueryFnData : TData,\n                    TQueryKey\n                  >\n                : // Fallback\n                  UseQueryOptionsForUseQueries\n\n// A defined initialData setting should return a DefinedUseQueryResult rather than UseQueryResult\ntype GetDefinedOrUndefinedQueryResult<T, TData, TError = unknown> = T extends {\n  initialData?: infer TInitialData\n}\n  ? unknown extends TInitialData\n    ? UseQueryResult<TData, TError>\n    : TInitialData extends TData\n      ? DefinedUseQueryResult<TData, TError>\n      : TInitialData extends () => infer TInitialDataResult\n        ? unknown extends TInitialDataResult\n          ? UseQueryResult<TData, TError>\n          : TInitialDataResult extends TData\n            ? DefinedUseQueryResult<TData, TError>\n            : UseQueryResult<TData, TError>\n        : UseQueryResult<TData, TError>\n  : UseQueryResult<TData, TError>\n\ntype GetUseQueryResult<T> =\n  // Part 1: responsible for mapping explicit type parameter to function result, if object\n  T extends { queryFnData: any; error?: infer TError; data: infer TData }\n    ? GetDefinedOrUndefinedQueryResult<T, TData, TError>\n    : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n      ? GetDefinedOrUndefinedQueryResult<T, TQueryFnData, TError>\n      : T extends { data: infer TData; error?: infer TError }\n        ? GetDefinedOrUndefinedQueryResult<T, TData, TError>\n        : // Part 2: responsible for mapping explicit type parameter to function result, if tuple\n          T extends [any, infer TError, infer TData]\n          ? GetDefinedOrUndefinedQueryResult<T, TData, TError>\n          : T extends [infer TQueryFnData, infer TError]\n            ? GetDefinedOrUndefinedQueryResult<T, TQueryFnData, TError>\n            : T extends [infer TQueryFnData]\n              ? GetDefinedOrUndefinedQueryResult<T, TQueryFnData>\n              : // Part 3: responsible for mapping inferred type to results, if no explicit parameter was provided\n                T extends {\n                    queryFn?:\n                      | QueryFunction<infer TQueryFnData, any>\n                      | SkipTokenForUseQueries\n                    select?: (data: any) => infer TData\n                    throwOnError?: ThrowOnError<any, infer TError, any, any>\n                  }\n                ? GetDefinedOrUndefinedQueryResult<\n                    T,\n                    unknown extends TData ? TQueryFnData : TData,\n                    unknown extends TError ? DefaultError : TError\n                  >\n                : // Fallback\n                  UseQueryResult\n\n/**\n * QueriesOptions reducer recursively unwraps function arguments to infer/enforce type param\n */\nexport type QueriesOptions<\n  T extends Array<any>,\n  TResults extends Array<any> = [],\n  TDepth extends ReadonlyArray<number> = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n  ? Array<UseQueryOptionsForUseQueries>\n  : T extends []\n    ? []\n    : T extends [infer Head]\n      ? [...TResults, GetUseQueryOptionsForUseQueries<Head>]\n      : T extends [infer Head, ...infer Tails]\n        ? QueriesOptions<\n            [...Tails],\n            [...TResults, GetUseQueryOptionsForUseQueries<Head>],\n            [...TDepth, 1]\n          >\n        : ReadonlyArray<unknown> extends T\n          ? T\n          : // If T is *some* array but we couldn't assign unknown[] to it, then it must hold some known/homogenous type!\n            // use this to infer the param types in the case of Array.map() argument\n            T extends Array<\n                UseQueryOptionsForUseQueries<\n                  infer TQueryFnData,\n                  infer TError,\n                  infer TData,\n                  infer TQueryKey\n                >\n              >\n            ? Array<\n                UseQueryOptionsForUseQueries<\n                  TQueryFnData,\n                  TError,\n                  TData,\n                  TQueryKey\n                >\n              >\n            : // Fallback\n              Array<UseQueryOptionsForUseQueries>\n\n/**\n * QueriesResults reducer recursively maps type param to results\n */\nexport type QueriesResults<\n  T extends Array<any>,\n  TResults extends Array<any> = [],\n  TDepth extends ReadonlyArray<number> = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n  ? Array<UseQueryResult>\n  : T extends []\n    ? []\n    : T extends [infer Head]\n      ? [...TResults, GetUseQueryResult<Head>]\n      : T extends [infer Head, ...infer Tails]\n        ? QueriesResults<\n            [...Tails],\n            [...TResults, GetUseQueryResult<Head>],\n            [...TDepth, 1]\n          >\n        : { [K in keyof T]: GetUseQueryResult<T[K]> }\n\nexport function useQueries<\n  T extends Array<any>,\n  TCombinedResult = QueriesResults<T>,\n>(\n  {\n    queries,\n    ...options\n  }: {\n    queries:\n      | readonly [...QueriesOptions<T>]\n      | readonly [...{ [K in keyof T]: GetUseQueryOptionsForUseQueries<T[K]> }]\n    combine?: (result: QueriesResults<T>) => TCombinedResult\n    subscribed?: boolean\n  },\n  queryClient?: QueryClient,\n): TCombinedResult {\n  const client = useQueryClient(queryClient)\n  const isRestoring = useIsRestoring()\n  const errorResetBoundary = useQueryErrorResetBoundary()\n\n  const defaultedQueries = React.useMemo(\n    () =>\n      queries.map((opts) => {\n        const defaultedOptions = client.defaultQueryOptions(\n          opts as QueryObserverOptions,\n        )\n\n        // Make sure the results are already in fetching state before subscribing or updating options\n        defaultedOptions._optimisticResults = isRestoring\n          ? 'isRestoring'\n          : 'optimistic'\n\n        return defaultedOptions\n      }),\n    [queries, client, isRestoring],\n  )\n\n  defaultedQueries.forEach((queryOptions) => {\n    ensureSuspenseTimers(queryOptions)\n    const query = client.getQueryCache().get(queryOptions.queryHash)\n    ensurePreventErrorBoundaryRetry(queryOptions, errorResetBoundary, query)\n  })\n\n  useClearResetErrorBoundary(errorResetBoundary)\n\n  const [observer] = React.useState(\n    () =>\n      new QueriesObserver<TCombinedResult>(\n        client,\n        defaultedQueries,\n        options as QueriesObserverOptions<TCombinedResult>,\n      ),\n  )\n\n  // note: this must be called before useSyncExternalStore\n  const [optimisticResult, getCombinedResult, trackResult] =\n    observer.getOptimisticResult(\n      defaultedQueries,\n      (options as QueriesObserverOptions<TCombinedResult>).combine,\n    )\n\n  const shouldSubscribe = !isRestoring && options.subscribed !== false\n  React.useSyncExternalStore(\n    React.useCallback(\n      (onStoreChange) =>\n        shouldSubscribe\n          ? observer.subscribe(notifyManager.batchCalls(onStoreChange))\n          : noop,\n      [observer, shouldSubscribe],\n    ),\n    () => observer.getCurrentResult(),\n    () => observer.getCurrentResult(),\n  )\n\n  React.useEffect(() => {\n    observer.setQueries(\n      defaultedQueries,\n      options as QueriesObserverOptions<TCombinedResult>,\n    )\n  }, [defaultedQueries, options, observer])\n\n  const shouldAtLeastOneSuspend = optimisticResult.some((result, index) =>\n    shouldSuspend(defaultedQueries[index], result),\n  )\n\n  const suspensePromises = shouldAtLeastOneSuspend\n    ? optimisticResult.flatMap((result, index) => {\n        const opts = defaultedQueries[index]\n\n        if (opts && shouldSuspend(opts, result)) {\n          const queryObserver = new QueryObserver(client, opts)\n          return fetchOptimistic(opts, queryObserver, errorResetBoundary)\n        }\n        return []\n      })\n    : []\n\n  if (suspensePromises.length > 0) {\n    throw Promise.all(suspensePromises)\n  }\n  const firstSingleResultWhichShouldThrow = optimisticResult.find(\n    (result, index) => {\n      const query = defaultedQueries[index]\n      return (\n        query &&\n        getHasError({\n          result,\n          errorResetBoundary,\n          throwOnError: query.throwOnError,\n          query: client.getQueryCache().get(query.queryHash),\n          suspense: query.suspense,\n        })\n      )\n    },\n  )\n\n  if (firstSingleResultWhichShouldThrow?.error) {\n    throw firstSingleResultWhichShouldThrow.error\n  }\n\n  return getCombinedResult(trackResult())\n}\n"
  },
  {
    "path": "packages/react-query/src/useQuery.ts",
    "content": "'use client'\nimport { QueryObserver } from '@tanstack/query-core'\nimport { useBaseQuery } from './useBaseQuery'\nimport type {\n  DefaultError,\n  NoInfer,\n  QueryClient,\n  QueryKey,\n} from '@tanstack/query-core'\nimport type {\n  DefinedUseQueryResult,\n  UseQueryOptions,\n  UseQueryResult,\n} from './types'\nimport type {\n  DefinedInitialDataOptions,\n  UndefinedInitialDataOptions,\n} from './queryOptions'\n\nexport function useQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,\n  queryClient?: QueryClient,\n): DefinedUseQueryResult<NoInfer<TData>, TError>\n\nexport function useQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,\n  queryClient?: QueryClient,\n): UseQueryResult<NoInfer<TData>, TError>\n\nexport function useQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  queryClient?: QueryClient,\n): UseQueryResult<NoInfer<TData>, TError>\n\nexport function useQuery(options: UseQueryOptions, queryClient?: QueryClient) {\n  return useBaseQuery(options, QueryObserver, queryClient)\n}\n"
  },
  {
    "path": "packages/react-query/src/useSuspenseInfiniteQuery.ts",
    "content": "'use client'\nimport { InfiniteQueryObserver, skipToken } from '@tanstack/query-core'\nimport { useBaseQuery } from './useBaseQuery'\nimport { defaultThrowOnError } from './suspense'\nimport type {\n  DefaultError,\n  InfiniteData,\n  InfiniteQueryObserverSuccessResult,\n  QueryClient,\n  QueryKey,\n  QueryObserver,\n} from '@tanstack/query-core'\nimport type {\n  UseSuspenseInfiniteQueryOptions,\n  UseSuspenseInfiniteQueryResult,\n} from './types'\n\nexport function useSuspenseInfiniteQuery<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: UseSuspenseInfiniteQueryOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n  queryClient?: QueryClient,\n): UseSuspenseInfiniteQueryResult<TData, TError> {\n  if (process.env.NODE_ENV !== 'production') {\n    if ((options.queryFn as any) === skipToken) {\n      console.error('skipToken is not allowed for useSuspenseInfiniteQuery')\n    }\n  }\n\n  return useBaseQuery(\n    {\n      ...options,\n      enabled: true,\n      suspense: true,\n      throwOnError: defaultThrowOnError,\n    },\n    InfiniteQueryObserver as typeof QueryObserver,\n    queryClient,\n  ) as InfiniteQueryObserverSuccessResult<TData, TError>\n}\n"
  },
  {
    "path": "packages/react-query/src/useSuspenseQueries.ts",
    "content": "'use client'\nimport { skipToken } from '@tanstack/query-core'\nimport { useQueries } from './useQueries'\nimport { defaultThrowOnError } from './suspense'\nimport type { UseSuspenseQueryOptions, UseSuspenseQueryResult } from './types'\nimport type {\n  DefaultError,\n  QueryClient,\n  QueryFunction,\n  ThrowOnError,\n} from '@tanstack/query-core'\n\n// Avoid TS depth-limit error in case of large array literal\ntype MAXIMUM_DEPTH = 20\n\n// Widen the type of the symbol to enable type inference even if skipToken is not immutable.\ntype SkipTokenForUseQueries = symbol\n\ntype GetUseSuspenseQueryOptions<T> =\n  // Part 1: responsible for applying explicit type parameter to function arguments, if object { queryFnData: TQueryFnData, error: TError, data: TData }\n  T extends {\n    queryFnData: infer TQueryFnData\n    error?: infer TError\n    data: infer TData\n  }\n    ? UseSuspenseQueryOptions<TQueryFnData, TError, TData>\n    : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n      ? UseSuspenseQueryOptions<TQueryFnData, TError>\n      : T extends { data: infer TData; error?: infer TError }\n        ? UseSuspenseQueryOptions<unknown, TError, TData>\n        : // Part 2: responsible for applying explicit type parameter to function arguments, if tuple [TQueryFnData, TError, TData]\n          T extends [infer TQueryFnData, infer TError, infer TData]\n          ? UseSuspenseQueryOptions<TQueryFnData, TError, TData>\n          : T extends [infer TQueryFnData, infer TError]\n            ? UseSuspenseQueryOptions<TQueryFnData, TError>\n            : T extends [infer TQueryFnData]\n              ? UseSuspenseQueryOptions<TQueryFnData>\n              : // Part 3: responsible for inferring and enforcing type if no explicit parameter was provided\n                T extends {\n                    queryFn?:\n                      | QueryFunction<infer TQueryFnData, infer TQueryKey>\n                      | SkipTokenForUseQueries\n                    select?: (data: any) => infer TData\n                    throwOnError?: ThrowOnError<any, infer TError, any, any>\n                  }\n                ? UseSuspenseQueryOptions<\n                    TQueryFnData,\n                    TError,\n                    TData,\n                    TQueryKey\n                  >\n                : T extends {\n                      queryFn?:\n                        | QueryFunction<infer TQueryFnData, infer TQueryKey>\n                        | SkipTokenForUseQueries\n                      throwOnError?: ThrowOnError<any, infer TError, any, any>\n                    }\n                  ? UseSuspenseQueryOptions<\n                      TQueryFnData,\n                      TError,\n                      TQueryFnData,\n                      TQueryKey\n                    >\n                  : // Fallback\n                    UseSuspenseQueryOptions\n\ntype GetUseSuspenseQueryResult<T> =\n  // Part 1: responsible for mapping explicit type parameter to function result, if object\n  T extends { queryFnData: any; error?: infer TError; data: infer TData }\n    ? UseSuspenseQueryResult<TData, TError>\n    : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n      ? UseSuspenseQueryResult<TQueryFnData, TError>\n      : T extends { data: infer TData; error?: infer TError }\n        ? UseSuspenseQueryResult<TData, TError>\n        : // Part 2: responsible for mapping explicit type parameter to function result, if tuple\n          T extends [any, infer TError, infer TData]\n          ? UseSuspenseQueryResult<TData, TError>\n          : T extends [infer TQueryFnData, infer TError]\n            ? UseSuspenseQueryResult<TQueryFnData, TError>\n            : T extends [infer TQueryFnData]\n              ? UseSuspenseQueryResult<TQueryFnData>\n              : // Part 3: responsible for mapping inferred type to results, if no explicit parameter was provided\n                T extends {\n                    queryFn?:\n                      | QueryFunction<infer TQueryFnData, any>\n                      | SkipTokenForUseQueries\n                    select?: (data: any) => infer TData\n                    throwOnError?: ThrowOnError<any, infer TError, any, any>\n                  }\n                ? UseSuspenseQueryResult<\n                    unknown extends TData ? TQueryFnData : TData,\n                    unknown extends TError ? DefaultError : TError\n                  >\n                : T extends {\n                      queryFn?:\n                        | QueryFunction<infer TQueryFnData, any>\n                        | SkipTokenForUseQueries\n                      throwOnError?: ThrowOnError<any, infer TError, any, any>\n                    }\n                  ? UseSuspenseQueryResult<\n                      TQueryFnData,\n                      unknown extends TError ? DefaultError : TError\n                    >\n                  : // Fallback\n                    UseSuspenseQueryResult\n\n/**\n * SuspenseQueriesOptions reducer recursively unwraps function arguments to infer/enforce type param\n */\nexport type SuspenseQueriesOptions<\n  T extends Array<any>,\n  TResults extends Array<any> = [],\n  TDepth extends ReadonlyArray<number> = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n  ? Array<UseSuspenseQueryOptions>\n  : T extends []\n    ? []\n    : T extends [infer Head]\n      ? [...TResults, GetUseSuspenseQueryOptions<Head>]\n      : T extends [infer Head, ...infer Tails]\n        ? SuspenseQueriesOptions<\n            [...Tails],\n            [...TResults, GetUseSuspenseQueryOptions<Head>],\n            [...TDepth, 1]\n          >\n        : Array<unknown> extends T\n          ? T\n          : // If T is *some* array but we couldn't assign unknown[] to it, then it must hold some known/homogenous type!\n            // use this to infer the param types in the case of Array.map() argument\n            T extends Array<\n                UseSuspenseQueryOptions<\n                  infer TQueryFnData,\n                  infer TError,\n                  infer TData,\n                  infer TQueryKey\n                >\n              >\n            ? Array<\n                UseSuspenseQueryOptions<TQueryFnData, TError, TData, TQueryKey>\n              >\n            : // Fallback\n              Array<UseSuspenseQueryOptions>\n\n/**\n * SuspenseQueriesResults reducer recursively maps type param to results\n */\nexport type SuspenseQueriesResults<\n  T extends Array<any>,\n  TResults extends Array<any> = [],\n  TDepth extends ReadonlyArray<number> = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n  ? Array<UseSuspenseQueryResult>\n  : T extends []\n    ? []\n    : T extends [infer Head]\n      ? [...TResults, GetUseSuspenseQueryResult<Head>]\n      : T extends [infer Head, ...infer Tails]\n        ? SuspenseQueriesResults<\n            [...Tails],\n            [...TResults, GetUseSuspenseQueryResult<Head>],\n            [...TDepth, 1]\n          >\n        : { [K in keyof T]: GetUseSuspenseQueryResult<T[K]> }\n\nexport function useSuspenseQueries<\n  T extends Array<any>,\n  TCombinedResult = SuspenseQueriesResults<T>,\n>(\n  options: {\n    queries:\n      | readonly [...SuspenseQueriesOptions<T>]\n      | readonly [...{ [K in keyof T]: GetUseSuspenseQueryOptions<T[K]> }]\n    combine?: (result: SuspenseQueriesResults<T>) => TCombinedResult\n  },\n  queryClient?: QueryClient,\n): TCombinedResult\n\nexport function useSuspenseQueries<\n  T extends Array<any>,\n  TCombinedResult = SuspenseQueriesResults<T>,\n>(\n  options: {\n    queries: readonly [...SuspenseQueriesOptions<T>]\n    combine?: (result: SuspenseQueriesResults<T>) => TCombinedResult\n  },\n  queryClient?: QueryClient,\n): TCombinedResult\n\nexport function useSuspenseQueries(options: any, queryClient?: QueryClient) {\n  return useQueries(\n    {\n      ...options,\n      queries: options.queries.map((query: any) => {\n        if (process.env.NODE_ENV !== 'production') {\n          if (query.queryFn === skipToken) {\n            console.error('skipToken is not allowed for useSuspenseQueries')\n          }\n        }\n\n        return {\n          ...query,\n          suspense: true,\n          throwOnError: defaultThrowOnError,\n          enabled: true,\n          placeholderData: undefined,\n        }\n      }),\n    },\n    queryClient,\n  )\n}\n"
  },
  {
    "path": "packages/react-query/src/useSuspenseQuery.ts",
    "content": "'use client'\nimport { QueryObserver, skipToken } from '@tanstack/query-core'\nimport { useBaseQuery } from './useBaseQuery'\nimport { defaultThrowOnError } from './suspense'\nimport type { UseSuspenseQueryOptions, UseSuspenseQueryResult } from './types'\nimport type { DefaultError, QueryClient, QueryKey } from '@tanstack/query-core'\n\nexport function useSuspenseQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: UseSuspenseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  queryClient?: QueryClient,\n): UseSuspenseQueryResult<TData, TError> {\n  if (process.env.NODE_ENV !== 'production') {\n    if ((options.queryFn as any) === skipToken) {\n      console.error('skipToken is not allowed for useSuspenseQuery')\n    }\n  }\n\n  return useBaseQuery(\n    {\n      ...options,\n      enabled: true,\n      suspense: true,\n      throwOnError: defaultThrowOnError,\n      placeholderData: undefined,\n    },\n    QueryObserver,\n    queryClient,\n  ) as UseSuspenseQueryResult<TData, TError>\n}\n"
  },
  {
    "path": "packages/react-query/test-setup.ts",
    "content": "import '@testing-library/jest-dom/vitest'\nimport { act, cleanup as cleanupRTL } from '@testing-library/react'\nimport { cleanup as cleanupRRS } from '@testing-library/react-render-stream'\nimport { afterEach } from 'vitest'\nimport { notifyManager } from '@tanstack/query-core'\n\n// https://testing-library.com/docs/react-testing-library/api#cleanup\nafterEach(() => {\n  cleanupRTL()\n  cleanupRRS()\n})\n\n// Wrap notifications with act to make sure React knows about React Query updates\nnotifyManager.setNotifyFunction((fn) => {\n  act(fn)\n})\n"
  },
  {
    "path": "packages/react-query/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\",\n    \"jsx\": \"react-jsx\"\n  },\n  \"include\": [\"src\", \"test-setup.ts\", \"*.config.*\", \"package.json\"]\n}\n"
  },
  {
    "path": "packages/react-query/tsconfig.legacy.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"jsx\": \"react-jsx\",\n    \"outDir\": \"./dist-ts/legacy\"\n  },\n  \"include\": [\"src\"],\n  \"exclude\": [\"src/__tests__\"],\n  \"references\": [{ \"path\": \"../query-persist-client-core\" }]\n}\n"
  },
  {
    "path": "packages/react-query/tsconfig.prod.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"incremental\": false,\n    \"composite\": false,\n    \"rootDir\": \"../../\"\n  }\n}\n"
  },
  {
    "path": "packages/react-query/tsup.config.ts",
    "content": "import { defineConfig } from 'tsup'\nimport { legacyConfig, modernConfig } from './root.tsup.config.js'\n\nexport default defineConfig([\n  modernConfig({ entry: ['src/*.ts', 'src/*.tsx'] }),\n  legacyConfig({ entry: ['src/*.ts', 'src/*.tsx'] }),\n])\n"
  },
  {
    "path": "packages/react-query/vite.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\nimport react from '@vitejs/plugin-react'\n\nimport packageJson from './package.json'\n\nexport default defineConfig({\n  plugins: [react()],\n  // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660\n  resolve: {\n    conditions: ['@tanstack/custom-condition'],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        conditions: ['@tanstack/custom-condition'],\n      },\n    },\n  },\n  test: {\n    name: packageJson.name,\n    dir: './src',\n    watch: false,\n    environment: 'jsdom',\n    setupFiles: ['test-setup.ts'],\n    coverage: {\n      enabled: true,\n      provider: 'istanbul',\n      include: ['src/**/*'],\n      exclude: ['src/__tests__/**'],\n    },\n    typecheck: { enabled: true },\n    restoreMocks: true,\n    retry: process.env.CI ? 3 : 0,\n  },\n})\n"
  },
  {
    "path": "packages/react-query-devtools/.attw.json",
    "content": "{\n  \"ignoreRules\": [\"no-resolution\"]\n}\n"
  },
  {
    "path": "packages/react-query-devtools/CHANGELOG.md",
    "content": "# @tanstack/react-query-devtools\n\n## 5.91.3\n\n### Patch Changes\n\n- Updated dependencies [[`83366c4`](https://github.com/TanStack/query/commit/83366c46a6825b5c591399c705d8128743c527dd)]:\n  - @tanstack/query-devtools@5.93.0\n\n## 5.91.2\n\n### Patch Changes\n\n- Updated dependencies [[`f9fc56a`](https://github.com/TanStack/query/commit/f9fc56a9b8724bcfae46f8f6cb229123478eb4db), [`0b29b6f`](https://github.com/TanStack/query/commit/0b29b6f877d4b3a6d05b1c85fb9cb1e6ea736291)]:\n  - @tanstack/query-devtools@5.92.0\n  - @tanstack/react-query@5.90.14\n\n## 5.91.1\n\n### Patch Changes\n\n- Updated dependencies [[`b261b6f`](https://github.com/TanStack/query/commit/b261b6f29eee2a9bdbe1bc20035fe9b83b15376b)]:\n  - @tanstack/query-devtools@5.91.1\n\n## 5.91.0\n\n### Minor Changes\n\n- feat(devtools): allow passing a theme via prop ([#9887](https://github.com/TanStack/query/pull/9887))\n\n### Patch Changes\n\n- Updated dependencies [[`0e9d5b5`](https://github.com/TanStack/query/commit/0e9d5b565276f0de2a1a14ffbb079b5988581c27)]:\n  - @tanstack/query-devtools@5.91.0\n"
  },
  {
    "path": "packages/react-query-devtools/eslint.config.js",
    "content": "// @ts-check\n\nimport pluginReact from '@eslint-react/eslint-plugin'\nimport reactHooks from 'eslint-plugin-react-hooks'\nimport rootConfig from './root.eslint.config.js'\n\nexport default [\n  ...rootConfig,\n  // @ts-expect-error wtf\n  ...reactHooks.configs['recommended-latest'],\n  {\n    files: ['**/*.{ts,tsx}'],\n    ...pluginReact.configs.recommended,\n    rules: {\n      '@eslint-react/no-context-provider': 'off', // We need to be React 18 compatible\n      'react-hooks/exhaustive-deps': 'error',\n      'react-hooks/rules-of-hooks': 'error',\n      'react-hooks/unsupported-syntax': 'error',\n      'react-hooks/incompatible-library': 'error',\n    },\n  },\n]\n"
  },
  {
    "path": "packages/react-query-devtools/package.json",
    "content": "{\n  \"name\": \"@tanstack/react-query-devtools\",\n  \"version\": \"5.91.3\",\n  \"description\": \"Developer tools to interact with and visualize the TanStack/react-query cache\",\n  \"author\": \"tannerlinsley\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/react-query-devtools\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"scripts\": {\n    \"clean\": \"premove ./build ./coverage ./dist-ts\",\n    \"compile\": \"tsc --build\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:types\": \"npm-run-all --serial test:types:*\",\n    \"test:types:ts54\": \"node ../../node_modules/typescript54/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts55\": \"node ../../node_modules/typescript55/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts56\": \"node ../../node_modules/typescript56/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts57\": \"node ../../node_modules/typescript57/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts58\": \"node ../../node_modules/typescript58/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts59\": \"node ../../node_modules/typescript59/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:tscurrent\": \"tsc --build\",\n    \"test:types:ts60\": \"node ../../node_modules/typescript60/lib/tsc.js --build\",\n    \"test:lib\": \"vitest\",\n    \"test:lib:dev\": \"pnpm run test:lib --watch\",\n    \"test:build\": \"publint --strict && attw --pack\",\n    \"build\": \"tsup --tsconfig tsconfig.prod.json\",\n    \"build:dev\": \"tsup --watch\"\n  },\n  \"type\": \"module\",\n  \"types\": \"build/legacy/index.d.ts\",\n  \"main\": \"build/legacy/index.cjs\",\n  \"module\": \"build/legacy/index.js\",\n  \"exports\": {\n    \".\": {\n      \"@tanstack/custom-condition\": \"./src/index.ts\",\n      \"import\": {\n        \"types\": \"./build/modern/index.d.ts\",\n        \"default\": \"./build/modern/index.js\"\n      },\n      \"require\": {\n        \"types\": \"./build/modern/index.d.cts\",\n        \"default\": \"./build/modern/index.cjs\"\n      }\n    },\n    \"./production\": {\n      \"import\": {\n        \"types\": \"./build/modern/production.d.ts\",\n        \"default\": \"./build/modern/production.js\"\n      },\n      \"require\": {\n        \"types\": \"./build/modern/production.d.cts\",\n        \"default\": \"./build/modern/production.cjs\"\n      }\n    },\n    \"./build/modern/production.js\": {\n      \"import\": {\n        \"types\": \"./build/modern/production.d.ts\",\n        \"default\": \"./build/modern/production.js\"\n      },\n      \"require\": {\n        \"types\": \"./build/modern/production.d.cts\",\n        \"default\": \"./build/modern/production.cjs\"\n      }\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"sideEffects\": false,\n  \"files\": [\n    \"build\",\n    \"src\",\n    \"!src/__tests__\"\n  ],\n  \"dependencies\": {\n    \"@tanstack/query-devtools\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"@tanstack/react-query\": \"workspace:*\",\n    \"@testing-library/react\": \"^16.1.0\",\n    \"@types/react\": \"^19.2.7\",\n    \"@vitejs/plugin-react\": \"^4.3.4\",\n    \"npm-run-all2\": \"^5.0.0\",\n    \"react\": \"^19.2.1\"\n  },\n  \"peerDependencies\": {\n    \"@tanstack/react-query\": \"workspace:^\",\n    \"react\": \"^18 || ^19\"\n  }\n}\n"
  },
  {
    "path": "packages/react-query-devtools/src/ReactQueryDevtools.tsx",
    "content": "'use client'\nimport * as React from 'react'\nimport { onlineManager, useQueryClient } from '@tanstack/react-query'\nimport { TanstackQueryDevtools } from '@tanstack/query-devtools'\nimport type {\n  DevtoolsButtonPosition,\n  DevtoolsErrorType,\n  DevtoolsPosition,\n  Theme,\n} from '@tanstack/query-devtools'\nimport type { QueryClient } from '@tanstack/react-query'\n\nexport interface DevtoolsOptions {\n  /**\n   * Set this true if you want the dev tools to default to being open\n   */\n  initialIsOpen?: boolean\n  /**\n   * The position of the React Query logo to open and close the devtools panel.\n   * 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'\n   * Defaults to 'bottom-right'.\n   */\n  buttonPosition?: DevtoolsButtonPosition\n  /**\n   * The position of the React Query devtools panel.\n   * 'top' | 'bottom' | 'left' | 'right'\n   * Defaults to 'bottom'.\n   */\n  position?: DevtoolsPosition\n  /**\n   * Custom instance of QueryClient\n   */\n  client?: QueryClient\n  /**\n   * Use this so you can define custom errors that can be shown in the devtools.\n   */\n  errorTypes?: Array<DevtoolsErrorType>\n  /**\n   * 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.\n   */\n  styleNonce?: string\n  /**\n   * Use this so you can attach the devtool's styles to specific element in the DOM.\n   */\n  shadowDOMTarget?: ShadowRoot\n  /**\n   * Set this to true to hide disabled queries from the devtools panel.\n   */\n  hideDisabledQueries?: boolean\n  /**\n   * Set this to 'light', 'dark', or 'system' to change the theme of the devtools panel.\n   * Defaults to 'system'.\n   */\n  theme?: Theme\n}\n\nexport function ReactQueryDevtools(\n  props: DevtoolsOptions,\n): React.ReactElement | null {\n  const queryClient = useQueryClient(props.client)\n  const ref = React.useRef<HTMLDivElement>(null)\n  const {\n    buttonPosition,\n    position,\n    initialIsOpen,\n    errorTypes,\n    styleNonce,\n    shadowDOMTarget,\n    hideDisabledQueries,\n    theme,\n  } = props\n  const [devtools] = React.useState(\n    new TanstackQueryDevtools({\n      client: queryClient,\n      queryFlavor: 'React Query',\n      version: '5',\n      onlineManager,\n      buttonPosition,\n      position,\n      initialIsOpen,\n      errorTypes,\n      styleNonce,\n      shadowDOMTarget,\n      hideDisabledQueries,\n      theme,\n    }),\n  )\n\n  React.useEffect(() => {\n    devtools.setClient(queryClient)\n  }, [queryClient, devtools])\n\n  React.useEffect(() => {\n    if (buttonPosition) {\n      devtools.setButtonPosition(buttonPosition)\n    }\n  }, [buttonPosition, devtools])\n\n  React.useEffect(() => {\n    if (position) {\n      devtools.setPosition(position)\n    }\n  }, [position, devtools])\n\n  React.useEffect(() => {\n    devtools.setInitialIsOpen(initialIsOpen || false)\n  }, [initialIsOpen, devtools])\n\n  React.useEffect(() => {\n    devtools.setErrorTypes(errorTypes || [])\n  }, [errorTypes, devtools])\n\n  React.useEffect(() => {\n    devtools.setTheme(theme)\n  }, [theme, devtools])\n\n  React.useEffect(() => {\n    if (ref.current) {\n      devtools.mount(ref.current)\n    }\n\n    return () => {\n      devtools.unmount()\n    }\n  }, [devtools])\n\n  return <div dir=\"ltr\" className=\"tsqd-parent-container\" ref={ref}></div>\n}\n"
  },
  {
    "path": "packages/react-query-devtools/src/ReactQueryDevtoolsPanel.tsx",
    "content": "'use client'\nimport * as React from 'react'\nimport { onlineManager, useQueryClient } from '@tanstack/react-query'\nimport { TanstackQueryDevtoolsPanel } from '@tanstack/query-devtools'\nimport type { DevtoolsErrorType, Theme } from '@tanstack/query-devtools'\nimport type { QueryClient } from '@tanstack/react-query'\n\nexport interface DevtoolsPanelOptions {\n  /**\n   * Custom instance of QueryClient\n   */\n  client?: QueryClient\n  /**\n   * Use this so you can define custom errors that can be shown in the devtools.\n   */\n  errorTypes?: Array<DevtoolsErrorType>\n  /**\n   * 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.\n   */\n  styleNonce?: string\n  /**\n   * Use this so you can attach the devtool's styles to specific element in the DOM.\n   */\n  shadowDOMTarget?: ShadowRoot\n\n  /**\n   * Custom styles for the devtools panel\n   * @default { height: '500px' }\n   * @example { height: '100%' }\n   * @example { height: '100%', width: '100%' }\n   */\n  style?: React.CSSProperties\n\n  /**\n   * Callback function that is called when the devtools panel is closed\n   */\n  onClose?: () => unknown\n  /**\n   * Set this to true to hide disabled queries from the devtools panel.\n   */\n  hideDisabledQueries?: boolean\n  /**\n   * Set this to 'light', 'dark', or 'system' to change the theme of the devtools panel.\n   * Defaults to 'system'.\n   */\n  theme?: Theme\n}\n\nexport function ReactQueryDevtoolsPanel(\n  props: DevtoolsPanelOptions,\n): React.ReactElement | null {\n  const queryClient = useQueryClient(props.client)\n  const ref = React.useRef<HTMLDivElement>(null)\n  const {\n    errorTypes,\n    styleNonce,\n    shadowDOMTarget,\n    hideDisabledQueries,\n    theme,\n  } = props\n  const [devtools] = React.useState(\n    new TanstackQueryDevtoolsPanel({\n      client: queryClient,\n      queryFlavor: 'React Query',\n      version: '5',\n      onlineManager,\n      buttonPosition: 'bottom-left',\n      position: 'bottom',\n      initialIsOpen: true,\n      errorTypes,\n      styleNonce,\n      shadowDOMTarget,\n      onClose: props.onClose,\n      hideDisabledQueries,\n      theme,\n    }),\n  )\n\n  React.useEffect(() => {\n    devtools.setClient(queryClient)\n  }, [queryClient, devtools])\n\n  React.useEffect(() => {\n    devtools.setOnClose(props.onClose ?? (() => {}))\n  }, [props.onClose, devtools])\n\n  React.useEffect(() => {\n    devtools.setErrorTypes(errorTypes || [])\n  }, [errorTypes, devtools])\n\n  React.useEffect(() => {\n    devtools.setTheme(theme)\n  }, [theme, devtools])\n\n  React.useEffect(() => {\n    if (ref.current) {\n      devtools.mount(ref.current)\n    }\n\n    return () => {\n      devtools.unmount()\n    }\n  }, [devtools])\n\n  return (\n    <div\n      style={{ height: '500px', ...props.style }}\n      className=\"tsqd-parent-container\"\n      ref={ref}\n    ></div>\n  )\n}\n"
  },
  {
    "path": "packages/react-query-devtools/src/__tests__/devtools.test.tsx",
    "content": "import { describe, expect, it } from 'vitest'\n\ndescribe('ReactQueryDevtools', () => {\n  it('should be able to open and close devtools', () => {\n    expect(1).toBe(1)\n  })\n})\n"
  },
  {
    "path": "packages/react-query-devtools/src/__tests__/not-development.test.tsx",
    "content": "import { describe, expect, it } from 'vitest'\nimport { ReactQueryDevtools } from '..'\n\ndescribe('ReactQueryDevtools not in process.env.NODE_ENV=development', () => {\n  it('should return null', () => {\n    expect(process.env.NODE_ENV).not.toBe('development')\n    expect(ReactQueryDevtools({})).toBeNull()\n  })\n})\n"
  },
  {
    "path": "packages/react-query-devtools/src/index.ts",
    "content": "'use client'\n\nimport * as Devtools from './ReactQueryDevtools'\nimport * as DevtoolsPanel from './ReactQueryDevtoolsPanel'\n\nexport const ReactQueryDevtools: (typeof Devtools)['ReactQueryDevtools'] =\n  process.env.NODE_ENV !== 'development'\n    ? function () {\n        return null\n      }\n    : Devtools.ReactQueryDevtools\n\nexport const ReactQueryDevtoolsPanel: (typeof DevtoolsPanel)['ReactQueryDevtoolsPanel'] =\n  process.env.NODE_ENV !== 'development'\n    ? function () {\n        return null\n      }\n    : DevtoolsPanel.ReactQueryDevtoolsPanel\n\nexport type DevtoolsPanelOptions = DevtoolsPanel.DevtoolsPanelOptions\n"
  },
  {
    "path": "packages/react-query-devtools/src/production.ts",
    "content": "'use client'\n\nimport * as Devtools from './ReactQueryDevtools'\nimport * as DevtoolsPanel from './ReactQueryDevtoolsPanel'\n\nexport const ReactQueryDevtools = Devtools.ReactQueryDevtools\nexport const ReactQueryDevtoolsPanel = DevtoolsPanel.ReactQueryDevtoolsPanel\n"
  },
  {
    "path": "packages/react-query-devtools/test-setup.ts",
    "content": "import '@testing-library/jest-dom/vitest'\nimport { act, cleanup } from '@testing-library/react'\nimport { afterEach } from 'vitest'\nimport { notifyManager } from '@tanstack/react-query'\n\n// https://testing-library.com/docs/react-testing-library/api#cleanup\nafterEach(() => cleanup())\n\n// Wrap notifications with act to make sure React knows about React Query updates\nnotifyManager.setNotifyFunction((fn) => {\n  act(fn)\n})\n"
  },
  {
    "path": "packages/react-query-devtools/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\",\n    \"jsx\": \"react-jsx\"\n  },\n  \"include\": [\"src\", \"test-setup.ts\", \"*.config.*\", \"package.json\"],\n  \"references\": [{ \"path\": \"../query-devtools\" }, { \"path\": \"../react-query\" }]\n}\n"
  },
  {
    "path": "packages/react-query-devtools/tsconfig.legacy.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"jsx\": \"react-jsx\",\n    \"outDir\": \"./dist-ts/legacy\"\n  },\n  \"include\": [\"src\"],\n  \"exclude\": [\"src/__tests__\"],\n  \"references\": [{ \"path\": \"../query-devtools\" }, { \"path\": \"../react-query\" }]\n}\n"
  },
  {
    "path": "packages/react-query-devtools/tsconfig.prod.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"incremental\": false,\n    \"composite\": false,\n    \"rootDir\": \"../../\",\n    \"customConditions\": []\n  }\n}\n"
  },
  {
    "path": "packages/react-query-devtools/tsup.config.ts",
    "content": "import { defineConfig } from 'tsup'\nimport { legacyConfig, modernConfig } from './root.tsup.config.js'\n\nexport default defineConfig([\n  modernConfig({ entry: ['src/*.ts', 'src/*.tsx'] }),\n  legacyConfig({ entry: ['src/*.ts', 'src/*.tsx'] }),\n])\n"
  },
  {
    "path": "packages/react-query-devtools/vite.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\nimport react from '@vitejs/plugin-react'\n\nimport packageJson from './package.json'\n\nexport default defineConfig({\n  plugins: [react()],\n  // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660\n  resolve: {\n    conditions: ['@tanstack/custom-condition'],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        conditions: ['@tanstack/custom-condition'],\n      },\n    },\n  },\n  test: {\n    name: packageJson.name,\n    dir: './src',\n    watch: false,\n    environment: 'jsdom',\n    setupFiles: ['test-setup.ts'],\n    coverage: {\n      enabled: true,\n      provider: 'istanbul',\n      include: ['src/**/*'],\n      exclude: ['src/__tests__/**'],\n    },\n    typecheck: { enabled: true },\n    restoreMocks: true,\n  },\n})\n"
  },
  {
    "path": "packages/react-query-next-experimental/CHANGELOG.md",
    "content": "# @tanstack/react-query-next-experimental\n\n## 5.91.0\n\n### Minor Changes\n\n- feat(react-query-next-experimental): support Next.js 16 ([#9868](https://github.com/TanStack/query/pull/9868))\n"
  },
  {
    "path": "packages/react-query-next-experimental/eslint.config.js",
    "content": "// @ts-check\n\nimport pluginReact from '@eslint-react/eslint-plugin'\nimport reactHooks from 'eslint-plugin-react-hooks'\nimport rootConfig from './root.eslint.config.js'\n\nexport default [\n  ...rootConfig,\n  // @ts-expect-error wtf\n  ...reactHooks.configs['recommended-latest'],\n  {\n    files: ['**/*.{ts,tsx}'],\n    ...pluginReact.configs.recommended,\n    rules: {\n      '@eslint-react/no-context-provider': 'off', // We need to be React 18 compatible\n      'react-hooks/exhaustive-deps': 'error',\n      'react-hooks/rules-of-hooks': 'error',\n      'react-hooks/unsupported-syntax': 'error',\n      'react-hooks/incompatible-library': 'error',\n    },\n  },\n]\n"
  },
  {
    "path": "packages/react-query-next-experimental/package.json",
    "content": "{\n  \"name\": \"@tanstack/react-query-next-experimental\",\n  \"version\": \"5.91.0\",\n  \"description\": \"Hydration utils for React Query in the NextJs app directory\",\n  \"author\": \"tannerlinsley\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/react-query-next-experimental\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"scripts\": {\n    \"clean\": \"premove ./build ./coverage ./dist-ts\",\n    \"compile\": \"tsc --build\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:types\": \"npm-run-all --serial test:types:*\",\n    \"test:types:ts54\": \"node ../../node_modules/typescript54/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts55\": \"node ../../node_modules/typescript55/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts56\": \"node ../../node_modules/typescript56/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts57\": \"node ../../node_modules/typescript57/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts58\": \"node ../../node_modules/typescript58/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts59\": \"node ../../node_modules/typescript59/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:tscurrent\": \"tsc --build\",\n    \"test:types:ts60\": \"node ../../node_modules/typescript60/lib/tsc.js --build\",\n    \"test:build\": \"publint --strict && attw --pack\",\n    \"build\": \"tsup --tsconfig tsconfig.prod.json\"\n  },\n  \"type\": \"module\",\n  \"types\": \"build/legacy/index.d.ts\",\n  \"main\": \"build/legacy/index.cjs\",\n  \"module\": \"build/legacy/index.js\",\n  \"exports\": {\n    \".\": {\n      \"@tanstack/custom-condition\": \"./src/index.ts\",\n      \"import\": {\n        \"types\": \"./build/modern/index.d.ts\",\n        \"default\": \"./build/modern/index.js\"\n      },\n      \"require\": {\n        \"types\": \"./build/modern/index.d.cts\",\n        \"default\": \"./build/modern/index.cjs\"\n      }\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"sideEffects\": false,\n  \"files\": [\n    \"build\",\n    \"src\",\n    \"!src/__tests__\"\n  ],\n  \"devDependencies\": {\n    \"@tanstack/react-query\": \"workspace:*\",\n    \"@types/react\": \"^19.2.7\",\n    \"@vitejs/plugin-react\": \"^4.3.4\",\n    \"next\": \"^16.0.1\",\n    \"npm-run-all2\": \"^5.0.0\",\n    \"react\": \"^19.2.1\"\n  },\n  \"peerDependencies\": {\n    \"@tanstack/react-query\": \"workspace:^\",\n    \"next\": \"^13 || ^14 || ^15 || ^16\",\n    \"react\": \"^18 || ^19\"\n  }\n}\n"
  },
  {
    "path": "packages/react-query-next-experimental/src/HydrationStreamProvider.tsx",
    "content": "'use client'\n\nimport { isServer } from '@tanstack/react-query'\nimport { useServerInsertedHTML } from 'next/navigation'\nimport * as React from 'react'\nimport { htmlEscapeJsonString } from './htmlescape'\n\nconst serializedSymbol = Symbol('serialized')\n\ninterface DataTransformer {\n  serialize: (object: any) => any\n  deserialize: (object: any) => any\n}\n\ntype Serialized<TData> = unknown & {\n  [serializedSymbol]: TData\n}\n\ninterface TypedDataTransformer<TData> {\n  serialize: (obj: TData) => Serialized<TData>\n  deserialize: (obj: Serialized<TData>) => TData\n}\n\ninterface HydrationStreamContext<TShape> {\n  id: string\n  stream: {\n    /**\n     * **Server method**\n     * Push a new entry to the stream\n     * Will be ignored on the client\n     */\n    push: (...shape: Array<TShape>) => void\n  }\n}\n\nexport interface HydrationStreamProviderProps<TShape> {\n  children: React.ReactNode\n  /**\n   * Optional transformer to serialize/deserialize the data\n   * Example devalue, superjson et al\n   */\n  transformer?: DataTransformer\n  /**\n   * **Client method**\n   * Called in the browser when new entries are received\n   */\n  onEntries: (entries: Array<TShape>) => void\n  /**\n   * **Server method**\n   * onFlush is called on the server when the cache is flushed\n   */\n  onFlush?: () => Array<TShape>\n  /**\n   * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n   */\n  nonce?: string\n}\n\nexport function createHydrationStreamProvider<TShape>() {\n  const context = React.createContext<HydrationStreamContext<TShape>>(\n    null as any,\n  )\n  /**\n\n   * 1. (Happens on server): `useServerInsertedHTML()` is called **on the server** whenever a `Suspense`-boundary completes\n   *    - This means that we might have some new entries in the cache that needs to be flushed\n   *    - We pass these to the client by inserting a `<script>`-tag where we do `window[id].push(serializedVersionOfCache)`\n   * 2. (Happens in browser) In `useEffect()`:\n   *   - We check if `window[id]` is set to an array and call `push()` on all the entries which will call `onEntries()` with the new entries\n   *   - We replace `window[id]` with a `push()`-method that will be called whenever new entries are received\n   **/\n  function UseClientHydrationStreamProvider(props: {\n    children: React.ReactNode\n    /**\n     * Optional transformer to serialize/deserialize the data\n     * Example devalue, superjson et al\n     */\n    transformer?: DataTransformer\n    /**\n     * **Client method**\n     * Called in the browser when new entries are received\n     */\n    onEntries: (entries: Array<TShape>) => void\n    /**\n     * **Server method**\n     * onFlush is called on the server when the cache is flushed\n     */\n    onFlush?: () => Array<TShape>\n    /**\n     * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n     */\n    nonce?: string\n  }) {\n    // unique id for the cache provider\n    const id = `__RQ${React.useId()}`\n    const idJSON = htmlEscapeJsonString(JSON.stringify(id))\n\n    const [transformer] = React.useState(\n      () =>\n        (props.transformer ?? {\n          // noop\n          serialize: (obj: any) => obj,\n          deserialize: (obj: any) => obj,\n        }) as unknown as TypedDataTransformer<TShape>,\n    )\n\n    // <server stuff>\n    const [stream] = React.useState<Array<TShape>>(() => {\n      if (!isServer) {\n        return {\n          push() {\n            // no-op on the client\n          },\n        } as unknown as Array<TShape>\n      }\n      return []\n    })\n    const count = React.useRef(0)\n    useServerInsertedHTML(() => {\n      // This only happens on the server\n      stream.push(...(props.onFlush?.() ?? []))\n\n      if (!stream.length) {\n        return null\n      }\n      // console.log(`pushing ${stream.length} entries`)\n      const serializedCacheArgs = stream\n        .map((entry) => transformer.serialize(entry))\n        .map((entry) => JSON.stringify(entry))\n        .join(',')\n\n      // Flush stream\n      // eslint-disable-next-line react-hooks/immutability\n      stream.length = 0\n\n      const html: Array<string> = [\n        `window[${idJSON}] = window[${idJSON}] || [];`,\n        `window[${idJSON}].push(${htmlEscapeJsonString(serializedCacheArgs)});`,\n      ]\n      return (\n        <script\n          key={count.current++}\n          nonce={props.nonce}\n          dangerouslySetInnerHTML={{\n            __html: html.join(''),\n          }}\n        />\n      )\n    })\n    // </server stuff>\n\n    // <client stuff>\n    // Setup and run the onEntries handler on the client only, but do it during\n    // the initial render so children have access to the data immediately\n    // This is important to avoid the client suspending during the initial render\n    // if the data has not yet been hydrated.\n    if (!isServer) {\n      const win = window as any\n      if (!win[id]?.initialized) {\n        // Client: consume cache:\n        const onEntries = (...serializedEntries: Array<Serialized<TShape>>) => {\n          const entries = serializedEntries.map((serialized) =>\n            transformer.deserialize(serialized),\n          )\n          props.onEntries(entries)\n        }\n\n        const winStream: Array<Serialized<TShape>> = win[id] ?? []\n\n        onEntries(...winStream)\n\n        // eslint-disable-next-line react-hooks/immutability\n        win[id] = {\n          initialized: true,\n          push: onEntries,\n        }\n      }\n    }\n    // </client stuff>\n\n    return (\n      <context.Provider value={{ stream, id }}>\n        {props.children}\n      </context.Provider>\n    )\n  }\n\n  return {\n    Provider: UseClientHydrationStreamProvider,\n    context,\n  }\n}\n"
  },
  {
    "path": "packages/react-query-next-experimental/src/ReactQueryStreamedHydration.tsx",
    "content": "'use client'\n\nimport {\n  defaultShouldDehydrateQuery,\n  dehydrate,\n  hydrate,\n  isServer,\n  useQueryClient,\n} from '@tanstack/react-query'\nimport * as React from 'react'\nimport { createHydrationStreamProvider } from './HydrationStreamProvider'\nimport type { HydrationStreamProviderProps } from './HydrationStreamProvider'\nimport type {\n  DehydrateOptions,\n  DehydratedState,\n  HydrateOptions,\n  QueryClient,\n} from '@tanstack/react-query'\n\nconst stream = createHydrationStreamProvider<DehydratedState>()\n\n/**\n * This component is responsible for:\n * - hydrating the query client on the server\n * - dehydrating the query client on the server\n */\nexport function ReactQueryStreamedHydration(props: {\n  children: React.ReactNode\n  queryClient?: QueryClient\n  nonce?: string\n  options?: {\n    hydrate?: HydrateOptions\n    dehydrate?: DehydrateOptions\n  }\n  transformer?: HydrationStreamProviderProps<DehydratedState>['transformer']\n}) {\n  const queryClient = useQueryClient(props.queryClient)\n\n  /**\n   * We need to track which queries were added/updated during the render\n   */\n  const [trackedKeys] = React.useState(() => new Set<string>())\n\n  // <server only>\n  if (isServer) {\n    // Do we need to care about unsubscribing? I don't think so to be honest\n    queryClient.getQueryCache().subscribe((event) => {\n      switch (event.type) {\n        case 'added':\n        case 'updated':\n          // console.log('tracking', event.query.queryHash, 'b/c of a', event.type)\n          trackedKeys.add(event.query.queryHash)\n      }\n    })\n  }\n  // </server only>\n\n  return (\n    <stream.Provider\n      // Happens on server:\n      onFlush={() => {\n        /**\n         * Dehydrated state of the client where we only include the queries that were added/updated since the last flush\n         */\n        const shouldDehydrate =\n          props.options?.dehydrate?.shouldDehydrateQuery ??\n          defaultShouldDehydrateQuery\n\n        const dehydratedState = dehydrate(queryClient, {\n          ...props.options?.dehydrate,\n          shouldDehydrateQuery(query) {\n            return trackedKeys.has(query.queryHash) && shouldDehydrate(query)\n          },\n        })\n        trackedKeys.clear()\n\n        if (!dehydratedState.queries.length) {\n          return []\n        }\n\n        return [dehydratedState]\n      }}\n      // Happens in browser:\n      onEntries={(entries) => {\n        for (const hydratedState of entries) {\n          hydrate(queryClient, hydratedState, props.options?.hydrate)\n        }\n      }}\n      // Handle BigInts etc using superjson\n      transformer={props.transformer}\n      nonce={props.nonce}\n    >\n      {props.children}\n    </stream.Provider>\n  )\n}\n"
  },
  {
    "path": "packages/react-query-next-experimental/src/htmlescape.ts",
    "content": "// --------------------------------------------------------------------------------\n//\n// copied from\n// https://github.com/vercel/next.js/blob/6bc07792a4462a4bf921a72ab30dc4ab2c4e1bda/packages/next/src/server/htmlescape.ts\n// License: https://github.com/vercel/next.js/blob/6bc07792a4462a4bf921a72ab30dc4ab2c4e1bda/packages/next/license.md\n//\n// --------------------------------------------------------------------------------\n\n// This utility is based on https://github.com/zertosh/htmlescape\n// License: https://github.com/zertosh/htmlescape/blob/0527ca7156a524d256101bb310a9f970f63078ad/LICENSE\n\nconst ESCAPE_LOOKUP: Record<string, string> = {\n  '&': '\\\\u0026',\n  '>': '\\\\u003e',\n  '<': '\\\\u003c',\n  '\\u2028': '\\\\u2028',\n  '\\u2029': '\\\\u2029',\n}\n\nexport const ESCAPE_REGEX = /[&><\\u2028\\u2029]/g\n\nexport function htmlEscapeJsonString(str: string): string {\n  return str.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]!)\n}\n"
  },
  {
    "path": "packages/react-query-next-experimental/src/index.ts",
    "content": "export { ReactQueryStreamedHydration } from './ReactQueryStreamedHydration'\n"
  },
  {
    "path": "packages/react-query-next-experimental/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\",\n    \"jsx\": \"react-jsx\"\n  },\n  \"include\": [\"src\", \"*.config.*\", \"package.json\"],\n  \"references\": [{ \"path\": \"../react-query\" }]\n}\n"
  },
  {
    "path": "packages/react-query-next-experimental/tsconfig.legacy.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"jsx\": \"react-jsx\",\n    \"outDir\": \"./dist-ts/legacy\"\n  },\n  \"include\": [\"src\"],\n  \"exclude\": [\"src/__tests__\"],\n  \"references\": [{ \"path\": \"../react-query\" }]\n}\n"
  },
  {
    "path": "packages/react-query-next-experimental/tsconfig.prod.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"incremental\": false,\n    \"composite\": false,\n    \"rootDir\": \"../../\"\n  }\n}\n"
  },
  {
    "path": "packages/react-query-next-experimental/tsup.config.ts",
    "content": "import { defineConfig } from 'tsup'\nimport { legacyConfig, modernConfig } from './root.tsup.config.js'\n\nexport default defineConfig([\n  modernConfig({ entry: ['src/*.ts', 'src/*.tsx'] }),\n  legacyConfig({ entry: ['src/*.ts', 'src/*.tsx'] }),\n])\n"
  },
  {
    "path": "packages/react-query-next-experimental/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\n\nexport default defineConfig({\n  plugins: [react()],\n  // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660\n  resolve: {\n    conditions: ['@tanstack/custom-condition'],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        conditions: ['@tanstack/custom-condition'],\n      },\n    },\n  },\n})\n"
  },
  {
    "path": "packages/react-query-persist-client/CHANGELOG.md",
    "content": "# @tanstack/react-query-persist-client\n\n## 5.90.27\n\n### Patch Changes\n\n- fix(streamedQuery): maintain error state on reset refetch with initialData defined ([#10287](https://github.com/TanStack/query/pull/10287))\n\n- Updated dependencies [[`248975e`](https://github.com/TanStack/query/commit/248975e896f585f6eaa505c796e73fcf7bfd1eec)]:\n  - @tanstack/query-persist-client-core@5.92.4\n  - @tanstack/react-query@5.91.2\n\n## 5.90.26\n\n### Patch Changes\n\n- Updated dependencies [[`a89aab9`](https://github.com/TanStack/query/commit/a89aab975581c25c113a26c8af486b4cafad272a)]:\n  - @tanstack/react-query@5.91.1\n  - @tanstack/query-persist-client-core@5.92.3\n\n## 5.90.25\n\n### Patch Changes\n\n- Updated dependencies [[`6fa901b`](https://github.com/TanStack/query/commit/6fa901b97a22a80d0fca3f6ed86237ff0cbdd13b)]:\n  - @tanstack/react-query@5.91.0\n  - @tanstack/query-persist-client-core@5.92.2\n\n## 5.90.24\n\n### Patch Changes\n\n- Updated dependencies [[`e505568`](https://github.com/TanStack/query/commit/e505568f4d51c8281d38e9687091094b7d32a405)]:\n  - @tanstack/query-persist-client-core@5.92.1\n  - @tanstack/react-query@5.90.21\n\n## 5.90.23\n\n### Patch Changes\n\n- Updated dependencies [[`978fc52`](https://github.com/TanStack/query/commit/978fc52728a8b9eb33f0a82f4ddf42a95815bd7f)]:\n  - @tanstack/query-persist-client-core@5.92.0\n  - @tanstack/react-query@5.90.21\n\n## 5.90.22\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.19\n  - @tanstack/react-query@5.90.20\n\n## 5.90.21\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.18\n  - @tanstack/react-query@5.90.19\n\n## 5.90.20\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.17\n  - @tanstack/react-query@5.90.18\n\n## 5.90.19\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.16\n  - @tanstack/react-query@5.90.17\n\n## 5.90.18\n\n### Patch Changes\n\n- Updated dependencies [[`4be3ad7`](https://github.com/TanStack/query/commit/4be3ad730c5b8a1e194a91911746be2fce06902a)]:\n  - @tanstack/react-query@5.90.16\n  - @tanstack/query-persist-client-core@5.91.15\n\n## 5.90.17\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.14\n  - @tanstack/react-query@5.90.15\n\n## 5.90.16\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.13\n  - @tanstack/react-query@5.90.14\n\n## 5.90.15\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.12\n  - @tanstack/react-query@5.90.13\n\n## 5.90.14\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.11\n  - @tanstack/react-query@5.90.12\n\n## 5.90.13\n\n### Patch Changes\n\n- Updated dependencies [[`c01b150`](https://github.com/TanStack/query/commit/c01b150e3673e11d6533768529a5e6fe3ebee68c)]:\n  - @tanstack/react-query@5.90.11\n  - @tanstack/query-persist-client-core@5.91.10\n\n## 5.90.12\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.9\n  - @tanstack/react-query@5.90.10\n\n## 5.90.11\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.8\n  - @tanstack/react-query@5.90.9\n\n## 5.90.10\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.7\n  - @tanstack/react-query@5.90.8\n\n## 5.90.9\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.6\n  - @tanstack/react-query@5.90.7\n\n## 5.90.8\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.5\n  - @tanstack/react-query@5.90.6\n\n## 5.90.7\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.4\n  - @tanstack/react-query@5.90.5\n\n## 5.90.6\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.3\n  - @tanstack/react-query@5.90.4\n\n## 5.90.5\n\n### Patch Changes\n\n- Updated dependencies [[`4e1c433`](https://github.com/TanStack/query/commit/4e1c4338a72f7384600bbda99e44bc1891695df4)]:\n  - @tanstack/react-query@5.90.3\n  - @tanstack/query-persist-client-core@5.91.2\n\n## 5.90.4\n\n### Patch Changes\n\n- Updated dependencies [[`846d53d`](https://github.com/TanStack/query/commit/846d53d98992d50606c40634efa43dea9965b787)]:\n  - @tanstack/query-persist-client-core@5.91.1\n  - @tanstack/react-query@5.90.2\n\n## 5.90.3\n\n### Patch Changes\n\n- Updated dependencies [[`5cd86c6`](https://github.com/TanStack/query/commit/5cd86c6ef1720b87b13e1ab70ee823616f1f029a)]:\n  - @tanstack/query-persist-client-core@5.91.0\n  - @tanstack/react-query@5.90.2\n"
  },
  {
    "path": "packages/react-query-persist-client/eslint.config.js",
    "content": "// @ts-check\n\nimport pluginReact from '@eslint-react/eslint-plugin'\nimport reactHooks from 'eslint-plugin-react-hooks'\nimport rootConfig from './root.eslint.config.js'\n\nexport default [\n  ...rootConfig,\n  // @ts-expect-error wtf\n  ...reactHooks.configs['recommended-latest'],\n  {\n    files: ['**/*.{ts,tsx}'],\n    ...pluginReact.configs.recommended,\n    rules: {\n      '@eslint-react/no-context-provider': 'off', // We need to be React 18 compatible\n      'react-hooks/exhaustive-deps': 'error',\n      'react-hooks/rules-of-hooks': 'error',\n      'react-hooks/unsupported-syntax': 'error',\n      'react-hooks/incompatible-library': 'error',\n    },\n  },\n]\n"
  },
  {
    "path": "packages/react-query-persist-client/package.json",
    "content": "{\n  \"name\": \"@tanstack/react-query-persist-client\",\n  \"version\": \"5.90.27\",\n  \"description\": \"React bindings to work with persisters in TanStack/react-query\",\n  \"author\": \"tannerlinsley\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/react-query-persist-client\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"scripts\": {\n    \"clean\": \"premove ./build ./coverage ./dist-ts\",\n    \"compile\": \"tsc --build\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:types\": \"npm-run-all --serial test:types:*\",\n    \"test:types:ts54\": \"node ../../node_modules/typescript54/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts55\": \"node ../../node_modules/typescript55/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts56\": \"node ../../node_modules/typescript56/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts57\": \"node ../../node_modules/typescript57/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts58\": \"node ../../node_modules/typescript58/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts59\": \"node ../../node_modules/typescript59/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:tscurrent\": \"tsc --build\",\n    \"test:types:ts60\": \"node ../../node_modules/typescript60/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:lib\": \"vitest --retry=3\",\n    \"test:lib:dev\": \"pnpm run test:lib --watch\",\n    \"test:build\": \"publint --strict && attw --pack\",\n    \"build\": \"tsup --tsconfig tsconfig.prod.json\"\n  },\n  \"type\": \"module\",\n  \"types\": \"build/legacy/index.d.ts\",\n  \"main\": \"build/legacy/index.cjs\",\n  \"module\": \"build/legacy/index.js\",\n  \"react-native\": \"src/index.ts\",\n  \"exports\": {\n    \".\": {\n      \"@tanstack/custom-condition\": \"./src/index.ts\",\n      \"import\": {\n        \"types\": \"./build/modern/index.d.ts\",\n        \"default\": \"./build/modern/index.js\"\n      },\n      \"require\": {\n        \"types\": \"./build/modern/index.d.cts\",\n        \"default\": \"./build/modern/index.cjs\"\n      }\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"sideEffects\": false,\n  \"files\": [\n    \"build\",\n    \"src\",\n    \"!src/__tests__\"\n  ],\n  \"dependencies\": {\n    \"@tanstack/query-persist-client-core\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"@tanstack/query-test-utils\": \"workspace:*\",\n    \"@tanstack/react-query\": \"workspace:*\",\n    \"@testing-library/react\": \"^16.1.0\",\n    \"@types/react\": \"^19.2.7\",\n    \"@vitejs/plugin-react\": \"^4.3.4\",\n    \"npm-run-all2\": \"^5.0.0\",\n    \"react\": \"^19.2.1\"\n  },\n  \"peerDependencies\": {\n    \"@tanstack/react-query\": \"workspace:^\",\n    \"react\": \"^18 || ^19\"\n  }\n}\n"
  },
  {
    "path": "packages/react-query-persist-client/src/PersistQueryClientProvider.tsx",
    "content": "'use client'\nimport * as React from 'react'\n\nimport {\n  persistQueryClientRestore,\n  persistQueryClientSubscribe,\n} from '@tanstack/query-persist-client-core'\nimport { IsRestoringProvider, QueryClientProvider } from '@tanstack/react-query'\nimport type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'\nimport type { OmitKeyof, QueryClientProviderProps } from '@tanstack/react-query'\n\nexport type PersistQueryClientProviderProps = QueryClientProviderProps & {\n  persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>\n  onSuccess?: () => Promise<unknown> | unknown\n  onError?: () => Promise<unknown> | unknown\n}\n\nexport const PersistQueryClientProvider = ({\n  children,\n  persistOptions,\n  onSuccess,\n  onError,\n  ...props\n}: PersistQueryClientProviderProps): React.JSX.Element => {\n  const [isRestoring, setIsRestoring] = React.useState(true)\n  const refs = React.useRef({ persistOptions, onSuccess, onError })\n  const didRestore = React.useRef(false)\n\n  React.useEffect(() => {\n    refs.current = { persistOptions, onSuccess, onError }\n  })\n\n  React.useEffect(() => {\n    const options = {\n      ...refs.current.persistOptions,\n      queryClient: props.client,\n    }\n    if (!didRestore.current) {\n      didRestore.current = true\n      persistQueryClientRestore(options)\n        .then(() => refs.current.onSuccess?.())\n        .catch(() => refs.current.onError?.())\n        .finally(() => {\n          setIsRestoring(false)\n        })\n    }\n    return isRestoring ? undefined : persistQueryClientSubscribe(options)\n  }, [props.client, isRestoring])\n\n  return (\n    <QueryClientProvider {...props}>\n      <IsRestoringProvider value={isRestoring}>{children}</IsRestoringProvider>\n    </QueryClientProvider>\n  )\n}\n"
  },
  {
    "path": "packages/react-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport * as React from 'react'\nimport { act, fireEvent, render } from '@testing-library/react'\nimport { QueryClient, useQueries, useQuery } from '@tanstack/react-query'\nimport { persistQueryClientSave } from '@tanstack/query-persist-client-core'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { PersistQueryClientProvider } from '../PersistQueryClientProvider'\nimport type {\n  PersistedClient,\n  Persister,\n} from '@tanstack/query-persist-client-core'\nimport type {\n  DefinedUseQueryResult,\n  UseQueryResult,\n} from '@tanstack/react-query'\n\nconst createMockPersister = (): Persister => {\n  let storedState: PersistedClient | undefined\n\n  return {\n    persistClient(persistClient: PersistedClient) {\n      storedState = persistClient\n    },\n    async restoreClient() {\n      return sleep(10).then(() => storedState)\n    },\n    removeClient() {\n      storedState = undefined\n    },\n  }\n}\n\nconst createMockErrorPersister = (\n  removeClient: Persister['removeClient'],\n): [Error, Persister] => {\n  const error = new Error('restore failed')\n  return [\n    error,\n    {\n      async persistClient() {\n        // noop\n      },\n      async restoreClient() {\n        await sleep(10)\n        throw error\n      },\n      removeClient,\n    },\n  ]\n}\n\ndescribe('PersistQueryClientProvider', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('restores cache from persister', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createMockPersister()\n\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'fetched'),\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <h1>{state.data}</h1>\n          <h2>fetchStatus: {state.fetchStatus}</h2>\n        </div>\n      )\n    }\n\n    const rendered = render(\n      <PersistQueryClientProvider\n        client={queryClient}\n        persistOptions={{ persister }}\n      >\n        <Page />\n      </PersistQueryClientProvider>,\n    )\n\n    expect(rendered.getByText('fetchStatus: idle')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('hydrated')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(11))\n    expect(rendered.getByText('fetched')).toBeInTheDocument()\n\n    expect(states).toHaveLength(4)\n\n    expect(states[0]).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'idle',\n      data: undefined,\n    })\n\n    expect(states[1]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: 'hydrated',\n    })\n\n    expect(states[2]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: 'hydrated',\n    })\n\n    expect(states[3]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: 'fetched',\n    })\n  })\n\n  test('should subscribe correctly in StrictMode', async () => {\n    const key = queryKey()\n\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createMockPersister()\n\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'fetched'),\n      })\n\n      return (\n        <div>\n          <h1>{state.data}</h1>\n          <h2>fetchStatus: {state.fetchStatus}</h2>\n          <button\n            onClick={() => {\n              queryClient.setQueryData(key, 'updated')\n            }}\n          >\n            update\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = render(\n      <React.StrictMode>\n        <PersistQueryClientProvider\n          client={queryClient}\n          persistOptions={{ persister }}\n        >\n          <Page />\n        </PersistQueryClientProvider>\n        ,\n      </React.StrictMode>,\n    )\n\n    expect(rendered.getByText('fetchStatus: idle')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('hydrated')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(11))\n    expect(rendered.getByText('fetched')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /update/i }))\n    await act(() => vi.advanceTimersByTimeAsync(0))\n    expect(rendered.getByText('updated')).toBeInTheDocument()\n\n    const statePromise = persister.restoreClient()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    const state = await statePromise\n\n    expect(state?.clientState.queries[0]?.state.data).toBe('updated')\n  })\n\n  test('should also put useQueries into idle state', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult> = []\n\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createMockPersister()\n\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    function Page() {\n      const [state] = useQueries({\n        queries: [\n          {\n            queryKey: key,\n            queryFn: () => sleep(10).then(() => 'fetched'),\n          },\n        ],\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <h1>{state.data}</h1>\n          <h2>fetchStatus: {state.fetchStatus}</h2>\n        </div>\n      )\n    }\n\n    const rendered = render(\n      <PersistQueryClientProvider\n        client={queryClient}\n        persistOptions={{ persister }}\n      >\n        <Page />\n      </PersistQueryClientProvider>,\n    )\n\n    expect(rendered.getByText('fetchStatus: idle')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('hydrated')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(11))\n    expect(rendered.getByText('fetched')).toBeInTheDocument()\n\n    expect(states).toHaveLength(4)\n\n    expect(states[0]).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'idle',\n      data: undefined,\n    })\n\n    expect(states[1]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: 'hydrated',\n    })\n\n    expect(states[2]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: 'hydrated',\n    })\n\n    expect(states[3]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: 'fetched',\n    })\n  })\n\n  test('should show initialData while restoring', async () => {\n    const key = queryKey()\n    const states: Array<DefinedUseQueryResult<string>> = []\n\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createMockPersister()\n\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'fetched'),\n        initialData: 'initial',\n        // make sure that initial data is older than the hydration data\n        // otherwise initialData would be newer and takes precedence\n        initialDataUpdatedAt: 1,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <h1>{state.data}</h1>\n          <h2>fetchStatus: {state.fetchStatus}</h2>\n        </div>\n      )\n    }\n\n    const rendered = render(\n      <PersistQueryClientProvider\n        client={queryClient}\n        persistOptions={{ persister }}\n      >\n        <Page />\n      </PersistQueryClientProvider>,\n    )\n\n    expect(rendered.getByText('initial')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('hydrated')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(11))\n    expect(rendered.getByText('fetched')).toBeInTheDocument()\n\n    expect(states).toHaveLength(4)\n\n    expect(states[0]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: 'initial',\n    })\n\n    expect(states[1]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: 'hydrated',\n    })\n\n    expect(states[2]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: 'hydrated',\n    })\n\n    expect(states[3]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: 'fetched',\n    })\n  })\n\n  test('should not refetch after restoring when data is fresh', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createMockPersister()\n\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    let fetched = false\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          fetched = true\n          return 'fetched'\n        },\n        staleTime: Infinity,\n      })\n\n      states.push(state)\n\n      return (\n        <div>\n          <h1>data: {state.data ?? 'null'}</h1>\n          <h2>fetchStatus: {state.fetchStatus}</h2>\n        </div>\n      )\n    }\n\n    const rendered = render(\n      <PersistQueryClientProvider\n        client={queryClient}\n        persistOptions={{ persister }}\n      >\n        <Page />\n      </PersistQueryClientProvider>,\n    )\n\n    expect(rendered.getByText('data: null')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('data: hydrated')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(11))\n    expect(rendered.getByText('data: hydrated')).toBeInTheDocument()\n\n    expect(states).toHaveLength(2)\n\n    expect(fetched).toBe(false)\n\n    expect(states[0]).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'idle',\n      data: undefined,\n    })\n\n    expect(states[1]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: 'hydrated',\n    })\n  })\n\n  test('should call onSuccess after successful restoring', async () => {\n    const key = queryKey()\n\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createMockPersister()\n\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'fetched'),\n      })\n\n      return (\n        <div>\n          <h1>{state.data}</h1>\n          <h2>fetchStatus: {state.fetchStatus}</h2>\n        </div>\n      )\n    }\n\n    const onSuccess = vi.fn()\n\n    const rendered = render(\n      <PersistQueryClientProvider\n        client={queryClient}\n        persistOptions={{ persister }}\n        onSuccess={onSuccess}\n      >\n        <Page />\n      </PersistQueryClientProvider>,\n    )\n\n    expect(onSuccess).toHaveBeenCalledTimes(0)\n\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('hydrated')).toBeInTheDocument()\n    expect(onSuccess).toHaveBeenCalledTimes(1)\n    await act(() => vi.advanceTimersByTimeAsync(11))\n    expect(rendered.getByText('fetched')).toBeInTheDocument()\n  })\n\n  test('should await onSuccess after successful restoring', async () => {\n    const key = queryKey()\n\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createMockPersister()\n\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    const states: Array<string> = []\n\n    function Page() {\n      const { data, fetchStatus } = useQuery({\n        queryKey: key,\n        queryFn: async () => {\n          states.push('fetching')\n          await sleep(10)\n          states.push('fetched')\n          return 'fetched'\n        },\n      })\n\n      return (\n        <div>\n          <h1>{data}</h1>\n          <h2>fetchStatus: {fetchStatus}</h2>\n        </div>\n      )\n    }\n\n    const rendered = render(\n      <PersistQueryClientProvider\n        client={queryClient}\n        persistOptions={{ persister }}\n        onSuccess={async () => {\n          states.push('onSuccess')\n          await sleep(20)\n          states.push('onSuccess done')\n        }}\n      >\n        <Page />\n      </PersistQueryClientProvider>,\n    )\n\n    await act(() => vi.advanceTimersByTimeAsync(30))\n    expect(rendered.getByText('hydrated')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(11))\n    expect(rendered.getByText('fetched')).toBeInTheDocument()\n\n    expect(states).toEqual([\n      'onSuccess',\n      'onSuccess done',\n      'fetching',\n      'fetched',\n    ])\n  })\n\n  test('should remove cache after non-successful restoring', async () => {\n    const key = queryKey()\n    const consoleMock = vi.spyOn(console, 'error')\n    const consoleWarn = vi\n      .spyOn(console, 'warn')\n      .mockImplementation(() => undefined)\n    consoleMock.mockImplementation(() => undefined)\n\n    const queryClient = new QueryClient()\n    const removeClient = vi.fn()\n    const onSuccess = vi.fn()\n    const onError = vi.fn()\n\n    const [error, persister] = createMockErrorPersister(removeClient)\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'fetched'),\n      })\n\n      return (\n        <div>\n          <h1>{state.data}</h1>\n          <h2>fetchStatus: {state.fetchStatus}</h2>\n        </div>\n      )\n    }\n\n    const rendered = render(\n      <PersistQueryClientProvider\n        client={queryClient}\n        persistOptions={{ persister }}\n        onSuccess={onSuccess}\n        onError={onError}\n      >\n        <Page />\n      </PersistQueryClientProvider>,\n    )\n\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    await act(() => vi.advanceTimersByTimeAsync(11))\n    expect(rendered.getByText('fetched')).toBeInTheDocument()\n    expect(removeClient).toHaveBeenCalledTimes(1)\n    expect(onSuccess).toHaveBeenCalledTimes(0)\n    expect(onError).toHaveBeenCalledTimes(1)\n\n    expect(consoleMock).toHaveBeenCalledTimes(1)\n    expect(consoleMock).toHaveBeenNthCalledWith(1, error)\n    consoleMock.mockRestore()\n    consoleWarn.mockRestore()\n  })\n\n  test('should be able to persist into multiple clients', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult> = []\n\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createMockPersister()\n\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    const onSuccess = vi.fn()\n\n    const queryFn1 = vi\n      .fn()\n      .mockImplementation(() => sleep(10).then(() => 'queryFn1'))\n    const queryFn2 = vi\n      .fn()\n      .mockImplementation(() => sleep(10).then(() => 'queryFn2'))\n\n    function App() {\n      const [client, setClient] = React.useState(\n        () =>\n          new QueryClient({\n            defaultOptions: {\n              queries: {\n                queryFn: queryFn1,\n              },\n            },\n          }),\n      )\n\n      React.useEffect(() => {\n        setClient(\n          new QueryClient({\n            defaultOptions: {\n              queries: {\n                queryFn: queryFn2,\n              },\n            },\n          }),\n        )\n      }, [])\n\n      return (\n        <PersistQueryClientProvider\n          client={client}\n          persistOptions={{ persister }}\n          onSuccess={onSuccess}\n        >\n          <Page />\n        </PersistQueryClientProvider>\n      )\n    }\n\n    function Page() {\n      const state = useQuery({ queryKey: key })\n\n      states.push(state)\n\n      return (\n        <div>\n          <h1>{String(state.data)}</h1>\n          <h2>fetchStatus: {state.fetchStatus}</h2>\n        </div>\n      )\n    }\n\n    const rendered = render(<App />)\n\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('hydrated')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(11))\n    expect(rendered.getByText('queryFn2')).toBeInTheDocument()\n\n    expect(queryFn1).toHaveBeenCalledTimes(0)\n    expect(queryFn2).toHaveBeenCalledTimes(1)\n    expect(onSuccess).toHaveBeenCalledTimes(1)\n\n    expect(states).toHaveLength(5)\n\n    expect(states[0]).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'idle',\n      data: undefined,\n    })\n\n    expect(states[1]).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'idle',\n      data: undefined,\n    })\n\n    expect(states[2]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: 'hydrated',\n    })\n\n    expect(states[3]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: 'hydrated',\n    })\n\n    expect(states[4]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: 'queryFn2',\n    })\n  })\n\n  test('should only restore once in StrictMode', async () => {\n    let restoreCount = 0\n    const createPersister = (): Persister => {\n      let storedState: PersistedClient | undefined\n\n      return {\n        persistClient(persistClient) {\n          storedState = persistClient\n        },\n        async restoreClient() {\n          restoreCount++\n          return sleep(10).then(() => storedState)\n        },\n        removeClient() {\n          storedState = undefined\n        },\n      }\n    }\n\n    const key = queryKey()\n\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createPersister()\n\n    const onSuccess = vi.fn()\n\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    function Page() {\n      const state = useQuery({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'fetched'),\n      })\n\n      return (\n        <div>\n          <h1>{state.data}</h1>\n          <h2>fetchStatus: {state.fetchStatus}</h2>\n        </div>\n      )\n    }\n\n    const rendered = render(\n      <React.StrictMode>\n        <PersistQueryClientProvider\n          client={queryClient}\n          persistOptions={{ persister }}\n          onSuccess={onSuccess}\n        >\n          <Page />\n        </PersistQueryClientProvider>\n      </React.StrictMode>,\n    )\n\n    expect(rendered.getByText('fetchStatus: idle')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    expect(rendered.getByText('hydrated')).toBeInTheDocument()\n    await act(() => vi.advanceTimersByTimeAsync(11))\n    expect(rendered.getByText('fetched')).toBeInTheDocument()\n\n    expect(onSuccess).toHaveBeenCalledTimes(1)\n    expect(restoreCount).toBe(1)\n  })\n})\n"
  },
  {
    "path": "packages/react-query-persist-client/src/__tests__/use-queries-with-persist.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { act, render } from '@testing-library/react'\nimport * as React from 'react'\nimport { QueryClient, useQueries } from '@tanstack/react-query'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'\nimport type {\n  PersistedClient,\n  Persister,\n} from '@tanstack/query-persist-client-core'\nimport type { QueryObserverResult } from '@tanstack/react-query'\n\ndescribe('useQueries with persist and memoized combine', () => {\n  const storage: { [key: string]: string } = {}\n\n  beforeEach(() => {\n    vi.useFakeTimers()\n    Object.defineProperty(window, 'localStorage', {\n      value: {\n        getItem: (key: string) => storage[key] || null,\n        setItem: (key: string, value: string) => {\n          storage[key] = value\n        },\n        removeItem: (key: string) => {\n          delete storage[key]\n        },\n        clear: () => {\n          Object.keys(storage).forEach((key) => delete storage[key])\n        },\n      },\n      writable: true,\n    })\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n    Object.keys(storage).forEach((key) => delete storage[key])\n  })\n\n  it('should update UI when combine is memoized with persist', async () => {\n    const queryClient = new QueryClient({\n      defaultOptions: {\n        queries: {\n          staleTime: 30_000,\n          gcTime: 1000 * 60 * 60 * 24,\n        },\n      },\n    })\n\n    const persister: Persister = {\n      persistClient: (client: PersistedClient) => {\n        storage['REACT_QUERY_OFFLINE_CACHE'] = JSON.stringify(client)\n        return Promise.resolve()\n      },\n      restoreClient: async () => {\n        const stored = storage['REACT_QUERY_OFFLINE_CACHE']\n        if (stored)\n          return sleep(10).then(() => JSON.parse(stored) as PersistedClient)\n\n        return undefined\n      },\n      removeClient: () => {\n        delete storage['REACT_QUERY_OFFLINE_CACHE']\n        return Promise.resolve()\n      },\n    }\n\n    const persistedData: PersistedClient = {\n      timestamp: Date.now(),\n      buster: '',\n      clientState: {\n        mutations: [],\n        queries: [1, 2, 3].map((id) => ({\n          queryHash: `[\"post\",${id}]`,\n          queryKey: ['post', id],\n          state: {\n            data: id,\n            dataUpdateCount: 1,\n            dataUpdatedAt: Date.now() - 1000,\n            error: null,\n            errorUpdateCount: 0,\n            errorUpdatedAt: 0,\n            fetchFailureCount: 0,\n            fetchFailureReason: null,\n            fetchMeta: null,\n            isInvalidated: false,\n            status: 'success' as const,\n            fetchStatus: 'idle' as const,\n          },\n        })),\n      },\n    }\n\n    storage['REACT_QUERY_OFFLINE_CACHE'] = JSON.stringify(persistedData)\n\n    function TestComponent() {\n      const combinedQueries = useQueries({\n        queries: [1, 2, 3].map((id) => ({\n          queryKey: ['post', id],\n          queryFn: () => sleep(100).then(() => id),\n          staleTime: 30_000,\n        })),\n        combine: React.useCallback(\n          (results: Array<QueryObserverResult<number, Error>>) => ({\n            data: results.map((r) => r.data),\n            isPending: results.some((r) => r.isPending),\n          }),\n          [],\n        ),\n      })\n\n      return (\n        <div>\n          <div data-testid=\"pending\">{String(combinedQueries.isPending)}</div>\n          <div data-testid=\"data\">\n            {combinedQueries.data.filter((d) => d !== undefined).join(',')}\n          </div>\n        </div>\n      )\n    }\n\n    const { getByTestId } = render(\n      <PersistQueryClientProvider\n        client={queryClient}\n        persistOptions={{ persister }}\n      >\n        <TestComponent />\n      </PersistQueryClientProvider>,\n    )\n\n    await act(() => vi.advanceTimersByTimeAsync(10))\n    await act(() => vi.advanceTimersByTimeAsync(0))\n    expect(getByTestId('pending').textContent).toBe('false')\n    expect(getByTestId('data').textContent).toBe('1,2,3')\n  })\n})\n"
  },
  {
    "path": "packages/react-query-persist-client/src/index.ts",
    "content": "// Re-export core\nexport * from '@tanstack/query-persist-client-core'\n\nexport * from './PersistQueryClientProvider'\n"
  },
  {
    "path": "packages/react-query-persist-client/test-setup.ts",
    "content": "import '@testing-library/jest-dom/vitest'\nimport { act, cleanup } from '@testing-library/react'\nimport { afterEach } from 'vitest'\nimport { notifyManager } from '@tanstack/react-query'\n\n// https://testing-library.com/docs/react-testing-library/api#cleanup\nafterEach(() => cleanup())\n\n// Wrap notifications with act to make sure React knows about React Query updates\nnotifyManager.setNotifyFunction((fn) => {\n  act(fn)\n})\n"
  },
  {
    "path": "packages/react-query-persist-client/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\",\n    \"jsx\": \"react-jsx\"\n  },\n  \"include\": [\"src\", \"test-setup.ts\", \"*.config.*\", \"package.json\"],\n  \"references\": [\n    { \"path\": \"../query-persist-client-core\" },\n    { \"path\": \"../react-query\" }\n  ]\n}\n"
  },
  {
    "path": "packages/react-query-persist-client/tsconfig.legacy.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"jsx\": \"react-jsx\",\n    \"outDir\": \"./dist-ts/legacy\"\n  },\n  \"include\": [\"src\"],\n  \"exclude\": [\"src/__tests__\"],\n  \"references\": [\n    { \"path\": \"../query-persist-client-core\" },\n    { \"path\": \"../react-query\" }\n  ]\n}\n"
  },
  {
    "path": "packages/react-query-persist-client/tsconfig.prod.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"incremental\": false,\n    \"composite\": false,\n    \"rootDir\": \"../../\"\n  }\n}\n"
  },
  {
    "path": "packages/react-query-persist-client/tsup.config.ts",
    "content": "import { defineConfig } from 'tsup'\nimport { legacyConfig, modernConfig } from './root.tsup.config.js'\n\nexport default defineConfig([\n  modernConfig({ entry: ['src/*.ts', 'src/*.tsx'] }),\n  legacyConfig({ entry: ['src/*.ts', 'src/*.tsx'] }),\n])\n"
  },
  {
    "path": "packages/react-query-persist-client/vite.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\nimport react from '@vitejs/plugin-react'\n\nimport packageJson from './package.json'\n\nexport default defineConfig({\n  plugins: [react()],\n  // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660\n  resolve: {\n    conditions: ['@tanstack/custom-condition'],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        conditions: ['@tanstack/custom-condition'],\n      },\n    },\n  },\n  test: {\n    name: packageJson.name,\n    dir: './src',\n    watch: false,\n    environment: 'jsdom',\n    setupFiles: ['test-setup.ts'],\n    coverage: {\n      enabled: true,\n      provider: 'istanbul',\n      include: ['src/**/*'],\n      exclude: ['src/__tests__/**'],\n    },\n    typecheck: { enabled: true },\n    restoreMocks: true,\n  },\n})\n"
  },
  {
    "path": "packages/solid-query/CHANGELOG.md",
    "content": "# @tanstack/solid-query\n\n## 5.91.3\n\n### Patch Changes\n\n- fix(streamedQuery): maintain error state on reset refetch with initialData defined ([#10287](https://github.com/TanStack/query/pull/10287))\n\n- Updated dependencies [[`248975e`](https://github.com/TanStack/query/commit/248975e896f585f6eaa505c796e73fcf7bfd1eec)]:\n  - @tanstack/query-core@5.91.2\n\n## 5.91.2\n\n### Patch Changes\n\n- fix(core): cancel paused initial fetch when last observer unsubscribes ([#10291](https://github.com/TanStack/query/pull/10291))\n\n- Updated dependencies [[`a89aab9`](https://github.com/TanStack/query/commit/a89aab975581c25c113a26c8af486b4cafad272a)]:\n  - @tanstack/query-core@5.91.1\n\n## 5.91.1\n\n### Patch Changes\n\n- Updated dependencies [[`6fa901b`](https://github.com/TanStack/query/commit/6fa901b97a22a80d0fca3f6ed86237ff0cbdd13b)]:\n  - @tanstack/query-core@5.91.0\n\n## 5.91.0\n\n### Minor Changes\n\n- feat(solid-query): add 'mutationOptions' ([#10138](https://github.com/TanStack/query/pull/10138))\n\n## 5.90.26\n\n### Patch Changes\n\n- fix(solid-router): should only have useQueryClient/useIsRestoring due to context read ([#10262](https://github.com/TanStack/query/pull/10262))\n\n## 5.90.25\n\n### Patch Changes\n\n- fix: allow both create/use for solid ([#10260](https://github.com/TanStack/query/pull/10260))\n\n## 5.90.24\n\n### Patch Changes\n\n- fix: forward generic parameters in deprecated type aliases ([#10093](https://github.com/TanStack/query/pull/10093))\n\n## 5.90.23\n\n### Patch Changes\n\n- Updated dependencies [[`e7258c5`](https://github.com/TanStack/query/commit/e7258c5cb30cafa456cdb4e6bc75b43bf619954d)]:\n  - @tanstack/query-core@5.90.20\n\n## 5.90.22\n\n### Patch Changes\n\n- Updated dependencies [[`53fc74e`](https://github.com/TanStack/query/commit/53fc74ebb16730bd3317f039a69c6821386bae93)]:\n  - @tanstack/query-core@5.90.19\n\n## 5.90.21\n\n### Patch Changes\n\n- Updated dependencies [[`dea1614`](https://github.com/TanStack/query/commit/dea1614aaad5c572cf43cea54b64ac09dc4d5b41)]:\n  - @tanstack/query-core@5.90.18\n\n## 5.90.20\n\n### Patch Changes\n\n- Updated dependencies [[`269351b`](https://github.com/TanStack/query/commit/269351b8ce4b4846da3d320ac5b850ee6aada0d6)]:\n  - @tanstack/query-core@5.90.17\n\n## 5.90.19\n\n### Patch Changes\n\n- Updated dependencies [[`7f47906`](https://github.com/TanStack/query/commit/7f47906eaccc3f3aa5ce24b77a83bd7a620a237b)]:\n  - @tanstack/query-core@5.90.16\n\n## 5.90.18\n\n### Patch Changes\n\n- Updated dependencies [[`fccef79`](https://github.com/TanStack/query/commit/fccef797d57d4a9566517bba87c8377f363920f2)]:\n  - @tanstack/query-core@5.90.15\n\n## 5.90.17\n\n### Patch Changes\n\n- Updated dependencies [[`d576092`](https://github.com/TanStack/query/commit/d576092e2ece4ca3936add3eb0da5234c1d82ed4)]:\n  - @tanstack/query-core@5.90.14\n\n## 5.90.16\n\n### Patch Changes\n\n- Updated dependencies [[`4a0a78a`](https://github.com/TanStack/query/commit/4a0a78afbc2432f8cb6828035965853fa98c86a0)]:\n  - @tanstack/query-core@5.90.13\n\n## 5.90.15\n\n### Patch Changes\n\n- Updated dependencies [[`72d8ac5`](https://github.com/TanStack/query/commit/72d8ac5c592004b8f9c3ee086fcb9c3cd615ca05)]:\n  - @tanstack/query-core@5.90.12\n\n## 5.90.14\n\n### Patch Changes\n\n- Updated dependencies [[`c01b150`](https://github.com/TanStack/query/commit/c01b150e3673e11d6533768529a5e6fe3ebee68c)]:\n  - @tanstack/query-core@5.90.11\n\n## 5.90.13\n\n### Patch Changes\n\n- Updated dependencies [[`8e2e174`](https://github.com/TanStack/query/commit/8e2e174e9fd2e7b94cd232041e49c9d014d74e26), [`eb559a6`](https://github.com/TanStack/query/commit/eb559a66dc0d77dd46435f624fa64fc068bef9ae)]:\n  - @tanstack/query-core@5.90.10\n\n## 5.90.12\n\n### Patch Changes\n\n- Updated dependencies [[`08b211f`](https://github.com/TanStack/query/commit/08b211f8aa475e05d2f13a36517fc556861ef962)]:\n  - @tanstack/query-core@5.90.9\n\n## 5.90.11\n\n### Patch Changes\n\n- Updated dependencies [[`c0ec9fe`](https://github.com/TanStack/query/commit/c0ec9fe0d1426fe3f233adda3ebf23989ffaa110)]:\n  - @tanstack/query-core@5.90.8\n\n## 5.90.10\n\n### Patch Changes\n\n- Updated dependencies [[`b4cd121`](https://github.com/TanStack/query/commit/b4cd121a39d07cefaa3a3411136d342cc54ce8fb)]:\n  - @tanstack/query-core@5.90.7\n\n## 5.90.9\n\n### Patch Changes\n\n- Skip errors if returned data is undefined ([#9841](https://github.com/TanStack/query/pull/9841))\n\n## 5.90.8\n\n### Patch Changes\n\n- Updated dependencies [[`1638c02`](https://github.com/TanStack/query/commit/1638c028df55648995d04431179904371a189772)]:\n  - @tanstack/query-core@5.90.6\n\n## 5.90.7\n\n### Patch Changes\n\n- fix(solid-query): enable experimental_prefetchInRender by default for… ([#9822](https://github.com/TanStack/query/pull/9822))\n\n## 5.90.6\n\n### Patch Changes\n\n- Updated dependencies [[`e42ddfe`](https://github.com/TanStack/query/commit/e42ddfe919f34f847ca101aeef162c69845f9a1e)]:\n  - @tanstack/query-core@5.90.5\n\n## 5.90.5\n\n### Patch Changes\n\n- Updated dependencies [[`20ef922`](https://github.com/TanStack/query/commit/20ef922a0a7c3aee00150bf69123c338b0922922)]:\n  - @tanstack/query-core@5.90.4\n\n## 5.90.4\n\n### Patch Changes\n\n- Updated dependencies [[`4e1c433`](https://github.com/TanStack/query/commit/4e1c4338a72f7384600bbda99e44bc1891695df4)]:\n  - @tanstack/query-core@5.90.3\n"
  },
  {
    "path": "packages/solid-query/README.md",
    "content": "<img src=\"https://static.scarf.sh/a.png?x-pxid=be2d8a11-9712-4c1d-9963-580b2d4fb133\" />\n\n![TanStack Query Header](https://github.com/TanStack/query/raw/main/media/repo-header.png)\n\nHooks for fetching, caching and updating asynchronous data in Solid\n\n<a href=\"https://twitter.com/intent/tweet?button_hashtag=TanStack\" target=\"\\_parent\">\n  <img alt=\"#TanStack\" src=\"https://img.shields.io/twitter/url?color=%2308a0e9&label=%23TanStack&style=social&url=https%3A%2F%2Ftwitter.com%2Fintent%2Ftweet%3Fbutton_hashtag%3DTanStack\">\n</a><a href=\"https://discord.com/invite/WrRKjPJ\" target=\"\\_parent\">\n  <img alt=\"\" src=\"https://img.shields.io/badge/Discord-TanStack-%235865F2\" />\n</a><a href=\"https://github.com/TanStack/query/actions?query=workflow%3A%ci%22\">\n<img src=\"https://github.com/TanStack/query/workflows/ci/badge.svg\" />\n</a><a href=\"https://www.npmjs.com/package/@tanstack/query-core\" target=\"\\_parent\">\n  <img alt=\"\" src=\"https://img.shields.io/npm/dm/@tanstack/query-core.svg\" />\n</a><a href=\"https://bundlejs.com/?q=%40tanstack%2Fsolid-query&config=%7B%22esbuild%22%3A%7B%22external%22%3A%5B%22solid-js%22%2C%5D%7D%7D&badge=\" target=\"\\_parent\">\n  <img alt=\"\" src=\"https://deno.bundlejs.com/?q=@tanstack/solid-query&config={%22esbuild%22:{%22external%22:[%22solid-js%22]}}&badge=detailed\" />\n</a><a href=\"#badge\">\n    <img alt=\"semantic-release\" src=\"https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg\">\n  </a><a href=\"https://github.com/TanStack/query/discussions\">\n  <img alt=\"Join the discussion on Github\" src=\"https://img.shields.io/badge/Github%20Discussions%20%26%20Support-Chat%20now!-blue\" />\n</a><a href=\"https://bestofjs.org/projects/tanstack-query\"><img alt=\"Best of JS\" src=\"https://img.shields.io/endpoint?url=https://bestofjs-serverless.now.sh/api/project-badge?fullName=TanStack%2Fquery%26since=daily\" /></a><a href=\"https://github.com/TanStack/query/\" target=\"\\_parent\">\n  <img alt=\"\" src=\"https://img.shields.io/github/stars/TanStack/query.svg?style=social&label=Star\" />\n</a><a href=\"https://twitter.com/tannerlinsley\" target=\"\\_parent\">\n  <img alt=\"\" src=\"https://img.shields.io/twitter/follow/tannerlinsley.svg?style=social&label=Follow\" />\n</a> <a href=\"https://gitpod.io/from-referrer/\">\n  <img src=\"https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod\" alt=\"Gitpod Ready-to-Code\"/>\n</a>\n\nEnjoy this library? Try the entire [TanStack](https://tanstack.com)! [TanStack Table](https://github.com/TanStack/table), [TanStack Router](https://github.com/tanstack/router), [TanStack Virtual](https://github.com/tanstack/virtual)\n\n## Visit [tanstack.com/query](https://tanstack.com/query) for docs, guides, API and more!\n\n## Quick Features\n\n- Transport/protocol/backend agnostic data fetching (REST, GraphQL, promises, whatever!)\n- Auto Caching + Refetching (stale-while-revalidate, Window Refocus, Polling/Realtime)\n- Parallel + Dependent Queries\n- Mutations + Reactive Query Refetching\n- Multi-layer Cache + Automatic Garbage Collection\n- Paginated + Cursor-based Queries\n- Load-More + Infinite Scroll Queries w/ Scroll Recovery\n- Request Cancellation\n- Suspense + Fetch-As-You-Render Query Prefetching\n- Dedicated Devtools\n\n### [Become a Sponsor!](https://github.com/sponsors/tannerlinsley/)\n\n<!-- Use the force, Luke -->\n"
  },
  {
    "path": "packages/solid-query/eslint.config.js",
    "content": "// @ts-check\n\nimport rootConfig from './root.eslint.config.js'\n\nexport default [...rootConfig]\n"
  },
  {
    "path": "packages/solid-query/package.json",
    "content": "{\n  \"name\": \"@tanstack/solid-query\",\n  \"version\": \"5.91.3\",\n  \"description\": \"Primitives for managing, caching and syncing asynchronous and remote data in Solid\",\n  \"author\": \"tannerlinsley\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/solid-query\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"scripts\": {\n    \"clean\": \"premove ./build ./coverage ./dist-ts\",\n    \"compile\": \"tsc --build\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:types\": \"npm-run-all --serial test:types:*\",\n    \"test:types:ts54\": \"node ../../node_modules/typescript54/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts55\": \"node ../../node_modules/typescript55/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts56\": \"node ../../node_modules/typescript56/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts57\": \"node ../../node_modules/typescript57/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts58\": \"node ../../node_modules/typescript58/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts59\": \"node ../../node_modules/typescript59/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:tscurrent\": \"tsc --build\",\n    \"test:types:ts60\": \"node ../../node_modules/typescript60/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:lib\": \"vitest --retry=3\",\n    \"test:lib:dev\": \"pnpm run test:lib --watch\",\n    \"test:build\": \"publint --strict && attw --pack\",\n    \"build\": \"tsup --tsconfig tsconfig.prod.json\",\n    \"build:watch\": \"tsup --watch\"\n  },\n  \"type\": \"module\",\n  \"main\": \"./build/index.cjs\",\n  \"module\": \"./build/index.js\",\n  \"types\": \"./build/index.d.ts\",\n  \"browser\": {},\n  \"exports\": {\n    \"@tanstack/custom-condition\": \"./src/index.ts\",\n    \"development\": {\n      \"import\": {\n        \"types\": \"./build/index.d.ts\",\n        \"default\": \"./build/dev.js\"\n      },\n      \"require\": {\n        \"types\": \"./build/index.d.cts\",\n        \"default\": \"./build/dev.cjs\"\n      }\n    },\n    \"import\": {\n      \"types\": \"./build/index.d.ts\",\n      \"default\": \"./build/index.js\"\n    },\n    \"require\": {\n      \"types\": \"./build/index.d.cts\",\n      \"default\": \"./build/index.cjs\"\n    }\n  },\n  \"files\": [\n    \"build\",\n    \"src\",\n    \"!src/__tests__\"\n  ],\n  \"dependencies\": {\n    \"@tanstack/query-core\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"@solidjs/testing-library\": \"^0.8.10\",\n    \"@tanstack/query-test-utils\": \"workspace:*\",\n    \"npm-run-all2\": \"^5.0.0\",\n    \"solid-js\": \"^1.9.7\",\n    \"tsup-preset-solid\": \"^2.2.0\",\n    \"vite-plugin-solid\": \"^2.11.6\"\n  },\n  \"peerDependencies\": {\n    \"solid-js\": \"^1.6.0\"\n  }\n}\n"
  },
  {
    "path": "packages/solid-query/src/QueryClient.ts",
    "content": "import { QueryClient as QueryCoreClient } from '@tanstack/query-core'\nimport type {\n  DefaultOptions as CoreDefaultOptions,\n  DefaultError,\n  OmitKeyof,\n  QueryClientConfig as QueryCoreClientConfig,\n  InfiniteQueryObserverOptions as QueryCoreInfiniteQueryObserverOptions,\n  QueryObserverOptions as QueryCoreObserverOptions,\n  QueryKey,\n} from '@tanstack/query-core'\n\nexport interface QueryObserverOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = never,\n> extends OmitKeyof<\n  QueryCoreObserverOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryData,\n    TQueryKey,\n    TPageParam\n  >,\n  'structuralSharing'\n> {\n  /**\n   * Set this to a reconciliation key to enable reconciliation between query results.\n   * Set this to `false` to disable reconciliation between query results.\n   * Set this to a function which accepts the old and new data and returns resolved data of the same type to implement custom reconciliation logic.\n   * Defaults reconciliation to false.\n   */\n  reconcile?:\n    | string\n    | false\n    | ((oldData: TData | undefined, newData: TData) => TData)\n}\n\nexport interface InfiniteQueryObserverOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> extends OmitKeyof<\n  QueryCoreInfiniteQueryObserverOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n  'structuralSharing'\n> {\n  /**\n   * Set this to a reconciliation key to enable reconciliation between query results.\n   * Set this to `false` to disable reconciliation between query results.\n   * Set this to a function which accepts the old and new data and returns resolved data of the same type to implement custom reconciliation logic.\n   * Defaults reconciliation to false.\n   */\n  reconcile?:\n    | string\n    | false\n    | ((oldData: TData | undefined, newData: TData) => TData)\n}\n\nexport interface DefaultOptions<\n  TError = DefaultError,\n> extends CoreDefaultOptions<TError> {\n  queries?: OmitKeyof<QueryObserverOptions<unknown, TError>, 'queryKey'>\n}\n\nexport interface QueryClientConfig extends QueryCoreClientConfig {\n  defaultOptions?: DefaultOptions\n}\n\nexport class QueryClient extends QueryCoreClient {\n  constructor(config: QueryClientConfig = {}) {\n    super(config)\n  }\n}\n"
  },
  {
    "path": "packages/solid-query/src/QueryClientProvider.tsx",
    "content": "import {\n  createContext,\n  createRenderEffect,\n  onCleanup,\n  useContext,\n} from 'solid-js'\nimport type { QueryClient } from './QueryClient'\nimport type { JSX } from 'solid-js'\n\nexport const QueryClientContext = createContext<\n  (() => QueryClient) | undefined\n>(undefined)\n\nexport const useQueryClient = (queryClient?: QueryClient) => {\n  if (queryClient) {\n    return queryClient\n  }\n  const client = useContext(QueryClientContext)\n\n  if (!client) {\n    throw new Error('No QueryClient set, use QueryClientProvider to set one')\n  }\n\n  return client()\n}\n\nexport type QueryClientProviderProps = {\n  client: QueryClient\n  children?: JSX.Element\n}\n\nexport const QueryClientProvider = (\n  props: QueryClientProviderProps,\n): JSX.Element => {\n  createRenderEffect<() => void>((unmount) => {\n    unmount?.()\n    props.client.mount()\n    return props.client.unmount.bind(props.client)\n  })\n  onCleanup(() => props.client.unmount())\n\n  return (\n    <QueryClientContext.Provider value={() => props.client}>\n      {props.children}\n    </QueryClientContext.Provider>\n  )\n}\n"
  },
  {
    "path": "packages/solid-query/src/__tests__/QueryClientProvider.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { render } from '@solidjs/testing-library'\nimport { QueryCache } from '@tanstack/query-core'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { QueryClient, QueryClientProvider, useQuery, useQueryClient } from '..'\n\ndescribe('QueryClientProvider', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('sets a specific cache for all queries to use', async () => {\n    const key = queryKey()\n\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({ queryCache })\n\n    function Page() {\n      const query = useQuery(() => ({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return 'test'\n        },\n      }))\n\n      return (\n        <div>\n          <h1>{query.data}</h1>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('test')).toBeInTheDocument()\n\n    expect(queryCache.find({ queryKey: key })).toBeDefined()\n  })\n\n  it('allows multiple caches to be partitioned', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    const queryCache1 = new QueryCache()\n    const queryCache2 = new QueryCache()\n\n    const queryClient1 = new QueryClient({ queryCache: queryCache1 })\n    const queryClient2 = new QueryClient({ queryCache: queryCache2 })\n\n    function Page1() {\n      const query = useQuery(() => ({\n        queryKey: key1,\n        queryFn: async () => {\n          await sleep(10)\n          return 'test1'\n        },\n      }))\n\n      return (\n        <div>\n          <h1>{query.data}</h1>\n        </div>\n      )\n    }\n    function Page2() {\n      const query = useQuery(() => ({\n        queryKey: key2,\n        queryFn: async () => {\n          await sleep(10)\n          return 'test2'\n        },\n      }))\n\n      return (\n        <div>\n          <h1>{query.data}</h1>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <>\n        <QueryClientProvider client={queryClient1}>\n          <Page1 />\n        </QueryClientProvider>\n        <QueryClientProvider client={queryClient2}>\n          <Page2 />\n        </QueryClientProvider>\n      </>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('test1')).toBeInTheDocument()\n    expect(rendered.getByText('test2')).toBeInTheDocument()\n\n    expect(queryCache1.find({ queryKey: key1 })).toBeDefined()\n    expect(queryCache1.find({ queryKey: key2 })).not.toBeDefined()\n    expect(queryCache2.find({ queryKey: key1 })).not.toBeDefined()\n    expect(queryCache2.find({ queryKey: key2 })).toBeDefined()\n  })\n\n  it(\"uses defaultOptions for queries when they don't provide their own config\", async () => {\n    const key = queryKey()\n\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({\n      queryCache,\n      defaultOptions: {\n        queries: {\n          gcTime: Infinity,\n        },\n      },\n    })\n\n    function Page() {\n      const query = useQuery(() => ({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return 'test'\n        },\n      }))\n\n      return (\n        <div>\n          <h1>{query.data}</h1>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('test')).toBeInTheDocument()\n\n    expect(queryCache.find({ queryKey: key })).toBeDefined()\n    expect(queryCache.find({ queryKey: key })?.options.gcTime).toBe(Infinity)\n  })\n\n  describe('useQueryClient', () => {\n    it('should throw an error if no query client has been set', () => {\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n\n      function Page() {\n        useQueryClient()\n        return null\n      }\n\n      expect(() => render(() => <Page />)).toThrow(\n        'No QueryClient set, use QueryClientProvider to set one',\n      )\n\n      consoleMock.mockRestore()\n    })\n  })\n\n  it('should not throw an error if user provides custom query client', () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n\n    function Page() {\n      const client = new QueryClient()\n      useQueryClient(client)\n      return null\n    }\n\n    render(() => <Page />)\n    expect(consoleMock).not.toHaveBeenCalled()\n\n    consoleMock.mockRestore()\n  })\n})\n"
  },
  {
    "path": "packages/solid-query/src/__tests__/createQueries.test-d.tsx",
    "content": "import { describe, expectTypeOf, it } from 'vitest'\nimport { queryOptions, useQueries } from '..'\nimport type { UseQueryResult } from '..'\n\ndescribe('useQueries', () => {\n  it('should return correct data for dynamic queries with mixed result types', () => {\n    const Queries1 = {\n      get: () =>\n        queryOptions({\n          queryKey: ['key1'],\n          queryFn: () => Promise.resolve(1),\n        }),\n    }\n    const Queries2 = {\n      get: () =>\n        queryOptions({\n          queryKey: ['key2'],\n          queryFn: () => Promise.resolve(true),\n        }),\n    }\n\n    const queries1List = [1, 2, 3].map(() => ({ ...Queries1.get() }))\n    const result = useQueries(() => ({\n      queries: [...queries1List, { ...Queries2.get() }],\n    }))\n\n    expectTypeOf(result).toEqualTypeOf<\n      [...Array<UseQueryResult<number, Error>>, UseQueryResult<boolean, Error>]\n    >()\n  })\n})\n"
  },
  {
    "path": "packages/solid-query/src/__tests__/mutationOptions.test-d.tsx",
    "content": "import { assertType, describe, expectTypeOf, it } from 'vitest'\nimport { QueryClient } from '@tanstack/query-core'\nimport { useIsMutating, useMutation, useMutationState } from '..'\nimport { mutationOptions } from '../mutationOptions'\nimport type {\n  DefaultError,\n  MutationFunctionContext,\n  MutationState,\n  WithRequired,\n} from '@tanstack/query-core'\nimport type { SolidMutationOptions, UseMutationResult } from '../types'\n\ndescribe('mutationOptions', () => {\n  it('should not allow excess properties', () => {\n    // @ts-expect-error this is a good error, because onMutates does not exist!\n    mutationOptions({\n      mutationFn: () => Promise.resolve(5),\n      mutationKey: ['key'],\n      onMutates: 1000,\n      onSuccess: (data) => {\n        expectTypeOf(data).toEqualTypeOf<number>()\n      },\n    })\n  })\n\n  it('should infer types for callbacks', () => {\n    mutationOptions({\n      mutationFn: () => Promise.resolve(5),\n      mutationKey: ['key'],\n      onSuccess: (data) => {\n        expectTypeOf(data).toEqualTypeOf<number>()\n      },\n    })\n  })\n\n  it('should infer types for onError callback', () => {\n    mutationOptions({\n      mutationFn: () => {\n        throw new Error('fail')\n      },\n      mutationKey: ['key'],\n      onError: (error) => {\n        expectTypeOf(error).toEqualTypeOf<DefaultError>()\n      },\n    })\n  })\n\n  it('should infer types for variables', () => {\n    mutationOptions<number, DefaultError, { id: string }>({\n      mutationFn: (vars) => {\n        expectTypeOf(vars).toEqualTypeOf<{ id: string }>()\n        return Promise.resolve(5)\n      },\n      mutationKey: ['with-vars'],\n    })\n  })\n\n  it('should infer result type correctly', () => {\n    mutationOptions<number, DefaultError, void, { name: string }>({\n      mutationFn: () => Promise.resolve(5),\n      mutationKey: ['key'],\n      onMutate: () => {\n        return { name: 'onMutateResult' }\n      },\n      onSuccess: (_data, _variables, onMutateResult) => {\n        expectTypeOf(onMutateResult).toEqualTypeOf<{ name: string }>()\n      },\n    })\n  })\n\n  it('should infer context type correctly', () => {\n    mutationOptions<number>({\n      mutationFn: (_variables, context) => {\n        expectTypeOf(context).toEqualTypeOf<MutationFunctionContext>()\n        return Promise.resolve(5)\n      },\n      mutationKey: ['key'],\n      onMutate: (_variables, context) => {\n        expectTypeOf(context).toEqualTypeOf<MutationFunctionContext>()\n      },\n      onSuccess: (_data, _variables, _onMutateResult, context) => {\n        expectTypeOf(context).toEqualTypeOf<MutationFunctionContext>()\n      },\n      onError: (_error, _variables, _onMutateResult, context) => {\n        expectTypeOf(context).toEqualTypeOf<MutationFunctionContext>()\n      },\n      onSettled: (_data, _error, _variables, _onMutateResult, context) => {\n        expectTypeOf(context).toEqualTypeOf<MutationFunctionContext>()\n      },\n    })\n  })\n\n  it('should error if mutationFn return type mismatches TData', () => {\n    assertType(\n      mutationOptions<number>({\n        // @ts-expect-error this is a good error, because return type is string, not number\n        mutationFn: async () => Promise.resolve('wrong return'),\n      }),\n    )\n  })\n\n  it('should allow mutationKey to be omitted', () => {\n    return mutationOptions({\n      mutationFn: () => Promise.resolve(123),\n      onSuccess: (data) => {\n        expectTypeOf(data).toEqualTypeOf<number>()\n      },\n    })\n  })\n\n  it('should infer all types when not explicitly provided', () => {\n    expectTypeOf(\n      mutationOptions({\n        mutationFn: (id: string) => Promise.resolve(id.length),\n        mutationKey: ['key'],\n        onSuccess: (data) => {\n          expectTypeOf(data).toEqualTypeOf<number>()\n        },\n      }),\n    ).toEqualTypeOf<\n      WithRequired<\n        SolidMutationOptions<number, DefaultError, string>,\n        'mutationKey'\n      >\n    >()\n    expectTypeOf(\n      mutationOptions({\n        mutationFn: (id: string) => Promise.resolve(id.length),\n        onSuccess: (data) => {\n          expectTypeOf(data).toEqualTypeOf<number>()\n        },\n      }),\n    ).toEqualTypeOf<\n      Omit<SolidMutationOptions<number, DefaultError, string>, 'mutationKey'>\n    >()\n  })\n\n  it('should infer types when used with useMutation', () => {\n    const mutation = useMutation(() =>\n      mutationOptions({\n        mutationKey: ['key'],\n        mutationFn: () => Promise.resolve('data'),\n        onSuccess: (data) => {\n          expectTypeOf(data).toEqualTypeOf<string>()\n        },\n      }),\n    )\n    expectTypeOf(mutation).toEqualTypeOf<\n      UseMutationResult<string, DefaultError, void, unknown>\n    >()\n\n    useMutation(() =>\n      // should allow when used with useMutation without mutationKey\n      mutationOptions({\n        mutationFn: () => Promise.resolve('data'),\n        onSuccess: (data) => {\n          expectTypeOf(data).toEqualTypeOf<string>()\n        },\n      }),\n    )\n  })\n\n  it('should infer types when used with useIsMutating', () => {\n    const isMutating = useIsMutating(() =>\n      mutationOptions({\n        mutationKey: ['key'],\n        mutationFn: () => Promise.resolve(5),\n      }),\n    )\n    expectTypeOf(isMutating).toEqualTypeOf<() => number>()\n\n    useIsMutating(\n      // @ts-expect-error filters should have mutationKey\n      () =>\n        mutationOptions({\n          mutationFn: () => Promise.resolve(5),\n        }),\n    )\n  })\n\n  it('should infer types when used with queryClient.isMutating', () => {\n    const queryClient = new QueryClient()\n\n    const isMutating = queryClient.isMutating(\n      mutationOptions({\n        mutationKey: ['key'],\n        mutationFn: () => Promise.resolve(5),\n      }),\n    )\n    expectTypeOf(isMutating).toEqualTypeOf<number>()\n\n    queryClient.isMutating(\n      // @ts-expect-error filters should have mutationKey\n      mutationOptions({\n        mutationFn: () => Promise.resolve(5),\n      }),\n    )\n  })\n\n  it('should infer types when used with useMutationState', () => {\n    const mutationState = useMutationState(() => ({\n      filters: mutationOptions({\n        mutationKey: ['key'],\n        mutationFn: () => Promise.resolve(5),\n      }),\n    }))\n    expectTypeOf(mutationState).toEqualTypeOf<\n      () => Array<MutationState<unknown, Error, unknown, unknown>>\n    >()\n\n    useMutationState(\n      // @ts-expect-error filters should have mutationKey\n      () => ({\n        filters: mutationOptions({\n          mutationFn: () => Promise.resolve(5),\n        }),\n      }),\n    )\n  })\n})\n"
  },
  {
    "path": "packages/solid-query/src/__tests__/mutationOptions.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { fireEvent, render } from '@solidjs/testing-library'\nimport { createEffect, createRenderEffect } from 'solid-js'\nimport { sleep } from '@tanstack/query-test-utils'\nimport {\n  QueryClient,\n  QueryClientProvider,\n  useIsMutating,\n  useMutation,\n  useMutationState,\n} from '..'\nimport { mutationOptions } from '../mutationOptions'\nimport type { MutationState } from '@tanstack/query-core'\n\ndescribe('mutationOptions', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should return the object received as a parameter without any modification (with mutationKey in mutationOptions)', () => {\n    const object = {\n      mutationKey: ['key'],\n      mutationFn: () => sleep(10).then(() => 5),\n    } as const\n\n    expect(mutationOptions(object)).toStrictEqual(object)\n  })\n\n  it('should return the object received as a parameter without any modification (without mutationKey in mutationOptions)', () => {\n    const object = {\n      mutationFn: () => sleep(10).then(() => 5),\n    } as const\n\n    expect(mutationOptions(object)).toStrictEqual(object)\n  })\n\n  it('should return the number of fetching mutations when used with useIsMutating (with mutationKey in mutationOptions)', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n    const mutationOpts = mutationOptions({\n      mutationKey: ['key'],\n      mutationFn: () => sleep(50).then(() => 'data'),\n    })\n\n    function Mutation() {\n      const isMutating = useIsMutating()\n      const { mutate } = useMutation(() => mutationOpts)\n\n      createRenderEffect(() => {\n        isMutatingArray.push(isMutating())\n      })\n\n      return (\n        <div>\n          <button onClick={() => mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Mutation />\n      </QueryClientProvider>\n    ))\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    expect(isMutatingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isMutatingArray[1]).toEqual(1)\n    await vi.advanceTimersByTimeAsync(50)\n    expect(isMutatingArray[2]).toEqual(0)\n    expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0)\n  })\n\n  it('should return the number of fetching mutations when used with useIsMutating (without mutationKey in mutationOptions)', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n    const mutationOpts = mutationOptions({\n      mutationFn: () => sleep(50).then(() => 'data'),\n    })\n\n    function Mutation() {\n      const isMutating = useIsMutating()\n      const { mutate } = useMutation(() => mutationOpts)\n\n      createRenderEffect(() => {\n        isMutatingArray.push(isMutating())\n      })\n\n      return (\n        <div>\n          <button onClick={() => mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Mutation />\n      </QueryClientProvider>\n    ))\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    expect(isMutatingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isMutatingArray[1]).toEqual(1)\n    await vi.advanceTimersByTimeAsync(50)\n    expect(isMutatingArray[2]).toEqual(0)\n    expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0)\n  })\n\n  it('should return the number of fetching mutations when used with useIsMutating', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['key'],\n      mutationFn: () => sleep(50).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(50).then(() => 'data2'),\n    })\n\n    function Mutation() {\n      const isMutating = useIsMutating()\n      const { mutate: mutate1 } = useMutation(() => mutationOpts1)\n      const { mutate: mutate2 } = useMutation(() => mutationOpts2)\n\n      createRenderEffect(() => {\n        isMutatingArray.push(isMutating())\n      })\n\n      return (\n        <div>\n          <button onClick={() => mutate1()}>mutate1</button>\n          <button onClick={() => mutate2()}>mutate2</button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Mutation />\n      </QueryClientProvider>\n    ))\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n    expect(isMutatingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isMutatingArray[2]).toEqual(2)\n    await vi.advanceTimersByTimeAsync(50)\n    expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0)\n  })\n\n  it('should return the number of fetching mutations when used with useIsMutating (filter mutationOpts1.mutationKey)', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['key'],\n      mutationFn: () => sleep(50).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(50).then(() => 'data2'),\n    })\n\n    function Mutation() {\n      const isMutating = useIsMutating(() => ({\n        mutationKey: mutationOpts1.mutationKey,\n      }))\n      const { mutate: mutate1 } = useMutation(() => mutationOpts1)\n      const { mutate: mutate2 } = useMutation(() => mutationOpts2)\n\n      createRenderEffect(() => {\n        isMutatingArray.push(isMutating())\n      })\n\n      return (\n        <div>\n          <button onClick={() => mutate1()}>mutate1</button>\n          <button onClick={() => mutate2()}>mutate2</button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Mutation />\n      </QueryClientProvider>\n    ))\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n    expect(isMutatingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    expect(isMutatingArray[1]).toEqual(1)\n    await vi.advanceTimersByTimeAsync(50)\n    expect(isMutatingArray[2]).toEqual(0)\n    expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0)\n  })\n\n  it('should return the number of fetching mutations when used with queryClient.isMutating (with mutationKey in mutationOptions)', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n    const mutationOpts = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(500).then(() => 'data'),\n    })\n\n    function Mutation() {\n      const { mutate } = useMutation(() => mutationOpts)\n\n      return (\n        <div>\n          <button onClick={() => mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Mutation />\n      </QueryClientProvider>\n    ))\n\n    const mutationCache = queryClient.getMutationCache()\n    const unsubscribe = mutationCache.subscribe(() => {\n      isMutatingArray.push(queryClient.isMutating(mutationOpts))\n    })\n\n    isMutatingArray.push(queryClient.isMutating(mutationOpts))\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    expect(isMutatingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    // Use Math.max because subscribe callback count is implementation-dependent\n    expect(Math.max(...isMutatingArray)).toEqual(1)\n    await vi.advanceTimersByTimeAsync(500)\n    expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0)\n\n    unsubscribe()\n  })\n\n  it('should return the number of fetching mutations when used with queryClient.isMutating (without mutationKey in mutationOptions)', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n    const mutationOpts = mutationOptions({\n      mutationFn: () => sleep(500).then(() => 'data'),\n    })\n\n    function Mutation() {\n      const { mutate } = useMutation(() => mutationOpts)\n\n      return (\n        <div>\n          <button onClick={() => mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Mutation />\n      </QueryClientProvider>\n    ))\n\n    const mutationCache = queryClient.getMutationCache()\n    const unsubscribe = mutationCache.subscribe(() => {\n      isMutatingArray.push(queryClient.isMutating())\n    })\n\n    isMutatingArray.push(queryClient.isMutating())\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    expect(isMutatingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    // Use Math.max because subscribe callback count is implementation-dependent\n    expect(Math.max(...isMutatingArray)).toEqual(1)\n    await vi.advanceTimersByTimeAsync(500)\n    expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0)\n\n    unsubscribe()\n  })\n\n  it('should return the number of fetching mutations when used with queryClient.isMutating', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(500).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(500).then(() => 'data2'),\n    })\n\n    function Mutation() {\n      const { mutate: mutate1 } = useMutation(() => mutationOpts1)\n      const { mutate: mutate2 } = useMutation(() => mutationOpts2)\n\n      return (\n        <div>\n          <button onClick={() => mutate1()}>mutate1</button>\n          <button onClick={() => mutate2()}>mutate2</button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Mutation />\n      </QueryClientProvider>\n    ))\n\n    const mutationCache = queryClient.getMutationCache()\n    const unsubscribe = mutationCache.subscribe(() => {\n      isMutatingArray.push(queryClient.isMutating())\n    })\n\n    isMutatingArray.push(queryClient.isMutating())\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n    expect(isMutatingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    // Use Math.max because subscribe callback count is implementation-dependent\n    expect(Math.max(...isMutatingArray)).toEqual(2)\n    await vi.advanceTimersByTimeAsync(500)\n    expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0)\n\n    unsubscribe()\n  })\n\n  it('should return the number of fetching mutations when used with queryClient.isMutating (filter mutationOpt1.mutationKey)', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(500).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(500).then(() => 'data2'),\n    })\n\n    function Mutation() {\n      const { mutate: mutate1 } = useMutation(() => mutationOpts1)\n      const { mutate: mutate2 } = useMutation(() => mutationOpts2)\n\n      return (\n        <div>\n          <button onClick={() => mutate1()}>mutate1</button>\n          <button onClick={() => mutate2()}>mutate2</button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Mutation />\n      </QueryClientProvider>\n    ))\n\n    const mutationCache = queryClient.getMutationCache()\n    const unsubscribe = mutationCache.subscribe(() => {\n      isMutatingArray.push(\n        queryClient.isMutating({\n          mutationKey: mutationOpts1.mutationKey,\n        }),\n      )\n    })\n\n    isMutatingArray.push(\n      queryClient.isMutating({\n        mutationKey: mutationOpts1.mutationKey,\n      }),\n    )\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n    expect(isMutatingArray[0]).toEqual(0)\n    await vi.advanceTimersByTimeAsync(0)\n    // Use Math.max because subscribe callback count is implementation-dependent\n    expect(Math.max(...isMutatingArray)).toEqual(1)\n    await vi.advanceTimersByTimeAsync(500)\n    expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0)\n\n    unsubscribe()\n  })\n\n  it('should return the number of fetching mutations when used with useMutationState (with mutationKey in mutationOptions)', async () => {\n    const mutationStateArray: Array<Array<MutationState>> = []\n    const queryClient = new QueryClient()\n    const mutationOpts = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(10).then(() => 'data'),\n    })\n\n    function Mutation() {\n      const { mutate } = useMutation(() => mutationOpts)\n      const states = useMutationState(() => ({\n        filters: { mutationKey: mutationOpts.mutationKey, status: 'success' },\n      }))\n\n      createEffect(() => {\n        mutationStateArray.push(states())\n      })\n\n      return (\n        <div>\n          <button onClick={() => mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Mutation />\n      </QueryClientProvider>\n    ))\n\n    expect(mutationStateArray[0]).toEqual([])\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(10)\n    const lastSnapshot = mutationStateArray[mutationStateArray.length - 1]!\n    expect(lastSnapshot.length).toEqual(1)\n    expect(lastSnapshot[0]?.data).toEqual('data')\n  })\n\n  it('should return the number of fetching mutations when used with useMutationState (without mutationKey in mutationOptions)', async () => {\n    const mutationStateArray: Array<Array<MutationState>> = []\n    const queryClient = new QueryClient()\n    const mutationOpts = mutationOptions({\n      mutationFn: () => sleep(10).then(() => 'data'),\n    })\n\n    function Mutation() {\n      const { mutate } = useMutation(() => mutationOpts)\n      const states = useMutationState(() => ({\n        filters: { status: 'success' },\n      }))\n\n      createEffect(() => {\n        mutationStateArray.push(states())\n      })\n\n      return (\n        <div>\n          <button onClick={() => mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Mutation />\n      </QueryClientProvider>\n    ))\n\n    expect(mutationStateArray[0]).toEqual([])\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(10)\n    const lastSnapshot = mutationStateArray[mutationStateArray.length - 1]!\n    expect(lastSnapshot.length).toEqual(1)\n    expect(lastSnapshot[0]?.data).toEqual('data')\n  })\n\n  it('should return the number of fetching mutations when used with useMutationState', async () => {\n    const mutationStateArray: Array<Array<MutationState>> = []\n    const queryClient = new QueryClient()\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(10).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(10).then(() => 'data2'),\n    })\n\n    function Mutation() {\n      const { mutate: mutate1 } = useMutation(() => mutationOpts1)\n      const { mutate: mutate2 } = useMutation(() => mutationOpts2)\n      const states = useMutationState(() => ({\n        filters: { status: 'success' },\n      }))\n\n      createEffect(() => {\n        mutationStateArray.push(states())\n      })\n\n      return (\n        <div>\n          <button onClick={() => mutate1()}>mutate1</button>\n          <button onClick={() => mutate2()}>mutate2</button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Mutation />\n      </QueryClientProvider>\n    ))\n\n    expect(mutationStateArray[0]).toEqual([])\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n    await vi.advanceTimersByTimeAsync(10)\n    const lastSnapshot = mutationStateArray[mutationStateArray.length - 1]!\n    expect(lastSnapshot.length).toEqual(2)\n    expect(lastSnapshot[0]?.data).toEqual('data1')\n    expect(lastSnapshot[1]?.data).toEqual('data2')\n  })\n\n  it('should return the number of fetching mutations when used with useMutationState (filter mutationOpt1.mutationKey)', async () => {\n    const mutationStateArray: Array<Array<MutationState>> = []\n    const queryClient = new QueryClient()\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(10).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(10).then(() => 'data2'),\n    })\n\n    function Mutation() {\n      const { mutate: mutate1 } = useMutation(() => mutationOpts1)\n      const { mutate: mutate2 } = useMutation(() => mutationOpts2)\n      const states = useMutationState(() => ({\n        filters: { mutationKey: mutationOpts1.mutationKey, status: 'success' },\n      }))\n\n      createEffect(() => {\n        mutationStateArray.push(states())\n      })\n\n      return (\n        <div>\n          <button onClick={() => mutate1()}>mutate1</button>\n          <button onClick={() => mutate2()}>mutate2</button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Mutation />\n      </QueryClientProvider>\n    ))\n\n    expect(mutationStateArray[0]).toEqual([])\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n    await vi.advanceTimersByTimeAsync(10)\n    const lastSnapshot = mutationStateArray[mutationStateArray.length - 1]!\n    expect(lastSnapshot.length).toEqual(1)\n    expect(lastSnapshot[0]?.data).toEqual('data1')\n    expect(lastSnapshot[1]).toBeFalsy()\n  })\n})\n"
  },
  {
    "path": "packages/solid-query/src/__tests__/queryOptions.test-d.tsx",
    "content": "import { assertType, describe, expectTypeOf, it } from 'vitest'\nimport {\n  QueryClient,\n  dataTagErrorSymbol,\n  dataTagSymbol,\n  skipToken,\n} from '@tanstack/query-core'\nimport { useQuery } from '../useQuery'\nimport { queryOptions } from '../queryOptions'\n\ndescribe('queryOptions', () => {\n  it('should not allow excess properties', () => {\n    assertType(\n      queryOptions({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        // @ts-expect-error this is a good error, because stallTime does not exist!\n        stallTime: 1000,\n      }),\n    )\n  })\n  it('should infer types for callbacks', () => {\n    queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n      staleTime: 1000,\n      select: (data) => {\n        expectTypeOf(data).toEqualTypeOf<number>()\n      },\n    })\n  })\n  it('should work when passed to useQuery', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const { data } = useQuery(() => options)\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n  it('should work when passed to fetchQuery', async () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const data = await new QueryClient().fetchQuery(options)\n    expectTypeOf(data).toEqualTypeOf<number>()\n  })\n  it('should tag the queryKey with the result type of the QueryFn', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<number>()\n  })\n  it('should tag the queryKey even if no promise is returned', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => 5,\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<number>()\n  })\n  it('should tag the queryKey with unknown if there is no queryFn', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<unknown>()\n  })\n  it('should tag the queryKey with the result type of the QueryFn if select is used', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n      select: (data) => data.toString(),\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<number>()\n  })\n  it('should tag the queryKey with the default error type', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(1),\n    })\n\n    expectTypeOf(queryKey[dataTagErrorSymbol]).toEqualTypeOf<Error>()\n  })\n  it('should return the proper type when passed to getQueryData', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryData(queryKey)\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n  it('should return the proper type when passed to getQueryState', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n    const state = queryClient.getQueryState(queryKey)\n    expectTypeOf(state?.data).toEqualTypeOf<number | undefined>()\n  })\n  it('should properly type updaterFn when passed to setQueryData', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.setQueryData(queryKey, (prev) => {\n      expectTypeOf(prev).toEqualTypeOf<number | undefined>()\n      return prev\n    })\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n  it('should properly type value when passed to setQueryData', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n\n    // @ts-expect-error value should be a number\n    queryClient.setQueryData(queryKey, '5')\n    // @ts-expect-error value should be a number\n    queryClient.setQueryData(queryKey, () => '5')\n\n    const data = queryClient.setQueryData(queryKey, 5)\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n\n  it('should infer even if there is a conditional skipToken', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryData(options.queryKey)\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n\n  it('should infer to unknown if we disable a query with just a skipToken', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: skipToken,\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryData(options.queryKey)\n    expectTypeOf(data).toEqualTypeOf<unknown>()\n  })\n})\n"
  },
  {
    "path": "packages/solid-query/src/__tests__/queryOptions.test.tsx",
    "content": "import { describe, expect, it } from 'vitest'\nimport { queryOptions } from '../queryOptions'\n\ndescribe('queryOptions', () => {\n  it('should return the object received as a parameter without any modification.', () => {\n    const object = {\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    } as const\n\n    expect(queryOptions(object)).toBe(object)\n  })\n})\n"
  },
  {
    "path": "packages/solid-query/src/__tests__/suspense.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { fireEvent, render } from '@solidjs/testing-library'\nimport {\n  ErrorBoundary,\n  Show,\n  Suspense,\n  createRenderEffect,\n  createSignal,\n  on,\n} from 'solid-js'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport {\n  QueryCache,\n  QueryClient,\n  QueryClientProvider,\n  useInfiniteQuery,\n  useQuery,\n} from '..'\nimport type { InfiniteData, UseInfiniteQueryResult, UseQueryResult } from '..'\n\ndescribe(\"useQuery's in Suspense mode\", () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  const queryCache = new QueryCache()\n  const queryClient = new QueryClient({ queryCache })\n\n  it('should render the correct amount of times in Suspense mode', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n\n    let count = 0\n    let renders = 0\n\n    function Page() {\n      const [stateKey, setStateKey] = createSignal(key)\n\n      const state = useQuery(() => ({\n        queryKey: stateKey(),\n        queryFn: () => sleep(10).then(() => ++count),\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      createRenderEffect(\n        on([() => ({ ...state }), () => key], () => {\n          renders++\n        }),\n      )\n\n      return (\n        <div>\n          <button aria-label=\"toggle\" onClick={() => setStateKey(queryKey())} />\n          data: {String(state.data)}\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Suspense fallback=\"loading\">\n          <Page />\n        </Suspense>\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByLabelText('toggle'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 2')).toBeInTheDocument()\n\n    expect(renders).toBe(4)\n    expect(states.length).toBe(4)\n    expect(states[1]).toMatchObject({ data: 1, status: 'success' })\n    expect(states[3]).toMatchObject({ data: 2, status: 'success' })\n  })\n\n  it('should return the correct states for a successful infinite query', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const [multiplier, setMultiplier] = createSignal(1)\n      const state = useInfiniteQuery(() => ({\n        queryKey: [`${key}_${multiplier()}`],\n        queryFn: ({ pageParam }) =>\n          sleep(10).then(() => pageParam * multiplier()),\n        initialPageParam: 1,\n        suspense: true,\n        getNextPageParam: (lastPage) => lastPage + 1,\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      return (\n        <div>\n          <button onClick={() => setMultiplier(2)}>next</button>\n          data: {state.data?.pages.join(',')}\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Suspense fallback=\"loading\">\n          <Page />\n        </Suspense>\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n    // eslint-disable-next-line cspell/spellchecker\n    // TODO(lukemurray): in react this is 1 in solid this is 2 because suspense\n    // occurs on read.\n    expect(states.length).toBe(2)\n    expect(states[1]).toMatchObject({\n      data: { pages: [1], pageParams: [1] },\n      status: 'success',\n    })\n\n    fireEvent.click(rendered.getByText('next'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 2')).toBeInTheDocument()\n    // eslint-disable-next-line cspell/spellchecker\n    // TODO(lukemurray): in react this is 2 and in solid it is 4\n    expect(states.length).toBe(4)\n    expect(states[3]).toMatchObject({\n      data: { pages: [2], pageParams: [1] },\n      status: 'success',\n    })\n  })\n\n  it('should not call the queryFn twice when used in Suspense mode', async () => {\n    const key = queryKey()\n\n    const queryFn = vi.fn(() => sleep(10).then(() => 'data'))\n\n    function Page() {\n      useQuery(() => ({\n        queryKey: [key],\n        queryFn,\n        suspense: true,\n      }))\n\n      return <>rendered</>\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Suspense fallback=\"loading\">\n          <Page />\n        </Suspense>\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(20)\n\n    expect(queryFn).toHaveBeenCalledTimes(1)\n  })\n\n  it('should remove query instance when component unmounted', async () => {\n    const key = queryKey()\n\n    function Page() {\n      useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'data'),\n      }))\n\n      return <>rendered</>\n    }\n\n    function App() {\n      const [show, setShow] = createSignal(false)\n\n      return (\n        <>\n          <Suspense fallback=\"loading\">{show() && <Page />}</Suspense>\n          <button\n            aria-label=\"toggle\"\n            onClick={() => setShow((prev) => !prev)}\n          />\n        </>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <App />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.queryByText('rendered')).not.toBeInTheDocument()\n    expect(queryCache.find({ queryKey: key })).toBeFalsy()\n\n    fireEvent.click(rendered.getByLabelText('toggle'))\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n\n    expect(queryCache.find({ queryKey: key })?.getObserversCount()).toBe(1)\n\n    fireEvent.click(rendered.getByLabelText('toggle'))\n    expect(rendered.queryByText('rendered')).not.toBeInTheDocument()\n\n    expect(queryCache.find({ queryKey: key })?.getObserversCount()).toBe(0)\n  })\n\n  // https://github.com/tannerlinsley/react-query/issues/468\n  it('should reset error state if new component instances are mounted', async () => {\n    const key = queryKey()\n\n    let succeed = false\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => {\n            if (!succeed) throw new Error('Suspense Error Bingo')\n            return 'data'\n          }),\n        retryDelay: 10,\n        suspense: true,\n      }))\n\n      // Suspense only triggers if used in JSX\n      return (\n        <Show when={state.data}>\n          <div>rendered</div>\n        </Show>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <ErrorBoundary\n          fallback={(_err, resetSolid) => (\n            <div>\n              <div>error boundary</div>\n              <button\n                onClick={() => {\n                  succeed = true\n                  resetSolid()\n                }}\n              >\n                retry\n              </button>\n            </div>\n          )}\n        >\n          <Suspense fallback=\"loading\">\n            <Page />\n          </Suspense>\n        </ErrorBoundary>\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(100)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n    expect(rendered.getByText('retry')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('retry'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n  })\n\n  it('should retry fetch if the reset error boundary has been reset', async () => {\n    const key = queryKey()\n\n    let succeed = false\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => {\n            if (!succeed) throw new Error('Suspense Error Bingo')\n            return 'data'\n          }),\n        retry: false,\n        suspense: true,\n      }))\n\n      // Suspense only triggers if used in JSX\n      return (\n        <Show when={state.data}>\n          <div>rendered</div>\n        </Show>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <ErrorBoundary\n          fallback={(_err, resetSolid) => (\n            <div>\n              <div>error boundary</div>\n              <button\n                onClick={() => {\n                  resetSolid()\n                }}\n              >\n                retry\n              </button>\n            </div>\n          )}\n        >\n          <Suspense fallback=\"loading\">\n            <Page />\n          </Suspense>\n        </ErrorBoundary>\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n    expect(rendered.getByText('retry')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('retry'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n    expect(rendered.getByText('retry')).toBeInTheDocument()\n\n    succeed = true\n\n    fireEvent.click(rendered.getByText('retry'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n  })\n\n  it('should refetch when re-mounting', async () => {\n    const key = queryKey()\n    let count = 0\n\n    function Component() {\n      const result = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(100).then(() => ++count),\n        retry: false,\n        suspense: true,\n        staleTime: 0,\n      }))\n\n      return (\n        <div>\n          <span>data: {result.data}</span>\n          <span>fetching: {result.isFetching ? 'true' : 'false'}</span>\n        </div>\n      )\n    }\n\n    function Page() {\n      const [show, setShow] = createSignal(true)\n      return (\n        <div>\n          <button\n            onClick={() => {\n              setShow(!show())\n            }}\n          >\n            {show() ? 'hide' : 'show'}\n          </button>\n          <Suspense fallback=\"loading\">{show() && <Component />}</Suspense>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(100)\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n    expect(rendered.getByText('fetching: false')).toBeInTheDocument()\n    expect(rendered.getByText('hide')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('hide'))\n    await vi.advanceTimersByTimeAsync(100)\n    expect(rendered.getByText('show')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('show'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('fetching: true')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(100)\n    expect(rendered.getByText('data: 2')).toBeInTheDocument()\n    expect(rendered.getByText('fetching: false')).toBeInTheDocument()\n  })\n\n  it('should suspend when switching to a new query', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    function Component(props: { queryKey: Array<string> }) {\n      const result = useQuery(() => ({\n        queryKey: props.queryKey,\n        queryFn: () => sleep(100).then(() => props.queryKey),\n        retry: false,\n        suspense: true,\n      }))\n\n      return <div>data: {result.data}</div>\n    }\n\n    function Page() {\n      const [key, setKey] = createSignal(key1)\n      return (\n        <div>\n          <button\n            onClick={() => {\n              setKey(key2)\n            }}\n          >\n            switch\n          </button>\n          <Suspense fallback=\"loading\">\n            <Component queryKey={key()} />\n          </Suspense>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(100)\n    expect(rendered.getByText(`data: ${key1}`)).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('switch'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(100)\n    expect(rendered.getByText(`data: ${key2}`)).toBeInTheDocument()\n  })\n\n  it('should throw errors to the error boundary by default', async () => {\n    const key = queryKey()\n\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => Promise.reject(new Error('Suspense Error a1x'))),\n        retry: false,\n        suspense: true,\n      }))\n\n      // read state.data to trigger suspense.\n      createRenderEffect(() => {\n        state.data\n      })\n\n      return <div>rendered</div>\n    }\n\n    function App() {\n      return (\n        <ErrorBoundary\n          fallback={() => (\n            <div>\n              <div>error boundary</div>\n            </div>\n          )}\n        >\n          <Suspense fallback=\"loading\">\n            <Page />\n          </Suspense>\n        </ErrorBoundary>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <App />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n\n    consoleMock.mockRestore()\n  })\n\n  it('should not throw errors to the error boundary when throwOnError: false', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => Promise.reject(new Error('Suspense Error a2x'))),\n        retry: false,\n        throwOnError: false,\n      }))\n\n      // read state.data to trigger suspense.\n      createRenderEffect(() => {\n        state.data\n      })\n\n      return <div>rendered</div>\n    }\n\n    function App() {\n      return (\n        <ErrorBoundary\n          fallback={() => (\n            <div>\n              <div>error boundary</div>\n            </div>\n          )}\n        >\n          <Suspense fallback=\"loading\">\n            <Page />\n          </Suspense>\n        </ErrorBoundary>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <App />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n  })\n\n  it('should throw errors to the error boundary when a throwOnError function returns true', async () => {\n    const key = queryKey()\n\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => Promise.reject(new Error('Remote Error'))),\n        retry: false,\n        throwOnError: (err) => err.message !== 'Local Error',\n      }))\n\n      // read state.data to trigger suspense.\n      createRenderEffect(() => {\n        state.data\n      })\n\n      return <div>rendered</div>\n    }\n\n    function App() {\n      return (\n        <ErrorBoundary\n          fallback={() => (\n            <div>\n              <div>error boundary</div>\n            </div>\n          )}\n        >\n          <Suspense fallback=\"loading\">\n            <Page />\n          </Suspense>\n        </ErrorBoundary>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <App />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n\n    consoleMock.mockRestore()\n  })\n\n  it('should not throw errors to the error boundary when a throwOnError function returns false', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => Promise.reject(new Error('Local Error'))),\n        retry: false,\n        suspense: true,\n        throwOnError: (err) => err.message !== 'Local Error',\n      }))\n\n      // read state.data to trigger suspense.\n      createRenderEffect(() => {\n        state.data\n      })\n\n      return <div>rendered</div>\n    }\n\n    function App() {\n      return (\n        <ErrorBoundary\n          fallback={() => (\n            <div>\n              <div>error boundary</div>\n            </div>\n          )}\n        >\n          <Suspense fallback=\"loading\">\n            <Page />\n          </Suspense>\n        </ErrorBoundary>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <App />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n  })\n\n  it('should not call the queryFn when not enabled', async () => {\n    const key = queryKey()\n\n    const queryFn = vi.fn(() => sleep(10).then(() => '23'))\n\n    function Page() {\n      const [enabled, setEnabled] = createSignal(false)\n\n      const result = useQuery(() => ({\n        queryKey: [key],\n        queryFn,\n        suspense: true,\n        enabled: enabled(),\n      }))\n\n      return (\n        <div>\n          <button onClick={() => setEnabled(true)}>fire</button>\n          <h1>{result.data}</h1>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Suspense fallback=\"loading\">\n          <Page />\n        </Suspense>\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    expect(queryFn).toHaveBeenCalledTimes(0)\n\n    await vi.advanceTimersByTimeAsync(10)\n    fireEvent.click(rendered.getByRole('button', { name: /fire/i }))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByRole('heading').textContent).toBe('23')\n    expect(queryFn).toHaveBeenCalledTimes(1)\n  })\n\n  it('should error caught in error boundary without infinite loop', async () => {\n    const key = queryKey()\n\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n\n    let succeed = true\n\n    function Page() {\n      const [nonce] = createSignal(0)\n      const queryKeys = [`${key}-${succeed}`]\n\n      const result = useQuery(() => ({\n        queryKey: queryKeys,\n        queryFn: () =>\n          sleep(10).then(() => {\n            if (!succeed) throw new Error('Suspense Error Bingo')\n            return nonce()\n          }),\n        retry: false,\n        suspense: true,\n      }))\n\n      return (\n        <div>\n          <span>rendered</span> <span>{result.data}</span>\n          <button aria-label=\"fail\" onClick={() => queryClient.resetQueries()}>\n            fail\n          </button>\n        </div>\n      )\n    }\n\n    function App() {\n      return (\n        <ErrorBoundary fallback={() => <div>error boundary</div>}>\n          <Suspense fallback=\"loading\">\n            <Page />\n          </Suspense>\n        </ErrorBoundary>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <App />\n      </QueryClientProvider>\n    ))\n\n    // render suspense fallback (Loading...)\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    // resolve promise -> render Page (rendered)\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n\n    // change query key\n    succeed = false\n    // reset query -> and throw error\n\n    fireEvent.click(rendered.getByLabelText('fail'))\n    // render error boundary fallback (error boundary)\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n\n    consoleMock.mockRestore()\n  })\n\n  it('should error caught in error boundary without infinite loop when query keys changed', async () => {\n    let succeed = true\n\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n\n    function Page() {\n      const [key, setKey] = createSignal(0)\n\n      const result = useQuery(() => ({\n        queryKey: [`${key()}-${succeed}`],\n        queryFn: async () =>\n          sleep(10).then(() => {\n            if (!succeed) throw new Error('Suspense Error Bingo')\n            return 'data'\n          }),\n        retry: false,\n        suspense: true,\n      }))\n\n      return (\n        <div>\n          <span>rendered</span> <span>{result.data}</span>\n          <button aria-label=\"fail\" onClick={() => setKey((k) => k + 1)}>\n            fail\n          </button>\n        </div>\n      )\n    }\n\n    function App() {\n      return (\n        <ErrorBoundary fallback={() => <div>error boundary</div>}>\n          <Suspense fallback=\"loading\">\n            <Page />\n          </Suspense>\n        </ErrorBoundary>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <App />\n      </QueryClientProvider>\n    ))\n\n    // render suspense fallback (Loading...)\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    // resolve promise -> render Page (rendered)\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n\n    // change promise result to error\n    succeed = false\n    // change query key\n\n    fireEvent.click(rendered.getByLabelText('fail'))\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    // render error boundary fallback (error boundary)\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n\n    consoleMock.mockRestore()\n  })\n\n  it('should error caught in error boundary without infinite loop when enabled changed', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n\n    function Page() {\n      const queryKeys = '1'\n      const [enabled, setEnabled] = createSignal(false)\n\n      const result = useQuery<string>(() => ({\n        queryKey: [queryKeys],\n        queryFn: () =>\n          sleep(10).then(() =>\n            Promise.reject(new Error('Suspense Error Bingo')),\n          ),\n        retry: false,\n        suspense: true,\n        enabled: enabled(),\n      }))\n\n      return (\n        <div>\n          <span>rendered</span> <span>{result.data}</span>\n          <button\n            aria-label=\"fail\"\n            onClick={() => {\n              setEnabled(true)\n            }}\n          >\n            fail\n          </button>\n        </div>\n      )\n    }\n\n    function App() {\n      return (\n        <ErrorBoundary fallback={() => <div>error boundary</div>}>\n          <Suspense fallback=\"loading\">\n            <Page />\n          </Suspense>\n        </ErrorBoundary>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <App />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    // render empty data with 'rendered' when enabled is false\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n\n    // change enabled to true\n    fireEvent.click(rendered.getByLabelText('fail'))\n    // render pending fallback\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n    // render error boundary fallback (error boundary)\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n\n    consoleMock.mockRestore()\n  })\n\n  it('should render the correct amount of times in Suspense mode when gcTime is set to 0', async () => {\n    const key = queryKey()\n    let state: UseQueryResult<number> | null = null\n\n    let count = 0\n    let renders = 0\n\n    function Page() {\n      state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => ++count),\n        gcTime: 0,\n      }))\n\n      createRenderEffect(\n        on([() => ({ ...state })], () => {\n          renders++\n        }),\n      )\n\n      return (\n        <div>\n          <span>rendered</span>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Suspense fallback=\"loading\">\n          <Page />\n        </Suspense>\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('loading')).toBeInTheDocument()\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(state).toMatchObject({\n      data: 1,\n      status: 'success',\n    })\n    expect(renders).toBe(2)\n    expect(rendered.queryByText('rendered')).toBeInTheDocument()\n  })\n})\n"
  },
  {
    "path": "packages/solid-query/src/__tests__/transition.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { fireEvent, render } from '@solidjs/testing-library'\nimport { Show, Suspense, createSignal, startTransition } from 'solid-js'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { QueryCache, QueryClient, QueryClientProvider, useQuery } from '..'\n\ndescribe(\"useQuery's in Suspense mode with transitions\", () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  const queryCache = new QueryCache()\n  const queryClient = new QueryClient({ queryCache })\n\n  it('should render the content when the transition is done', async () => {\n    const key = queryKey()\n\n    function Suspended() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return true\n        },\n      }))\n      return <Show when={state.data}>Message</Show>\n    }\n\n    function Page() {\n      const [showSignal, setShowSignal] = createSignal(false)\n\n      return (\n        <div>\n          <button\n            aria-label=\"toggle\"\n            onClick={() =>\n              startTransition(() => setShowSignal((value) => !value))\n            }\n          >\n            {showSignal() ? 'Hide' : 'Show'}\n          </button>\n          <Suspense fallback=\"Loading\">\n            <Show when={showSignal()}>\n              <Suspended />\n            </Show>\n          </Suspense>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('Show')).toBeInTheDocument()\n    fireEvent.click(rendered.getByLabelText('toggle'))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('Message')).toBeInTheDocument()\n    // verify that the button also updated. See https://github.com/solidjs/solid/issues/1249\n    expect(rendered.getByText('Hide')).toBeInTheDocument()\n  })\n})\n"
  },
  {
    "path": "packages/solid-query/src/__tests__/useInfiniteQuery.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { fireEvent, render } from '@solidjs/testing-library'\n\nimport {\n  For,\n  Index,\n  Match,\n  Switch,\n  createEffect,\n  createRenderEffect,\n  createSignal,\n  on,\n} from 'solid-js'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport {\n  QueryCache,\n  QueryClient,\n  QueryClientProvider,\n  infiniteQueryOptions,\n  keepPreviousData,\n  useInfiniteQuery,\n} from '..'\nimport { Blink, setActTimeout } from './utils'\nimport type {\n  InfiniteData,\n  QueryFunctionContext,\n  UseInfiniteQueryResult,\n} from '..'\nimport type { Mock } from 'vitest'\n\ninterface Result {\n  items: Array<number>\n  nextId?: number\n  prevId?: number\n  ts: number\n}\n\nconst pageSize = 10\n\nconst fetchItems = (\n  page: number,\n  ts: number,\n  noNext?: boolean,\n  noPrev?: boolean,\n): Promise<Result> =>\n  sleep(10).then(() => ({\n    items: [...new Array(10)].fill(null).map((_, d) => page * pageSize + d),\n    nextId: noNext ? undefined : page + 1,\n    prevId: noPrev ? undefined : page - 1,\n    ts,\n  }))\n\ndescribe('useInfiniteQuery', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  const queryCache = new QueryCache()\n  const queryClient = new QueryClient({ queryCache })\n\n  it('should return the correct states for a successful query', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery(() => ({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        getNextPageParam: (lastPage) => lastPage + 1,\n        initialPageParam: 0,\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toEqual({\n      data: undefined,\n      dataUpdatedAt: 0,\n      error: null,\n      errorUpdatedAt: 0,\n      failureCount: 0,\n      failureReason: null,\n      errorUpdateCount: 0,\n      fetchNextPage: expect.any(Function),\n      fetchPreviousPage: expect.any(Function),\n      hasNextPage: false,\n      hasPreviousPage: false,\n      isError: false,\n      isFetched: false,\n      isFetchedAfterMount: false,\n      isFetching: true,\n      isPaused: false,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isPending: true,\n      isLoading: true,\n      isInitialLoading: true,\n      isLoadingError: false,\n      isPlaceholderData: false,\n      isRefetchError: false,\n      isRefetching: false,\n      isStale: true,\n      isSuccess: false,\n      isEnabled: true,\n      refetch: expect.any(Function),\n      status: 'pending',\n      fetchStatus: 'fetching',\n      promise: expect.any(Promise),\n    })\n    expect(states[1]).toEqual({\n      data: { pages: [0], pageParams: [0] },\n      dataUpdatedAt: expect.any(Number),\n      error: null,\n      errorUpdatedAt: 0,\n      failureCount: 0,\n      failureReason: null,\n      errorUpdateCount: 0,\n      fetchNextPage: expect.any(Function),\n      fetchPreviousPage: expect.any(Function),\n      hasNextPage: true,\n      hasPreviousPage: false,\n      isError: false,\n      isFetched: true,\n      isFetchedAfterMount: true,\n      isFetching: false,\n      isPaused: false,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isPending: false,\n      isLoading: false,\n      isInitialLoading: false,\n      isLoadingError: false,\n      isPlaceholderData: false,\n      isRefetchError: false,\n      isRefetching: false,\n      isStale: true,\n      isSuccess: true,\n      isEnabled: true,\n      refetch: expect.any(Function),\n      status: 'success',\n      fetchStatus: 'idle',\n      promise: expect.any(Promise),\n    })\n  })\n\n  it('should not throw when fetchNextPage returns an error', async () => {\n    const key = queryKey()\n    let noThrow = false\n\n    function Page() {\n      const start = 1\n      const state = useInfiniteQuery(() => ({\n        queryKey: key,\n        queryFn: ({ pageParam }) =>\n          sleep(10).then(() => {\n            if (pageParam === 2) throw new Error('error')\n            return pageParam\n          }),\n        retry: 1,\n        retryDelay: 10,\n        initialPageParam: start,\n        getNextPageParam: (lastPage) => lastPage + 1,\n      }))\n\n      createEffect(() => {\n        const fetchNextPage = state.fetchNextPage\n        setActTimeout(() => {\n          fetchNextPage()\n            .then(() => {\n              noThrow = true\n            })\n            .catch(() => undefined)\n        }, 20)\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(50)\n\n    expect(noThrow).toBe(true)\n  })\n\n  it('should keep the previous data when placeholderData is set', async () => {\n    const key = queryKey()\n    const states: Array<Partial<UseInfiniteQueryResult<InfiniteData<string>>>> =\n      []\n\n    function Page() {\n      const [order, setOrder] = createSignal('desc')\n\n      const state = useInfiniteQuery(() => ({\n        queryKey: [key, order()],\n        queryFn: ({ pageParam }) =>\n          sleep(10).then(() => `${pageParam}-${order()}`),\n        getNextPageParam: () => 1,\n        initialPageParam: 0,\n        placeholderData: keepPreviousData,\n        notifyOnChangeProps: 'all',\n      }))\n\n      createRenderEffect(() => {\n        states.push({\n          ...state,\n          data: state.data ? JSON.parse(JSON.stringify(state.data)) : undefined,\n        })\n      })\n\n      return (\n        <div>\n          <button onClick={() => state.fetchNextPage()}>fetchNextPage</button>\n          <button onClick={() => setOrder('asc')}>order</button>\n          <div>data: {state.data?.pages.join(',') ?? 'null'}</div>\n          <div>isFetching: {String(state.isFetching)}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 0-desc')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i }))\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 0-desc,1-desc')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /order/i }))\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 0-asc')).toBeInTheDocument()\n    expect(rendered.getByText('isFetching: false')).toBeInTheDocument()\n\n    expect(states.length).toBe(6)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: false,\n      isPlaceholderData: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: ['0-desc'] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    expect(states[2]).toMatchObject({\n      data: { pages: ['0-desc'] },\n      isFetching: true,\n      isFetchingNextPage: true,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    expect(states[3]).toMatchObject({\n      data: { pages: ['0-desc', '1-desc'] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Set state\n    expect(states[4]).toMatchObject({\n      data: { pages: ['0-desc', '1-desc'] },\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    expect(states[5]).toMatchObject({\n      data: { pages: ['0-asc'] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n  })\n\n  it('should be able to select a part of the data', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<string>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => ({ count: 1 })),\n        select: (data) => ({\n          pages: data.pages.map((x) => `count: ${x.count}`),\n          pageParams: data.pageParams,\n        }),\n        getNextPageParam: () => undefined,\n        initialPageParam: 0,\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isSuccess: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: ['count: 1'] },\n      isSuccess: true,\n    })\n  })\n\n  it('should be able to select a new result and not cause infinite renders', async () => {\n    const key = queryKey()\n    const states: Array<\n      UseInfiniteQueryResult<InfiniteData<{ count: number; id: number }>>\n    > = []\n    let selectCalled = 0\n\n    function Page() {\n      const state = useInfiniteQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => ({ count: 1 })),\n        select: (data) => {\n          selectCalled++\n          return {\n            pages: data.pages.map((x) => ({ ...x, id: Math.random() })),\n            pageParams: data.pageParams,\n          }\n        },\n        getNextPageParam: () => undefined,\n        initialPageParam: 0,\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    expect(selectCalled).toBe(1)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isSuccess: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: [{ count: 1 }] },\n      isSuccess: true,\n    })\n  })\n\n  it('should be able to reverse the data', async () => {\n    const key = queryKey()\n    const states: Array<Partial<UseInfiniteQueryResult<InfiniteData<number>>>> =\n      []\n\n    function Page() {\n      const state = useInfiniteQuery(() => ({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        select: (data) => ({\n          pages: [...data.pages].reverse(),\n          pageParams: [...data.pageParams].reverse(),\n        }),\n        notifyOnChangeProps: 'all',\n        getNextPageParam: () => 1,\n        initialPageParam: 0,\n      }))\n\n      createRenderEffect(\n        on(\n          () => ({ ...state }),\n          () => {\n            states.push({\n              data: state.data\n                ? JSON.parse(JSON.stringify(state.data))\n                : undefined,\n              isSuccess: state.isSuccess,\n            })\n          },\n        ),\n      )\n\n      return (\n        <div>\n          <button onClick={() => state.fetchNextPage()}>fetchNextPage</button>\n          <div>data: {state.data?.pages.join(',') ?? 'null'}</div>\n          <div>isFetching: {state.isFetching}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i }))\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 1,0')).toBeInTheDocument()\n\n    expect(states.length).toBe(4)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isSuccess: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: [0] },\n      isSuccess: true,\n    })\n    expect(states[2]).toMatchObject({\n      data: { pages: [0] },\n      isSuccess: true,\n    })\n    expect(states[3]).toMatchObject({\n      data: { pages: [1, 0] },\n      isSuccess: true,\n    })\n  })\n\n  it('should be able to fetch a previous page', async () => {\n    const key = queryKey()\n    const states: Array<Partial<UseInfiniteQueryResult<InfiniteData<number>>>> =\n      []\n\n    function Page() {\n      const start = 10\n      const state = useInfiniteQuery(() => ({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        getNextPageParam: (lastPage) => lastPage + 1,\n        getPreviousPageParam: (firstPage) => firstPage - 1,\n        initialPageParam: start,\n        notifyOnChangeProps: 'all',\n      }))\n\n      createRenderEffect(() => {\n        states.push({\n          data: state.data ? JSON.parse(JSON.stringify(state.data)) : undefined,\n          hasNextPage: state.hasNextPage,\n          hasPreviousPage: state.hasPreviousPage,\n          isFetching: state.isFetching,\n          isFetchingNextPage: state.isFetchingNextPage,\n          isFetchingPreviousPage: state.isFetchingPreviousPage,\n          isSuccess: state.isSuccess,\n        })\n      })\n\n      createEffect(() => {\n        const fetchPreviousPage = state.fetchPreviousPage\n        setActTimeout(() => {\n          fetchPreviousPage()\n        }, 20)\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(30)\n\n    expect(states.length).toBe(4)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      hasNextPage: false,\n      hasPreviousPage: false,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isFetchingPreviousPage: false,\n      isSuccess: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: [10] },\n      hasNextPage: true,\n      hasPreviousPage: true,\n      isFetching: false,\n      isFetchingNextPage: false,\n      isFetchingPreviousPage: false,\n      isSuccess: true,\n    })\n    expect(states[2]).toMatchObject({\n      data: { pages: [10] },\n      hasNextPage: true,\n      hasPreviousPage: true,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isFetchingPreviousPage: true,\n      isSuccess: true,\n    })\n    expect(states[3]).toMatchObject({\n      data: { pages: [9, 10] },\n      hasNextPage: true,\n      hasPreviousPage: true,\n      isFetching: false,\n      isFetchingNextPage: false,\n      isFetchingPreviousPage: false,\n      isSuccess: true,\n    })\n  })\n\n  it('should be able to refetch when providing page params automatically', async () => {\n    const key = queryKey()\n    const states: Array<Partial<UseInfiniteQueryResult<InfiniteData<number>>>> =\n      []\n\n    function Page() {\n      const state = useInfiniteQuery(() => ({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        getPreviousPageParam: (firstPage) => firstPage - 1,\n        getNextPageParam: (lastPage) => lastPage + 1,\n        initialPageParam: 10,\n        notifyOnChangeProps: 'all',\n      }))\n\n      createRenderEffect(() => {\n        states.push({\n          data: state.data ? JSON.parse(JSON.stringify(state.data)) : undefined,\n          isFetching: state.isFetching,\n          isFetchingNextPage: state.isFetchingNextPage,\n          isRefetching: state.isRefetching,\n          isFetchingPreviousPage: state.isFetchingPreviousPage,\n        })\n      })\n\n      return (\n        <div>\n          <button onClick={() => state.fetchNextPage()}>fetchNextPage</button>\n          <button onClick={() => state.fetchPreviousPage()}>\n            fetchPreviousPage\n          </button>\n          <button onClick={() => state.refetch()}>refetch</button>\n          <div>data: {state.data?.pages.join(',') ?? 'null'}</div>\n          <div>isFetching: {String(state.isFetching)}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 10')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i }))\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 10,11')).toBeInTheDocument()\n\n    fireEvent.click(\n      rendered.getByRole('button', { name: /fetchPreviousPage/i }),\n    )\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 9,10,11')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n    await vi.advanceTimersByTimeAsync(30)\n    expect(rendered.getByText('isFetching: false')).toBeInTheDocument()\n\n    expect(states.length).toBe(8)\n    // Initial fetch\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isRefetching: false,\n    })\n    // Initial fetch done\n    expect(states[1]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isRefetching: false,\n    })\n    // Fetch next page\n    expect(states[2]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: true,\n      isFetchingNextPage: true,\n      isRefetching: false,\n    })\n    // Fetch next page done\n    expect(states[3]).toMatchObject({\n      data: { pages: [10, 11] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isRefetching: false,\n    })\n    // Fetch previous page\n    expect(states[4]).toMatchObject({\n      data: { pages: [10, 11] },\n      isFetching: true,\n      isFetchingNextPage: false,\n      isFetchingPreviousPage: true,\n      isRefetching: false,\n    })\n    // Fetch previous page done\n    expect(states[5]).toMatchObject({\n      data: { pages: [9, 10, 11] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isFetchingPreviousPage: false,\n      isRefetching: false,\n    })\n    // Refetch\n    expect(states[6]).toMatchObject({\n      data: { pages: [9, 10, 11] },\n      isFetching: true,\n      isFetchingNextPage: false,\n      isFetchingPreviousPage: false,\n      isRefetching: true,\n    })\n    // Refetch done\n    expect(states[7]).toMatchObject({\n      data: { pages: [9, 10, 11] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isFetchingPreviousPage: false,\n      isRefetching: false,\n    })\n  })\n\n  it('should return the correct states when refetch fails', async () => {\n    const key = queryKey()\n    const states: Array<Partial<UseInfiniteQueryResult<InfiniteData<number>>>> =\n      []\n\n    let isRefetch = false\n\n    function Page() {\n      const state = useInfiniteQuery(() => ({\n        queryKey: key,\n        queryFn: ({ pageParam }) =>\n          sleep(10).then(() => {\n            if (isRefetch) throw new Error()\n            return pageParam\n          }),\n        getPreviousPageParam: (firstPage) => firstPage - 1,\n        getNextPageParam: (lastPage) => lastPage + 1,\n        initialPageParam: 10,\n        notifyOnChangeProps: 'all',\n        retry: false,\n      }))\n\n      createRenderEffect(() => {\n        states.push({\n          data: state.data ? JSON.parse(JSON.stringify(state.data)) : undefined,\n          isFetching: state.isFetching,\n          isFetchNextPageError: state.isFetchNextPageError,\n          isFetchingNextPage: state.isFetchingNextPage,\n          isFetchPreviousPageError: state.isFetchPreviousPageError,\n          isFetchingPreviousPage: state.isFetchingPreviousPage,\n          isRefetchError: state.isRefetchError as true,\n          isRefetching: state.isRefetching,\n        })\n      })\n\n      return (\n        <div>\n          <button\n            onClick={() => {\n              isRefetch = true\n              state.refetch()\n            }}\n          >\n            refetch\n          </button>\n          <div>data: {state.data?.pages.join(',') ?? 'null'}</div>\n          <div>isFetching: {String(state.isFetching)}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 10')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('isFetching: false')).toBeInTheDocument()\n\n    expect(states.length).toBe(4)\n    // Initial fetch\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n    // Initial fetch done\n    expect(states[1]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: false,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n    // Refetch\n    expect(states[2]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: true,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: true,\n    })\n    // Refetch failed\n    expect(states[3]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: false,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: true,\n      isRefetching: false,\n    })\n  })\n\n  it('should return the correct states when fetchNextPage fails', async () => {\n    const key = queryKey()\n    const states: Array<Partial<UseInfiniteQueryResult<InfiniteData<number>>>> =\n      []\n\n    function Page() {\n      const state = useInfiniteQuery(() => ({\n        queryKey: key,\n        queryFn: ({ pageParam }) =>\n          sleep(10).then(() => {\n            if (pageParam !== 10) throw new Error()\n            return pageParam\n          }),\n        getPreviousPageParam: (firstPage) => firstPage - 1,\n        getNextPageParam: (lastPage) => lastPage + 1,\n        initialPageParam: 10,\n        notifyOnChangeProps: 'all',\n        retry: false,\n      }))\n\n      createRenderEffect(() => {\n        states.push({\n          data: state.data ? JSON.parse(JSON.stringify(state.data)) : undefined,\n          isFetching: state.isFetching,\n          isFetchNextPageError: state.isFetchNextPageError,\n          isFetchingNextPage: state.isFetchingNextPage,\n          isFetchPreviousPageError: state.isFetchPreviousPageError,\n          isFetchingPreviousPage: state.isFetchingPreviousPage,\n          isRefetchError: state.isRefetchError as true,\n          isRefetching: state.isRefetching,\n        })\n      })\n\n      return (\n        <div>\n          <button onClick={() => state.fetchNextPage()}>fetchNextPage</button>\n          <div>data: {state.data?.pages.join(',') ?? 'null'}</div>\n          <div>isFetching: {String(state.isFetching)}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 10')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i }))\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('isFetching: false')).toBeInTheDocument()\n\n    expect(states.length).toBe(4)\n    // Initial fetch\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n    // Initial fetch done\n    expect(states[1]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: false,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n    // Fetch next page\n    expect(states[2]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: true,\n      isFetchNextPageError: false,\n      isFetchingNextPage: true,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n    // Fetch next page failed\n    expect(states[3]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: false,\n      isFetchNextPageError: true,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n  })\n\n  it('should return the correct states when fetchPreviousPage fails', async () => {\n    const key = queryKey()\n    const states: Array<Partial<UseInfiniteQueryResult<InfiniteData<number>>>> =\n      []\n\n    function Page() {\n      const state = useInfiniteQuery(() => ({\n        queryKey: key,\n        queryFn: ({ pageParam }) =>\n          sleep(10).then(() => {\n            if (pageParam !== 10) throw new Error()\n            return pageParam\n          }),\n        getPreviousPageParam: (firstPage) => firstPage - 1,\n        getNextPageParam: (lastPage) => lastPage + 1,\n        initialPageParam: 10,\n        notifyOnChangeProps: 'all',\n        retry: false,\n      }))\n\n      createRenderEffect(() => {\n        states.push({\n          data: state.data ? JSON.parse(JSON.stringify(state.data)) : undefined,\n          isFetching: state.isFetching,\n          isFetchNextPageError: state.isFetchNextPageError,\n          isFetchingNextPage: state.isFetchingNextPage,\n          isFetchPreviousPageError: state.isFetchPreviousPageError,\n          isFetchingPreviousPage: state.isFetchingPreviousPage,\n          isRefetchError: state.isRefetchError as true,\n          isRefetching: state.isRefetching,\n        })\n      })\n\n      return (\n        <div>\n          <button onClick={() => state.fetchPreviousPage()}>\n            fetchPreviousPage\n          </button>\n          <div>data: {state.data?.pages.join(',') ?? 'null'}</div>\n          <div>isFetching: {String(state.isFetching)}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 10')).toBeInTheDocument()\n\n    fireEvent.click(\n      rendered.getByRole('button', { name: /fetchPreviousPage/i }),\n    )\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('isFetching: false')).toBeInTheDocument()\n\n    expect(states.length).toBe(4)\n    // Initial fetch\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n    // Initial fetch done\n    expect(states[1]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: false,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n    // Fetch previous page\n    expect(states[2]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: true,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: true,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n    // Fetch previous page failed\n    expect(states[3]).toMatchObject({\n      data: { pages: [10] },\n      isFetching: false,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: true,\n      isFetchingPreviousPage: false,\n      isRefetchError: false,\n      isRefetching: false,\n    })\n  })\n\n  it('should silently cancel any ongoing fetch when fetching more', async () => {\n    const key = queryKey()\n    const states: Array<Partial<UseInfiniteQueryResult<InfiniteData<number>>>> =\n      []\n\n    function Page() {\n      const start = 10\n      const state = useInfiniteQuery(() => ({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(50).then(() => pageParam),\n        getNextPageParam: (lastPage) => lastPage + 1,\n        initialPageParam: start,\n        notifyOnChangeProps: 'all',\n      }))\n\n      createRenderEffect(() => {\n        states.push({\n          hasNextPage: state.hasNextPage,\n          data: state.data ? JSON.parse(JSON.stringify(state.data)) : undefined,\n          isFetching: state.isFetching,\n          isFetchingNextPage: state.isFetchingNextPage,\n          isSuccess: state.isSuccess,\n        })\n      })\n\n      createEffect(() => {\n        const { refetch, fetchNextPage } = state\n        setActTimeout(() => {\n          refetch()\n        }, 100)\n        setActTimeout(() => {\n          fetchNextPage()\n        }, 110)\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(160)\n\n    expect(states.length).toBe(5)\n    expect(states[0]).toMatchObject({\n      hasNextPage: false,\n      data: undefined,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: false,\n    })\n    expect(states[1]).toMatchObject({\n      hasNextPage: true,\n      data: { pages: [10] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n    expect(states[2]).toMatchObject({\n      hasNextPage: true,\n      data: { pages: [10] },\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n    expect(states[3]).toMatchObject({\n      hasNextPage: true,\n      data: { pages: [10] },\n      isFetching: true,\n      isFetchingNextPage: true,\n      isSuccess: true,\n    })\n    expect(states[4]).toMatchObject({\n      hasNextPage: true,\n      data: { pages: [10, 11] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n  })\n\n  it('should silently cancel an ongoing fetchNextPage request when another fetchNextPage is invoked', async () => {\n    const key = queryKey()\n    const start = 10\n    const onAborts: Array<Mock<(...args: Array<any>) => any>> = []\n    const abortListeners: Array<Mock<(...args: Array<any>) => any>> = []\n    const fetchPage = vi.fn<\n      (context: QueryFunctionContext<typeof key, number>) => Promise<number>\n    >(async ({ pageParam, signal }) => {\n      const onAbort = vi.fn()\n      const abortListener = vi.fn()\n      onAborts.push(onAbort)\n      abortListeners.push(abortListener)\n      signal.onabort = onAbort\n      signal.addEventListener('abort', abortListener)\n\n      await sleep(50)\n      return pageParam\n    })\n\n    function Page() {\n      const state = useInfiniteQuery(() => ({\n        queryKey: key,\n        queryFn: fetchPage,\n        getNextPageParam: (lastPage) => lastPage + 1,\n        initialPageParam: start,\n      }))\n\n      createEffect(() => {\n        const { fetchNextPage } = state\n        setActTimeout(() => {\n          fetchNextPage()\n        }, 100)\n        setActTimeout(() => {\n          fetchNextPage()\n        }, 110)\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(160)\n\n    const expectedCallCount = 3\n    expect(fetchPage).toBeCalledTimes(expectedCallCount)\n    expect(onAborts).toHaveLength(expectedCallCount)\n    expect(abortListeners).toHaveLength(expectedCallCount)\n\n    let callIndex = 0\n    const firstCtx = fetchPage.mock.calls[callIndex]![0]\n    expect(firstCtx.pageParam).toEqual(start)\n    expect(firstCtx.queryKey).toEqual(key)\n    expect(firstCtx.signal).toBeInstanceOf(AbortSignal)\n    expect(firstCtx.signal.aborted).toBe(false)\n    expect(onAborts[callIndex]).not.toHaveBeenCalled()\n    expect(abortListeners[callIndex]).not.toHaveBeenCalled()\n\n    callIndex = 1\n    const secondCtx = fetchPage.mock.calls[callIndex]![0]\n    expect(secondCtx.pageParam).toBe(11)\n    expect(secondCtx.queryKey).toEqual(key)\n    expect(secondCtx.signal).toBeInstanceOf(AbortSignal)\n    expect(secondCtx.signal.aborted).toBe(true)\n    expect(onAborts[callIndex]).toHaveBeenCalledTimes(1)\n    expect(abortListeners[callIndex]).toHaveBeenCalledTimes(1)\n\n    callIndex = 2\n    const thirdCtx = fetchPage.mock.calls[callIndex]![0]\n    expect(thirdCtx.pageParam).toBe(11)\n    expect(thirdCtx.queryKey).toEqual(key)\n    expect(thirdCtx.signal).toBeInstanceOf(AbortSignal)\n    expect(thirdCtx.signal.aborted).toBe(false)\n    expect(onAborts[callIndex]).not.toHaveBeenCalled()\n    expect(abortListeners[callIndex]).not.toHaveBeenCalled()\n  })\n\n  it('should not cancel an ongoing fetchNextPage request when another fetchNextPage is invoked if `cancelRefetch: false` is used', async () => {\n    const key = queryKey()\n    const start = 10\n    const onAborts: Array<Mock<(...args: Array<any>) => any>> = []\n    const abortListeners: Array<Mock<(...args: Array<any>) => any>> = []\n    const fetchPage = vi.fn<\n      (context: QueryFunctionContext<typeof key, number>) => Promise<number>\n    >(async ({ pageParam, signal }) => {\n      const onAbort = vi.fn()\n      const abortListener = vi.fn()\n      onAborts.push(onAbort)\n      abortListeners.push(abortListener)\n      signal.onabort = onAbort\n      signal.addEventListener('abort', abortListener)\n\n      await sleep(50)\n      return pageParam\n    })\n\n    function Page() {\n      const state = useInfiniteQuery(() => ({\n        queryKey: key,\n        queryFn: fetchPage,\n        getNextPageParam: (lastPage) => lastPage + 1,\n        initialPageParam: start,\n      }))\n\n      createEffect(() => {\n        const { fetchNextPage } = state\n        setActTimeout(() => {\n          fetchNextPage()\n        }, 100)\n        setActTimeout(() => {\n          fetchNextPage({ cancelRefetch: false })\n        }, 110)\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(160)\n\n    const expectedCallCount = 2\n    expect(fetchPage).toBeCalledTimes(expectedCallCount)\n    expect(onAborts).toHaveLength(expectedCallCount)\n    expect(abortListeners).toHaveLength(expectedCallCount)\n\n    let callIndex = 0\n    const firstCtx = fetchPage.mock.calls[callIndex]![0]\n    expect(firstCtx.pageParam).toEqual(start)\n    expect(firstCtx.queryKey).toEqual(key)\n    expect(firstCtx.signal).toBeInstanceOf(AbortSignal)\n    expect(firstCtx.signal.aborted).toBe(false)\n    expect(onAborts[callIndex]).not.toHaveBeenCalled()\n    expect(abortListeners[callIndex]).not.toHaveBeenCalled()\n\n    callIndex = 1\n    const secondCtx = fetchPage.mock.calls[callIndex]![0]\n    expect(secondCtx.pageParam).toBe(11)\n    expect(secondCtx.queryKey).toEqual(key)\n    expect(secondCtx.signal).toBeInstanceOf(AbortSignal)\n    expect(secondCtx.signal.aborted).toBe(false)\n    expect(onAborts[callIndex]).not.toHaveBeenCalled()\n    expect(abortListeners[callIndex]).not.toHaveBeenCalled()\n  })\n\n  it('should keep fetching first page when not loaded yet and triggering fetch more', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const start = 10\n      const state = useInfiniteQuery(() => ({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(50).then(() => pageParam),\n        getNextPageParam: (lastPage) => lastPage + 1,\n        initialPageParam: start,\n        notifyOnChangeProps: 'all',\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      createEffect(() => {\n        const { fetchNextPage } = state\n        setActTimeout(() => {\n          fetchNextPage()\n        }, 10)\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(60)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      hasNextPage: false,\n      data: undefined,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: false,\n    })\n    expect(states[1]).toMatchObject({\n      hasNextPage: true,\n      data: { pages: [10] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n  })\n\n  it('should stop fetching additional pages when the component is unmounted and AbortSignal is consumed', async () => {\n    const key = queryKey()\n    let fetches = 0\n\n    const initialData = { pages: [1, 2, 3, 4], pageParams: [0, 1, 2, 3] }\n\n    function List() {\n      useInfiniteQuery(() => ({\n        queryKey: key,\n        queryFn: ({ pageParam }) =>\n          sleep(50).then(() => {\n            fetches++\n            return pageParam * 10\n          }),\n        initialData,\n        getNextPageParam: (_, allPages) => {\n          return allPages.length === 4 ? undefined : allPages.length\n        },\n        initialPageParam: 0,\n      }))\n\n      return null\n    }\n\n    function Page() {\n      const [show, setShow] = createSignal(true)\n\n      createEffect(() => {\n        setActTimeout(() => {\n          setShow(false)\n        }, 75)\n      })\n\n      return <>{show() ? <List /> : null}</>\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(125)\n\n    expect(fetches).toBe(2)\n    expect(queryClient.getQueryState(key)).toMatchObject({\n      data: initialData,\n      status: 'success',\n      error: null,\n    })\n  })\n\n  it('should be able to set new pages with the query client', async () => {\n    const key = queryKey()\n    const states: Array<Partial<UseInfiniteQueryResult<InfiniteData<number>>>> =\n      []\n\n    function Page() {\n      const [firstPage, setFirstPage] = createSignal(0)\n\n      const state = useInfiniteQuery(() => ({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        getNextPageParam: (lastPage) => lastPage + 1,\n        notifyOnChangeProps: 'all',\n        initialPageParam: firstPage(),\n      }))\n\n      createRenderEffect(() => {\n        states.push({\n          hasNextPage: state.hasNextPage,\n          data: state.data ? JSON.parse(JSON.stringify(state.data)) : undefined,\n          isFetching: state.isFetching,\n          isFetchingNextPage: state.isFetchingNextPage,\n          isSuccess: state.isSuccess,\n        })\n      })\n\n      createEffect(() => {\n        const { refetch } = state\n        setActTimeout(() => {\n          queryClient.setQueryData(key, { pages: [7, 8], pageParams: [7, 8] })\n          setFirstPage(7)\n        }, 20)\n\n        setActTimeout(() => {\n          refetch()\n        }, 50)\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(70)\n\n    expect(states.length).toBe(5)\n    expect(states[0]).toMatchObject({\n      hasNextPage: false,\n      data: undefined,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: false,\n    })\n    // After first fetch\n    expect(states[1]).toMatchObject({\n      hasNextPage: true,\n      data: { pages: [0] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n    // Set state\n    expect(states[2]).toMatchObject({\n      hasNextPage: true,\n      data: { pages: [7, 8] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n    // Refetch\n    expect(states[3]).toMatchObject({\n      hasNextPage: true,\n      data: { pages: [7, 8] },\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n    // Refetch done\n    expect(states[4]).toMatchObject({\n      hasNextPage: true,\n      data: { pages: [7, 8] },\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n  })\n\n  it('should only refetch the first page when initialData is provided', async () => {\n    const key = queryKey()\n    const states: Array<Partial<UseInfiniteQueryResult<InfiniteData<number>>>> =\n      []\n\n    function Page() {\n      const state = useInfiniteQuery(() => ({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        initialData: { pages: [1], pageParams: [1] },\n        getNextPageParam: (lastPage) => lastPage + 1,\n        initialPageParam: 0,\n        notifyOnChangeProps: 'all',\n      }))\n\n      createRenderEffect(() => {\n        states.push({\n          data: JSON.parse(JSON.stringify(state.data)),\n          hasNextPage: state.hasNextPage,\n          isFetching: state.isFetching,\n          isFetchingNextPage: state.isFetchingNextPage,\n          isSuccess: state.isSuccess,\n        })\n      })\n\n      createEffect(() => {\n        const { fetchNextPage } = state\n        setActTimeout(() => {\n          fetchNextPage()\n        }, 20)\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(30)\n\n    expect(states.length).toBe(4)\n    expect(states[0]).toMatchObject({\n      data: { pages: [1] },\n      hasNextPage: true,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: [1] },\n      hasNextPage: true,\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n    expect(states[2]).toMatchObject({\n      data: { pages: [1] },\n      hasNextPage: true,\n      isFetching: true,\n      isFetchingNextPage: true,\n      isSuccess: true,\n    })\n    expect(states[3]).toMatchObject({\n      data: { pages: [1, 2] },\n      hasNextPage: true,\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n  })\n\n  it('should set hasNextPage to false if getNextPageParam returns undefined', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery(() => ({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        initialPageParam: 1,\n        getNextPageParam: () => undefined,\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      hasNextPage: false,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: [1] },\n      hasNextPage: false,\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n  })\n\n  it('should compute hasNextPage correctly using initialData', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery(() => ({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        initialPageParam: 10,\n        initialData: { pages: [10], pageParams: [10] },\n        getNextPageParam: (lastPage) => (lastPage === 10 ? 11 : undefined),\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: { pages: [10] },\n      hasNextPage: true,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: [10] },\n      hasNextPage: true,\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n  })\n\n  it('should compute hasNextPage correctly for falsy getFetchMore return value using initialData', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery(() => ({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        initialPageParam: 10,\n        initialData: { pages: [10], pageParams: [10] },\n        getNextPageParam: () => undefined,\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: { pages: [10] },\n      hasNextPage: false,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: [10] },\n      hasNextPage: false,\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n  })\n\n  it('should not use selected data when computing hasNextPage', async () => {\n    const key = queryKey()\n    const states: Array<UseInfiniteQueryResult<InfiniteData<string>>> = []\n\n    function Page() {\n      const state = useInfiniteQuery(() => ({\n        queryKey: key,\n        queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n        initialPageParam: 1,\n        getNextPageParam: (lastPage) => (lastPage === 1 ? 2 : undefined),\n        select: (data) => ({\n          pages: data.pages.map((x) => x.toString()),\n          pageParams: data.pageParams,\n        }),\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      hasNextPage: false,\n      isFetching: true,\n      isFetchingNextPage: false,\n      isSuccess: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: { pages: ['1'] },\n      hasNextPage: true,\n      isFetching: false,\n      isFetchingNextPage: false,\n      isSuccess: true,\n    })\n  })\n\n  it('should build fresh cursors on refetch', async () => {\n    const key = queryKey()\n\n    const genItems = (size: number) =>\n      [...new Array(size)].fill(null).map((_, d) => d)\n    const items = genItems(15)\n    const limit = 3\n\n    const fetchItemsWithLimit = (cursor = 0, ts: number) =>\n      sleep(10).then(() => ({\n        nextId: cursor + limit,\n        items: items.slice(cursor, cursor + limit),\n        ts,\n      }))\n\n    function Page() {\n      let fetchCountRef = 0\n      const state = useInfiniteQuery(() => ({\n        queryKey: key,\n        queryFn: ({ pageParam }) =>\n          fetchItemsWithLimit(pageParam, fetchCountRef++),\n        initialPageParam: 0,\n        getNextPageParam: (lastPage) => lastPage.nextId,\n      }))\n\n      return (\n        <div>\n          <h1>Pagination</h1>\n          <Switch\n            fallback={\n              <>\n                <div>Data:</div>\n                <For each={state.data?.pages ?? []}>\n                  {(page, i) => (\n                    <div>\n                      <div>\n                        Page {i()}: {page.ts}\n                      </div>\n                      <div>\n                        <Index each={page.items}>\n                          {(item) => <p>Item: {item()}</p>}\n                        </Index>\n                      </div>\n                    </div>\n                  )}\n                </For>\n                <div>\n                  <button\n                    onClick={() => state.fetchNextPage()}\n                    disabled={\n                      !state.hasNextPage || Boolean(state.isFetchingNextPage)\n                    }\n                  >\n                    <Switch fallback={<>Nothing more to load</>}>\n                      <Match when={state.isFetchingNextPage}>\n                        Loading more...\n                      </Match>\n                      <Match when={state.hasNextPage}>Load More</Match>\n                    </Switch>\n                  </button>\n                  <button onClick={() => state.refetch()}>Refetch</button>\n                  <button\n                    onClick={() => {\n                      // Imagine that this mutation happens somewhere else\n                      // makes an actual network request\n                      // and calls invalidateQueries in an onSuccess\n                      items.splice(4, 1)\n                      queryClient.invalidateQueries({ queryKey: key })\n                    }}\n                  >\n                    Remove item\n                  </button>\n                </div>\n                <div>\n                  {!state.isFetchingNextPage ? 'Background Updating...' : null}\n                </div>\n              </>\n            }\n          >\n            <Match when={state.status === 'pending'}>Loading...</Match>\n            <Match when={state.status === 'error'}>\n              <span>Error: {state.error?.message}</span>\n            </Match>\n          </Switch>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('Loading...')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('Item: 2')).toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('Load More'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Loading more...')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('Item: 5')).toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 0')).toBeInTheDocument()\n    expect(rendered.getByText('Page 1: 1')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('Load More'))\n    await vi.advanceTimersByTimeAsync(0)\n    rendered.getByText('Loading more...')\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('Item: 8')).toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 0')).toBeInTheDocument()\n    expect(rendered.getByText('Page 1: 1')).toBeInTheDocument()\n    expect(rendered.getByText('Page 2: 2')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('Refetch'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Background Updating...')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(30)\n    expect(rendered.getByText('Item: 8')).toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 3')).toBeInTheDocument()\n    expect(rendered.getByText('Page 1: 4')).toBeInTheDocument()\n    expect(rendered.getByText('Page 2: 5')).toBeInTheDocument()\n\n    // ensure that Item: 4 is rendered before removing it\n    expect(rendered.queryAllByText('Item: 4')).toHaveLength(1)\n\n    // remove Item: 4\n    fireEvent.click(rendered.getByText('Remove item'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Background Updating...')).toBeInTheDocument()\n    // ensure that an additional item is rendered (it means that cursors were properly rebuilt)\n    await vi.advanceTimersByTimeAsync(30)\n    expect(rendered.getByText('Item: 9')).toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 6')).toBeInTheDocument()\n    expect(rendered.getByText('Page 1: 7')).toBeInTheDocument()\n    expect(rendered.getByText('Page 2: 8')).toBeInTheDocument()\n\n    // ensure that Item: 4 is no longer rendered\n    expect(rendered.queryAllByText('Item: 4')).toHaveLength(0)\n  })\n\n  it('should compute hasNextPage correctly for falsy getFetchMore return value on refetching', async () => {\n    const key = queryKey()\n    const MAX = 2\n\n    function Page() {\n      let fetchCountRef = 0\n      const [isRemovedLastPage, setIsRemovedLastPage] =\n        createSignal<boolean>(false)\n\n      const state = useInfiniteQuery(() => ({\n        queryKey: key,\n        queryFn: ({ pageParam }) =>\n          fetchItems(\n            pageParam,\n            fetchCountRef++,\n            pageParam === MAX || (pageParam === MAX - 1 && isRemovedLastPage()),\n          ),\n        initialPageParam: 0,\n        getNextPageParam: (lastPage) => lastPage.nextId,\n      }))\n\n      return (\n        <div>\n          <h1>Pagination</h1>\n          <Switch\n            fallback={\n              <>\n                <div>Data:</div>\n                <For each={state.data!.pages}>\n                  {(page, i) => (\n                    <div>\n                      <div>\n                        Page {i()}: {page.ts}\n                      </div>\n                      <div>\n                        <Index each={page.items}>\n                          {(item) => <p>Item: {item()}</p>}\n                        </Index>\n                      </div>\n                    </div>\n                  )}\n                </For>\n                <div>\n                  <button\n                    onClick={() => state.fetchNextPage()}\n                    disabled={\n                      !state.hasNextPage || Boolean(state.isFetchingNextPage)\n                    }\n                  >\n                    {state.isFetchingNextPage\n                      ? 'Loading more...'\n                      : state.hasNextPage\n                        ? 'Load More'\n                        : 'Nothing more to load'}\n                  </button>\n                  <button onClick={() => state.refetch()}>Refetch</button>\n                  <button onClick={() => setIsRemovedLastPage(true)}>\n                    Remove Last Page\n                  </button>\n                </div>\n                <div>\n                  {state.isFetching && !state.isFetchingNextPage\n                    ? 'Background Updating...'\n                    : null}\n                </div>\n              </>\n            }\n          >\n            <Match when={state.status === 'pending'}>Loading...</Match>\n            <Match when={state.status === 'error'}>\n              <span>Error: {state.error?.message}</span>\n            </Match>\n          </Switch>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('Loading...')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('Item: 9')).toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('Load More'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Loading more...')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('Item: 19')).toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 0')).toBeInTheDocument()\n    expect(rendered.getByText('Page 1: 1')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('Load More'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Loading more...')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('Item: 29')).toBeInTheDocument()\n    expect(rendered.getByText('Page 0: 0')).toBeInTheDocument()\n    expect(rendered.getByText('Page 1: 1')).toBeInTheDocument()\n    expect(rendered.getByText('Page 2: 2')).toBeInTheDocument()\n    expect(rendered.getByText('Nothing more to load')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('Remove Last Page'))\n    fireEvent.click(rendered.getByText('Refetch'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Background Updating...')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(20)\n    expect(rendered.getByText('Page 0: 3')).toBeInTheDocument()\n    expect(rendered.getByText('Page 1: 4')).toBeInTheDocument()\n    expect(rendered.getByText('Nothing more to load')).toBeInTheDocument()\n    expect(rendered.queryByText('Item: 29')).toBeNull()\n    expect(rendered.queryByText('Page 2: 5')).toBeNull()\n  })\n\n  it('should cancel the query function when there are no more subscriptions', async () => {\n    const key = queryKey()\n    let cancelFn: Mock = vi.fn()\n\n    const queryFn = ({ signal }: { signal?: AbortSignal }) => {\n      const promise = new Promise<string>((resolve, reject) => {\n        cancelFn = vi.fn(() => reject('Cancelled'))\n        signal?.addEventListener('abort', cancelFn)\n        sleep(20).then(() => resolve('OK'))\n      })\n\n      return promise\n    }\n\n    function Page() {\n      const state = useInfiniteQuery(() => ({\n        queryKey: key,\n        queryFn,\n        getNextPageParam: () => undefined,\n        initialPageParam: 0,\n      }))\n      return (\n        <div>\n          <h1>Status: {state.status}</h1>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Blink duration={5}>\n          <Page />\n        </Blink>\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(5)\n    expect(rendered.getByText('off')).toBeInTheDocument()\n\n    expect(cancelFn).toHaveBeenCalled()\n  })\n\n  it('should use provided custom queryClient', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const state = useInfiniteQuery(\n        () => ({\n          queryKey: key,\n          queryFn: () => sleep(10).then(() => 'custom client'),\n          getNextPageParam: () => undefined,\n          initialPageParam: 0,\n        }),\n        () => queryClient,\n      )\n      return (\n        <div>\n          <h1>Status: {state.data?.pages[0]}</h1>\n        </div>\n      )\n    }\n\n    const rendered = render(() => <Page />)\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('Status: custom client')).toBeInTheDocument()\n  })\n\n  it('should work with infiniteQueryOptions', async () => {\n    const key = queryKey()\n\n    const options = infiniteQueryOptions({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 220),\n      getNextPageParam: () => undefined,\n      initialPageParam: 0,\n    })\n\n    function Page() {\n      const state = useInfiniteQuery(\n        () => options,\n        () => queryClient,\n      )\n      return (\n        <div>\n          <h1>Status: {state.data?.pages[0]}</h1>\n        </div>\n      )\n    }\n\n    const rendered = render(() => <Page />)\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('Status: 220')).toBeInTheDocument()\n  })\n})\n"
  },
  {
    "path": "packages/solid-query/src/__tests__/useIsFetching.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { fireEvent, render } from '@solidjs/testing-library'\nimport { Show, createEffect, createRenderEffect, createSignal } from 'solid-js'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport {\n  QueryCache,\n  QueryClient,\n  QueryClientProvider,\n  useIsFetching,\n  useQuery,\n} from '..'\nimport { setActTimeout } from './utils'\n\ndescribe('useIsFetching', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/105\n  it('should update as queries start and stop fetching', async () => {\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({ queryCache })\n    const key = queryKey()\n\n    function IsFetching() {\n      const isFetching = useIsFetching()\n\n      return <div>isFetching: {isFetching()}</div>\n    }\n\n    function Query() {\n      const [ready, setReady] = createSignal(false)\n\n      useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(50).then(() => 'test'),\n        enabled: ready(),\n      }))\n\n      return <button onClick={() => setReady(true)}>setReady</button>\n    }\n\n    function Page() {\n      return (\n        <div>\n          <IsFetching />\n          <Query />\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('isFetching: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /setReady/i }))\n    expect(rendered.getByText('isFetching: 1')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(50)\n    expect(rendered.getByText('isFetching: 0')).toBeInTheDocument()\n  })\n\n  it('should not update state while rendering', async () => {\n    const queryCache = new QueryCache()\n    const queryClient = new QueryClient({ queryCache })\n\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    const isFetchingArray: Array<number> = []\n\n    function IsFetching() {\n      const isFetching = useIsFetching()\n\n      createRenderEffect(() => {\n        isFetchingArray.push(isFetching())\n      })\n\n      return null\n    }\n\n    function FirstQuery() {\n      useQuery(() => ({\n        queryKey: key1,\n        queryFn: () => sleep(150).then(() => 'data'),\n      }))\n\n      return null\n    }\n\n    function SecondQuery() {\n      useQuery(() => ({\n        queryKey: key2,\n        queryFn: () => sleep(200).then(() => 'data'),\n      }))\n\n      return null\n    }\n\n    function Page() {\n      const [renderSecond, setRenderSecond] = createSignal(false)\n\n      createEffect(() => {\n        setActTimeout(() => {\n          setRenderSecond(true)\n        }, 100)\n      })\n\n      return (\n        <>\n          <IsFetching />\n          <FirstQuery />\n          <Show when={renderSecond()}>\n            <SecondQuery />\n          </Show>\n        </>\n      )\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    // unlike react, Updating renderSecond wont cause a rerender for FirstQuery\n    await vi.advanceTimersByTimeAsync(300)\n\n    expect(isFetchingArray).toEqual([0, 1, 2, 1, 0])\n  })\n\n  it('should be able to filter', async () => {\n    const queryClient = new QueryClient()\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    const isFetchingArray: Array<number> = []\n\n    function One() {\n      useQuery(() => ({\n        queryKey: key1,\n        queryFn: () => sleep(10).then(() => 'test'),\n      }))\n\n      return null\n    }\n\n    function Two() {\n      useQuery(() => ({\n        queryKey: key2,\n        queryFn: () => sleep(20).then(() => 'test'),\n      }))\n\n      return null\n    }\n\n    function Page() {\n      const [started, setStarted] = createSignal(false)\n      const isFetching = useIsFetching(() => ({\n        queryKey: key1,\n      }))\n\n      createRenderEffect(() => {\n        isFetchingArray.push(isFetching())\n      })\n\n      return (\n        <div>\n          <button onClick={() => setStarted(true)}>setStarted</button>\n          <div>isFetching: {isFetching()}</div>\n          <Show when={started()}>\n            <>\n              <One />\n              <Two />\n            </>\n          </Show>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('isFetching: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /setStarted/i }))\n    expect(rendered.getByText('isFetching: 1')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(20)\n    expect(rendered.getByText('isFetching: 0')).toBeInTheDocument()\n\n    // at no point should we have isFetching: 2\n    expect(isFetchingArray).toEqual(expect.not.arrayContaining([2]))\n  })\n\n  it('should show the correct fetching state when mounted after a query', async () => {\n    const queryClient = new QueryClient()\n    const key = queryKey()\n\n    function Page() {\n      useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'test'),\n      }))\n\n      const isFetching = useIsFetching()\n\n      return (\n        <div>\n          <div>isFetching: {isFetching()}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('isFetching: 1')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('isFetching: 0')).toBeInTheDocument()\n  })\n\n  it('should use provided custom queryClient', async () => {\n    const queryClient = new QueryClient()\n    const key = queryKey()\n\n    function Page() {\n      useQuery(\n        () => ({\n          queryKey: key,\n          queryFn: () => sleep(10).then(() => 'test'),\n        }),\n        () => queryClient,\n      )\n\n      const isFetching = useIsFetching(undefined, () => queryClient)\n\n      return (\n        <div>\n          <div>isFetching: {isFetching()}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => <Page></Page>)\n\n    expect(rendered.getByText('isFetching: 1')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('isFetching: 0')).toBeInTheDocument()\n  })\n})\n"
  },
  {
    "path": "packages/solid-query/src/__tests__/useIsMutating.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { fireEvent, render } from '@solidjs/testing-library'\nimport { Show, createEffect, createRenderEffect, createSignal } from 'solid-js'\nimport * as QueryCore from '@tanstack/query-core'\nimport { sleep } from '@tanstack/query-test-utils'\nimport {\n  QueryClient,\n  QueryClientProvider,\n  useIsMutating,\n  useMutation,\n} from '..'\nimport { setActTimeout } from './utils'\n\ndescribe('useIsMutating', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should return the number of fetching mutations', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n\n    function IsMutating() {\n      const isMutating = useIsMutating()\n\n      createRenderEffect(() => {\n        isMutatingArray.push(isMutating())\n      })\n\n      return null\n    }\n\n    function Mutations() {\n      const { mutate: mutate1 } = useMutation(() => ({\n        mutationKey: ['mutation1'],\n        mutationFn: () => sleep(150).then(() => 'data'),\n      }))\n      const { mutate: mutate2 } = useMutation(() => ({\n        mutationKey: ['mutation2'],\n        mutationFn: () => sleep(50).then(() => 'data'),\n      }))\n\n      createEffect(() => {\n        mutate1()\n        setActTimeout(() => {\n          mutate2()\n        }, 50)\n      })\n\n      return null\n    }\n\n    function Page() {\n      return (\n        <div>\n          <IsMutating />\n          <Mutations />\n        </div>\n      )\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(150)\n\n    expect(isMutatingArray).toEqual([0, 1, 2, 1, 0])\n  })\n\n  it('should filter correctly by mutationKey', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n\n    function IsMutating() {\n      const isMutating = useIsMutating(() => ({ mutationKey: ['mutation1'] }))\n\n      createRenderEffect(() => {\n        isMutatingArray.push(isMutating())\n      })\n\n      return null\n    }\n\n    function Page() {\n      const { mutate: mutate1 } = useMutation(() => ({\n        mutationKey: ['mutation1'],\n        mutationFn: () => sleep(100).then(() => 'data'),\n      }))\n      const { mutate: mutate2 } = useMutation(() => ({\n        mutationKey: ['mutation2'],\n        mutationFn: () => sleep(100).then(() => 'data'),\n      }))\n\n      createEffect(() => {\n        mutate1()\n        mutate2()\n      })\n\n      return <IsMutating />\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    // Unlike React, IsMutating Wont re-render twice with mutation2\n    await vi.advanceTimersByTimeAsync(100)\n\n    expect(isMutatingArray).toEqual([0, 1, 0])\n  })\n\n  it('should filter correctly by predicate', async () => {\n    const isMutatingArray: Array<number> = []\n    const queryClient = new QueryClient()\n\n    function IsMutating() {\n      const isMutating = useIsMutating(() => ({\n        predicate: (mutation) =>\n          mutation.options.mutationKey?.[0] === 'mutation1',\n      }))\n\n      createRenderEffect(() => {\n        isMutatingArray.push(isMutating())\n      })\n\n      return null\n    }\n\n    function Page() {\n      const { mutate: mutate1 } = useMutation(() => ({\n        mutationKey: ['mutation1'],\n        mutationFn: () => sleep(100).then(() => 'data'),\n      }))\n      const { mutate: mutate2 } = useMutation(() => ({\n        mutationKey: ['mutation2'],\n        mutationFn: () => sleep(100).then(() => 'data'),\n      }))\n\n      createEffect(() => {\n        mutate1()\n        mutate2()\n      })\n\n      return <IsMutating />\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    // Again, No unnecessary re-renders like React\n    await vi.advanceTimersByTimeAsync(100)\n\n    expect(isMutatingArray).toEqual([0, 1, 0])\n  })\n\n  it('should use provided custom queryClient', async () => {\n    const queryClient = new QueryClient()\n\n    function Page() {\n      const isMutating = useIsMutating(undefined, () => queryClient)\n      const { mutate } = useMutation(\n        () => ({\n          mutationKey: ['mutation1'],\n          mutationFn: () => sleep(20).then(() => 'data'),\n        }),\n        () => queryClient,\n      )\n\n      createEffect(() => {\n        setActTimeout(() => {\n          mutate()\n        }, 10)\n      })\n\n      return (\n        <div>\n          <div>mutating: {isMutating()}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => <Page></Page>)\n\n    expect(rendered.getByText('mutating: 0')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('mutating: 1')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(20)\n    expect(rendered.getByText('mutating: 0')).toBeInTheDocument()\n  })\n\n  // eslint-disable-next-line vitest/expect-expect\n  it('should not change state if unmounted', async () => {\n    // We have to mock the MutationCache to not unsubscribe\n    // the listener when the component is unmounted\n    class MutationCacheMock extends QueryCore.MutationCache {\n      subscribe(listener: any) {\n        super.subscribe(listener)\n        return () => void 0\n      }\n    }\n\n    const MutationCacheSpy = vi\n      .spyOn(QueryCore, 'MutationCache')\n      .mockImplementation((fn) => {\n        return new MutationCacheMock(fn)\n      })\n\n    const queryClient = new QueryClient()\n\n    function IsMutating() {\n      useIsMutating()\n      return null\n    }\n\n    function Page() {\n      const [mounted, setMounted] = createSignal(true)\n\n      const { mutate: mutate1 } = useMutation(() => ({\n        mutationKey: ['mutation1'],\n        mutationFn: () => sleep(10).then(() => 'data'),\n      }))\n\n      createEffect(() => {\n        mutate1()\n      })\n\n      return (\n        <div>\n          <button onClick={() => setMounted(false)}>unmount</button>\n          <Show when={mounted()}>\n            <IsMutating />\n          </Show>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    fireEvent.click(rendered.getByText('unmount'))\n\n    // Should not display the console error\n    // \"Warning: Can't perform a React state update on an unmounted component\"\n\n    await vi.advanceTimersByTimeAsync(20)\n    MutationCacheSpy.mockRestore()\n  })\n})\n"
  },
  {
    "path": "packages/solid-query/src/__tests__/useMutation.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport {\n  ErrorBoundary,\n  createEffect,\n  createRenderEffect,\n  createSignal,\n} from 'solid-js'\nimport { fireEvent, render } from '@solidjs/testing-library'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport {\n  MutationCache,\n  QueryCache,\n  QueryClient,\n  QueryClientProvider,\n  useMutation,\n} from '..'\nimport { mockOnlineManagerIsOnline, setActTimeout } from './utils'\nimport type { UseMutationResult } from '../types'\n\ndescribe('useMutation', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  const queryCache = new QueryCache()\n  const mutationCache = new MutationCache()\n  const queryClient = new QueryClient({ queryCache, mutationCache })\n\n  it('should be able to reset `data`', async () => {\n    function Page() {\n      const mutation = useMutation(() => ({\n        mutationFn: () => Promise.resolve('mutation'),\n      }))\n\n      return (\n        <div>\n          <h1>{mutation.data ?? 'empty'}</h1>\n          <button onClick={() => mutation.reset()}>reset</button>\n          <button onClick={() => mutation.mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByRole('heading').textContent).toBe('empty')\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByRole('heading').textContent).toBe('mutation')\n\n    fireEvent.click(rendered.getByRole('button', { name: /reset/i }))\n    expect(rendered.getByRole('heading').textContent).toBe('empty')\n  })\n\n  it('should be able to reset `error`', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n\n    function Page() {\n      const mutation = useMutation<string, Error>(() => ({\n        mutationFn: () => {\n          const err = new Error('Expected mock error. All is well!')\n          err.stack = ''\n          return Promise.reject(err)\n        },\n      }))\n\n      return (\n        <div>\n          {mutation.error && <h1>{mutation.error.message}</h1>}\n          <button onClick={() => mutation.reset()}>reset</button>\n          <button onClick={() => mutation.mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.queryByRole('heading')).toBeNull()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByRole('heading').textContent).toBe(\n      'Expected mock error. All is well!',\n    )\n\n    fireEvent.click(rendered.getByRole('button', { name: /reset/i }))\n    expect(rendered.queryByRole('heading')).toBeNull()\n\n    consoleMock.mockRestore()\n  })\n\n  it('should be able to call `onSuccess` and `onSettled` after each successful mutate', async () => {\n    const [count, setCount] = createSignal(0)\n    const onSuccessMock = vi.fn()\n    const onSettledMock = vi.fn()\n\n    function Page() {\n      const mutation = useMutation(() => ({\n        mutationFn: (vars: { count: number }) => Promise.resolve(vars.count),\n        onSuccess: (data) => {\n          onSuccessMock(data)\n        },\n        onSettled: (data) => {\n          onSettledMock(data)\n        },\n      }))\n\n      return (\n        <div>\n          <h1>{count()}</h1>\n          <button\n            onClick={() => {\n              setCount((c) => c + 1)\n              return mutation.mutate({ count: count() })\n            }}\n          >\n            mutate\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByRole('heading').textContent).toBe('0')\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByRole('heading').textContent).toBe('3')\n\n    expect(onSuccessMock).toHaveBeenCalledTimes(3)\n\n    expect(onSuccessMock).toHaveBeenCalledWith(1)\n    expect(onSuccessMock).toHaveBeenCalledWith(2)\n    expect(onSuccessMock).toHaveBeenCalledWith(3)\n\n    expect(onSettledMock).toHaveBeenCalledTimes(3)\n\n    expect(onSettledMock).toHaveBeenCalledWith(1)\n    expect(onSettledMock).toHaveBeenCalledWith(2)\n    expect(onSettledMock).toHaveBeenCalledWith(3)\n  })\n\n  it('should set correct values for `failureReason` and `failureCount` on multiple mutate calls', async () => {\n    const [count, setCount] = createSignal(0)\n    type Value = { count: number }\n\n    const mutateFn = vi.fn<(value: Value) => Promise<Value>>()\n\n    mutateFn.mockImplementationOnce(() =>\n      Promise.reject(new Error('Error test Jonas')),\n    )\n\n    mutateFn.mockImplementation((value) => sleep(10).then(() => value))\n\n    function Page() {\n      const mutation = useMutation(() => ({\n        mutationFn: mutateFn,\n      }))\n\n      return (\n        <div>\n          <h1>Data {mutation.data?.count}</h1>\n          <h2>Status {mutation.status}</h2>\n          <h2>Failed {mutation.failureCount} times</h2>\n          <h2>Failed because {mutation.failureReason?.message ?? 'null'}</h2>\n          <button\n            onClick={() => {\n              setCount((c) => c + 1)\n              return mutation.mutate({ count: count() })\n            }}\n          >\n            mutate\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('Data')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    expect(rendered.getByText('Data')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Status error')).toBeInTheDocument()\n    expect(rendered.getByText('Failed 1 times')).toBeInTheDocument()\n    expect(\n      rendered.getByText('Failed because Error test Jonas'),\n    ).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Status pending')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('Status success')).toBeInTheDocument()\n    expect(rendered.getByText('Data 2')).toBeInTheDocument()\n    expect(rendered.getByText('Failed 0 times')).toBeInTheDocument()\n    expect(rendered.getByText('Failed because null')).toBeInTheDocument()\n  })\n\n  it('should be able to call `onError` and `onSettled` after each failed mutate', async () => {\n    const onErrorMock = vi.fn()\n    const onSettledMock = vi.fn()\n    const [count, setCount] = createSignal(0)\n\n    function Page() {\n      const mutation = useMutation(() => ({\n        mutationFn: (vars: { count: number }) => {\n          const error = new Error(\n            `Expected mock error. All is well! ${vars.count}`,\n          )\n          error.stack = ''\n          return Promise.reject(error)\n        },\n        onError: (error: Error) => {\n          onErrorMock(error.message)\n        },\n        onSettled: (_data, error) => {\n          onSettledMock(error?.message)\n        },\n      }))\n\n      return (\n        <div>\n          <h1>{count()}</h1>\n          <button\n            onClick={() => {\n              setCount((c) => c + 1)\n              return mutation.mutate({ count: count() })\n            }}\n          >\n            mutate\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByRole('heading').textContent).toBe('0')\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByRole('heading').textContent).toBe('3')\n\n    expect(onErrorMock).toHaveBeenCalledTimes(3)\n    expect(onErrorMock).toHaveBeenCalledWith(\n      'Expected mock error. All is well! 1',\n    )\n    expect(onErrorMock).toHaveBeenCalledWith(\n      'Expected mock error. All is well! 2',\n    )\n    expect(onErrorMock).toHaveBeenCalledWith(\n      'Expected mock error. All is well! 3',\n    )\n\n    expect(onSettledMock).toHaveBeenCalledTimes(3)\n    expect(onSettledMock).toHaveBeenCalledWith(\n      'Expected mock error. All is well! 1',\n    )\n    expect(onSettledMock).toHaveBeenCalledWith(\n      'Expected mock error. All is well! 2',\n    )\n    expect(onSettledMock).toHaveBeenCalledWith(\n      'Expected mock error. All is well! 3',\n    )\n  })\n\n  it('should be able to override the useMutation success callbacks', async () => {\n    const callbacks: Array<string> = []\n\n    function Page() {\n      const mutation = useMutation(() => ({\n        mutationFn: (text: string) => Promise.resolve(text),\n        onSuccess: () => {\n          callbacks.push('useMutation.onSuccess')\n        },\n        onSettled: () => {\n          callbacks.push('useMutation.onSettled')\n        },\n      }))\n\n      createEffect(() => {\n        const { mutateAsync } = mutation\n        setActTimeout(async () => {\n          try {\n            const result = await mutateAsync('todo', {\n              onSuccess: () => {\n                callbacks.push('mutateAsync.onSuccess')\n              },\n              onSettled: () => {\n                callbacks.push('mutateAsync.onSettled')\n              },\n            })\n            callbacks.push(`mutateAsync.result:${result}`)\n          } catch {}\n        }, 10)\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(callbacks).toEqual([\n      'useMutation.onSuccess',\n      'useMutation.onSettled',\n      'mutateAsync.onSuccess',\n      'mutateAsync.onSettled',\n      'mutateAsync.result:todo',\n    ])\n  })\n\n  it('should be able to override the error callbacks when using mutateAsync', async () => {\n    const callbacks: Array<string> = []\n\n    function Page() {\n      const mutation = useMutation(() => ({\n        mutationFn: (_text: string) => Promise.reject(new Error('oops')),\n\n        onError: () => {\n          callbacks.push('useMutation.onError')\n        },\n        onSettled: () => {\n          callbacks.push('useMutation.onSettled')\n        },\n      }))\n\n      createEffect(() => {\n        const { mutateAsync } = mutation\n        setActTimeout(async () => {\n          try {\n            await mutateAsync('todo', {\n              onError: () => {\n                callbacks.push('mutateAsync.onError')\n              },\n              onSettled: () => {\n                callbacks.push('mutateAsync.onSettled')\n              },\n            })\n          } catch (error) {\n            callbacks.push(`mutateAsync.error:${(error as Error).message}`)\n          }\n        }, 10)\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(callbacks).toEqual([\n      'useMutation.onError',\n      'useMutation.onSettled',\n      'mutateAsync.onError',\n      'mutateAsync.onSettled',\n      'mutateAsync.error:oops',\n    ])\n  })\n\n  it('should be able to use mutation defaults', async () => {\n    const key = queryKey()\n\n    queryClient.setMutationDefaults(key, {\n      mutationFn: (text: string) => sleep(10).then(() => text),\n    })\n\n    const states: Array<UseMutationResult<any, any, any, any>> = []\n\n    function Page() {\n      const mutation = useMutation<string, unknown, string>(() => ({\n        mutationKey: key,\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...mutation })\n      })\n\n      createEffect(() => {\n        const { mutate } = mutation\n        setActTimeout(() => {\n          mutate('todo')\n        }, 10)\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(20)\n\n    expect(states.length).toBe(3)\n    expect(states[0]).toMatchObject({ data: undefined, isPending: false })\n    expect(states[1]).toMatchObject({ data: undefined, isPending: true })\n    expect(states[2]).toMatchObject({ data: 'todo', isPending: false })\n  })\n\n  it('should be able to retry a failed mutation', async () => {\n    let count = 0\n\n    function Page() {\n      const mutation = useMutation(() => ({\n        mutationFn: (_text: string) => {\n          count++\n          return Promise.reject(new Error('oops'))\n        },\n        retry: 1,\n        retryDelay: 5,\n      }))\n\n      createEffect(() => {\n        const { mutate } = mutation\n        setActTimeout(() => {\n          mutate('todo')\n        }, 10)\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(20)\n\n    expect(count).toBe(2)\n  })\n\n  it('should not retry mutations while offline', async () => {\n    const onlineMock = mockOnlineManagerIsOnline(false)\n\n    let count = 0\n\n    function Page() {\n      const mutation = useMutation(() => ({\n        mutationFn: (_text: string) => {\n          count++\n          return Promise.reject(new Error('oops'))\n        },\n        retry: 1,\n        retryDelay: 5,\n      }))\n\n      return (\n        <div>\n          <button onClick={() => mutation.mutate('todo')}>mutate</button>\n          <div>\n            {`error: ${\n              mutation.error instanceof Error ? mutation.error.message : 'null'\n            }, status: ${mutation.status}, isPaused: ${String(\n              mutation.isPaused,\n            )}`}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(\n      rendered.getByText('error: null, status: idle, isPaused: false'),\n    ).toBeInTheDocument()\n\n    window.dispatchEvent(new Event('offline'))\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n\n    expect(\n      rendered.getByText('error: null, status: pending, isPaused: true'),\n    ).toBeInTheDocument()\n\n    expect(count).toBe(0)\n\n    onlineMock.mockRestore()\n    window.dispatchEvent(new Event('online'))\n\n    await vi.advanceTimersByTimeAsync(5)\n    expect(\n      rendered.getByText('error: oops, status: error, isPaused: false'),\n    ).toBeInTheDocument()\n\n    expect(count).toBe(2)\n  })\n\n  it('should call onMutate even if paused', async () => {\n    const onlineMock = mockOnlineManagerIsOnline(false)\n    const onMutate = vi.fn()\n    let count = 0\n\n    function Page() {\n      const mutation = useMutation(() => ({\n        mutationFn: async (_text: string) => {\n          count++\n          await sleep(10)\n          return count\n        },\n        onMutate,\n      }))\n\n      return (\n        <div>\n          <button onClick={() => mutation.mutate('todo')}>mutate</button>\n          <div>\n            data: {mutation.data ?? 'null'}, status: {mutation.status},\n            isPaused: {String(mutation.isPaused)}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(\n      rendered.getByText('data: null, status: idle, isPaused: false'),\n    ).toBeInTheDocument()\n\n    window.dispatchEvent(new Event('offline'))\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(\n      rendered.getByText('data: null, status: pending, isPaused: true'),\n    ).toBeInTheDocument()\n\n    expect(onMutate).toHaveBeenCalledTimes(1)\n    expect(onMutate).toHaveBeenCalledWith('todo', {\n      client: queryClient,\n      meta: undefined,\n      mutationKey: undefined,\n    })\n\n    onlineMock.mockRestore()\n    window.dispatchEvent(new Event('online'))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(\n      rendered.getByText('data: 1, status: success, isPaused: false'),\n    ).toBeInTheDocument()\n\n    expect(onMutate).toHaveBeenCalledTimes(1)\n    expect(count).toBe(1)\n  })\n\n  it('should optimistically go to paused state if offline', async () => {\n    const onlineMock = mockOnlineManagerIsOnline(false)\n    let count = 0\n    const states: Array<string> = []\n\n    function Page() {\n      const mutation = useMutation(() => ({\n        mutationFn: async (_text: string) => {\n          count++\n          await sleep(10)\n          return count\n        },\n      }))\n\n      createRenderEffect(() => {\n        states.push(`${mutation.status}, ${mutation.isPaused}`)\n      })\n\n      return (\n        <div>\n          <button onClick={() => mutation.mutate('todo')}>mutate</button>\n          <div>\n            data: {mutation.data ?? 'null'}, status: {mutation.status},\n            isPaused: {String(mutation.isPaused)}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    rendered.getByText('data: null, status: idle, isPaused: false')\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    expect(\n      rendered.getByText('data: null, status: pending, isPaused: true'),\n    ).toBeInTheDocument()\n\n    // no intermediate 'pending, false' state is expected because we don't start mutating!\n    expect(states[0]).toBe('idle, false')\n    expect(states[1]).toBe('pending, true')\n\n    onlineMock.mockReturnValue(true)\n    window.dispatchEvent(new Event('online'))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(\n      rendered.getByText('data: 1, status: success, isPaused: false'),\n    ).toBeInTheDocument()\n\n    onlineMock.mockRestore()\n  })\n\n  it('should be able to retry a mutation when online', async () => {\n    const onlineMock = mockOnlineManagerIsOnline(false)\n\n    let count = 0\n    const states: Array<UseMutationResult<any, any, any, any>> = []\n\n    function Page() {\n      const mutation = useMutation(() => ({\n        mutationFn: async (_text: string) => {\n          await sleep(1)\n          count++\n          return count > 1\n            ? Promise.resolve('data')\n            : Promise.reject(new Error('oops'))\n        },\n        retry: 1,\n        retryDelay: 5,\n        networkMode: 'offlineFirst',\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...mutation })\n      })\n\n      createEffect(() => {\n        const { mutate } = mutation\n        setActTimeout(() => {\n          window.dispatchEvent(new Event('offline'))\n          mutate('todo')\n        }, 10)\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(16)\n\n    expect(states.length).toBe(4)\n    expect(states[0]).toMatchObject({\n      isPending: false,\n      isPaused: false,\n      failureCount: 0,\n      failureReason: null,\n    })\n    expect(states[1]).toMatchObject({\n      isPending: true,\n      isPaused: false,\n      failureCount: 0,\n      failureReason: null,\n    })\n    expect(states[2]).toMatchObject({\n      isPending: true,\n      isPaused: false,\n      failureCount: 1,\n      failureReason: new Error('oops'),\n    })\n    expect(states[3]).toMatchObject({\n      isPending: true,\n      isPaused: true,\n      failureCount: 1,\n      failureReason: new Error('oops'),\n    })\n\n    onlineMock.mockRestore()\n    window.dispatchEvent(new Event('online'))\n\n    await vi.advanceTimersByTimeAsync(1)\n\n    expect(states.length).toBe(6)\n    expect(states[4]).toMatchObject({\n      isPending: true,\n      isPaused: false,\n      failureCount: 1,\n      failureReason: new Error('oops'),\n    })\n    expect(states[5]).toMatchObject({\n      isPending: false,\n      isPaused: false,\n      failureCount: 0,\n      failureReason: null,\n      data: 'data',\n    })\n  })\n\n  // eslint-disable-next-line vitest/expect-expect\n  it('should not change state if unmounted', () => {\n    function Mutates() {\n      const mutation = useMutation(() => ({ mutationFn: () => sleep(10) }))\n      return <button onClick={() => mutation.mutate()}>mutate</button>\n    }\n    function Page() {\n      const [mounted, setMounted] = createSignal(true)\n      return (\n        <div>\n          <button onClick={() => setMounted(false)}>unmount</button>\n          {mounted() && <Mutates />}\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n    fireEvent.click(rendered.getByText('mutate'))\n    fireEvent.click(rendered.getByText('unmount'))\n  })\n\n  it('should be able to throw an error when throwOnError is set to true', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n\n    function Page() {\n      const mutation = useMutation<string, Error>(() => ({\n        mutationFn: () => {\n          const err = new Error('Expected mock error. All is well!')\n          err.stack = ''\n          return Promise.reject(err)\n        },\n        throwOnError: true,\n      }))\n\n      return (\n        <div>\n          <button onClick={() => mutation.mutate()}>mutate</button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <ErrorBoundary\n          fallback={() => (\n            <div>\n              <span>error</span>\n            </div>\n          )}\n        >\n          <Page />\n        </ErrorBoundary>\n      </QueryClientProvider>\n    ))\n\n    fireEvent.click(rendered.getByText('mutate'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.queryByText('error')).not.toBeNull()\n\n    consoleMock.mockRestore()\n  })\n\n  it('should be able to throw an error when throwOnError is a function that returns true', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n\n    let boundary = false\n    function Page() {\n      const mutation = useMutation<string, Error>(() => ({\n        mutationFn: () => {\n          const err = new Error('mock error')\n          err.stack = ''\n          return Promise.reject(err)\n        },\n        throwOnError: () => {\n          boundary = !boundary\n          return !boundary\n        },\n      }))\n\n      return (\n        <div>\n          <button onClick={() => mutation.mutate()}>mutate</button>\n          {mutation.error && mutation.error.message}\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <ErrorBoundary\n          fallback={() => (\n            <div>\n              <span>error boundary</span>\n            </div>\n          )}\n        >\n          <Page />\n        </ErrorBoundary>\n      </QueryClientProvider>\n    ))\n\n    // first error goes to component\n    fireEvent.click(rendered.getByText('mutate'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.queryByText('mock error')).not.toBeNull()\n\n    // second error goes to boundary\n    fireEvent.click(rendered.getByText('mutate'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.queryByText('error boundary')).not.toBeNull()\n\n    consoleMock.mockRestore()\n  })\n\n  it('should pass meta to mutation', async () => {\n    const errorMock = vi.fn()\n    const successMock = vi.fn()\n\n    const queryClientMutationMeta = new QueryClient({\n      mutationCache: new MutationCache({\n        onSuccess: (_, __, ___, mutation) => {\n          successMock(mutation.meta?.metaSuccessMessage)\n        },\n        onError: (_, __, ___, mutation) => {\n          errorMock(mutation.meta?.metaErrorMessage)\n        },\n      }),\n    })\n\n    const metaSuccessMessage = 'mutation succeeded'\n    const metaErrorMessage = 'mutation failed'\n\n    function Page() {\n      const mutationSucceed = useMutation(() => ({\n        mutationFn: () => Promise.resolve(''),\n        meta: { metaSuccessMessage },\n      }))\n      const mutationError = useMutation(() => ({\n        mutationFn: () => {\n          throw new Error('')\n        },\n        meta: { metaErrorMessage },\n      }))\n\n      return (\n        <div>\n          <button onClick={() => mutationSucceed.mutate()}>succeed</button>\n          <button onClick={() => mutationError.mutate()}>error</button>\n          {mutationSucceed.isSuccess && <div>successTest</div>}\n          {mutationError.isError && <div>errorTest</div>}\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClientMutationMeta}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    fireEvent.click(rendered.getByText('succeed'))\n    fireEvent.click(rendered.getByText('error'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.queryByText('successTest')).not.toBeNull()\n    expect(rendered.queryByText('errorTest')).not.toBeNull()\n\n    expect(successMock).toHaveBeenCalledTimes(1)\n    expect(successMock).toHaveBeenCalledWith(metaSuccessMessage)\n\n    expect(errorMock).toHaveBeenCalledTimes(1)\n    expect(errorMock).toHaveBeenCalledWith(metaErrorMessage)\n  })\n\n  it('should call cache callbacks when unmounted', async () => {\n    const onSuccess = vi.fn()\n    const onSuccessMutate = vi.fn()\n    const onSettled = vi.fn()\n    const onSettledMutate = vi.fn()\n    const mutationKey = queryKey()\n    let count = 0\n\n    function Page() {\n      const [show, setShow] = createSignal(true)\n      return (\n        <div>\n          <button onClick={() => setShow(false)}>hide</button>\n          {show() && <Component />}\n        </div>\n      )\n    }\n\n    function Component() {\n      const mutation = useMutation(() => ({\n        mutationFn: async (_text: string) => {\n          count++\n          await sleep(10)\n          return count\n        },\n        mutationKey: mutationKey,\n        gcTime: 0,\n        onSuccess,\n        onSettled,\n      }))\n\n      return (\n        <div>\n          <button\n            onClick={() =>\n              mutation.mutate('todo', {\n                onSuccess: onSuccessMutate,\n                onSettled: onSettledMutate,\n              })\n            }\n          >\n            mutate\n          </button>\n          <div>\n            data: {mutation.data ?? 'null'}, status: {mutation.status},\n            isPaused: {String(mutation.isPaused)}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await rendered.findByText('data: null, status: idle, isPaused: false')\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /hide/i }))\n    await vi.advanceTimersByTimeAsync(10)\n    expect(\n      queryClient.getMutationCache().findAll({ mutationKey: mutationKey }),\n    ).toHaveLength(0)\n    expect(count).toBe(1)\n\n    expect(onSuccess).toHaveBeenCalledTimes(1)\n    expect(onSettled).toHaveBeenCalledTimes(1)\n    expect(onSuccessMutate).toHaveBeenCalledTimes(0)\n    expect(onSettledMutate).toHaveBeenCalledTimes(0)\n  })\n\n  it('should call mutate callbacks only for the last observer', async () => {\n    const onSuccess = vi.fn()\n    const onSuccessMutate = vi.fn()\n    const onSettled = vi.fn()\n    const onSettledMutate = vi.fn()\n    let count = 0\n\n    function Page() {\n      const mutation = useMutation(() => ({\n        mutationFn: async (_text: string) => {\n          count++\n          await sleep(10)\n          return `result${count}`\n        },\n        onSuccess,\n        onSettled,\n      }))\n\n      return (\n        <div>\n          <button\n            onClick={() =>\n              mutation.mutate('todo', {\n                onSuccess: onSuccessMutate,\n                onSettled: onSettledMutate,\n              })\n            }\n          >\n            mutate\n          </button>\n          <div>\n            data: {mutation.data ?? 'null'}, status: {mutation.status}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await rendered.findByText('data: null, status: idle')\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n\n    await vi.advanceTimersByTimeAsync(10)\n    await rendered.findByText('data: result2, status: success')\n\n    expect(count).toBe(2)\n\n    expect(onSuccess).toHaveBeenCalledTimes(2)\n    expect(onSettled).toHaveBeenCalledTimes(2)\n    expect(onSuccessMutate).toHaveBeenCalledTimes(1)\n    expect(onSuccessMutate).toHaveBeenCalledWith('result2', 'todo', undefined, {\n      client: queryClient,\n      meta: undefined,\n      mutationKey: undefined,\n    })\n    expect(onSettledMutate).toHaveBeenCalledTimes(1)\n    expect(onSettledMutate).toHaveBeenCalledWith(\n      'result2',\n      null,\n      'todo',\n      undefined,\n      {\n        client: queryClient,\n        meta: undefined,\n        mutationKey: undefined,\n      },\n    )\n  })\n\n  it('should go to error state if onSuccess callback errors', async () => {\n    const error = new Error('error from onSuccess')\n    const onError = vi.fn()\n\n    function Page() {\n      const mutation = useMutation(() => ({\n        mutationFn: async (_text: string) => {\n          await sleep(10)\n          return 'result'\n        },\n        onSuccess: () => Promise.reject(error),\n        onError,\n      }))\n\n      return (\n        <div>\n          <button onClick={() => mutation.mutate('todo')}>mutate</button>\n          <div>status: {mutation.status}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await rendered.findByText('status: idle')\n\n    rendered.getByRole('button', { name: /mutate/i }).click()\n\n    await vi.advanceTimersByTimeAsync(10)\n    await rendered.findByText('status: error')\n\n    expect(onError).toHaveBeenCalledWith(error, 'todo', undefined, {\n      client: queryClient,\n      meta: undefined,\n      mutationKey: undefined,\n    })\n  })\n\n  it('should go to error state if onError callback errors', async ({\n    onTestFinished,\n  }) => {\n    const unhandledRejectionFn = vi.fn()\n    process.on('unhandledRejection', (error) => unhandledRejectionFn(error))\n    onTestFinished(() => {\n      process.off('unhandledRejection', unhandledRejectionFn)\n    })\n\n    const error = new Error('error from onError')\n    const mutateFnError = new Error('mutateFnError')\n\n    function Page() {\n      const mutation = useMutation(() => ({\n        mutationFn: async (_text: string) => {\n          await sleep(10)\n          throw mutateFnError\n        },\n        onError: () => Promise.reject(error),\n      }))\n\n      return (\n        <div>\n          <button onClick={() => mutation.mutate('todo')}>mutate</button>\n          <div>\n            error:{' '}\n            {mutation.error instanceof Error ? mutation.error.message : 'null'},\n            status: {mutation.status}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error: null, status: idle')).toBeInTheDocument()\n\n    rendered.getByRole('button', { name: /mutate/i }).click()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(\n      rendered.getByText('error: mutateFnError, status: error'),\n    ).toBeInTheDocument()\n  })\n\n  it('should go to error state if onSettled callback errors', async ({\n    onTestFinished,\n  }) => {\n    const unhandledRejectionFn = vi.fn()\n    process.on('unhandledRejection', (error) => unhandledRejectionFn(error))\n    onTestFinished(() => {\n      process.off('unhandledRejection', unhandledRejectionFn)\n    })\n\n    const error = new Error('error from onSettled')\n    const mutateFnError = new Error('mutateFnError')\n    const onError = vi.fn()\n\n    function Page() {\n      const mutation = useMutation(() => ({\n        mutationFn: async (_text: string) => {\n          await sleep(10)\n          throw mutateFnError\n        },\n        onSettled: () => Promise.reject(error),\n        onError,\n      }))\n\n      return (\n        <div>\n          <button onClick={() => mutation.mutate('todo')}>mutate</button>\n          <div>\n            error:{' '}\n            {mutation.error instanceof Error ? mutation.error.message : 'null'},\n            status: {mutation.status}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('error: null, status: idle')).toBeInTheDocument()\n\n    rendered.getByRole('button', { name: /mutate/i }).click()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(\n      rendered.getByText('error: mutateFnError, status: error'),\n    ).toBeInTheDocument()\n\n    expect(onError).toHaveBeenCalledWith(mutateFnError, 'todo', undefined, {\n      client: queryClient,\n      meta: undefined,\n      mutationKey: undefined,\n    })\n  })\n\n  it('should use provided custom queryClient', async () => {\n    function Page() {\n      const mutation = useMutation(\n        () => ({\n          mutationFn: async (text: string) => {\n            return Promise.resolve(text)\n          },\n        }),\n        () => queryClient,\n      )\n\n      return (\n        <div>\n          <button onClick={() => mutation.mutate('custom client')}>\n            mutate\n          </button>\n          <div>\n            data: {mutation.data ?? 'null'}, status: {mutation.status}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => <Page></Page>)\n\n    expect(rendered.getByText('data: null, status: idle')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(\n      rendered.getByText('data: custom client, status: success'),\n    ).toBeInTheDocument()\n  })\n})\n"
  },
  {
    "path": "packages/solid-query/src/__tests__/useMutationState.test-d.tsx",
    "content": "import { describe, expectTypeOf, it } from 'vitest'\nimport { useMutationState } from '../useMutationState'\nimport type { MutationState, MutationStatus } from '@tanstack/query-core'\n\ndescribe('useMutationState', () => {\n  it('should default to QueryState', () => {\n    const result = useMutationState(() => ({\n      filters: { status: 'pending' },\n    }))\n\n    expectTypeOf(result()).toEqualTypeOf<Array<MutationState>>()\n  })\n  it('should infer with select', () => {\n    const result = useMutationState(() => ({\n      filters: { status: 'pending' },\n      select: (mutation) => mutation.state.status,\n    }))\n\n    expectTypeOf(result()).toEqualTypeOf<Array<MutationStatus>>()\n  })\n})\n"
  },
  {
    "path": "packages/solid-query/src/__tests__/useMutationState.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { fireEvent, render } from '@solidjs/testing-library'\nimport { createEffect } from 'solid-js'\nimport { sleep } from '@tanstack/query-test-utils'\nimport {\n  QueryClient,\n  QueryClientProvider,\n  useMutation,\n  useMutationState,\n} from '..'\n\ndescribe('useMutationState', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should return all mutation states when called without options', async () => {\n    const queryClient = new QueryClient()\n    const mutationKey = ['mutation']\n\n    function States() {\n      const mutationStates = useMutationState()\n\n      return <div>count: {mutationStates().length}</div>\n    }\n\n    function Mutate() {\n      const mutation = useMutation(() => ({\n        mutationKey,\n        mutationFn: (input: number) => sleep(150).then(() => 'data' + input),\n      }))\n\n      return (\n        <div>\n          <button onClick={() => mutation.mutate(1)}>mutate</button>\n        </div>\n      )\n    }\n\n    function Page() {\n      return (\n        <div>\n          <States />\n          <Mutate />\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('count: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('count: 1')).toBeInTheDocument()\n\n    await vi.advanceTimersByTimeAsync(150)\n    expect(rendered.getByText('count: 1')).toBeInTheDocument()\n  })\n\n  it('should return variables after calling mutate', async () => {\n    const queryClient = new QueryClient()\n    const variables: Array<Array<unknown>> = []\n    const mutationKey = ['mutation']\n\n    function Variables() {\n      const states = useMutationState(() => ({\n        filters: { mutationKey, status: 'pending' },\n        select: (mutation) => mutation.state.variables,\n      }))\n\n      createEffect(() => {\n        variables.push(states())\n      })\n\n      return null\n    }\n\n    function Mutate() {\n      const mutation = useMutation(() => ({\n        mutationKey,\n        mutationFn: async (input: number) => {\n          await sleep(150)\n          return 'data' + input\n        },\n      }))\n\n      return (\n        <div>\n          data: {mutation.data ?? 'null'}\n          <button onClick={() => mutation.mutate(1)}>mutate</button>\n        </div>\n      )\n    }\n\n    function Page() {\n      return (\n        <div>\n          <Variables />\n          <Mutate />\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('data: null')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(150)\n    expect(rendered.getByText('data: data1')).toBeInTheDocument()\n\n    expect(variables).toEqual([[], [1], []])\n  })\n})\n"
  },
  {
    "path": "packages/solid-query/src/__tests__/useQueries.test.tsx",
    "content": "import {\n  afterEach,\n  beforeEach,\n  describe,\n  expect,\n  expectTypeOf,\n  it,\n  vi,\n} from 'vitest'\nimport { fireEvent, render } from '@solidjs/testing-library'\nimport * as QueryCore from '@tanstack/query-core'\nimport { createRenderEffect, createSignal } from 'solid-js'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport {\n  QueriesObserver,\n  QueryCache,\n  QueryClient,\n  QueryClientProvider,\n  useQueries,\n} from '..'\nimport type {\n  QueryFunction,\n  QueryFunctionContext,\n  QueryKey,\n  SolidQueryOptions,\n  UseQueryResult,\n} from '..'\n\ndescribe('useQueries', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  const queryCache = new QueryCache()\n  const queryClient = new QueryClient({ queryCache })\n\n  it('should return the correct states', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const results: Array<Array<UseQueryResult>> = []\n\n    function Page() {\n      const result = useQueries(() => ({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: async () => {\n              await sleep(10)\n              return 1\n            },\n          },\n          {\n            queryKey: key2,\n            queryFn: async () => {\n              await sleep(100)\n              return 2\n            },\n          },\n        ],\n      }))\n\n      createRenderEffect(() => {\n        results.push([{ ...result[0] }, { ...result[1] }])\n      })\n\n      return (\n        <div>\n          <div>\n            data1: {String(result[0].data ?? 'null')}, data2:{' '}\n            {String(result[1].data ?? 'null')}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(100)\n    expect(rendered.getByText('data1: 1, data2: 2')).toBeInTheDocument()\n\n    expect(results.length).toBe(3)\n    expect(results[0]).toMatchObject([{ data: undefined }, { data: undefined }])\n    expect(results[1]).toMatchObject([{ data: 1 }, { data: undefined }])\n    expect(results[2]).toMatchObject([{ data: 1 }, { data: 2 }])\n  })\n\n  it('handles type parameter - tuple of tuples', () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const key3 = queryKey()\n\n    // @ts-expect-error (Page component is not rendered)\n    function Page() {\n      const result1 = useQueries<\n        [[number], [string], [Array<string>, boolean]]\n      >(() => ({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 1,\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n          },\n          {\n            queryKey: key3,\n            queryFn: () => ['string[]'],\n          },\n        ],\n      }))\n      expectTypeOf(result1[0]).toEqualTypeOf<UseQueryResult<number>>()\n      expectTypeOf(result1[1]).toEqualTypeOf<UseQueryResult<string>>()\n      expectTypeOf(result1[2]).toEqualTypeOf<\n        UseQueryResult<Array<string>, boolean>\n      >()\n      expectTypeOf(result1[0].data).toEqualTypeOf<number | undefined>()\n      expectTypeOf(result1[1].data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(result1[2].data).toEqualTypeOf<Array<string> | undefined>()\n      expectTypeOf(result1[2].error).toEqualTypeOf<boolean | null>()\n\n      // TData (3rd element) takes precedence over TQueryFnData (1st element)\n      const result2 = useQueries<\n        [[string, unknown, string], [string, unknown, number]]\n      >(() => ({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return a.toLowerCase()\n            },\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return parseInt(a)\n            },\n          },\n        ],\n      }))\n      expectTypeOf(result2[0]).toEqualTypeOf<UseQueryResult<string, unknown>>()\n      expectTypeOf(result2[1]).toEqualTypeOf<UseQueryResult<number, unknown>>()\n      expectTypeOf(result2[0].data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(result2[1].data).toEqualTypeOf<number | undefined>()\n\n      // types should be enforced\n      useQueries<[[string, unknown, string], [string, boolean, number]]>(\n        () => ({\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: () => 'string',\n              select: (a) => {\n                expectTypeOf(a).toEqualTypeOf<string>()\n                return a.toLowerCase()\n              },\n              placeholderData: 'string',\n              // @ts-expect-error (initialData: string)\n              initialData: 123,\n            },\n            {\n              queryKey: key2,\n              queryFn: () => 'string',\n              select: (a) => {\n                expectTypeOf(a).toEqualTypeOf<string>()\n                return parseInt(a)\n              },\n              placeholderData: 'string',\n              // @ts-expect-error (initialData: string)\n              initialData: 123,\n            },\n          ],\n        }),\n      )\n\n      // field names should be enforced\n      useQueries<[[string]]>(() => ({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n          },\n        ],\n      }))\n    }\n  })\n\n  it('handles type parameter - tuple of objects', () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const key3 = queryKey()\n\n    // @ts-expect-error (Page component is not rendered)\n    function Page() {\n      const result1 = useQueries<\n        [\n          { queryFnData: number },\n          { queryFnData: string },\n          { queryFnData: Array<string>; error: boolean },\n        ]\n      >(() => ({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 1,\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n          },\n          {\n            queryKey: key3,\n            queryFn: () => ['string[]'],\n          },\n        ],\n      }))\n      expectTypeOf(result1[0]).toEqualTypeOf<UseQueryResult<number, unknown>>()\n      expectTypeOf(result1[1]).toEqualTypeOf<UseQueryResult<string, unknown>>()\n      expectTypeOf(result1[2]).toEqualTypeOf<\n        UseQueryResult<Array<string>, boolean>\n      >()\n      expectTypeOf(result1[0].data).toEqualTypeOf<number | undefined>()\n      expectTypeOf(result1[1].data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(result1[2].data).toEqualTypeOf<Array<string> | undefined>()\n      expectTypeOf(result1[2].error).toEqualTypeOf<boolean | null>()\n\n      // TData (data prop) takes precedence over TQueryFnData (queryFnData prop)\n      const result2 = useQueries<\n        [\n          { queryFnData: string; data: string },\n          { queryFnData: string; data: number },\n        ]\n      >(() => ({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return a.toLowerCase()\n            },\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return parseInt(a)\n            },\n          },\n        ],\n      }))\n      expectTypeOf(result2[0]).toEqualTypeOf<UseQueryResult<string, unknown>>()\n      expectTypeOf(result2[1]).toEqualTypeOf<UseQueryResult<number, unknown>>()\n      expectTypeOf(result2[0].data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(result2[1].data).toEqualTypeOf<number | undefined>()\n\n      // can pass only TData (data prop) although TQueryFnData will be left unknown\n      const result3 = useQueries<[{ data: string }, { data: number }]>(() => ({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<unknown>()\n              return a as string\n            },\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<unknown>()\n              return a as number\n            },\n          },\n        ],\n      }))\n      expectTypeOf(result3[0]).toEqualTypeOf<UseQueryResult<string, unknown>>()\n      expectTypeOf(result3[1]).toEqualTypeOf<UseQueryResult<number, unknown>>()\n      expectTypeOf(result3[0].data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(result3[1].data).toEqualTypeOf<number | undefined>()\n\n      // types should be enforced\n      useQueries<\n        [\n          { queryFnData: string; data: string },\n          { queryFnData: string; data: number; error: boolean },\n        ]\n      >(() => ({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return a.toLowerCase()\n            },\n            placeholderData: 'string',\n            // @ts-expect-error (initialData: string)\n            initialData: 123,\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n            select: (a) => {\n              expectTypeOf(a).toEqualTypeOf<string>()\n              return parseInt(a)\n            },\n            placeholderData: 'string',\n            // @ts-expect-error (initialData: string)\n            initialData: 123,\n          },\n        ],\n      }))\n\n      // field names should be enforced\n      useQueries<[{ queryFnData: string }]>(() => ({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n          },\n        ],\n      }))\n    }\n  })\n\n  it('handles array literal without type parameter to infer result type', () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n    const key3 = queryKey()\n    const key4 = queryKey()\n\n    // @ts-expect-error (Page component is not rendered)\n    function Page() {\n      // Array.map preserves TQueryFnData\n      const result1 = useQueries(() => ({\n        queries: Array(50).map((_, i) => ({\n          queryKey: ['key', i] as const,\n          queryFn: () => i + 10,\n        })),\n      }))\n      expectTypeOf(result1).toEqualTypeOf<\n        Array<UseQueryResult<number, Error>>\n      >()\n      if (result1[0]) {\n        expectTypeOf(result1[0].data).toEqualTypeOf<number | undefined>()\n      }\n\n      // Array.map preserves TData\n      const result2 = useQueries(() => ({\n        queries: Array(50).map((_, i) => ({\n          queryKey: ['key', i] as const,\n          queryFn: () => i + 10,\n          select: (data: number) => data.toString(),\n        })),\n      }))\n      expectTypeOf(result2).toEqualTypeOf<\n        Array<UseQueryResult<string, Error>>\n      >()\n\n      const result3 = useQueries(() => ({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 1,\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n          },\n          {\n            queryKey: key3,\n            queryFn: () => ['string[]'],\n            select: () => 123,\n          },\n        ],\n      }))\n      expectTypeOf(result3[0]).toEqualTypeOf<UseQueryResult<number, Error>>()\n      expectTypeOf(result3[1]).toEqualTypeOf<UseQueryResult<string, Error>>()\n      expectTypeOf(result3[2]).toEqualTypeOf<UseQueryResult<number, Error>>()\n      expectTypeOf(result3[0].data).toEqualTypeOf<number | undefined>()\n      expectTypeOf(result3[1].data).toEqualTypeOf<string | undefined>()\n      // select takes precedence over queryFn\n      expectTypeOf(result3[2].data).toEqualTypeOf<number | undefined>()\n\n      // initialData/placeholderData are enforced\n      useQueries(() => ({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n            placeholderData: 'string',\n            // @ts-expect-error (initialData: string)\n            initialData: 123,\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 123,\n            // @ts-expect-error (placeholderData: number)\n            placeholderData: 'string',\n            initialData: 123,\n          },\n        ],\n      }))\n\n      // select params are \"indirectly\" enforced\n      useQueries(() => ({\n        queries: [\n          // unfortunately TS will not suggest the type for you\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n          },\n          // however you can add a type to the callback\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n          },\n          // the type you do pass is enforced\n          {\n            queryKey: key3,\n            queryFn: () => 'string',\n          },\n          {\n            queryKey: key4,\n            queryFn: () => 'string',\n            select: (a: string) => parseInt(a),\n          },\n        ],\n      }))\n\n      // callbacks are also indirectly enforced with Array.map\n      useQueries(() => ({\n        queries: Array(50).map((_, i) => ({\n          queryKey: ['key', i] as const,\n          queryFn: () => i + 10,\n          select: (data: number) => data.toString(),\n        })),\n      }))\n\n      useQueries(() => ({\n        queries: Array(50).map((_, i) => ({\n          queryKey: ['key', i] as const,\n          queryFn: () => i + 10,\n          select: (data: number) => data.toString(),\n        })),\n      }))\n\n      // results inference works when all the handlers are defined\n      const result4 = useQueries(() => ({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n          },\n          {\n            queryKey: key2,\n            queryFn: () => 'string',\n          },\n          {\n            queryKey: key4,\n            queryFn: () => 'string',\n            select: (a: string) => parseInt(a),\n          },\n        ],\n      }))\n      expectTypeOf(result4[0]).toEqualTypeOf<UseQueryResult<string, Error>>()\n      expectTypeOf(result4[1]).toEqualTypeOf<UseQueryResult<string, Error>>()\n      expectTypeOf(result4[2]).toEqualTypeOf<UseQueryResult<number, Error>>()\n\n      // handles when queryFn returns a Promise\n      const result5 = useQueries(() => ({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => Promise.resolve('string'),\n          },\n        ],\n      }))\n      expectTypeOf(result5[0]).toEqualTypeOf<UseQueryResult<string, Error>>()\n\n      // Array as const does not throw error\n      const result6 = useQueries(\n        () =>\n          ({\n            queries: [\n              {\n                queryKey: ['key1'],\n                queryFn: () => 'string',\n              },\n              {\n                queryKey: ['key1'],\n                queryFn: () => 123,\n              },\n            ],\n          }) as const,\n      )\n      expectTypeOf(result6[0]).toEqualTypeOf<UseQueryResult<string, Error>>()\n      expectTypeOf(result6[1]).toEqualTypeOf<UseQueryResult<number, Error>>()\n\n      // field names should be enforced - array literal\n      useQueries(() => ({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n          },\n        ],\n      }))\n\n      // field names should be enforced - Array.map() result\n      useQueries(() => ({\n        // @ts-expect-error (invalidField)\n        queries: Array(10).map(() => ({\n          someInvalidField: '',\n        })),\n      }))\n\n      // field names should be enforced - array literal\n      useQueries(() => ({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () => 'string',\n          },\n        ],\n      }))\n\n      // supports queryFn using fetch() to return Promise<any> - Array.map() result\n      useQueries(() => ({\n        queries: Array(50).map((_, i) => ({\n          queryKey: ['key', i] as const,\n          queryFn: () =>\n            fetch('return Promise<any>').then((resp) => resp.json()),\n        })),\n      }))\n\n      // supports queryFn using fetch() to return Promise<any> - array literal\n      useQueries(() => ({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: () =>\n              fetch('return Promise<any>').then((resp) => resp.json()),\n          },\n        ],\n      }))\n    }\n  })\n\n  it('handles strongly typed queryFn factories and useQueries wrappers', () => {\n    // QueryKey + queryFn factory\n    type QueryKeyA = ['queryA']\n    const getQueryKeyA = (): QueryKeyA => ['queryA']\n    type GetQueryFunctionA = () => QueryFunction<number, QueryKeyA>\n    const getQueryFunctionA: GetQueryFunctionA = () => () => {\n      return 1\n    }\n    type SelectorA = (data: number) => [number, string]\n    const getSelectorA = (): SelectorA => (data) => [data, data.toString()]\n\n    type QueryKeyB = ['queryB', string]\n    const getQueryKeyB = (id: string): QueryKeyB => ['queryB', id]\n    type GetQueryFunctionB = () => QueryFunction<string, QueryKeyB>\n    const getQueryFunctionB: GetQueryFunctionB = () => () => {\n      return '1'\n    }\n    type SelectorB = (data: string) => [string, number]\n    const getSelectorB = (): SelectorB => (data) => [data, +data]\n\n    // Wrapper with strongly typed array-parameter\n    function useWrappedQueries<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey extends QueryKey,\n    >(\n      queries: Array<SolidQueryOptions<TQueryFnData, TError, TData, TQueryKey>>,\n    ) {\n      return useQueries(() => ({\n        queries: queries.map(\n          // no need to type the mapped query\n          (query) => {\n            const { queryFn: fn, queryKey: key } = query\n            expectTypeOf(fn).toEqualTypeOf<\n              | typeof QueryCore.skipToken\n              | QueryCore.QueryFunction<TQueryFnData, TQueryKey, never>\n              | undefined\n            >()\n            return {\n              queryKey: key,\n              queryFn: fn\n                ? (ctx: QueryFunctionContext<TQueryKey>) => {\n                    // eslint-disable-next-line vitest/valid-expect\n                    expectTypeOf<TQueryKey>(ctx.queryKey)\n                    return (fn as QueryFunction<TQueryFnData, TQueryKey>).call(\n                      {},\n                      ctx,\n                    )\n                  }\n                : undefined,\n            }\n          },\n        ),\n      }))\n    }\n\n    // @ts-expect-error (Page component is not rendered)\n    function Page() {\n      const result = useQueries(() => ({\n        queries: [\n          {\n            queryKey: getQueryKeyA(),\n            queryFn: getQueryFunctionA(),\n          },\n          {\n            queryKey: getQueryKeyB('id'),\n            queryFn: getQueryFunctionB(),\n          },\n        ],\n      }))\n      expectTypeOf(result[0]).toEqualTypeOf<UseQueryResult<number, Error>>()\n      expectTypeOf(result[1]).toEqualTypeOf<UseQueryResult<string, Error>>()\n\n      const withSelector = useQueries(() => ({\n        queries: [\n          {\n            queryKey: getQueryKeyA(),\n            queryFn: getQueryFunctionA(),\n            select: getSelectorA(),\n          },\n          {\n            queryKey: getQueryKeyB('id'),\n            queryFn: getQueryFunctionB(),\n            select: getSelectorB(),\n          },\n        ],\n      }))\n      expectTypeOf(withSelector[0]).toEqualTypeOf<\n        UseQueryResult<[number, string], Error>\n      >()\n      expectTypeOf(withSelector[1]).toEqualTypeOf<\n        UseQueryResult<[string, number], Error>\n      >()\n\n      const withWrappedQueries = useWrappedQueries(\n        Array(10).map(() => ({\n          queryKey: getQueryKeyA(),\n          queryFn: getQueryFunctionA(),\n          select: getSelectorA(),\n        })),\n      )\n\n      expectTypeOf(withWrappedQueries).toEqualTypeOf<\n        Array<UseQueryResult<number, Error>>\n      >()\n    }\n  })\n\n  // eslint-disable-next-line vitest/expect-expect\n  it('should not change state if unmounted', async () => {\n    const key1 = queryKey()\n\n    // We have to mock the QueriesObserver to not unsubscribe\n    // the listener when the component is unmounted\n    class QueriesObserverMock extends QueriesObserver {\n      subscribe(listener: any) {\n        super.subscribe(listener)\n        return () => void 0\n      }\n    }\n\n    const QueriesObserverSpy = vi\n      .spyOn(QueryCore, 'QueriesObserver')\n      .mockImplementation(function (\n        client: InstanceType<typeof QueryCore.QueryClient>,\n        queries: Array<QueryCore.QueryObserverOptions>,\n      ) {\n        return new QueriesObserverMock(client, queries)\n      })\n\n    function Queries() {\n      useQueries(() => ({\n        queries: [\n          {\n            queryKey: key1,\n            queryFn: async () => {\n              await sleep(10)\n              return 1\n            },\n          },\n        ],\n      }))\n\n      return (\n        <div>\n          <span>queries</span>\n        </div>\n      )\n    }\n\n    function Page() {\n      const [mounted, setMounted] = createSignal(true)\n\n      return (\n        <div>\n          <button onClick={() => setMounted(false)}>unmount</button>\n          {mounted() && <Queries />}\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    fireEvent.click(rendered.getByText('unmount'))\n\n    // Should not display the console error\n    // \"Warning: Can't perform a React state update on an unmounted component\"\n\n    await vi.advanceTimersByTimeAsync(20)\n    QueriesObserverSpy.mockRestore()\n  })\n})\n"
  },
  {
    "path": "packages/solid-query/src/__tests__/useQuery.test-d.tsx",
    "content": "import { describe, expectTypeOf, it } from 'vitest'\nimport { queryOptions, useQuery } from '../index'\n\ndescribe('initialData', () => {\n  describe('Config object overload', () => {\n    it('TData should always be defined when initialData is provided as an object', () => {\n      const { data } = useQuery(() => ({\n        queryKey: ['key'],\n        queryFn: () => ({ wow: true }),\n        initialData: { wow: true },\n      }))\n\n      expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n    })\n\n    it('TData should be defined when passed through queryOptions', () => {\n      const options = queryOptions({\n        queryKey: ['key'],\n        queryFn: () => ({ wow: true }),\n        initialData: { wow: true },\n      })\n      const { data } = useQuery(() => options)\n\n      expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n    })\n\n    it('TData should always be defined when initialData is provided as a function which ALWAYS returns the data', () => {\n      const { data } = useQuery(() => ({\n        queryKey: ['key'],\n        queryFn: () => ({ wow: true }),\n        initialData: () => ({ wow: true }),\n      }))\n\n      expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n    })\n\n    it('TData should have undefined in the union when initialData is NOT provided', () => {\n      const { data } = useQuery(() => ({\n        queryKey: ['key'],\n        queryFn: () => ({ wow: true }),\n      }))\n\n      expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()\n    })\n\n    it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => {\n      const { data } = useQuery(() => ({\n        queryKey: ['key'],\n        queryFn: () => ({ wow: true }),\n        initialData: () => undefined as { wow: boolean } | undefined,\n      }))\n\n      expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()\n    })\n  })\n\n  describe('Query key overload', () => {\n    it('TData should always be defined when initialData is provided', () => {\n      const { data } = useQuery(() => ({\n        queryKey: ['key'],\n        queryFn: () => ({ wow: true }),\n        initialData: { wow: true },\n      }))\n\n      expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n    })\n\n    it('TData should have undefined in the union when initialData is NOT provided', () => {\n      const { data } = useQuery(() => ({\n        queryKey: ['key'],\n        queryFn: () => ({ wow: true }),\n      }))\n\n      expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()\n    })\n  })\n\n  describe('Query key and func', () => {\n    it('TData should always be defined when initialData is provided', () => {\n      const { data } = useQuery(() => ({\n        queryKey: ['key'],\n        queryFn: () => ({ wow: true }),\n        initialData: { wow: true },\n      }))\n\n      expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n    })\n\n    it('TData should have undefined in the union when initialData is NOT provided', () => {\n      const { data } = useQuery(() => ({\n        queryKey: ['key'],\n        queryFn: () => ({ wow: true }),\n      }))\n\n      expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/solid-query/src/__tests__/useQuery.test.tsx",
    "content": "import {\n  afterEach,\n  beforeEach,\n  describe,\n  expect,\n  expectTypeOf,\n  it,\n  vi,\n} from 'vitest'\nimport {\n  ErrorBoundary,\n  Match,\n  Switch,\n  createEffect,\n  createMemo,\n  createRenderEffect,\n  createSignal,\n  on,\n} from 'solid-js'\nimport { fireEvent, render } from '@solidjs/testing-library'\nimport { reconcile } from 'solid-js/store'\nimport {\n  mockVisibilityState,\n  queryKey,\n  sleep,\n} from '@tanstack/query-test-utils'\nimport {\n  IsRestoringProvider,\n  QueryCache,\n  QueryClient,\n  QueryClientProvider,\n  keepPreviousData,\n  useQuery,\n} from '..'\nimport { Blink, mockOnlineManagerIsOnline, setActTimeout } from './utils'\nimport type {\n  DefinedUseQueryResult,\n  OmitKeyof,\n  QueryFunction,\n  UseQueryOptions,\n  UseQueryResult,\n} from '..'\nimport type { Mock } from 'vitest'\nimport type { JSX } from 'solid-js'\n\ndescribe('useQuery', () => {\n  const queryCache = new QueryCache()\n  const queryClient = new QueryClient({ queryCache })\n\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should return the correct types', () => {\n    const key = queryKey()\n\n    // @ts-expect-error\n    function Page() {\n      // unspecified query function should default to unknown\n      const noQueryFn = useQuery(() => ({ queryKey: key }))\n      expectTypeOf(noQueryFn.data).toEqualTypeOf<unknown>()\n      expectTypeOf(noQueryFn.error).toEqualTypeOf<Error | null>()\n\n      // it should infer the result type from the query function\n      const fromQueryFn = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => 'test',\n      }))\n      expectTypeOf(fromQueryFn.data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(fromQueryFn.error).toEqualTypeOf<Error | null>()\n\n      // it should be possible to specify the result type\n      const withResult = useQuery<string>(() => ({\n        queryKey: key,\n        queryFn: () => 'test',\n      }))\n      expectTypeOf(withResult.data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(withResult.error).toEqualTypeOf<Error | null>()\n\n      // it should be possible to specify the error type\n      const withError = useQuery<string, Error>(() => ({\n        queryKey: key,\n        queryFn: () => 'test',\n      }))\n      expectTypeOf(withError.data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(withError.error).toEqualTypeOf<Error | null>()\n\n      // it should provide the result type in the configuration\n      useQuery(() => ({\n        queryKey: [key],\n        queryFn: () => true,\n      }))\n\n      // it should be possible to specify a union type as result type\n      const unionTypeSync = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => (Math.random() > 0.5 ? ('a' as const) : ('b' as const)),\n      }))\n      expectTypeOf(unionTypeSync.data).toEqualTypeOf<'a' | 'b' | undefined>()\n      const unionTypeAsync = useQuery<'a' | 'b'>(() => ({\n        queryKey: key,\n        queryFn: () => Promise.resolve(Math.random() > 0.5 ? 'a' : 'b'),\n      }))\n      expectTypeOf(unionTypeAsync.data).toEqualTypeOf<'a' | 'b' | undefined>()\n\n      // should error when the query function result does not match with the specified type\n      // @ts-expect-error\n      useQuery<number>(() => ({ queryKey: key, queryFn: () => 'test' }))\n\n      // it should infer the result type from a generic query function\n      function queryFn<T = string>(): Promise<T> {\n        return Promise.resolve({} as T)\n      }\n\n      const fromGenericQueryFn = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => queryFn(),\n      }))\n      expectTypeOf(fromGenericQueryFn.data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(fromGenericQueryFn.error).toEqualTypeOf<Error | null>()\n\n      const fromGenericOptionsQueryFn = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => queryFn(),\n      }))\n      expectTypeOf(fromGenericOptionsQueryFn.data).toEqualTypeOf<\n        string | undefined\n      >()\n      expectTypeOf(\n        fromGenericOptionsQueryFn.error,\n      ).toEqualTypeOf<Error | null>()\n\n      type MyData = number\n      type MyQueryKey = readonly ['my-data', number]\n\n      const getMyDataArrayKey: QueryFunction<MyData, MyQueryKey> = ({\n        queryKey: [, n],\n      }) => {\n        return n + 42\n      }\n\n      useQuery(() => ({\n        queryKey: ['my-data', 100] as const,\n        queryFn: getMyDataArrayKey,\n      }))\n\n      const getMyDataStringKey: QueryFunction<MyData, ['1']> = (context) => {\n        expectTypeOf(context.queryKey).toEqualTypeOf<['1']>()\n        return Number(context.queryKey[0]) + 42\n      }\n\n      useQuery(() => ({\n        queryKey: ['1'] as ['1'],\n        queryFn: getMyDataStringKey,\n      }))\n\n      // it should handle query-functions that return Promise<any>\n      useQuery(() => ({\n        queryKey: key,\n        queryFn: () => fetch('return Promise<any>').then((resp) => resp.json()),\n      }))\n\n      // handles wrapped queries with custom fetcher passed as inline queryFn\n      const useWrappedQuery = <\n        TQueryKey extends [string, Record<string, unknown>?],\n        TQueryFnData,\n        TError,\n        TData = TQueryFnData,\n      >(\n        qk: TQueryKey,\n        fetcher: (\n          obj: TQueryKey[1],\n          token: string,\n          // return type must be wrapped with TQueryFnReturn\n        ) => Promise<TQueryFnData>,\n        options?: OmitKeyof<\n          UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n          'queryKey' | 'queryFn' | 'initialData',\n          'safely'\n        >,\n      ) =>\n        useQuery(() => ({\n          queryKey: qk,\n          queryFn: () => fetcher(qk[1], 'token'),\n          ...options,\n        }))\n      const test = useWrappedQuery([''], () => Promise.resolve('1'))\n      expectTypeOf(test.data).toEqualTypeOf<string | undefined>()\n\n      // handles wrapped queries with custom fetcher passed directly to useQuery\n      const useWrappedFuncStyleQuery = <\n        TQueryKey extends [string, Record<string, unknown>?],\n        TQueryFnData,\n        TError,\n        TData = TQueryFnData,\n      >(\n        qk: TQueryKey,\n        fetcher: () => Promise<TQueryFnData>,\n        options?: OmitKeyof<\n          UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n          'queryKey' | 'queryFn' | 'initialData',\n          'safely'\n        >,\n      ) => useQuery(() => ({ queryKey: qk, queryFn: fetcher, ...options }))\n      const testFuncStyle = useWrappedFuncStyleQuery([''], () =>\n        Promise.resolve(true),\n      )\n      expectTypeOf(testFuncStyle.data).toEqualTypeOf<boolean | undefined>()\n    }\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/105\n  it('should allow to set default data value', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'test'),\n      }))\n\n      return (\n        <div>\n          <h1>{state.data ?? 'default'}</h1>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('default')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('test')).toBeInTheDocument()\n  })\n\n  it('should return the correct states for a successful query', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page(): JSX.Element {\n      const state = useQuery<string, Error>(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'test'),\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      if (state.isPending) {\n        expectTypeOf(state.data).toEqualTypeOf<undefined>()\n        expectTypeOf(state.error).toEqualTypeOf<null>()\n      } else if (state.isLoadingError) {\n        expectTypeOf(state.data).toEqualTypeOf<undefined>()\n        expectTypeOf(state.error).toEqualTypeOf<Error>()\n      } else {\n        expectTypeOf(state.data).toEqualTypeOf<string>()\n        expectTypeOf(state.error).toEqualTypeOf<Error | null>()\n      }\n\n      return (\n        <Switch fallback={<span>{state.data}</span>}>\n          <Match when={state.isPending}>\n            <span>pending</span>\n          </Match>\n          <Match when={state.isLoadingError}>\n            <span>{state.error!.message}</span>\n          </Match>\n        </Switch>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('test')).toBeInTheDocument()\n\n    expect(states.length).toEqual(2)\n\n    expect(states[0]).toEqual({\n      data: undefined,\n      dataUpdatedAt: 0,\n      error: null,\n      errorUpdatedAt: 0,\n      failureCount: 0,\n      failureReason: null,\n      errorUpdateCount: 0,\n      isError: false,\n      isFetched: false,\n      isFetchedAfterMount: false,\n      isFetching: true,\n      isPaused: false,\n      isPending: true,\n      isInitialLoading: true,\n      isLoading: true,\n      isLoadingError: false,\n      isPlaceholderData: false,\n      isRefetchError: false,\n      isRefetching: false,\n      isStale: true,\n      isSuccess: false,\n      isEnabled: true,\n      refetch: expect.any(Function),\n      status: 'pending',\n      fetchStatus: 'fetching',\n      promise: expect.any(Promise),\n    })\n\n    expect(states[1]).toEqual({\n      data: 'test',\n      dataUpdatedAt: expect.any(Number),\n      error: null,\n      errorUpdatedAt: 0,\n      failureCount: 0,\n      failureReason: null,\n      errorUpdateCount: 0,\n      isError: false,\n      isFetched: true,\n      isFetchedAfterMount: true,\n      isFetching: false,\n      isPaused: false,\n      isPending: false,\n      isInitialLoading: false,\n      isLoading: false,\n      isLoadingError: false,\n      isPlaceholderData: false,\n      isRefetchError: false,\n      isRefetching: false,\n      isStale: true,\n      isSuccess: true,\n      isEnabled: true,\n      refetch: expect.any(Function),\n      status: 'success',\n      fetchStatus: 'idle',\n      promise: expect.any(Promise),\n    })\n  })\n\n  it('should return the correct states for an unsuccessful query', async () => {\n    const key = queryKey()\n\n    const states: Array<UseQueryResult<unknown, Error>> = []\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => Promise.reject(new Error('rejected'))),\n        retry: 1,\n        retryDelay: 1,\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      return (\n        <div>\n          <h1>Status: {state.status}</h1>\n          <div>Failure Count: {state.failureCount}</div>\n          <div>Failure Reason: {state.failureReason?.message}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(21)\n    expect(rendered.getByText('Status: error')).toBeInTheDocument()\n\n    expect(states[0]).toEqual({\n      data: undefined,\n      dataUpdatedAt: 0,\n      error: null,\n      errorUpdatedAt: 0,\n      failureCount: 0,\n      failureReason: null,\n      errorUpdateCount: 0,\n      isError: false,\n      isFetched: false,\n      isFetchedAfterMount: false,\n      isFetching: true,\n      isPaused: false,\n      isPending: true,\n      isInitialLoading: true,\n      isLoading: true,\n      isLoadingError: false,\n      isPlaceholderData: false,\n      isRefetchError: false,\n      isRefetching: false,\n      isStale: true,\n      isSuccess: false,\n      isEnabled: true,\n      refetch: expect.any(Function),\n      status: 'pending',\n      fetchStatus: 'fetching',\n      promise: expect.any(Promise),\n    })\n\n    expect(states[1]).toEqual({\n      data: undefined,\n      dataUpdatedAt: 0,\n      error: null,\n      errorUpdatedAt: 0,\n      failureCount: 1,\n      failureReason: new Error('rejected'),\n      errorUpdateCount: 0,\n      isError: false,\n      isFetched: false,\n      isFetchedAfterMount: false,\n      isFetching: true,\n      isPaused: false,\n      isPending: true,\n      isInitialLoading: true,\n      isLoading: true,\n      isLoadingError: false,\n      isPlaceholderData: false,\n      isRefetchError: false,\n      isRefetching: false,\n      isStale: true,\n      isSuccess: false,\n      isEnabled: true,\n      refetch: expect.any(Function),\n      status: 'pending',\n      fetchStatus: 'fetching',\n      promise: expect.any(Promise),\n    })\n\n    expect(states[2]).toEqual({\n      data: undefined,\n      dataUpdatedAt: 0,\n      error: new Error('rejected'),\n      errorUpdatedAt: expect.any(Number),\n      failureCount: 2,\n      failureReason: new Error('rejected'),\n      errorUpdateCount: 1,\n      isError: true,\n      isFetched: true,\n      isFetchedAfterMount: true,\n      isFetching: false,\n      isPaused: false,\n      isPending: false,\n      isInitialLoading: false,\n      isLoading: false,\n      isLoadingError: true,\n      isPlaceholderData: false,\n      isRefetchError: false,\n      isRefetching: false,\n      isStale: true,\n      isSuccess: false,\n      isEnabled: true,\n      refetch: expect.any(Function),\n      status: 'error',\n      fetchStatus: 'idle',\n      promise: expect.any(Promise),\n    })\n  })\n\n  it('should set isFetchedAfterMount to true after a query has been fetched', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'prefetched'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'data'),\n      }))\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(states.length).toBe(2)\n\n    expect(states[0]).toMatchObject({\n      data: 'prefetched',\n      isFetched: true,\n      isFetchedAfterMount: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: 'data',\n      isFetched: true,\n      isFetchedAfterMount: true,\n    })\n  })\n\n  it('should not cancel an ongoing fetch when refetch is called with cancelRefetch=false if we have data already', async () => {\n    const key = queryKey()\n    let fetchCount = 0\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          fetchCount++\n          return 'data'\n        },\n        enabled: false,\n        initialData: 'initialData',\n      }))\n\n      createEffect(() => {\n        setActTimeout(() => {\n          state.refetch()\n        }, 5)\n        setActTimeout(() => {\n          state.refetch({ cancelRefetch: false })\n        }, 5)\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(15)\n    // first refetch only, second refetch is ignored\n    expect(fetchCount).toBe(1)\n  })\n\n  it('should cancel an ongoing fetch when refetch is called (cancelRefetch=true) if we have data already', async () => {\n    const key = queryKey()\n    let fetchCount = 0\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          fetchCount++\n          return 'data'\n        },\n        enabled: false,\n        initialData: 'initialData',\n      }))\n\n      createEffect(() => {\n        setActTimeout(() => {\n          state.refetch()\n        }, 5)\n        setActTimeout(() => {\n          state.refetch()\n        }, 5)\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(15)\n    // first refetch (gets cancelled) and second refetch\n    expect(fetchCount).toBe(2)\n  })\n\n  it('should not cancel an ongoing fetch when refetch is called (cancelRefetch=true) if we do not have data yet', async () => {\n    const key = queryKey()\n    let fetchCount = 0\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          fetchCount++\n          return 'data'\n        },\n        enabled: false,\n      }))\n\n      createEffect(() => {\n        setActTimeout(() => {\n          state.refetch()\n        }, 5)\n        setActTimeout(() => {\n          state.refetch()\n        }, 5)\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(15)\n    // first refetch will not get cancelled, second one gets skipped\n    expect(fetchCount).toBe(1)\n  })\n\n  it('should be able to watch a query without providing a query function', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    queryClient.setQueryDefaults(key, {\n      queryFn: () => sleep(10).then(() => 'data'),\n    })\n\n    function Page() {\n      const state = useQuery<string>(() => ({ queryKey: key }))\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined })\n    expect(states[1]).toMatchObject({ data: 'data' })\n  })\n\n  it('should pick up a query when re-mounting with gcTime 0', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const [toggle, setToggle] = createSignal(false)\n\n      return (\n        <div>\n          <button onClick={() => setToggle(true)}>toggle</button>\n          <Switch>\n            <Match when={toggle()}>\n              <Component value=\"2\" />\n            </Match>\n            <Match when={!toggle()}>\n              <Component value=\"1\" />\n            </Match>\n          </Switch>\n        </div>\n      )\n    }\n\n    function Component({ value }: { value: string }) {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'data: ' + value),\n        gcTime: 0,\n      }))\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n      return (\n        <div>\n          <div>{state.data}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /toggle/i }))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 2')).toBeInTheDocument()\n\n    expect(states.length).toBe(4)\n    // First load\n    expect(states[0]).toMatchObject({\n      isPending: true,\n      isSuccess: false,\n      isFetching: true,\n    })\n    // First success\n    expect(states[1]).toMatchObject({\n      isPending: false,\n      isSuccess: true,\n      isFetching: false,\n    })\n    // Switch, goes to fetching\n    expect(states[2]).toMatchObject({\n      isPending: false,\n      isSuccess: true,\n      isFetching: true,\n    })\n    // Second success\n    expect(states[3]).toMatchObject({\n      isPending: false,\n      isSuccess: true,\n      isFetching: false,\n    })\n  })\n\n  it('should fetch when refetchOnMount is false and nothing has been fetched yet', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'test'),\n        refetchOnMount: false,\n      }))\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined })\n    expect(states[1]).toMatchObject({ data: 'test' })\n  })\n\n  it('should not fetch when refetchOnMount is false and data has been fetched already', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    queryClient.setQueryData(key, 'prefetched')\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'test'),\n        refetchOnMount: false,\n      }))\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(1)\n    expect(states[0]).toMatchObject({ data: 'prefetched' })\n  })\n\n  it('should be able to select a part of the data with select', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => ({ name: 'test' })),\n        select: (data) => data.name,\n      }))\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined })\n    expect(states[1]).toMatchObject({ data: 'test' })\n  })\n\n  it('should be able to select a part of the data with select in object syntax 2', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => ({ name: 'test' })),\n        select: (data) => data.name,\n      }))\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined })\n    expect(states[1]).toMatchObject({ data: 'test' })\n  })\n\n  it('should be able to select a part of the data with select in object syntax 1', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => ({ name: 'test' })),\n        select: (data) => data.name,\n      }))\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined })\n    expect(states[1]).toMatchObject({ data: 'test' })\n  })\n\n  it('should not re-render when it should only re-render only data change and the selected data did not change', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => ({ name: 'test' })),\n        select: (data) => data.name,\n        notifyOnChangeProps: ['data'],\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      return (\n        <div>\n          data: {state.data}\n          <button onClick={() => state.refetch()}>refetch</button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: test')).toBeInTheDocument()\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined })\n    expect(states[1]).toMatchObject({ data: 'test' })\n  })\n\n  it('should throw an error when a selector throws', async () => {\n    const key = queryKey()\n    const states: Array<{ status: string; data?: unknown; error?: Error }> = []\n    const error = new Error('Select Error')\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => ({ name: 'test' })),\n        select: () => {\n          throw error\n        },\n      }))\n      createRenderEffect(() => {\n        if (state.status === 'pending')\n          states.push({ status: 'pending', data: undefined })\n        else if (state.status === 'error')\n          states.push({ status: 'error', error: state.error })\n      })\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n\n    expect(states[0]).toMatchObject({ status: 'pending', data: undefined })\n    expect(states[1]).toMatchObject({ status: 'error', error })\n  })\n\n  it('should track properties and only re-render when a tracked property changes', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'test'),\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      createEffect(() => {\n        const data = state.data\n        const refetch = state.refetch\n        setActTimeout(() => {\n          if (data) {\n            refetch()\n          }\n        }, 20)\n      })\n\n      return (\n        <div>\n          <h1>{state.data ?? null}</h1>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(rendered.getByText('test')).toBeInTheDocument()\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined })\n    expect(states[1]).toMatchObject({ data: 'test' })\n  })\n\n  it('should always re-render if we are tracking props but not using any', async () => {\n    const key = queryKey()\n    let renderCount = 0\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'test'),\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      createEffect(\n        on(\n          () => ({ ...state }),\n          () => {\n            renderCount++\n          },\n        ),\n      )\n\n      return (\n        <div>\n          <h1>hello</h1>\n        </div>\n      )\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(renderCount).toBe(2)\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined })\n    expect(states[1]).toMatchObject({ data: 'test' })\n  })\n\n  it('should maintain referential equality when reconcile option is a string key', async () => {\n    const key = queryKey()\n    const states: Array<Array<{ id: string; done: boolean }>> = []\n\n    let count = 0\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          return [\n            { id: '1', done: false },\n            { id: '2', done: count > 1 },\n          ]\n        },\n        reconcile: 'id',\n      }))\n\n      createEffect(() => {\n        if (state.data) {\n          states.push(state.data)\n        }\n      })\n\n      const { refetch } = state\n\n      return (\n        <div>\n          <button onClick={() => refetch()}>refetch</button>\n          <h2>Data: {JSON.stringify(state.data)}</h2>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(\n      rendered.getByText(\n        'Data: [{\"id\":\"1\",\"done\":false},{\"id\":\"2\",\"done\":false}]',\n      ),\n    ).toBeInTheDocument()\n    expect(states).toHaveLength(1)\n\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n    await vi.advanceTimersByTimeAsync(10)\n    expect(\n      rendered.getByText(\n        'Data: [{\"id\":\"1\",\"done\":false},{\"id\":\"2\",\"done\":true}]',\n      ),\n    ).toBeInTheDocument()\n\n    // reconcile by 'id' updates in-place, so the array reference stays the same\n    // and the effect is not triggered again\n    expect(states).toHaveLength(1)\n  })\n\n  it('should share equal data structures between query results', async () => {\n    const key = queryKey()\n    const result1 = [\n      { id: '1', done: false },\n      { id: '2', done: false },\n    ]\n\n    const result2 = [\n      { id: '1', done: false },\n      { id: '2', done: true },\n    ]\n\n    const states: Array<UseQueryResult<typeof result1>> = []\n\n    let count = 0\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          return count === 1 ? result1 : result2\n        },\n        reconcile: (oldData, newData) => {\n          return reconcile(newData)(oldData)\n        },\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      const { refetch } = state\n\n      return (\n        <div>\n          <button onClick={() => refetch()}>refetch</button>\n          data: {String(state.data?.[1]?.done)}\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: false')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: true')).toBeInTheDocument()\n\n    expect(states.length).toBe(4)\n\n    const todos = states[2]?.data\n    const todo1 = todos?.[0]\n    const todo2 = todos?.[1]\n\n    const newTodos = states[3]?.data\n    const newTodo1 = newTodos?.[0]\n    const newTodo2 = newTodos?.[1]\n\n    expect(todos).toEqual(result1)\n    expect(newTodos).toEqual(result2)\n    expect(newTodo1).toBe(todo1)\n    expect(newTodo2).toBe(todo2)\n\n    return null\n  })\n\n  it('should use query function from hook when the existing query does not have a query function', async () => {\n    const key = queryKey()\n    const results: Array<UseQueryResult<string>> = []\n\n    queryClient.setQueryData(key, 'set')\n\n    function Page() {\n      const result = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'fetched'),\n        initialData: 'initial',\n        staleTime: Infinity,\n      }))\n\n      createRenderEffect(() => {\n        results.push({ ...result })\n      })\n\n      return (\n        <div>\n          <div>isFetching: {result.isFetching}</div>\n          <button onClick={() => queryClient.refetchQueries({ queryKey: key })}>\n            refetch\n          </button>\n          data: {result.data}\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: set')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: fetched')).toBeInTheDocument()\n\n    expect(results.length).toBe(3)\n\n    expect(results[0]).toMatchObject({ data: 'set', isFetching: false })\n    expect(results[1]).toMatchObject({ data: 'set', isFetching: true })\n    expect(results[2]).toMatchObject({ data: 'fetched', isFetching: false })\n  })\n\n  it('should update query stale state and refetch when invalidated with invalidateQueries', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          return count\n        },\n        staleTime: Infinity,\n      }))\n\n      createEffect(() => {\n        states.push({ ...state })\n      })\n\n      return (\n        <div>\n          <button\n            onClick={() => queryClient.invalidateQueries({ queryKey: key })}\n          >\n            invalidate\n          </button>\n          data: {state.data}\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 2')).toBeInTheDocument()\n\n    expect(states.length).toBe(4)\n\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isRefetching: false,\n      isSuccess: false,\n      isStale: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: 1,\n      isFetching: false,\n      isRefetching: false,\n      isSuccess: true,\n      isStale: false,\n    })\n    expect(states[2]).toMatchObject({\n      data: 1,\n      isFetching: true,\n      isRefetching: true,\n      isSuccess: true,\n      isStale: true,\n    })\n    expect(states[3]).toMatchObject({\n      data: 2,\n      isFetching: false,\n      isRefetching: false,\n      isSuccess: true,\n      isStale: false,\n    })\n  })\n\n  it('should not update disabled query when refetch with refetchQueries', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          return count\n        },\n        enabled: false,\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      createEffect(() => {\n        setActTimeout(() => {\n          queryClient.refetchQueries({ queryKey: key })\n        }, 20)\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(30)\n\n    expect(states.length).toBe(1)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: false,\n      isSuccess: false,\n      isStale: false,\n    })\n  })\n\n  it('should not refetch disabled query when invalidated with invalidateQueries', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          return count\n        },\n        enabled: false,\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      createEffect(() => {\n        setActTimeout(() => {\n          queryClient.invalidateQueries({ queryKey: key })\n        }, 20)\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(30)\n\n    expect(states.length).toBe(1)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: false,\n      isSuccess: false,\n      isStale: false,\n    })\n  })\n\n  it('should not fetch when switching to a disabled query', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n\n    function Page() {\n      const [count, setCount] = createSignal(0)\n\n      const state = useQuery(() => ({\n        queryKey: [key, count()],\n        queryFn: () => sleep(5).then(() => count()),\n        enabled: count() === 0,\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      createEffect(() => {\n        setActTimeout(() => {\n          setCount(1)\n        }, 10)\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(3)\n\n    // Fetch query\n    expect(states[0]).toMatchObject({\n      isFetching: true,\n      isSuccess: false,\n    })\n    // Fetched query\n    expect(states[1]).toMatchObject({\n      data: 0,\n      isFetching: false,\n      isSuccess: true,\n    })\n    // Switch to disabled query\n    expect(states[2]).toMatchObject({\n      isFetching: false,\n      isSuccess: false,\n    })\n  })\n\n  it('should keep the previous data when placeholderData is set', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n\n    function Page() {\n      const [count, setCount] = createSignal(0)\n\n      const state = useQuery(() => ({\n        queryKey: [key, count()],\n        queryFn: () => sleep(10).then(() => count()),\n        placeholderData: keepPreviousData,\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      createEffect(() => {\n        setActTimeout(() => {\n          setCount(1)\n        }, 20)\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(30)\n\n    expect(states.length).toBe(4)\n\n    // Initial\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      isFetching: true,\n      isSuccess: false,\n      isPlaceholderData: false,\n    })\n    // Fetched\n    expect(states[1]).toMatchObject({\n      data: 0,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Set state\n    expect(states[2]).toMatchObject({\n      data: 0,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // New data\n    expect(states[3]).toMatchObject({\n      data: 1,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n  })\n\n  it('should not show initial data from next query if placeholderData is set', async () => {\n    const key = queryKey()\n    const states: Array<DefinedUseQueryResult<number>> = []\n\n    function Page() {\n      const [count, setCount] = createSignal(0)\n\n      const state = useQuery(() => ({\n        queryKey: [key, count()],\n        queryFn: () => sleep(10).then(() => count()),\n        initialData: 99,\n        placeholderData: keepPreviousData,\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      return (\n        <div>\n          <h1>\n            data: {state.data}, count: {count()}, isFetching:{' '}\n            {String(state.isFetching)}\n          </h1>\n          <button onClick={() => setCount(1)}>inc</button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(\n      rendered.getByText('data: 0, count: 0, isFetching: false'),\n    ).toBeInTheDocument()\n    fireEvent.click(rendered.getByRole('button', { name: 'inc' }))\n    await vi.advanceTimersByTimeAsync(10)\n    expect(\n      rendered.getByText('data: 1, count: 1, isFetching: false'),\n    ).toBeInTheDocument()\n\n    expect(states.length).toBe(4)\n\n    // Initial\n    expect(states[0]).toMatchObject({\n      data: 99,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Fetched\n    expect(states[1]).toMatchObject({\n      data: 0,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Set state\n    expect(states[2]).toMatchObject({\n      data: 99,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // New data\n    expect(states[3]).toMatchObject({\n      data: 1,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n  })\n\n  it('should keep the previous data on disabled query when placeholderData is set and switching query key multiple times', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n\n    queryClient.setQueryData([key, 10], 10)\n\n    function Page() {\n      const [count, setCount] = createSignal(10)\n\n      const state = useQuery(() => ({\n        queryKey: [key, count()],\n        queryFn: () => sleep(10).then(() => count()),\n        enabled: false,\n        placeholderData: keepPreviousData,\n        notifyOnChangeProps: 'all',\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      createEffect(() => {\n        const refetch = state.refetch\n        setActTimeout(() => {\n          setCount(11)\n        }, 20)\n        setActTimeout(() => {\n          setCount(12)\n        }, 30)\n        setActTimeout(() => {\n          refetch()\n        }, 40)\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(50)\n\n    expect(states.length).toBe(4)\n\n    // Disabled query\n    expect(states[0]).toMatchObject({\n      data: 10,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n    // Set state\n    expect(states[1]).toMatchObject({\n      data: 10,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // Refetch\n    expect(states[2]).toMatchObject({\n      data: 10,\n      isFetching: true,\n      isSuccess: true,\n      isPlaceholderData: true,\n    })\n    // Refetch done\n    expect(states[3]).toMatchObject({\n      data: 12,\n      isFetching: false,\n      isSuccess: true,\n      isPlaceholderData: false,\n    })\n  })\n\n  it('should use the correct query function when components use different configurations', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n\n    function FirstComponent() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 1),\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      return (\n        <div>\n          <button onClick={() => state.refetch()}>refetch</button>\n          data: {state.data}\n        </div>\n      )\n    }\n\n    function SecondComponent() {\n      useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(15).then(() => 2),\n      }))\n      return null\n    }\n\n    function Page() {\n      return (\n        <>\n          <FirstComponent />\n          <SecondComponent />\n        </>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(4)\n\n    expect(states[0]).toMatchObject({\n      data: undefined,\n    })\n    expect(states[1]).toMatchObject({\n      data: 1,\n    })\n    expect(states[2]).toMatchObject({\n      data: 1,\n    })\n    // This state should be 1 instead of 2\n    expect(states[3]).toMatchObject({\n      data: 1,\n    })\n  })\n\n  it('should be able to set different stale times for a query', async () => {\n    const key = queryKey()\n    const states1: Array<UseQueryResult<string>> = []\n    const states2: Array<UseQueryResult<string>> = []\n\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'prefetch'),\n    })\n    await vi.advanceTimersByTimeAsync(20)\n\n    function FirstComponent() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'one'),\n        staleTime: 100,\n      }))\n      createRenderEffect(() => {\n        states1.push({ ...state })\n      })\n      return null\n    }\n\n    function SecondComponent() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'two'),\n        staleTime: 10,\n      }))\n      createRenderEffect(() => {\n        states2.push({ ...state })\n      })\n      return null\n    }\n\n    function Page() {\n      return (\n        <>\n          <FirstComponent />\n          <SecondComponent />\n        </>\n      )\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(200)\n\n    expect(states1.length).toBe(4)\n    expect(states2.length).toBe(3)\n\n    expect(states1).toMatchObject([\n      // First render\n      {\n        data: 'prefetch',\n        isStale: false,\n      },\n      // Second useQuery started fetching\n      {\n        data: 'prefetch',\n        isStale: false,\n      },\n      // Second useQuery data came in\n      {\n        data: 'two',\n        isStale: false,\n      },\n      // Data became stale after 100ms\n      {\n        data: 'two',\n        isStale: true,\n      },\n    ])\n\n    expect(states2).toMatchObject([\n      // First render, data is stale and starts fetching\n      {\n        data: 'prefetch',\n        isStale: true,\n      },\n      // Second useQuery data came in\n      {\n        data: 'two',\n        isStale: false,\n      },\n      // Data became stale after 10ms\n      {\n        data: 'two',\n        isStale: true,\n      },\n    ])\n  })\n\n  it('should re-render when a query becomes stale', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'test'),\n        staleTime: 50,\n      }))\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(70)\n\n    expect(states.length).toBe(3)\n    expect(states[0]).toMatchObject({ isStale: true })\n    expect(states[1]).toMatchObject({ isStale: false })\n    expect(states[2]).toMatchObject({ isStale: true })\n  })\n\n  it('should not re-render when it should only re-render on data changes and the data did not change', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(5).then(() => 'test'),\n        notifyOnChangeProps: ['data'],\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      createEffect(() => {\n        const refetch = state.refetch\n        setActTimeout(() => {\n          refetch()\n        }, 10)\n      })\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(15)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: undefined,\n      status: 'pending',\n      isFetching: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: 'test',\n      status: 'success',\n      isFetching: false,\n    })\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/137\n  it('should not override initial data in dependent queries', () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    function Page() {\n      const first = useQuery(() => ({\n        queryKey: key1,\n        queryFn: () => sleep(10).then(() => 'data'),\n        enabled: false,\n        initialData: 'init',\n      }))\n\n      const second = useQuery(() => ({\n        queryKey: key2,\n        queryFn: () => sleep(10).then(() => 'data'),\n        enabled: false,\n        initialData: 'init',\n      }))\n\n      return (\n        <div>\n          <h2>First Data: {first.data}</h2>\n          <h2>Second Data: {second.data}</h2>\n          <div>First Status: {first.status}</div>\n          <div>Second Status: {second.status}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('First Data: init')).toBeInTheDocument()\n    expect(rendered.getByText('Second Data: init')).toBeInTheDocument()\n    expect(rendered.getByText('First Status: success')).toBeInTheDocument()\n    expect(rendered.getByText('Second Status: success')).toBeInTheDocument()\n  })\n\n  it('should update query options', () => {\n    const key = queryKey()\n\n    const queryFn = () => sleep(10).then(() => 'data1')\n\n    function Page() {\n      useQuery(() => ({ queryKey: key, queryFn, retryDelay: 10 }))\n      useQuery(() => ({ queryKey: key, queryFn, retryDelay: 20 }))\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(queryCache.find({ queryKey: key })!.options.retryDelay).toBe(20)\n  })\n\n  it('should batch re-renders', async () => {\n    const key = queryKey()\n\n    let renders = 0\n\n    const queryFn = () => sleep(15).then(() => 'data')\n\n    function Page() {\n      useQuery(() => ({ queryKey: key, queryFn }))\n      useQuery(() => ({ queryKey: key, queryFn }))\n      renders++\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    // Since components are rendered once\n    // There will only be one pass\n    expect(renders).toBe(1)\n  })\n\n  it('should render latest data even if react has discarded certain renders', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const [, setNewState] = createSignal('state')\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'data'),\n      }))\n      createEffect(() => {\n        setActTimeout(() => {\n          queryClient.setQueryData(key, 'new')\n          // Update with same state to make react discard the next render\n          setNewState('state')\n        }, 10)\n      })\n      return <div>{state.data}</div>\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(rendered.getByText('new')).toBeInTheDocument()\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/170\n  it('should start with status pending, fetchStatus idle if enabled is false', async () => {\n    const key1 = queryKey()\n    const key2 = queryKey()\n\n    function Page() {\n      const first = useQuery(() => ({\n        queryKey: key1,\n        queryFn: () => sleep(10).then(() => 'data'),\n        enabled: false,\n      }))\n      const second = useQuery(() => ({\n        queryKey: key2,\n        queryFn: () => sleep(10).then(() => 'data'),\n      }))\n\n      return (\n        <div>\n          <div>\n            First Status: {first.status}, {first.fetchStatus}\n          </div>\n          <div>\n            Second Status: {second.status}, {second.fetchStatus}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    // use \"act\" to wait for state update and prevent console warning\n\n    expect(\n      rendered.getByText('First Status: pending, idle'),\n    ).toBeInTheDocument()\n    expect(\n      rendered.getByText('Second Status: pending, fetching'),\n    ).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(\n      rendered.getByText('Second Status: success, idle'),\n    ).toBeInTheDocument()\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/144\n  it('should be in \"pending\" state by default', () => {\n    const key = queryKey()\n\n    function Page() {\n      const { status } = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'test'),\n      }))\n\n      return <div>status: {status}</div>\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('status: pending')).toBeInTheDocument()\n  })\n\n  it('should not refetch query on focus when `enabled` is set to `false`', async () => {\n    const key = queryKey()\n    const queryFn = vi\n      .fn<(...args: Array<unknown>) => string>()\n      .mockReturnValue('data')\n\n    function Page() {\n      const { data = 'default' } = useQuery(() => ({\n        queryKey: key,\n        queryFn,\n        enabled: false,\n      }))\n\n      return (\n        <div>\n          <h1>{data}</h1>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('default')).toBeInTheDocument()\n\n    window.dispatchEvent(new Event('visibilitychange'))\n\n    expect(queryFn).not.toHaveBeenCalled()\n  })\n\n  it('should not refetch stale query on focus when `refetchOnWindowFocus` is set to `false`', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => count++),\n        staleTime: 0,\n        refetchOnWindowFocus: false,\n      }))\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    window.dispatchEvent(new Event('visibilitychange'))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined, isFetching: true })\n    expect(states[1]).toMatchObject({ data: 0, isFetching: false })\n  })\n\n  it('should not refetch stale query on focus when `refetchOnWindowFocus` is set to a function that returns `false`', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => count++),\n        staleTime: 0,\n        refetchOnWindowFocus: () => false,\n      }))\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    window.dispatchEvent(new Event('visibilitychange'))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined, isFetching: true })\n    expect(states[1]).toMatchObject({ data: 0, isFetching: false })\n  })\n\n  it('should not refetch fresh query on focus when `refetchOnWindowFocus` is set to `true`', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => count++),\n        staleTime: Infinity,\n        refetchOnWindowFocus: true,\n      }))\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    window.dispatchEvent(new Event('visibilitychange'))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined, isFetching: true })\n    expect(states[1]).toMatchObject({ data: 0, isFetching: false })\n  })\n\n  it('should refetch fresh query on focus when `refetchOnWindowFocus` is set to `always`', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => count++),\n        staleTime: Infinity,\n        refetchOnWindowFocus: 'always',\n      }))\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    window.dispatchEvent(new Event('visibilitychange'))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(4)\n    expect(states[0]).toMatchObject({ data: undefined, isFetching: true })\n    expect(states[1]).toMatchObject({ data: 0, isFetching: false })\n    expect(states[2]).toMatchObject({ data: 0, isFetching: true })\n    expect(states[3]).toMatchObject({ data: 1, isFetching: false })\n  })\n\n  it('should calculate focus behavior for refetchOnWindowFocus depending on function', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => count++),\n        staleTime: 0,\n        retry: 0,\n        refetchOnWindowFocus: (query) => (query.state.data || 0) < 1,\n      }))\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n      return <div>data: {state.data}</div>\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(rendered.getByText('data: 0')).toBeInTheDocument()\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({ data: undefined, isFetching: true })\n    expect(states[1]).toMatchObject({ data: 0, isFetching: false })\n\n    window.dispatchEvent(new Event('visibilitychange'))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n\n    // refetch should happen\n    expect(states.length).toBe(4)\n\n    expect(states[2]).toMatchObject({ data: 0, isFetching: true })\n    expect(states[3]).toMatchObject({ data: 1, isFetching: false })\n\n    window.dispatchEvent(new Event('visibilitychange'))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    // no more refetch now\n    expect(states.length).toBe(4)\n  })\n\n  it('should refetch fresh query when refetchOnMount is set to always', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'prefetched'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'data'),\n        refetchOnMount: 'always',\n        staleTime: Infinity,\n      }))\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: 'prefetched',\n      isStale: false,\n      isFetching: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: 'data',\n      isStale: false,\n      isFetching: false,\n    })\n  })\n\n  it('should refetch stale query when refetchOnMount is set to true', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'prefetched'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'data'),\n        refetchOnMount: true,\n        staleTime: 0,\n      }))\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: 'prefetched',\n      isStale: true,\n      isFetching: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: 'data',\n      isStale: true,\n      isFetching: false,\n    })\n  })\n\n  it('should set status to error if queryFn throws', async () => {\n    const key = queryKey()\n\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => Promise.reject(new Error('Error test'))),\n        retry: false,\n      }))\n\n      return (\n        <div>\n          <h1>{state.status}</h1>\n          <h2>{state.error?.message}</h2>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error')).toBeInTheDocument()\n    expect(rendered.getByText('Error test')).toBeInTheDocument()\n\n    consoleMock.mockRestore()\n  })\n\n  it('should throw error if queryFn throws and throwOnError is in use', async () => {\n    const key = queryKey()\n\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => Promise.reject(new Error('Error test'))),\n        retry: false,\n        throwOnError: true,\n      }))\n\n      return (\n        <div>\n          <h1>{state.data}</h1>\n          <h1>{state.status}</h1>\n          <h2>{state.error?.message}</h2>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <ErrorBoundary fallback={() => <div>error boundary</div>}>\n          <Page />\n        </ErrorBoundary>\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n\n    consoleMock.mockRestore()\n  })\n\n  it('should throw error inside the same component if queryFn throws and throwOnError is in use', async () => {\n    const key = queryKey()\n\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => Promise.reject(new Error('Error test'))),\n        retry: false,\n        throwOnError: true,\n      }))\n\n      return (\n        <div>\n          <ErrorBoundary fallback={() => <div>error boundary</div>}>\n            <h1>{state.data}</h1>\n            <h1>{state.status}</h1>\n            <h2>{state.error?.message}</h2>\n          </ErrorBoundary>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n\n    consoleMock.mockRestore()\n  })\n\n  it('should throw error inside the same component if queryFn throws and show the correct error message', async () => {\n    const key = queryKey()\n\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => Promise.reject(new Error('Error test'))),\n        retry: false,\n        throwOnError: true,\n      }))\n\n      return (\n        <div>\n          <ErrorBoundary\n            fallback={(err) => <div>Fallback error: {err.message}</div>}\n          >\n            <h1>{state.data}</h1>\n            <h1>{state.status}</h1>\n            <h2>{state.error?.message}</h2>\n          </ErrorBoundary>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('Fallback error: Error test')).toBeInTheDocument()\n\n    consoleMock.mockRestore()\n  })\n\n  it('should show the correct error message on the error property when accessed outside error boundary', async () => {\n    const key = queryKey()\n\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => Promise.reject(new Error('Error test'))),\n        retry: false,\n        throwOnError: true,\n      }))\n\n      return (\n        <div>\n          <h2>Outside error boundary: {state.error?.message}</h2>\n          <ErrorBoundary\n            fallback={(err) => <div>Fallback error: {err.message}</div>}\n          >\n            <h1>{state.data}</h1>\n            <h1>{state.status}</h1>\n          </ErrorBoundary>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(\n      rendered.getByText('Outside error boundary: Error test'),\n    ).toBeInTheDocument()\n    expect(rendered.getByText('Fallback error: Error test')).toBeInTheDocument()\n\n    consoleMock.mockRestore()\n  })\n\n  it('should update with data if we observe no properties and throwOnError', async () => {\n    const key = queryKey()\n\n    let result: UseQueryResult<string> | undefined\n\n    function Page() {\n      const query = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'data'),\n        throwOnError: true,\n      }))\n\n      createEffect(() => {\n        result = query\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(result?.data).toBe('data')\n  })\n\n  it('should set status to error instead of throwing when error should not be thrown', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => Promise.reject(new Error('Local Error'))),\n        retry: false,\n        throwOnError: (err) => err.message !== 'Local Error',\n      }))\n\n      return (\n        <div>\n          <h1>{state.status}</h1>\n          <h2>{state.error?.message}</h2>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <ErrorBoundary fallback={() => <div>error boundary</div>}>\n          <Page />\n        </ErrorBoundary>\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error')).toBeInTheDocument()\n    expect(rendered.getByText('Local Error')).toBeInTheDocument()\n  })\n\n  it('should throw error instead of setting status when error should be thrown', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => Promise.reject(new Error('Remote Error'))),\n        retry: false,\n        throwOnError: (err) => err.message !== 'Local Error',\n      }))\n\n      return (\n        <div>\n          <div>{state.data}</div>\n          <h1>{state.status}</h1>\n          <h2>{state.error?.message ?? ''}</h2>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <ErrorBoundary\n          fallback={(error) => (\n            <div>\n              <div>error boundary</div>\n              <div>{error?.message}</div>\n            </div>\n          )}\n        >\n          <Page />\n        </ErrorBoundary>\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error boundary')).toBeInTheDocument()\n    expect(rendered.getByText('Remote Error')).toBeInTheDocument()\n  })\n\n  it('should continue retries when observers unmount and remount while waiting for a retry (#3031)', async () => {\n    const key = queryKey()\n    let count = 0\n\n    function Page() {\n      const result = useQuery(() => ({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          throw new Error('some error')\n        },\n        retry: 2,\n\n        retryDelay: 100,\n      }))\n\n      return (\n        <div>\n          <div>error: {result.error?.message ?? 'null'}</div>\n          <div>failureCount: {result.failureCount}</div>\n          <div>failureReason: {result.failureReason?.message}</div>\n        </div>\n      )\n    }\n\n    function App() {\n      const [show, setShow] = createSignal(true)\n\n      const toggle = () => setShow((s) => !s)\n\n      return (\n        <div>\n          <button onClick={toggle}>{show() ? 'hide' : 'show'}</button>\n          {show() && <Page />}\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <App />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(rendered.getByText('failureCount: 1')).toBeInTheDocument()\n    expect(rendered.getByText('failureReason: some error')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /hide/i }))\n    expect(rendered.getByRole('button', { name: /show/i })).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /show/i }))\n\n    // Wait for retry delay and second attempt\n    await vi.advanceTimersByTimeAsync(100)\n    await vi.advanceTimersByTimeAsync(10)\n\n    // Wait for third attempt\n    await vi.advanceTimersByTimeAsync(100)\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(rendered.getByText('error: some error')).toBeInTheDocument()\n\n    expect(count).toBe(3)\n  })\n\n  it('should restart when observers unmount and remount while waiting for a retry when query was cancelled in between (#3031)', async () => {\n    const key = queryKey()\n    let count = 0\n\n    function Page() {\n      const result = useQuery(() => ({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          throw new Error('some error')\n        },\n        retry: 2,\n        retryDelay: 100,\n      }))\n\n      return (\n        <div>\n          <div>error: {result.error?.message ?? 'null'}</div>\n          <div>failureCount: {result.failureCount}</div>\n          <div>failureReason: {result.failureReason?.message}</div>\n        </div>\n      )\n    }\n\n    function App() {\n      const [show, setShow] = createSignal(true)\n\n      const toggle = () => setShow((s) => !s)\n\n      return (\n        <div>\n          <button onClick={toggle}>{show() ? 'hide' : 'show'}</button>\n          <button onClick={() => queryClient.cancelQueries({ queryKey: key })}>\n            cancel\n          </button>\n          {show() && <Page />}\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <App />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(rendered.getByText('failureCount: 1')).toBeInTheDocument()\n    expect(rendered.getByText('failureReason: some error')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /hide/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /cancel/i }))\n\n    expect(rendered.getByRole('button', { name: /show/i })).toBeInTheDocument()\n    fireEvent.click(rendered.getByRole('button', { name: /show/i }))\n\n    // Wait for new mount fetch\n    await vi.advanceTimersByTimeAsync(10)\n\n    // Wait for first retry\n    await vi.advanceTimersByTimeAsync(100)\n    await vi.advanceTimersByTimeAsync(10)\n\n    // Wait for second retry\n    await vi.advanceTimersByTimeAsync(100)\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(rendered.getByText('error: some error')).toBeInTheDocument()\n\n    // initial fetch (1), which will be cancelled, followed by new mount(2) + 2 retries = 4\n    expect(count).toBe(4)\n  })\n\n  it('should always fetch if refetchOnMount is set to always', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'prefetched'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'data'),\n        refetchOnMount: 'always',\n        staleTime: 50,\n      }))\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n      return (\n        <div>\n          <div>data: {state.data ?? 'null'}</div>\n          <div>isFetching: {state.isFetching}</div>\n          <div>isStale: {state.isStale}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: data')).toBeInTheDocument()\n\n    await vi.advanceTimersByTimeAsync(60)\n\n    expect(states.length).toBe(3)\n\n    expect(states[0]).toMatchObject({\n      data: 'prefetched',\n      isStale: false,\n      isFetching: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: 'data',\n      isStale: false,\n      isFetching: false,\n    })\n    expect(states[2]).toMatchObject({\n      data: 'data',\n      isStale: true,\n      isFetching: false,\n    })\n  })\n\n  it('should fetch if initial data is set', async () => {\n    const key = queryKey()\n    const states: Array<DefinedUseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'data'),\n        initialData: 'initial',\n      }))\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n\n    expect(states[0]).toMatchObject({\n      data: 'initial',\n      isStale: true,\n      isFetching: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: 'data',\n      isStale: true,\n      isFetching: false,\n    })\n  })\n\n  it('should not fetch if initial data is set with a stale time', async () => {\n    const key = queryKey()\n    const states: Array<DefinedUseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'data'),\n        staleTime: 50,\n        initialData: 'initial',\n      }))\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(60)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: 'initial',\n      isStale: false,\n      isFetching: false,\n    })\n    expect(states[1]).toMatchObject({\n      data: 'initial',\n      isStale: true,\n      isFetching: false,\n    })\n  })\n\n  it('should fetch if initial data updated at is older than stale time', async () => {\n    const key = queryKey()\n    const states: Array<DefinedUseQueryResult<string>> = []\n\n    const oneSecondAgo = Date.now() - 1000\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'data'),\n        staleTime: 50,\n        initialData: 'initial',\n        initialDataUpdatedAt: oneSecondAgo,\n      }))\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(70)\n\n    expect(states.length).toBe(3)\n    expect(states[0]).toMatchObject({\n      data: 'initial',\n      isStale: true,\n      isFetching: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: 'data',\n      isStale: false,\n      isFetching: false,\n    })\n    expect(states[2]).toMatchObject({\n      data: 'data',\n      isStale: true,\n      isFetching: false,\n    })\n  })\n\n  it('should fetch if \"initial data updated at\" is exactly 0', async () => {\n    const key = queryKey()\n    const states: Array<DefinedUseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'data'),\n        staleTime: 10 * 1000, // 10 seconds\n        initialData: 'initial',\n        initialDataUpdatedAt: 0,\n      }))\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    expect(states[0]).toMatchObject({\n      data: 'initial',\n      isStale: true,\n      isFetching: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: 'data',\n      isStale: false,\n      isFetching: false,\n    })\n  })\n\n  it('should keep initial data when the query key changes', async () => {\n    const key = queryKey()\n    const states: Array<Partial<DefinedUseQueryResult<{ count: number }>>> = []\n\n    function Page() {\n      const [count, setCount] = createSignal(0)\n      const state = useQuery(() => ({\n        queryKey: [key, count()],\n        queryFn: () => sleep(10).then(() => ({ count: 10 })),\n        staleTime: Infinity,\n        initialData: () => ({ count: count() }),\n        reconcile: false,\n      }))\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      createEffect(() => {\n        setActTimeout(() => {\n          setCount(1)\n        }, 10)\n      }, [])\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    // Initial\n    expect(states[0]).toMatchObject({ data: { count: 0 } })\n    // Set state\n    expect(states[1]).toMatchObject({ data: { count: 1 } })\n  })\n\n  it('should retry specified number of times', async () => {\n    const key = queryKey()\n\n    const queryFn = vi.fn<(...args: Array<unknown>) => unknown>()\n    queryFn.mockImplementation(() =>\n      sleep(10).then(() => Promise.reject(new Error('Error test Barrett'))),\n    )\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn,\n        retry: 1,\n        retryDelay: 1,\n      }))\n\n      return (\n        <div>\n          <h1>{state.status}</h1>\n          <h2>Failed {state.failureCount} times</h2>\n          <h2>Failed because {state.failureReason?.message}</h2>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('pending')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('pending')).toBeInTheDocument()\n    expect(rendered.getByText('Failed 1 times')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error')).toBeInTheDocument()\n    expect(rendered.getByText('Failed 2 times')).toBeInTheDocument()\n    expect(\n      rendered.getByText('Failed because Error test Barrett'),\n    ).toBeInTheDocument()\n\n    expect(queryFn).toHaveBeenCalledTimes(2)\n  })\n\n  it('should not retry if retry function `false`', async () => {\n    const key = queryKey()\n\n    const queryFn = vi.fn<(...args: Array<unknown>) => unknown>()\n\n    queryFn.mockImplementationOnce(() =>\n      sleep(10).then(() => Promise.reject(new Error('Error test Tanner'))),\n    )\n\n    queryFn.mockImplementation(() =>\n      sleep(10).then(() => Promise.reject(new Error('NoRetry'))),\n    )\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn,\n        retryDelay: 1,\n        retry: (_failureCount, err) => err.message !== 'NoRetry',\n      }))\n\n      return (\n        <div>\n          <h1>{state.status}</h1>\n          <h2>Failed {state.failureCount} times</h2>\n          <h2>Failed because {state.failureReason?.message}</h2>\n          <h2>{state.error?.message}</h2>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('pending')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('pending')).toBeInTheDocument()\n    expect(rendered.getByText('Failed 1 times')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error')).toBeInTheDocument()\n    expect(rendered.getByText('Failed 2 times')).toBeInTheDocument()\n    expect(rendered.getByText('Failed because NoRetry')).toBeInTheDocument()\n    expect(rendered.getByText('NoRetry')).toBeInTheDocument()\n\n    expect(queryFn).toHaveBeenCalledTimes(2)\n  })\n\n  it('should extract retryDelay from error', async () => {\n    const key = queryKey()\n\n    type DelayError = { delay: number }\n\n    const queryFn = vi.fn<(...args: Array<unknown>) => unknown>()\n    queryFn.mockImplementation(async () => {\n      await sleep(10)\n      throw { delay: 50 }\n    })\n\n    function Page() {\n      const state = useQuery<unknown, DelayError>(() => ({\n        queryKey: key,\n        queryFn,\n        retry: 1,\n        retryDelay: (_, error: DelayError) => error.delay,\n      }))\n\n      return (\n        <div>\n          <h1>{state.status}</h1>\n          <h2>Failed {state.failureCount} times</h2>\n          <h2>Failed because DelayError: {state.failureReason?.delay}ms</h2>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('pending')).toBeInTheDocument()\n    expect(rendered.getByText('Failed 1 times')).toBeInTheDocument()\n    expect(queryFn).toHaveBeenCalledTimes(1)\n    await vi.advanceTimersByTimeAsync(10)\n    await vi.advanceTimersByTimeAsync(50)\n    expect(\n      rendered.getByText('Failed because DelayError: 50ms'),\n    ).toBeInTheDocument()\n    expect(rendered.getByText('Failed 2 times')).toBeInTheDocument()\n\n    expect(queryFn).toHaveBeenCalledTimes(2)\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/160\n  it('should continue retry after focus regain', async () => {\n    const key = queryKey()\n\n    // make page unfocused\n    const visibilityMock = mockVisibilityState('hidden')\n\n    let count = 0\n\n    function Page() {\n      const query = useQuery<unknown, string>(() => ({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          throw `fetching error ${count}`\n        },\n        retry: 3,\n        retryDelay: 1,\n      }))\n\n      return (\n        <div>\n          <div>error {String(query.error)}</div>\n          <div>status {query.status}</div>\n          <div>failureCount {query.failureCount}</div>\n          <div>failureReason {query.failureReason}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    // The query should display the first error result\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(rendered.getByText('failureCount 1')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(\n      rendered.getByText('failureReason fetching error 1'),\n    ).toBeInTheDocument()\n    expect(rendered.getByText('status pending')).toBeInTheDocument()\n    expect(rendered.getByText('error null')).toBeInTheDocument()\n    // Check if the query really paused\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(rendered.getByText('failureCount 1')).toBeInTheDocument()\n\n    expect(\n      rendered.getByText('failureReason fetching error 1'),\n    ).toBeInTheDocument()\n\n    visibilityMock.mockRestore()\n    window.dispatchEvent(new Event('visibilitychange'))\n\n    // Wait for the final result\n    // 2nd retry: 10ms (queryFn)\n    await vi.advanceTimersByTimeAsync(10)\n    // 3rd retry: 1ms (retryDelay) + 10ms (queryFn)\n    await vi.advanceTimersByTimeAsync(11)\n    // 4th retry (final): 1ms (retryDelay) + 10ms (queryFn)\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(rendered.getByText('failureCount 4')).toBeInTheDocument()\n\n    expect(\n      rendered.getByText('failureReason fetching error 4'),\n    ).toBeInTheDocument()\n\n    expect(rendered.getByText('status error')).toBeInTheDocument()\n\n    expect(rendered.getByText('error fetching error 4')).toBeInTheDocument()\n    // Check if the query really stopped\n    await vi.advanceTimersByTimeAsync(11)\n\n    expect(rendered.getByText('failureCount 4')).toBeInTheDocument()\n    expect(\n      rendered.getByText('failureReason fetching error 4'),\n    ).toBeInTheDocument()\n  })\n\n  it('should fetch on mount when a query was already created with setQueryData', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    queryClient.setQueryData(key, 'prefetched')\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'data'),\n      }))\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n    expect(states).toMatchObject([\n      {\n        data: 'prefetched',\n        isFetching: true,\n        isStale: true,\n      },\n      {\n        data: 'data',\n        isFetching: false,\n        isStale: true,\n      },\n    ])\n  })\n\n  it('should refetch after focus regain', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    // make page unfocused\n    const visibilityMock = mockVisibilityState('hidden')\n\n    // set data in cache to check if the hook query fn is actually called\n    queryClient.setQueryData(key, 'prefetched')\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'data'),\n      }))\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n      return (\n        <div>\n          {state.data}, {state.isStale}, {state.isFetching}\n        </div>\n      )\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n\n    // reset visibilityState to original value\n    visibilityMock.mockRestore()\n    window.dispatchEvent(new Event('visibilitychange'))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(4)\n\n    expect(states).toMatchObject([\n      {\n        data: 'prefetched',\n        isFetching: true,\n        isStale: true,\n      },\n      {\n        data: 'data',\n        isFetching: false,\n        isStale: true,\n      },\n      {\n        data: 'data',\n        isFetching: true,\n        isStale: true,\n      },\n      {\n        data: 'data',\n        isFetching: false,\n        isStale: true,\n      },\n    ])\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/195\n  it('should refetch if stale after a prefetch', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    const queryFn = vi.fn<(...args: Array<unknown>) => string>()\n    queryFn.mockImplementation(() => 'data')\n\n    const prefetchQueryFn = vi.fn<(...args: Array<unknown>) => string>()\n    prefetchQueryFn.mockImplementation(() => 'not yet...')\n\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: prefetchQueryFn,\n      staleTime: 10,\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    function Page() {\n      const state = useQuery(() => ({ queryKey: key, queryFn }))\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(states.length).toBe(2)\n\n    expect(prefetchQueryFn).toHaveBeenCalledTimes(1)\n    expect(queryFn).toHaveBeenCalledTimes(1)\n  })\n\n  it('should not refetch if not stale after a prefetch', async () => {\n    const key = queryKey()\n\n    const queryFn = vi.fn<(...args: Array<unknown>) => Promise<string>>()\n    queryFn.mockImplementation(() => sleep(10).then(() => 'data'))\n\n    const prefetchQueryFn =\n      vi.fn<(...args: Array<unknown>) => Promise<string>>()\n    prefetchQueryFn.mockImplementation(() => sleep(10).then(() => 'not yet...'))\n\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: prefetchQueryFn,\n      staleTime: 1000,\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    function Page() {\n      useQuery(() => ({ queryKey: key, queryFn, staleTime: 1000 }))\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(prefetchQueryFn).toHaveBeenCalledTimes(1)\n    expect(queryFn).toHaveBeenCalledTimes(0)\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/190\n  it('should reset failureCount and failureReason on successful fetch', async () => {\n    const key = queryKey()\n\n    function Page() {\n      let counter = 0\n\n      const query = useQuery<unknown, Error>(() => ({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          if (counter < 2) {\n            counter++\n            throw new Error('error')\n          } else {\n            return 'data'\n          }\n        },\n        retryDelay: 10,\n      }))\n\n      return (\n        <div>\n          <div>failureCount {query.failureCount}</div>\n          <div>failureReason {query.failureReason?.message ?? 'null'}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    // First attempt fails immediately\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('failureCount 1')).toBeInTheDocument()\n\n    // Wait for first retry\n    await vi.advanceTimersByTimeAsync(10)\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('failureCount 2')).toBeInTheDocument()\n    expect(rendered.getByText('failureReason error')).toBeInTheDocument()\n\n    // Wait for second retry (success)\n    await vi.advanceTimersByTimeAsync(10)\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('failureCount 0')).toBeInTheDocument()\n    expect(rendered.getByText('failureReason null')).toBeInTheDocument()\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/199\n  it('should use prefetched data for dependent query', async () => {\n    const key = queryKey()\n    let count = 0\n\n    function Page() {\n      const [enabled, setEnabled] = createSignal(false)\n      const [isPrefetched, setPrefetched] = createSignal(false)\n\n      const query = useQuery(() => ({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          return count\n        },\n        enabled: enabled(),\n      }))\n\n      createEffect(() => {\n        async function prefetch() {\n          await queryClient.prefetchQuery({\n            queryKey: key,\n            queryFn: () => Promise.resolve('prefetched data'),\n          })\n          setPrefetched(true)\n        }\n        prefetch()\n      })\n\n      return (\n        <div>\n          {isPrefetched() && <div>isPrefetched</div>}\n          <button onClick={() => setEnabled(true)}>setKey</button>\n          <div>data: {query.data}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('isPrefetched')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('setKey'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('data: prefetched data')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n\n    expect(count).toBe(1)\n  })\n\n  it('should support dependent queries via the enable config option', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const [shouldFetch, setShouldFetch] = createSignal(false)\n\n      const query = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'data'),\n        enabled: shouldFetch(),\n      }))\n\n      return (\n        <div>\n          <div>FetchStatus: {query.fetchStatus}</div>\n          <h2>Data: {query.data || 'no data'}</h2>\n          {shouldFetch() ? null : (\n            <button onClick={() => setShouldFetch(true)}>fetch</button>\n          )}\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('FetchStatus: idle')).toBeInTheDocument()\n    expect(rendered.getByText('Data: no data')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('fetch'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('FetchStatus: fetching')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('Data: data')).toBeInTheDocument()\n  })\n\n  // See https://github.com/TanStack/query/issues/7711\n  it('race condition: should cleanup observers after component that created the query is unmounted #1', async () => {\n    const key = queryKey()\n\n    function Component() {\n      let val = 1\n      const dataQuery = useQuery(() => ({\n        queryKey: [key],\n        queryFn: () => sleep(10).then(() => val++),\n      }))\n\n      return (\n        <div>\n          <p>component</p>\n          <p>data: {String(dataQuery.data)}</p>\n        </div>\n      )\n    }\n\n    const Outer = () => {\n      const [showComp, setShowComp] = createSignal(true)\n      return (\n        <div>\n          <button\n            onClick={() => {\n              queryClient.invalidateQueries()\n              setShowComp(!showComp())\n            }}\n          >\n            toggle\n          </button>\n          {showComp() ? <Component /> : <div>not showing</div>}\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Outer />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('component')).toBeInTheDocument()\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('toggle'))\n    expect(rendered.getByText('not showing')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('toggle'))\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('component')).toBeInTheDocument()\n    expect(rendered.getByText('data: 2')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('toggle'))\n    expect(rendered.getByText('not showing')).toBeInTheDocument()\n\n    const entry = queryClient.getQueryCache().find({\n      queryKey: [key],\n    })!\n\n    expect(entry.getObserversCount()).toBe(0)\n  })\n\n  // See https://github.com/TanStack/query/issues/7711\n  it('race condition: should cleanup observers after component that created the query is unmounted #2', async () => {\n    const key = queryKey()\n\n    function Component() {\n      let val = 1\n      const dataQuery = useQuery(() => ({\n        queryKey: [key],\n        queryFn: () => sleep(10).then(() => val++),\n      }))\n\n      return (\n        <div>\n          <p>component</p>\n          <p>data: {String(dataQuery.data)}</p>\n        </div>\n      )\n    }\n\n    const Outer = () => {\n      const [showComp, setShowComp] = createSignal(true)\n      return (\n        <div>\n          <button\n            onClick={() => {\n              queueMicrotask(() => setShowComp(!showComp()))\n              queryClient.invalidateQueries()\n            }}\n          >\n            toggle\n          </button>\n          {showComp() ? <Component /> : <div>not showing</div>}\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Outer />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('component')).toBeInTheDocument()\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('toggle'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('not showing')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('toggle'))\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('component')).toBeInTheDocument()\n    expect(rendered.getByText('data: 2')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('toggle'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('not showing')).toBeInTheDocument()\n\n    const entry = queryClient.getQueryCache().find({\n      queryKey: [key],\n    })!\n\n    expect(entry.getObserversCount()).toBe(0)\n  })\n\n  it('should mark query as fetching, when using initialData', async () => {\n    const key = queryKey()\n    const results: Array<DefinedUseQueryResult<string>> = []\n\n    function Page() {\n      const result = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'serverData'),\n        initialData: 'initialData',\n      }))\n\n      createRenderEffect(() => {\n        results.push({ ...result })\n      })\n\n      return <div>data: {result.data}</div>\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('data: initialData')).toBeInTheDocument()\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: serverData')).toBeInTheDocument()\n\n    expect(results.length).toBe(2)\n    expect(results[0]).toMatchObject({ data: 'initialData', isFetching: true })\n    expect(results[1]).toMatchObject({ data: 'serverData', isFetching: false })\n  })\n\n  it('should initialize state properly, when initialData is falsy', async () => {\n    const key = queryKey()\n    const results: Array<DefinedUseQueryResult<number>> = []\n\n    function Page() {\n      const result = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 1),\n        initialData: 0,\n      }))\n\n      createRenderEffect(() => {\n        results.push({ ...result })\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(results.length).toBe(2)\n    expect(results[0]).toMatchObject({ data: 0, isFetching: true })\n    expect(results[1]).toMatchObject({ data: 1, isFetching: false })\n  })\n\n  // // See https://github.com/tannerlinsley/react-query/issues/214\n  it('data should persist when enabled is changed to false', async () => {\n    const key = queryKey()\n    const results: Array<DefinedUseQueryResult<string>> = []\n\n    function Page() {\n      const [shouldFetch, setShouldFetch] = createSignal(true)\n\n      const result = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'fetched data'),\n        enabled: shouldFetch(),\n        initialData: shouldFetch() ? 'initial' : 'initial falsy',\n      }))\n\n      createRenderEffect(() => {\n        results.push({ ...result })\n      })\n\n      createEffect(() => {\n        setActTimeout(() => {\n          setShouldFetch(false)\n        }, 15)\n      })\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(15)\n\n    expect(results.length).toBe(3)\n    expect(results[0]).toMatchObject({ data: 'initial', isStale: true })\n    expect(results[1]).toMatchObject({ data: 'fetched data', isStale: true })\n    // disabled observers are not stale\n    expect(results[2]).toMatchObject({ data: 'fetched data', isStale: false })\n  })\n\n  it('should support enabled:false in query object syntax', () => {\n    const key = queryKey()\n    const queryFn = vi.fn<(...args: Array<unknown>) => string>()\n    queryFn.mockImplementation(() => 'data')\n\n    function Page() {\n      const { fetchStatus } = useQuery(() => ({\n        queryKey: key,\n        queryFn,\n        enabled: false,\n      }))\n\n      return <div>fetchStatus: {fetchStatus}</div>\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(queryFn).not.toHaveBeenCalled()\n    expect(queryCache.find({ queryKey: key })).not.toBeUndefined()\n    expect(rendered.getByText('fetchStatus: idle')).toBeInTheDocument()\n  })\n\n  // See https://github.com/tannerlinsley/react-query/issues/360\n  it('should init to status:pending, fetchStatus:idle when enabled is false', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const query = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'data'),\n        enabled: false,\n      }))\n\n      return (\n        <div>\n          <div>\n            status: {query.status}, {query.fetchStatus}\n          </div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('status: pending, idle')).toBeInTheDocument()\n  })\n\n  it('should not schedule garbage collection, if gcTimeout is set to `Infinity`', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const query = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'fetched data'),\n        gcTime: Infinity,\n      }))\n      return <div>{query.data}</div>\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(rendered.getByText('fetched data')).toBeInTheDocument()\n    const setTimeoutSpy = vi.spyOn(window, 'setTimeout')\n\n    rendered.unmount()\n\n    expect(setTimeoutSpy).not.toHaveBeenCalled()\n  })\n\n  it('should schedule garbage collection, if gcTimeout is not set to `Infinity`', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const query = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'fetched data'),\n        gcTime: 1000 * 60 * 10, // 10 Minutes\n      }))\n      return <div>{query.data}</div>\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(rendered.getByText('fetched data')).toBeInTheDocument()\n    const setTimeoutSpy = vi.spyOn(window, 'setTimeout')\n\n    rendered.unmount()\n\n    expect(setTimeoutSpy).toHaveBeenLastCalledWith(\n      expect.any(Function),\n      1000 * 60 * 10,\n    )\n  })\n\n  it('should not cause memo churn when data does not change', async () => {\n    const key = queryKey()\n    const queryFn = vi\n      .fn<(...args: Array<unknown>) => string>()\n      .mockReturnValue('data')\n    const memoFn = vi.fn()\n\n    function Page() {\n      const result = useQuery(() => ({\n        queryKey: key,\n        queryFn: () =>\n          sleep(10).then(() => queryFn() || { data: { nested: true } }),\n      }))\n\n      createMemo(() => {\n        memoFn()\n        return result.data\n      })\n\n      return (\n        <div>\n          <div>status {result.status}</div>\n          <div>isFetching {result.isFetching ? 'true' : 'false'}</div>\n          <button onClick={() => result.refetch()}>refetch</button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('status pending')).toBeInTheDocument()\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('status success')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByText('refetch'))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('isFetching true')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('isFetching false')).toBeInTheDocument()\n\n    expect(queryFn).toHaveBeenCalledTimes(2)\n    expect(memoFn).toHaveBeenCalledTimes(2)\n  })\n\n  it('should update data upon interval changes', async () => {\n    const key = queryKey()\n    let count = 0\n\n    function Page() {\n      const [int, setInt] = createSignal(200)\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => count++),\n        refetchInterval: int(),\n      }))\n\n      createEffect(() => {\n        if (state.data === 2) {\n          setInt(0)\n        }\n      })\n\n      return <div>count: {state.data}</div>\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    // mount\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('count: 0')).toBeInTheDocument()\n    // Wait for first interval\n    await vi.advanceTimersByTimeAsync(210)\n    expect(rendered.getByText('count: 1')).toBeInTheDocument()\n    // Wait for second interval\n    await vi.advanceTimersByTimeAsync(210)\n    expect(rendered.getByText('count: 2')).toBeInTheDocument()\n  })\n\n  it('should refetch in an interval depending on function result', async () => {\n    const key = queryKey()\n    let count = 0\n    const states: Array<UseQueryResult<number>> = []\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => count++),\n        refetchInterval: ({ state: { data = 0 } }) => (data < 2 ? 10 : false),\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      return (\n        <div>\n          <h1>count: {state.data}</h1>\n          <h2>status: {state.status}</h2>\n          <h2>data: {state.data}</h2>\n          <h2>refetch: {state.isRefetching}</h2>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    // Initial fetch (10ms)\n    await vi.advanceTimersByTimeAsync(10)\n\n    // First interval (10ms delay + 10ms fetch)\n    await vi.advanceTimersByTimeAsync(10)\n    await vi.advanceTimersByTimeAsync(10)\n\n    // Second interval (10ms delay + 10ms fetch)\n    await vi.advanceTimersByTimeAsync(10)\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(rendered.getByText('count: 2')).toBeInTheDocument()\n\n    expect(states.length).toEqual(6)\n\n    expect(states).toMatchObject([\n      {\n        status: 'pending',\n        isFetching: true,\n        data: undefined,\n      },\n      {\n        status: 'success',\n        isFetching: false,\n        data: 0,\n      },\n      {\n        status: 'success',\n        isFetching: true,\n        data: 0,\n      },\n      {\n        status: 'success',\n        isFetching: false,\n        data: 1,\n      },\n      {\n        status: 'success',\n        isFetching: true,\n        data: 1,\n      },\n      {\n        status: 'success',\n        isFetching: false,\n        data: 2,\n      },\n    ])\n  })\n\n  it('should not interval fetch with a refetchInterval of 0', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 1),\n        refetchInterval: 0,\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      return <div>count: {state.data}</div>\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('count: 1')).toBeInTheDocument()\n\n    // extra advance to make sure we're not re-fetching\n    await vi.advanceTimersByTimeAsync(100)\n\n    expect(states.length).toEqual(2)\n\n    expect(states).toMatchObject([\n      {\n        status: 'pending',\n        isFetching: true,\n        data: undefined,\n      },\n      {\n        status: 'success',\n        isFetching: false,\n        data: 1,\n      },\n    ])\n  })\n\n  it('should accept an empty string as query key', async () => {\n    function Page() {\n      const result = useQuery(() => ({\n        queryKey: [''],\n        queryFn: (ctx) => sleep(10).then(() => ctx.queryKey),\n      }))\n      return <>{JSON.stringify(result.data)}</>\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('[\"\"]')).toBeInTheDocument()\n  })\n\n  it('should accept an object as query key', async () => {\n    function Page() {\n      const result = useQuery(() => ({\n        queryKey: [{ a: 'a' }],\n        queryFn: (ctx) => sleep(10).then(() => ctx.queryKey),\n      }))\n      return <>{JSON.stringify(result.data)}</>\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('[{\"a\":\"a\"}]')).toBeInTheDocument()\n  })\n\n  it('should refetch if any query instance becomes enabled', async () => {\n    const key = queryKey()\n\n    const queryFn = vi\n      .fn<(...args: Array<unknown>) => Promise<string>>()\n      .mockReturnValue(sleep(10).then(() => 'data'))\n\n    function Disabled() {\n      useQuery(() => ({ queryKey: key, queryFn, enabled: false }))\n      return null\n    }\n\n    function Page() {\n      const [enabled, setEnabled] = createSignal(false)\n      const result = useQuery(() => ({\n        queryKey: key,\n        queryFn,\n        enabled: enabled(),\n      }))\n      return (\n        <>\n          <Disabled />\n          <div>{result.data}</div>\n          <button onClick={() => setEnabled(true)}>enable</button>\n        </>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(queryFn).toHaveBeenCalledTimes(0)\n\n    fireEvent.click(rendered.getByText('enable'))\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data')).toBeInTheDocument()\n\n    expect(queryFn).toHaveBeenCalledTimes(1)\n  })\n\n  it('should use placeholder data while the query loads', async () => {\n    const key1 = queryKey()\n\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key1,\n        queryFn: () => sleep(10).then(() => 'data'),\n        placeholderData: 'placeholder',\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      return (\n        <div>\n          <h2>Data: {state.data}</h2>\n          <div>Status: {state.status}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('Data: data')).toBeInTheDocument()\n\n    expect(states).toMatchObject([\n      {\n        isSuccess: true,\n        isPlaceholderData: true,\n        data: 'placeholder',\n      },\n      {\n        isSuccess: true,\n        isPlaceholderData: false,\n        data: 'data',\n      },\n    ])\n  })\n\n  it('should use placeholder data even for disabled queries', async () => {\n    const key1 = queryKey()\n\n    const states: Array<{ state: UseQueryResult<string>; count: number }> = []\n\n    function Page() {\n      const [count, setCount] = createSignal(0)\n\n      const state = useQuery(() => ({\n        queryKey: key1,\n        queryFn: () => sleep(10).then(() => 'data'),\n        placeholderData: 'placeholder',\n        enabled: count() === 0,\n      }))\n\n      createRenderEffect(() => {\n        states.push({ state: { ...state }, count: count() })\n      })\n\n      createEffect(() => {\n        setCount(1)\n      })\n\n      return (\n        <div>\n          <h2>Data: {state.data}</h2>\n          <div>Status: {state.status}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('Data: data')).toBeInTheDocument()\n\n    expect(states).toMatchObject([\n      {\n        state: {\n          isSuccess: true,\n          isPlaceholderData: true,\n          data: 'placeholder',\n        },\n        count: 0,\n      },\n      {\n        state: {\n          isSuccess: true,\n          isPlaceholderData: true,\n          data: 'placeholder',\n        },\n        count: 1,\n      },\n      {\n        state: {\n          isSuccess: true,\n          isPlaceholderData: false,\n          data: 'data',\n        },\n        count: 1,\n      },\n    ])\n  })\n\n  it('placeholder data should run through select', async () => {\n    const key1 = queryKey()\n\n    const states: Array<UseQueryResult<string>> = []\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key1,\n        queryFn: () => sleep(10).then(() => 1),\n        placeholderData: 23,\n        select: (data) => String(data * 2),\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      return (\n        <div>\n          <h2>Data: {state.data}</h2>\n          <div>Status: {state.status}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('Data: 2')).toBeInTheDocument()\n\n    expect(states).toMatchObject([\n      {\n        isSuccess: true,\n        isPlaceholderData: true,\n        data: '46',\n      },\n      {\n        isSuccess: true,\n        isPlaceholderData: false,\n        data: '2',\n      },\n    ])\n  })\n\n  it('placeholder data function result should run through select', async () => {\n    const key1 = queryKey()\n\n    const states: Array<UseQueryResult<string>> = []\n    let placeholderFunctionRunCount = 0\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key1,\n        queryFn: () => sleep(10).then(() => 1),\n        placeholderData: () => {\n          placeholderFunctionRunCount++\n          return 23\n        },\n        select: (data) => String(data * 2),\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      return (\n        <div>\n          <h2>Data: {state.data}</h2>\n          <div>Status: {state.status}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('Data: 2')).toBeInTheDocument()\n\n    expect(states).toMatchObject([\n      {\n        isSuccess: true,\n        isPlaceholderData: true,\n        data: '46',\n      },\n      {\n        isSuccess: true,\n        isPlaceholderData: false,\n        data: '2',\n      },\n    ])\n\n    expect(placeholderFunctionRunCount).toEqual(1)\n  })\n\n  it('select should always return the correct state', async () => {\n    const key1 = queryKey()\n\n    function Page() {\n      const [count, setCount] = createSignal(2)\n      const [forceValue, setForceValue] = createSignal(1)\n\n      const inc = () => {\n        setCount((prev) => prev + 1)\n      }\n\n      const forceUpdate = () => {\n        setForceValue((prev) => prev + 1)\n      }\n\n      const state = useQuery(() => ({\n        queryKey: key1,\n        queryFn: () => sleep(10).then(() => 0),\n        get select() {\n          const currentCount = count()\n          return (data: number) => `selected ${data + currentCount}`\n        },\n        placeholderData: 99,\n      }))\n\n      return (\n        <div>\n          <h2>Data: {state.data}</h2>\n          <h2>forceValue: {forceValue()}</h2>\n          <button onClick={inc}>inc: {count()}</button>\n          <button onClick={forceUpdate}>forceUpdate</button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('Data: selected 101')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('Data: selected 2')).toBeInTheDocument()\n    fireEvent.click(rendered.getByRole('button', { name: /inc/i }))\n    expect(rendered.getByText('Data: selected 3')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /forceUpdate/i }))\n    expect(rendered.getByText('forceValue: 2')).toBeInTheDocument()\n    // data should still be 3 after an independent re-render\n    expect(rendered.getByText('Data: selected 3')).toBeInTheDocument()\n  })\n\n  it('select should structurally share data', async () => {\n    const key1 = queryKey()\n    const states: Array<Array<number>> = []\n\n    function Page() {\n      const [forceValue, setForceValue] = createSignal(1)\n\n      const state = useQuery(() => ({\n        queryKey: key1,\n        queryFn: () => sleep(10).then(() => [1, 2]),\n        select: (res) => res.map((x) => x + 1),\n      }))\n\n      createEffect(() => {\n        if (state.data) {\n          states.push(state.data)\n        }\n      })\n\n      const forceUpdate = () => {\n        setForceValue((prev) => prev + 1)\n      }\n\n      return (\n        <div>\n          <h2>Data: {JSON.stringify(state.data)}</h2>\n          <h2>forceValue: {forceValue()}</h2>\n          <button onClick={forceUpdate}>forceUpdate</button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('Data: [2,3]')).toBeInTheDocument()\n    expect(states).toHaveLength(1)\n\n    fireEvent.click(rendered.getByRole('button', { name: /forceUpdate/i }))\n    expect(rendered.getByText('forceValue: 2')).toBeInTheDocument()\n    expect(rendered.getByText('Data: [2,3]')).toBeInTheDocument()\n\n    // effect should not be triggered again due to structural sharing\n    expect(states).toHaveLength(1)\n  })\n\n  it('The reconcile fn callback should correctly maintain referential equality', async () => {\n    const key1 = queryKey()\n    const states: Array<Array<number>> = []\n\n    function Page() {\n      const [forceValue, setForceValue] = createSignal(1)\n\n      const state = useQuery(() => ({\n        queryKey: key1,\n        queryFn: () => sleep(10).then(() => [1, 2]),\n        select: (res) => res.map((x) => x + 1),\n        reconcile(oldData, newData) {\n          return reconcile(newData)(oldData)\n        },\n      }))\n\n      createEffect(() => {\n        if (state.data) {\n          states.push(state.data)\n        }\n      })\n\n      const forceUpdate = () => {\n        setForceValue((prev) => prev + 1)\n      }\n\n      return (\n        <div>\n          <h2>Data: {JSON.stringify(state.data)}</h2>\n          <h2>forceValue: {forceValue()}</h2>\n          <button onClick={forceUpdate}>forceUpdate</button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('Data: [2,3]')).toBeInTheDocument()\n    expect(states).toHaveLength(1)\n\n    fireEvent.click(rendered.getByRole('button', { name: /forceUpdate/i }))\n    expect(rendered.getByText('forceValue: 2')).toBeInTheDocument()\n    expect(rendered.getByText('Data: [2,3]')).toBeInTheDocument()\n\n    // effect should not be triggered again due to structural sharing\n    expect(states).toHaveLength(1)\n  })\n\n  it('should cancel the query function when there are no more subscriptions', async () => {\n    const key = queryKey()\n    let cancelFn: Mock = vi.fn()\n\n    const queryFn = ({ signal }: { signal?: AbortSignal }) => {\n      const promise = new Promise<string>((resolve, reject) => {\n        cancelFn = vi.fn(() => reject('Cancelled'))\n        signal?.addEventListener('abort', cancelFn)\n        sleep(20).then(() => resolve('OK'))\n      })\n\n      return promise\n    }\n\n    function Page() {\n      const state = useQuery(() => ({ queryKey: key, queryFn }))\n      return (\n        <div>\n          <h1>Status: {state.status}</h1>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Blink duration={5}>\n          <Page />\n        </Blink>\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('off')).toBeInTheDocument()\n\n    expect(cancelFn).toHaveBeenCalled()\n  })\n\n  it('should cancel the query if the signal was consumed and there are no more subscriptions', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    const queryFn: QueryFunction<\n      string,\n      readonly [typeof key, number]\n    > = async (ctx) => {\n      const [, limit] = ctx.queryKey\n      // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n      const value = limit % 2 && ctx.signal ? 'abort' : `data ${limit}`\n      await sleep(25)\n      return value\n    }\n\n    function Page(props: { limit: number }) {\n      const state = useQuery(() => ({\n        queryKey: [key, props.limit] as const,\n        queryFn,\n      }))\n      states[props.limit] = state\n      return (\n        <div>\n          <h1>Status: {state.status}</h1>\n          <h1>data: {state.data}</h1>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Blink duration={5}>\n          <Page limit={0} />\n          <Page limit={1} />\n          <Page limit={2} />\n          <Page limit={3} />\n        </Blink>\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('off')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(15)\n\n    expect(states).toHaveLength(4)\n\n    expect(queryCache.find({ queryKey: [key, 0] })?.state).toMatchObject({\n      data: 'data 0',\n      status: 'success',\n      dataUpdateCount: 1,\n    })\n\n    expect(queryCache.find({ queryKey: [key, 1] })?.state).toMatchObject({\n      data: undefined,\n      status: 'pending',\n      fetchStatus: 'idle',\n    })\n\n    expect(queryCache.find({ queryKey: [key, 2] })?.state).toMatchObject({\n      data: 'data 2',\n      status: 'success',\n      dataUpdateCount: 1,\n    })\n\n    expect(queryCache.find({ queryKey: [key, 3] })?.state).toMatchObject({\n      data: undefined,\n      status: 'pending',\n      fetchStatus: 'idle',\n    })\n  })\n\n  it('should refetch when quickly switching to a failed query', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<string>> = []\n\n    const queryFn = () => sleep(50).then(() => 'OK')\n\n    function Page() {\n      const [id, setId] = createSignal(1)\n      const [hasChanged, setHasChanged] = createSignal(false)\n\n      const state = useQuery(() => ({ queryKey: [key, id()], queryFn }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      createEffect(\n        on(hasChanged, () => {\n          setId((prevId) => (prevId === 1 ? 2 : 1))\n          setHasChanged(true)\n        }),\n      )\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(50)\n    expect(states.length).toBe(2)\n    // Load query 1\n    expect(states[0]).toMatchObject({\n      status: 'pending',\n      error: null,\n    })\n    // No rerenders - No state updates\n    // Loaded query 1\n    expect(states[1]).toMatchObject({\n      status: 'success',\n      error: null,\n    })\n  })\n\n  it('should update query state and refetch when reset with resetQueries', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          return count\n        },\n        staleTime: Infinity,\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      return (\n        <div>\n          <button onClick={() => queryClient.resetQueries({ queryKey: key })}>\n            reset\n          </button>\n          <div>data: {state.data ?? 'null'}</div>\n          <div>isFetching: {state.isFetching}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /reset/i }))\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 2')).toBeInTheDocument()\n\n    expect(count).toBe(2)\n    expect(states.length).toBe(4)\n\n    expect(states[0]).toMatchObject({\n      isPending: true,\n      isFetching: true,\n      isSuccess: false,\n      isStale: true,\n    })\n    expect(states[1]).toMatchObject({\n      data: 1,\n      isPending: false,\n      isFetching: false,\n      isSuccess: true,\n      isStale: false,\n    })\n    expect(states[2]).toMatchObject({\n      isPending: true,\n      isFetching: true,\n      isSuccess: false,\n      isStale: true,\n    })\n    expect(states[3]).toMatchObject({\n      data: 2,\n      isPending: false,\n      isFetching: false,\n      isSuccess: true,\n      isStale: false,\n    })\n  })\n\n  it('should update query state and not refetch when resetting a disabled query with resetQueries', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    let count = 0\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          count++\n          return count\n        },\n        staleTime: Infinity,\n        enabled: false,\n        notifyOnChangeProps: 'all',\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      const { refetch } = state\n\n      return (\n        <div>\n          <button onClick={() => refetch()}>refetch</button>\n          <button onClick={() => queryClient.resetQueries({ queryKey: key })}>\n            reset\n          </button>\n          <div>data: {state.data ?? 'null'}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(rendered.getByText('data: null')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /reset/i }))\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: null')).toBeInTheDocument()\n\n    expect(states.length).toBe(4)\n\n    expect(count).toBe(1)\n\n    expect(states[0]).toMatchObject({\n      isPending: true,\n      isFetching: false,\n      isSuccess: false,\n      isStale: false,\n    })\n    expect(states[1]).toMatchObject({\n      isPending: true,\n      isFetching: true,\n      isSuccess: false,\n      isStale: false,\n    })\n    expect(states[2]).toMatchObject({\n      data: 1,\n      isPending: false,\n      isFetching: false,\n      isSuccess: true,\n      isStale: false,\n    })\n    expect(states[3]).toMatchObject({\n      isPending: true,\n      isFetching: false,\n      isSuccess: false,\n      isStale: false,\n    })\n  })\n\n  it('should only call the query hash function once', async () => {\n    const key = queryKey()\n\n    let hashes = 0\n\n    function queryKeyHashFn(x: any) {\n      hashes++\n      return JSON.stringify(x)\n    }\n\n    function Page() {\n      useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'test'),\n        queryKeyHashFn,\n      }))\n\n      return null\n    }\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(hashes).toBe(1)\n  })\n\n  it('should refetch when changed enabled to true in error state', async () => {\n    const queryFn = vi.fn<(...args: Array<unknown>) => unknown>()\n    queryFn.mockImplementation(() =>\n      sleep(10).then(() => Promise.reject(new Error('Suspense Error Bingo'))),\n    )\n\n    function Page(props: { enabled: boolean }) {\n      const state = useQuery(() => ({\n        queryKey: ['key'],\n        queryFn,\n        enabled: props.enabled,\n        retry: false,\n        retryOnMount: false,\n        refetchOnMount: false,\n        refetchOnWindowFocus: false,\n      }))\n\n      return (\n        <Switch fallback={<div>rendered</div>}>\n          <Match when={state.isPending}>\n            <div>status: pending</div>\n          </Match>\n          <Match when={state.error instanceof Error}>\n            <div>error</div>\n          </Match>\n        </Switch>\n      )\n    }\n\n    function App() {\n      const [enabled, setEnabled] = createSignal(true)\n      const toggle = () => setEnabled((prev) => !prev)\n\n      return (\n        <div>\n          <Page enabled={enabled()} />\n          <button aria-label=\"retry\" onClick={toggle}>\n            retry {enabled()}\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <App />\n      </QueryClientProvider>\n    ))\n\n    // initial state check\n    expect(rendered.getByText('status: pending')).toBeInTheDocument()\n\n    // // render error state component\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(rendered.getByText('error')).toBeInTheDocument()\n    expect(queryFn).toBeCalledTimes(1)\n\n    // change to enabled to false\n    fireEvent.click(rendered.getByLabelText('retry'))\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(rendered.getByText('error')).toBeInTheDocument()\n    expect(queryFn).toBeCalledTimes(1)\n\n    // // change to enabled to true\n    fireEvent.click(rendered.getByLabelText('retry'))\n    expect(queryFn).toBeCalledTimes(2)\n  })\n\n  it('should refetch when query key changed when previous status is error', async () => {\n    function Page(props: { id: number }) {\n      const state = useQuery(() => ({\n        queryKey: [props.id],\n        queryFn: () =>\n          sleep(10).then(() =>\n            props.id % 2 === 1 ? Promise.reject(new Error('Error')) : 'data',\n          ),\n        retry: false,\n        retryOnMount: false,\n        refetchOnMount: false,\n        refetchOnWindowFocus: false,\n      }))\n\n      return (\n        <Switch fallback={<div>rendered</div>}>\n          <Match when={state.isPending}>\n            <div>status: pending</div>\n          </Match>\n          <Match when={state.error instanceof Error}>\n            <div>error</div>\n          </Match>\n        </Switch>\n      )\n    }\n\n    function App() {\n      const [id, setId] = createSignal(1)\n      const changeId = () => setId((x) => x + 1)\n\n      return (\n        <div>\n          <Page id={id()} />\n          <button aria-label=\"change\" onClick={changeId}>\n            change {id()}\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <App />\n      </QueryClientProvider>\n    ))\n\n    // initial state check\n    expect(rendered.getByText('status: pending')).toBeInTheDocument()\n    // render error state component\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error')).toBeInTheDocument()\n\n    // change to unmount query\n    fireEvent.click(rendered.getByLabelText('change'))\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('rendered')).toBeInTheDocument()\n\n    // change to mount new query\n    fireEvent.click(rendered.getByLabelText('change'))\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error')).toBeInTheDocument()\n  })\n\n  it('should refetch when query key changed when switching between erroneous queries', async () => {\n    function Page(props: { id: boolean }) {\n      const state = useQuery(() => ({\n        queryKey: [props.id],\n        queryFn: () => sleep(10).then(() => Promise.reject(new Error('Error'))),\n        retry: false,\n        retryOnMount: false,\n        refetchOnMount: false,\n        refetchOnWindowFocus: false,\n      }))\n      return (\n        <Switch fallback={<div>rendered</div>}>\n          <Match when={state.isFetching}>\n            <div>status: fetching</div>\n          </Match>\n          <Match when={state.error instanceof Error}>\n            <div>error</div>\n          </Match>\n        </Switch>\n      )\n    }\n\n    function App() {\n      const [value, setValue] = createSignal(true)\n      const toggle = () => setValue((x) => !x)\n\n      return (\n        <div>\n          <Page id={value()} />\n          <button aria-label=\"change\" onClick={toggle}>\n            change {value()}\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <App />\n      </QueryClientProvider>\n    ))\n\n    // initial state check\n    expect(rendered.getByText('status: fetching')).toBeInTheDocument()\n    // render error state component\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error')).toBeInTheDocument()\n\n    // change to mount second query\n    fireEvent.click(rendered.getByLabelText('change'))\n    expect(rendered.getByText('status: fetching')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error')).toBeInTheDocument()\n\n    // change to mount first query again\n    fireEvent.click(rendered.getByLabelText('change'))\n    expect(rendered.getByText('status: fetching')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error')).toBeInTheDocument()\n  })\n\n  it('should have no error in pending state when refetching after error occurred', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<number>> = []\n    const error = new Error('oops')\n\n    let count = 0\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          if (count === 0) {\n            count++\n            throw error\n          }\n          return 5\n        },\n        retry: false,\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      return (\n        <Switch fallback={<div>data: {state.data}</div>}>\n          <Match when={state.isPending}>\n            <div>status: pending</div>\n          </Match>\n          <Match when={state.error instanceof Error}>\n            <div>\n              <div>error</div>\n              <button onClick={() => state.refetch()}>refetch</button>\n            </div>\n          </Match>\n        </Switch>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('error')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 5')).toBeInTheDocument()\n\n    expect(states.length).toBe(4)\n\n    expect(states[0]).toMatchObject({\n      status: 'pending',\n      data: undefined,\n      error: null,\n    })\n\n    expect(states[1]).toMatchObject({\n      status: 'error',\n      data: undefined,\n      error,\n    })\n\n    expect(states[2]).toMatchObject({\n      status: 'pending',\n      data: undefined,\n      error: null,\n    })\n\n    expect(states[3]).toMatchObject({\n      status: 'success',\n      data: 5,\n      error: null,\n    })\n  })\n\n  describe('networkMode online', () => {\n    it('online queries should not start fetching if you are offline', async () => {\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const key = queryKey()\n      const states: Array<any> = []\n\n      function Page() {\n        const state = useQuery(() => ({\n          queryKey: key,\n          queryFn: () => sleep(10).then(() => 'data'),\n        }))\n\n        createEffect(() => {\n          states.push(state.fetchStatus)\n        })\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, isPaused: {String(state.isPaused)}\n            </div>\n            <div>data: {state.data}</div>\n          </div>\n        )\n      }\n\n      const rendered = render(() => (\n        <QueryClientProvider client={queryClient}>\n          <Page />\n        </QueryClientProvider>\n      ))\n\n      window.dispatchEvent(new Event('offline'))\n\n      await vi.advanceTimersByTimeAsync(10)\n      expect(\n        rendered.getByText('status: pending, isPaused: true'),\n      ).toBeInTheDocument()\n\n      onlineMock.mockRestore()\n      window.dispatchEvent(new Event('online'))\n\n      await vi.advanceTimersByTimeAsync(10)\n      expect(\n        rendered.getByText('status: success, isPaused: false'),\n      ).toBeInTheDocument()\n      expect(rendered.getByText('data: data')).toBeInTheDocument()\n\n      expect(states).toEqual(['paused', 'fetching', 'idle'])\n    })\n\n    it('online queries should not refetch if you are offline', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery<unknown, string, string>(() => ({\n          queryKey: key,\n          queryFn: async () => {\n            await sleep(10)\n            count++\n            return 'data' + count\n          },\n        }))\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus},\n              failureCount: {state.failureCount}\n            </div>\n            <div>failureReason: {state.failureReason ?? 'null'}</div>\n            <div>data: {state.data}</div>\n            <button\n              onClick={() => queryClient.invalidateQueries({ queryKey: key })}\n            >\n              invalidate\n            </button>\n          </div>\n        )\n      }\n\n      const rendered = render(() => (\n        <QueryClientProvider client={queryClient}>\n          <Page />\n        </QueryClientProvider>\n      ))\n\n      expect(\n        rendered.getByText(\n          'status: pending, fetchStatus: fetching, failureCount: 0',\n        ),\n      ).toBeInTheDocument()\n      await vi.advanceTimersByTimeAsync(10)\n      expect(rendered.getByText('data: data1')).toBeInTheDocument()\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n      window.dispatchEvent(new Event('offline'))\n\n      fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))\n      await vi.advanceTimersByTimeAsync(10)\n      expect(\n        rendered.getByText(\n          'status: success, fetchStatus: paused, failureCount: 0',\n        ),\n      ).toBeInTheDocument()\n      expect(rendered.getByText('failureReason: null')).toBeInTheDocument()\n\n      onlineMock.mockRestore()\n      window.dispatchEvent(new Event('online'))\n\n      await vi.advanceTimersByTimeAsync(0)\n      expect(\n        rendered.getByText(\n          'status: success, fetchStatus: fetching, failureCount: 0',\n        ),\n      ).toBeInTheDocument()\n      await vi.advanceTimersByTimeAsync(10)\n      expect(\n        rendered.getByText(\n          'status: success, fetchStatus: idle, failureCount: 0',\n        ),\n      ).toBeInTheDocument()\n      expect(rendered.getByText('failureReason: null')).toBeInTheDocument()\n      expect(rendered.getByText('data: data2')).toBeInTheDocument()\n    })\n\n    it('online queries should not refetch if you are offline and refocus', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery(() => ({\n          queryKey: key,\n          queryFn: async () => {\n            await sleep(10)\n            count++\n            return 'data' + count\n          },\n        }))\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus}\n            </div>\n            <div>data: {state.data}</div>\n            <button\n              onClick={() => queryClient.invalidateQueries({ queryKey: key })}\n            >\n              invalidate\n            </button>\n          </div>\n        )\n      }\n\n      const rendered = render(() => (\n        <QueryClientProvider client={queryClient}>\n          <Page />\n        </QueryClientProvider>\n      ))\n\n      expect(\n        rendered.getByText('status: pending, fetchStatus: fetching'),\n      ).toBeInTheDocument()\n      await vi.advanceTimersByTimeAsync(10)\n      expect(rendered.getByText('data: data1')).toBeInTheDocument()\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))\n      await vi.advanceTimersByTimeAsync(10)\n      expect(\n        rendered.getByText('status: success, fetchStatus: paused'),\n      ).toBeInTheDocument()\n      window.dispatchEvent(new Event('visibilitychange'))\n      await vi.advanceTimersByTimeAsync(10)\n      expect(rendered.queryByText('data: data2')).not.toBeInTheDocument()\n      expect(count).toBe(1)\n      onlineMock.mockRestore()\n    })\n\n    it('online queries should not refetch while already paused', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery(() => ({\n          queryKey: key,\n          queryFn: async () => {\n            await sleep(10)\n            count++\n            return 'data' + count\n          },\n        }))\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus}\n            </div>\n            <div>data: {state.data}</div>\n            <button\n              onClick={() => queryClient.invalidateQueries({ queryKey: key })}\n            >\n              invalidate\n            </button>\n          </div>\n        )\n      }\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const rendered = render(() => (\n        <QueryClientProvider client={queryClient}>\n          <Page />\n        </QueryClientProvider>\n      ))\n\n      expect(\n        rendered.getByText('status: pending, fetchStatus: paused'),\n      ).toBeInTheDocument()\n      fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))\n      // invalidation should not trigger a refetch\n      await vi.advanceTimersByTimeAsync(10)\n      expect(\n        rendered.getByText('status: pending, fetchStatus: paused'),\n      ).toBeInTheDocument()\n      expect(count).toBe(0)\n      onlineMock.mockRestore()\n    })\n\n    it('online queries should not refetch while already paused if data is in the cache', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery(() => ({\n          queryKey: key,\n          queryFn: async () => {\n            await sleep(10)\n            count++\n            return 'data' + count\n          },\n          initialData: 'initial',\n        }))\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus}\n            </div>\n            <div>data: {state.data}</div>\n            <button\n              onClick={() => queryClient.invalidateQueries({ queryKey: key })}\n            >\n              invalidate\n            </button>\n          </div>\n        )\n      }\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const rendered = render(() => (\n        <QueryClientProvider client={queryClient}>\n          <Page />\n        </QueryClientProvider>\n      ))\n\n      expect(\n        rendered.getByText('status: success, fetchStatus: paused'),\n      ).toBeInTheDocument()\n      expect(rendered.getByText('data: initial')).toBeInTheDocument()\n\n      fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))\n      // invalidation should not trigger a refetch\n      await vi.advanceTimersByTimeAsync(10)\n      expect(\n        rendered.getByText('status: success, fetchStatus: paused'),\n      ).toBeInTheDocument()\n      expect(count).toBe(0)\n      onlineMock.mockRestore()\n    })\n\n    it('online queries should not get stuck in fetching state when pausing multiple times', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery(() => ({\n          queryKey: key,\n          queryFn: async () => {\n            await sleep(10)\n            count++\n            return 'data' + count\n          },\n          initialData: 'initial',\n        }))\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus}\n            </div>\n            <div>data: {state.data}</div>\n            <button\n              onClick={() => queryClient.invalidateQueries({ queryKey: key })}\n            >\n              invalidate\n            </button>\n          </div>\n        )\n      }\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const rendered = render(() => (\n        <QueryClientProvider client={queryClient}>\n          <Page />\n        </QueryClientProvider>\n      ))\n\n      window.dispatchEvent(new Event('offline'))\n\n      await vi.advanceTimersByTimeAsync(10)\n      expect(\n        rendered.getByText('status: success, fetchStatus: paused'),\n      ).toBeInTheDocument()\n      expect(rendered.getByText('data: initial')).toBeInTheDocument()\n\n      // triggers one pause\n      fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))\n\n      await vi.advanceTimersByTimeAsync(10)\n\n      expect(\n        rendered.getByText('status: success, fetchStatus: paused'),\n      ).toBeInTheDocument()\n      // triggers a second pause\n      window.dispatchEvent(new Event('visibilitychange'))\n\n      onlineMock.mockRestore()\n      window.dispatchEvent(new Event('online'))\n\n      await vi.advanceTimersByTimeAsync(10)\n      expect(\n        rendered.getByText('status: success, fetchStatus: idle'),\n      ).toBeInTheDocument()\n      expect(rendered.getByText('data: data1')).toBeInTheDocument()\n\n      expect(count).toBe(1)\n    })\n\n    it('online queries should pause retries if you are offline', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery<unknown, Error>(() => ({\n          queryKey: key,\n          queryFn: async () => {\n            await sleep(10)\n            count++\n            throw new Error('failed' + count)\n          },\n          retry: 2,\n          retryDelay: 10,\n        }))\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus},\n              failureCount: {state.failureCount}\n            </div>\n            <div>failureReason: {state.failureReason?.message ?? 'null'}</div>\n          </div>\n        )\n      }\n\n      const rendered = render(() => (\n        <QueryClientProvider client={queryClient}>\n          <Page />\n        </QueryClientProvider>\n      ))\n\n      // First retry (online): retryDelay (10ms) + queryFn (10ms)\n      await vi.advanceTimersByTimeAsync(10)\n      expect(\n        rendered.getByText(\n          'status: pending, fetchStatus: fetching, failureCount: 1',\n        ),\n      ).toBeInTheDocument()\n      await vi.advanceTimersByTimeAsync(10)\n      expect(rendered.getByText('failureReason: failed1')).toBeInTheDocument()\n\n      window.dispatchEvent(new Event('offline'))\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      // Second retry (offline, paused): retryDelay (10ms) + queryFn (10ms)\n      // Third retry is scheduled but paused due to offline\n      await vi.advanceTimersByTimeAsync(10)\n      await vi.advanceTimersByTimeAsync(10)\n      expect(\n        rendered.getByText(\n          'status: pending, fetchStatus: paused, failureCount: 2',\n        ),\n      ).toBeInTheDocument()\n      expect(rendered.getByText('failureReason: failed2')).toBeInTheDocument()\n\n      expect(count).toBe(2)\n\n      onlineMock.mockRestore()\n      window.dispatchEvent(new Event('online'))\n\n      // Third retry (resumed): only queryFn (10ms), retryDelay already consumed while paused\n      await vi.advanceTimersByTimeAsync(10)\n      expect(\n        rendered.getByText('status: error, fetchStatus: idle, failureCount: 3'),\n      ).toBeInTheDocument()\n      expect(rendered.getByText('failureReason: failed3')).toBeInTheDocument()\n\n      expect(count).toBe(3)\n    })\n\n    it('online queries should not fetch if paused initial load and we go online after unmount', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Component() {\n        const state = useQuery(() => ({\n          queryKey: key,\n          queryFn: async ({ signal: _signal }) => {\n            count++\n            await sleep(10)\n            return `signal${count}`\n          },\n        }))\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus}\n            </div>\n            <div>data: {state.data}</div>\n          </div>\n        )\n      }\n\n      function Page() {\n        const [show, setShow] = createSignal(true)\n\n        return (\n          <div>\n            {show() && <Component />}\n            <button onClick={() => setShow(false)}>hide</button>\n          </div>\n        )\n      }\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const rendered = render(() => (\n        <QueryClientProvider client={queryClient}>\n          <Page />\n        </QueryClientProvider>\n      ))\n\n      window.dispatchEvent(new Event('offline'))\n\n      expect(\n        rendered.getByText('status: pending, fetchStatus: paused'),\n      ).toBeInTheDocument()\n\n      fireEvent.click(rendered.getByRole('button', { name: /hide/i }))\n\n      onlineMock.mockRestore()\n      window.dispatchEvent(new Event('online'))\n\n      await vi.advanceTimersByTimeAsync(10)\n      expect(queryClient.getQueryState(key)).toMatchObject({\n        fetchStatus: 'idle',\n        status: 'pending',\n      })\n\n      expect(count).toBe(0)\n    })\n\n    it('online queries should re-fetch if paused and we go online even if already unmounted (because not cancelled)', async () => {\n      const key = queryKey()\n      let count = 0\n\n      queryClient.setQueryData(key, 'initial')\n\n      function Component() {\n        const state = useQuery(() => ({\n          queryKey: key,\n          queryFn: async () => {\n            count++\n            await sleep(10)\n            return 'data' + count\n          },\n        }))\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus}\n            </div>\n            <div>data: {state.data}</div>\n          </div>\n        )\n      }\n\n      function Page() {\n        const [show, setShow] = createSignal(true)\n\n        return (\n          <div>\n            {show() && <Component />}\n            <button onClick={() => setShow(false)}>hide</button>\n          </div>\n        )\n      }\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const rendered = render(() => (\n        <QueryClientProvider client={queryClient}>\n          <Page />\n        </QueryClientProvider>\n      ))\n\n      expect(\n        rendered.getByText('status: success, fetchStatus: paused'),\n      ).toBeInTheDocument()\n\n      fireEvent.click(rendered.getByRole('button', { name: /hide/i }))\n\n      onlineMock.mockReturnValue(true)\n      queryClient.getQueryCache().onOnline()\n\n      await vi.advanceTimersByTimeAsync(10)\n      expect(queryClient.getQueryState(key)).toMatchObject({\n        fetchStatus: 'idle',\n        status: 'success',\n      })\n\n      expect(count).toBe(1)\n\n      onlineMock.mockRestore()\n    })\n\n    it('online queries should not fetch if paused and we go online when cancelled and no refetchOnReconnect', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery(() => ({\n          queryKey: key,\n          queryFn: async () => {\n            await sleep(10)\n            count++\n            return 'data' + count\n          },\n          refetchOnReconnect: false,\n        }))\n\n        return (\n          <div>\n            <button\n              onClick={() => queryClient.cancelQueries({ queryKey: key })}\n            >\n              cancel\n            </button>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus}\n            </div>\n            <div>data: {state.data}</div>\n          </div>\n        )\n      }\n\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const rendered = render(() => (\n        <QueryClientProvider client={queryClient}>\n          <Page />\n        </QueryClientProvider>\n      ))\n\n      expect(\n        rendered.getByText('status: pending, fetchStatus: paused'),\n      ).toBeInTheDocument()\n\n      fireEvent.click(rendered.getByRole('button', { name: /cancel/i }))\n      await vi.advanceTimersByTimeAsync(10)\n      expect(\n        rendered.getByText('status: pending, fetchStatus: idle'),\n      ).toBeInTheDocument()\n      expect(count).toBe(0)\n\n      onlineMock.mockReturnValue(true)\n      window.dispatchEvent(new Event('online'))\n\n      expect(\n        rendered.getByText('status: pending, fetchStatus: idle'),\n      ).toBeInTheDocument()\n      expect(count).toBe(0)\n\n      onlineMock.mockRestore()\n    })\n\n    it('online queries should fetch if paused and we go online even if already unmounted when refetch was not cancelled', async () => {\n      const key = queryKey()\n      let count = 0\n\n      function Component() {\n        const state = useQuery(() => ({\n          queryKey: key,\n          queryFn: async () => {\n            count++\n            return `data${count}`\n          },\n        }))\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus}\n            </div>\n            <div>data: {state.data}</div>\n          </div>\n        )\n      }\n\n      function Page() {\n        const [show, setShow] = createSignal(true)\n\n        return (\n          <div>\n            {show() && <Component />}\n            <button onClick={() => setShow(false)}>hide</button>\n            <button\n              onClick={() => queryClient.invalidateQueries({ queryKey: key })}\n            >\n              invalidate\n            </button>\n          </div>\n        )\n      }\n\n      const rendered = render(() => (\n        <QueryClientProvider client={queryClient}>\n          <Page />\n        </QueryClientProvider>\n      ))\n\n      await vi.advanceTimersByTimeAsync(10)\n      expect(\n        rendered.getByText('status: success, fetchStatus: idle'),\n      ).toBeInTheDocument()\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))\n      await vi.advanceTimersByTimeAsync(10)\n      expect(\n        rendered.getByText('status: success, fetchStatus: paused'),\n      ).toBeInTheDocument()\n      fireEvent.click(rendered.getByRole('button', { name: /hide/i }))\n\n      onlineMock.mockReturnValue(true)\n      queryClient.getQueryCache().onOnline()\n\n      await vi.advanceTimersByTimeAsync(10)\n\n      expect(queryClient.getQueryState(key)).toMatchObject({\n        fetchStatus: 'idle',\n        status: 'success',\n      })\n\n      expect(count).toBe(2)\n    })\n  })\n\n  describe('networkMode always', () => {\n    it('always queries should start fetching even if you are offline', async () => {\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery(() => ({\n          queryKey: key,\n          queryFn: async () => {\n            await sleep(10)\n            count++\n            return 'data ' + count\n          },\n          networkMode: 'always',\n        }))\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, isPaused: {String(state.isPaused)}\n            </div>\n            <div>data: {state.data}</div>\n          </div>\n        )\n      }\n\n      const rendered = render(() => (\n        <QueryClientProvider client={queryClient}>\n          <Page />\n        </QueryClientProvider>\n      ))\n\n      await vi.advanceTimersByTimeAsync(10)\n      expect(\n        rendered.getByText('status: success, isPaused: false'),\n      ).toBeInTheDocument()\n      expect(rendered.getByText('data: data 1')).toBeInTheDocument()\n\n      onlineMock.mockRestore()\n    })\n\n    it('always queries should not pause retries', async () => {\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery(() => ({\n          queryKey: key,\n          queryFn: async () => {\n            await sleep(10)\n            count++\n            throw new Error('error ' + count)\n          },\n          networkMode: 'always',\n          retry: 1,\n          retryDelay: 5,\n        }))\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, isPaused: {String(state.isPaused)}\n            </div>\n            <div>\n              error: {state.error instanceof Error && state.error.message}\n            </div>\n          </div>\n        )\n      }\n\n      const rendered = render(() => (\n        <QueryClientProvider client={queryClient}>\n          <Page />\n        </QueryClientProvider>\n      ))\n\n      await vi.advanceTimersByTimeAsync(10)\n      await vi.advanceTimersByTimeAsync(10)\n      await vi.advanceTimersByTimeAsync(10)\n\n      expect(\n        rendered.getByText('status: error, isPaused: false'),\n      ).toBeInTheDocument()\n\n      expect(rendered.getByText('error: error 2')).toBeInTheDocument()\n\n      expect(count).toBe(2)\n\n      onlineMock.mockRestore()\n    })\n  })\n\n  describe('networkMode offlineFirst', () => {\n    it('offlineFirst queries should start fetching if you are offline, but pause retries', async () => {\n      const onlineMock = mockOnlineManagerIsOnline(false)\n\n      const key = queryKey()\n      let count = 0\n\n      function Page() {\n        const state = useQuery<unknown, Error>(() => ({\n          queryKey: key,\n          queryFn: async () => {\n            await sleep(10)\n            count++\n            throw new Error('failed' + count)\n          },\n          retry: 2,\n          retryDelay: 1,\n          networkMode: 'offlineFirst',\n        }))\n\n        return (\n          <div>\n            <div>\n              status: {state.status}, fetchStatus: {state.fetchStatus},\n              failureCount: {state.failureCount}\n            </div>\n            <div>failureReason: {state.failureReason?.message ?? 'null'}</div>\n          </div>\n        )\n      }\n\n      const rendered = render(() => (\n        <QueryClientProvider client={queryClient}>\n          <Page />\n        </QueryClientProvider>\n      ))\n\n      window.dispatchEvent(new Event('offline'))\n\n      // Initial fetch completes while offline: queryFn (10ms) + micro delay (1ms)\n      // First retry is scheduled but paused due to offline\n      await vi.advanceTimersByTimeAsync(10)\n      await vi.advanceTimersByTimeAsync(1)\n\n      expect(\n        rendered.getByText(\n          'status: pending, fetchStatus: paused, failureCount: 1',\n        ),\n      ).toBeInTheDocument()\n      expect(rendered.getByText('failureReason: failed1')).toBeInTheDocument()\n\n      expect(count).toBe(1)\n\n      onlineMock.mockRestore()\n      window.dispatchEvent(new Event('online'))\n\n      // Resume retries when back online\n      // First retry (resumed): queryFn (10ms)\n      // Second retry: retryDelay (10ms) + queryFn (10ms) - but only 10ms shown means they overlap or execute together\n      await vi.advanceTimersByTimeAsync(10)\n      await vi.advanceTimersByTimeAsync(10)\n      await vi.advanceTimersByTimeAsync(10)\n\n      expect(\n        rendered.getByText('status: error, fetchStatus: idle, failureCount: 3'),\n      ).toBeInTheDocument()\n      expect(rendered.getByText('failureReason: failed3')).toBeInTheDocument()\n\n      expect(count).toBe(3)\n    })\n  })\n\n  it('should have status=error on mount when a query has failed', async () => {\n    const key = queryKey()\n    const states: Array<UseQueryResult<unknown>> = []\n    const error = new Error('oops')\n\n    const queryFn = () => sleep(10).then(() => Promise.reject(error))\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn,\n        retry: false,\n        retryOnMount: false,\n      }))\n\n      createRenderEffect(() => {\n        states.push({ ...state })\n      })\n\n      return <></>\n    }\n\n    queryClient.prefetchQuery({ queryKey: key, queryFn })\n    await vi.advanceTimersByTimeAsync(10)\n\n    render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    expect(states).toHaveLength(1)\n\n    expect(states[0]).toMatchObject({\n      status: 'error',\n      error,\n    })\n  })\n\n  it('setQueryData - should respect updatedAt', async () => {\n    const key = queryKey()\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'data'),\n      }))\n      return (\n        <div>\n          <div>data: {state.data}</div>\n          <div>dataUpdatedAt: {state.dataUpdatedAt}</div>\n          <button\n            onClick={() => {\n              queryClient.setQueryData(key, 'newData', {\n                updatedAt: 100,\n              })\n            }}\n          >\n            setQueryData\n          </button>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: data')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /setQueryData/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('data: newData')).toBeInTheDocument()\n    expect(rendered.getByText('dataUpdatedAt: 100')).toBeInTheDocument()\n  })\n\n  it('errorUpdateCount should increased on each fetch failure', async () => {\n    const key = queryKey()\n    const error = new Error('oops')\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => Promise.reject(error)),\n        retry: false,\n      }))\n      return (\n        <div>\n          <button onClick={() => state.refetch()}>refetch</button>\n          <span>data: {state.errorUpdateCount}</span>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <Page />\n      </QueryClientProvider>\n    ))\n\n    const fetchBtn = rendered.getByRole('button', { name: 'refetch' })\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 1')).toBeInTheDocument()\n    fireEvent.click(fetchBtn)\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 2')).toBeInTheDocument()\n    fireEvent.click(fetchBtn)\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: 3')).toBeInTheDocument()\n  })\n\n  it('should not fetch while restoring and refetch after restoring is complete', async () => {\n    const key = queryKey()\n    const queryFn = vi\n      .fn()\n      .mockImplementation(() => sleep(10).then(() => 'data'))\n\n    const [isRestoring, setIsRestoring] = createSignal(true)\n\n    function Page() {\n      const query = useQuery(() => ({\n        queryKey: key,\n        queryFn,\n      }))\n\n      return (\n        <div>\n          <div data-testid=\"status\">{query.status}</div>\n          <div data-testid=\"fetchStatus\">{query.fetchStatus}</div>\n          <div data-testid=\"data\">{query.data ?? 'undefined'}</div>\n        </div>\n      )\n    }\n\n    const rendered = render(() => (\n      <QueryClientProvider client={queryClient}>\n        <IsRestoringProvider value={isRestoring}>\n          <Page />\n        </IsRestoringProvider>\n      </QueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(rendered.getByTestId('status')).toHaveTextContent('pending')\n    expect(rendered.getByTestId('fetchStatus')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('data')).toHaveTextContent('undefined')\n    expect(queryFn).toHaveBeenCalledTimes(0)\n\n    // Restoring complete: should refetch\n    setIsRestoring(false)\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(rendered.getByTestId('status')).toHaveTextContent('success')\n    expect(rendered.getByTestId('fetchStatus')).toHaveTextContent('idle')\n    expect(rendered.getByTestId('data')).toHaveTextContent('data')\n    expect(queryFn).toHaveBeenCalledTimes(1)\n  })\n\n  it('should use provided custom queryClient', async () => {\n    const key = queryKey()\n    const queryFn = () => sleep(10).then(() => 'custom client')\n\n    function Page() {\n      const state = useQuery(\n        () => ({ queryKey: key, queryFn }),\n        () => queryClient,\n      )\n      return (\n        <div>\n          <h1>Status: {state.data}</h1>\n        </div>\n      )\n    }\n\n    const rendered = render(() => <Page />)\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('Status: custom client')).toBeInTheDocument()\n  })\n\n  it('should refetch query when queryClient changes', async () => {\n    const key = queryKey()\n\n    const queryClient1 = new QueryClient()\n    const queryClient2 = new QueryClient()\n\n    const queryFn = vi\n      .fn()\n      .mockImplementation(() => sleep(10).then(() => 'data'))\n\n    function Page(props: { client: () => QueryClient }) {\n      const query = useQuery(\n        () => ({\n          queryKey: key,\n          queryFn,\n        }),\n        props.client,\n      )\n\n      return <div>status: {query.status}</div>\n    }\n\n    const [client, setClient] = createSignal(queryClient1)\n\n    const rendered = render(() => <Page client={client} />)\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(rendered.getByText('status: success')).toBeInTheDocument()\n    expect(queryClient1.getQueryCache().find({ queryKey: key })).toBeDefined()\n    expect(queryFn).toHaveBeenCalledTimes(1)\n\n    setClient(queryClient2)\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(rendered.getByText('status: success')).toBeInTheDocument()\n    expect(queryClient2.getQueryCache().find({ queryKey: key })).toBeDefined()\n    expect(queryFn).toHaveBeenCalledTimes(2)\n  })\n})\n"
  },
  {
    "path": "packages/solid-query/src/__tests__/useQueryOptions.test-d.tsx",
    "content": "import { describe, expectTypeOf, it } from 'vitest'\nimport { dataTagSymbol } from '@tanstack/query-core'\nimport { useInfiniteQuery } from '../useInfiniteQuery'\nimport { infiniteQueryOptions } from '../infiniteQueryOptions'\nimport type { InfiniteData } from '@tanstack/query-core'\nimport type {\n  DefinedInitialDataInfiniteOptions,\n  UndefinedInitialDataInfiniteOptions,\n} from '../infiniteQueryOptions'\n\ndescribe('infiniteQueryOptions', () => {\n  it('should infer defined types', () => {\n    const options = infiniteQueryOptions({\n      getNextPageParam: () => 10,\n      queryKey: ['key'],\n      queryFn: () => ({ wow: true }),\n      initialData: {\n        pageParams: [undefined],\n        pages: [{ wow: true }],\n      },\n      initialPageParam: 0,\n    })\n\n    expectTypeOf(useInfiniteQuery(() => options).data).toEqualTypeOf<\n      InfiniteData<{ wow: boolean }, unknown>\n    >()\n\n    expectTypeOf(options).toMatchTypeOf<\n      ReturnType<\n        DefinedInitialDataInfiniteOptions<\n          { wow: boolean },\n          Error,\n          InfiniteData<{ wow: boolean }, unknown>,\n          Array<string>,\n          number | undefined\n        >\n      >\n    >()\n\n    expectTypeOf(options.queryKey[dataTagSymbol]).toEqualTypeOf<\n      InfiniteData<{ wow: boolean }>\n    >()\n  })\n\n  it('should work without defined types', () => {\n    const options = infiniteQueryOptions({\n      getNextPageParam: () => undefined,\n      queryKey: ['key'],\n      queryFn: () => ({ wow: true }),\n      initialPageParam: 0,\n    })\n\n    expectTypeOf(() => useInfiniteQuery(() => options).data).toEqualTypeOf<\n      () => InfiniteData<{ wow: boolean }, unknown> | undefined\n    >()\n\n    expectTypeOf(options).toMatchTypeOf<\n      ReturnType<\n        UndefinedInitialDataInfiniteOptions<\n          { wow: boolean },\n          Error,\n          InfiniteData<{ wow: boolean }, unknown>,\n          Array<string>,\n          number\n        >\n      >\n    >()\n\n    expectTypeOf(options.queryKey[dataTagSymbol]).toEqualTypeOf<\n      InfiniteData<{\n        wow: boolean\n      }>\n    >()\n  })\n})\n"
  },
  {
    "path": "packages/solid-query/src/__tests__/utils.tsx",
    "content": "import { vi } from 'vitest'\nimport { Show, createEffect, createSignal, onCleanup } from 'solid-js'\nimport { onlineManager } from '@tanstack/query-core'\nimport type { ParentProps } from 'solid-js'\nimport type { MockInstance } from 'vitest'\n\nexport function Blink(\n  props: {\n    duration: number\n  } & ParentProps,\n) {\n  const [shouldShow, setShouldShow] = createSignal<boolean>(true)\n\n  createEffect(() => {\n    setShouldShow(true)\n    const timeout = setActTimeout(() => setShouldShow(false), props.duration)\n    onCleanup(() => clearTimeout(timeout))\n  })\n\n  return (\n    <Show when={shouldShow()} fallback={<>off</>}>\n      <>{props.children}</>\n    </Show>\n  )\n}\n\nexport function mockOnlineManagerIsOnline(\n  value: boolean,\n): MockInstance<() => boolean> {\n  return vi.spyOn(onlineManager, 'isOnline').mockReturnValue(value)\n}\n\nexport function setActTimeout(fn: () => void, ms?: number) {\n  return setTimeout(() => {\n    fn()\n  }, ms)\n}\n"
  },
  {
    "path": "packages/solid-query/src/index.ts",
    "content": "/* istanbul ignore file */\n\nimport { useQuery } from './useQuery'\nimport { useInfiniteQuery } from './useInfiniteQuery'\nimport { useMutation } from './useMutation'\nimport { useQueries } from './useQueries'\n\n// Re-export core\nexport * from '@tanstack/query-core'\n\n// Solid Query\nexport * from './types'\n\nexport type {\n  DefinedUseBaseQueryResult,\n  DefinedUseInfiniteQueryResult,\n  DefinedUseQueryResult,\n  SolidInfiniteQueryOptions,\n  SolidMutationOptions,\n  SolidQueryOptions,\n  UseBaseMutationResult,\n  UseBaseQueryOptions,\n  UseBaseQueryResult,\n  UseInfiniteQueryOptions,\n  UseInfiniteQueryResult,\n  UseMutateAsyncFunction,\n  UseMutateFunction,\n  UseMutationOptions,\n  UseMutationResult,\n  UseQueryOptions,\n  UseQueryResult,\n  // Aliases (create* and use* are both supported)\n  UseBaseQueryOptions as CreateBaseQueryOptions,\n  UseBaseQueryResult as CreateBaseQueryResult,\n  UseInfiniteQueryOptions as CreateInfiniteQueryOptions,\n  UseInfiniteQueryResult as CreateInfiniteQueryResult,\n  UseMutateAsyncFunction as CreateMutateAsyncFunction,\n  UseMutateFunction as CreateMutateFunction,\n  UseMutationOptions as CreateMutationOptions,\n  UseMutationResult as CreateMutationResult,\n  UseBaseMutationResult as CreateBaseMutationResult,\n  UseQueryOptions as CreateQueryOptions,\n  UseQueryResult as CreateQueryResult,\n  DefinedUseBaseQueryResult as DefinedCreateBaseQueryResult,\n  DefinedUseInfiniteQueryResult as DefinedCreateInfiniteQueryResult,\n  DefinedUseQueryResult as DefinedCreateQueryResult,\n} from './types'\n\nexport { QueryClient } from './QueryClient'\nexport type {\n  QueryObserverOptions,\n  DefaultOptions,\n  QueryClientConfig,\n  InfiniteQueryObserverOptions,\n} from './QueryClient'\nexport { useQuery } from './useQuery'\nexport const createQuery = useQuery\nexport { queryOptions } from './queryOptions'\nexport type {\n  DefinedInitialDataOptions,\n  UndefinedInitialDataOptions,\n} from './queryOptions'\nexport {\n  QueryClientContext,\n  QueryClientProvider,\n  useQueryClient,\n} from './QueryClientProvider'\nexport type { QueryClientProviderProps } from './QueryClientProvider'\nexport { useIsFetching } from './useIsFetching'\nexport { useIsFetching as createIsFetching } from './useIsFetching'\nexport { useInfiniteQuery }\nexport const createInfiniteQuery = useInfiniteQuery\nexport { infiniteQueryOptions } from './infiniteQueryOptions'\nexport type {\n  DefinedInitialDataInfiniteOptions,\n  UndefinedInitialDataInfiniteOptions,\n} from './infiniteQueryOptions'\nexport { useMutation } from './useMutation'\nexport { mutationOptions } from './mutationOptions'\nexport const createMutation = useMutation\nexport { useIsMutating } from './useIsMutating'\nexport { useIsMutating as createIsMutating } from './useIsMutating'\nexport { useMutationState } from './useMutationState'\nexport { useMutationState as createMutationState } from './useMutationState'\nexport { useQueries } from './useQueries'\nexport const createQueries = useQueries\nexport { useIsRestoring, IsRestoringProvider } from './isRestoring'\n"
  },
  {
    "path": "packages/solid-query/src/infiniteQueryOptions.ts",
    "content": "import type {\n  DataTag,\n  DefaultError,\n  InfiniteData,\n  NonUndefinedGuard,\n  QueryKey,\n} from '@tanstack/query-core'\nimport type { SolidInfiniteQueryOptions } from './types'\nimport type { Accessor } from 'solid-js'\n\nexport type UndefinedInitialDataInfiniteOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> = Accessor<\n  SolidInfiniteQueryOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  > & {\n    initialData?: undefined\n  }\n>\n\nexport type DefinedInitialDataInfiniteOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  // should we handle page param correctly\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> = Accessor<\n  SolidInfiniteQueryOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  > & {\n    initialData:\n      | NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>\n      | (() => NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>)\n  }\n>\nexport function infiniteQueryOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: ReturnType<\n    DefinedInitialDataInfiniteOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey,\n      TPageParam\n    >\n  >,\n): ReturnType<\n  DefinedInitialDataInfiniteOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >\n> & {\n  queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>>\n}\nexport function infiniteQueryOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: ReturnType<\n    UndefinedInitialDataInfiniteOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey,\n      TPageParam\n    >\n  >,\n): ReturnType<\n  UndefinedInitialDataInfiniteOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >\n> & {\n  queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>>\n}\n\nexport function infiniteQueryOptions(options: unknown) {\n  return options\n}\n"
  },
  {
    "path": "packages/solid-query/src/isRestoring.ts",
    "content": "import { createContext, useContext } from 'solid-js'\nimport type { Accessor } from 'solid-js'\n\nconst IsRestoringContext = createContext<Accessor<boolean>>(() => false)\n\nexport const useIsRestoring = () => useContext(IsRestoringContext)\nexport const IsRestoringProvider = IsRestoringContext.Provider\n"
  },
  {
    "path": "packages/solid-query/src/mutationOptions.ts",
    "content": "import type { DefaultError, WithRequired } from '@tanstack/query-core'\nimport type { SolidMutationOptions } from './types'\n\nexport function mutationOptions<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n>(\n  options: WithRequired<\n    SolidMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n    'mutationKey'\n  >,\n): WithRequired<\n  SolidMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n  'mutationKey'\n>\nexport function mutationOptions<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n>(\n  options: Omit<\n    SolidMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n    'mutationKey'\n  >,\n): Omit<\n  SolidMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n  'mutationKey'\n>\nexport function mutationOptions<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n>(\n  options: SolidMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n): SolidMutationOptions<TData, TError, TVariables, TOnMutateResult> {\n  return options\n}\n"
  },
  {
    "path": "packages/solid-query/src/queryOptions.ts",
    "content": "import type { DataTag, DefaultError, QueryKey } from '@tanstack/query-core'\nimport type { SolidQueryOptions } from './types'\nimport type { Accessor } from 'solid-js'\n\nexport type UndefinedInitialDataOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = Accessor<\n  SolidQueryOptions<TQueryFnData, TError, TData, TQueryKey> & {\n    initialData?: undefined\n  }\n>\n\nexport type DefinedInitialDataOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = Accessor<\n  SolidQueryOptions<TQueryFnData, TError, TData, TQueryKey> & {\n    initialData: TQueryFnData | (() => TQueryFnData)\n  }\n>\n\nexport function queryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: ReturnType<\n    UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>\n  >,\n): ReturnType<\n  UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>\n> & {\n  queryKey: DataTag<TQueryKey, TQueryFnData, TError>\n}\n\nexport function queryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: ReturnType<\n    DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>\n  >,\n): ReturnType<\n  DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>\n> & {\n  queryKey: DataTag<TQueryKey, TQueryFnData, TError>\n}\n\nexport function queryOptions(options: unknown) {\n  return options\n}\n"
  },
  {
    "path": "packages/solid-query/src/types.ts",
    "content": "/* istanbul ignore file */\n\nimport type {\n  DefaultError,\n  DefinedInfiniteQueryObserverResult,\n  DefinedQueryObserverResult,\n  InfiniteQueryObserverResult,\n  MutateFunction,\n  MutationObserverOptions,\n  MutationObserverResult,\n  OmitKeyof,\n  Override,\n  QueryKey,\n  QueryObserverResult,\n} from '@tanstack/query-core'\nimport type {\n  InfiniteQueryObserverOptions,\n  QueryObserverOptions,\n} from './QueryClient'\nimport type { Accessor } from 'solid-js'\n\nexport interface UseBaseQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> extends OmitKeyof<\n  QueryObserverOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>,\n  'suspense'\n> {\n  /**\n   * Only applicable while rendering queries on the server with streaming.\n   * Set `deferStream` to `true` to wait for the query to resolve on the server before flushing the stream.\n   * This can be useful to avoid sending a loading state to the client before the query has resolved.\n   * Defaults to `false`.\n   */\n  deferStream?: boolean\n  /**\n   * @deprecated The `suspense` option has been deprecated in v5 and will be removed in the next major version.\n   * The `data` property on useQuery is a SolidJS resource and will automatically suspend when the data is loading.\n   * Setting `suspense` to `false` will be a no-op.\n   */\n  suspense?: boolean\n}\n\nexport interface SolidQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> extends UseBaseQueryOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryFnData,\n  TQueryKey\n> {}\n\nexport type UseQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = Accessor<SolidQueryOptions<TQueryFnData, TError, TData, TQueryKey>>\n\n/* --- Create Query and Create Base Query  Types --- */\n\nexport type UseBaseQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = QueryObserverResult<TData, TError>\n\nexport type UseQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = UseBaseQueryResult<TData, TError>\n\nexport type DefinedUseBaseQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = DefinedQueryObserverResult<TData, TError>\n\nexport type DefinedUseQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = DefinedUseBaseQueryResult<TData, TError>\n\n/* --- Create Infinite Queries Types --- */\nexport interface SolidInfiniteQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> extends OmitKeyof<\n  InfiniteQueryObserverOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n  'queryKey' | 'suspense'\n> {\n  queryKey: TQueryKey\n  /**\n   * Only applicable while rendering queries on the server with streaming.\n   * Set `deferStream` to `true` to wait for the query to resolve on the server before flushing the stream.\n   * This can be useful to avoid sending a loading state to the client before the query has resolved.\n   * Defaults to `false`.\n   */\n  deferStream?: boolean\n  /**\n   * @deprecated The `suspense` option has been deprecated in v5 and will be removed in the next major version.\n   * The `data` property on useInfiniteQuery is a SolidJS resource and will automatically suspend when the data is loading.\n   * Setting `suspense` to `false` will be a no-op.\n   */\n  suspense?: boolean\n}\n\nexport type UseInfiniteQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> = Accessor<\n  SolidInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>\n>\n\nexport type UseInfiniteQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = InfiniteQueryObserverResult<TData, TError>\n\nexport type DefinedUseInfiniteQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = DefinedInfiniteQueryObserverResult<TData, TError>\n\n/* --- Create Mutation Types --- */\nexport interface SolidMutationOptions<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> extends OmitKeyof<\n  MutationObserverOptions<TData, TError, TVariables, TOnMutateResult>,\n  '_defaulted'\n> {}\n\nexport type UseMutationOptions<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> = Accessor<SolidMutationOptions<TData, TError, TVariables, TOnMutateResult>>\n\nexport type UseMutateFunction<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> = (\n  ...args: Parameters<\n    MutateFunction<TData, TError, TVariables, TOnMutateResult>\n  >\n) => void\n\nexport type UseMutateAsyncFunction<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> = MutateFunction<TData, TError, TVariables, TOnMutateResult>\n\nexport type UseBaseMutationResult<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = unknown,\n  TOnMutateResult = unknown,\n> = Override<\n  MutationObserverResult<TData, TError, TVariables, TOnMutateResult>,\n  { mutate: UseMutateFunction<TData, TError, TVariables, TOnMutateResult> }\n> & {\n  mutateAsync: UseMutateAsyncFunction<\n    TData,\n    TError,\n    TVariables,\n    TOnMutateResult\n  >\n}\n\nexport type UseMutationResult<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = unknown,\n  TOnMutateResult = unknown,\n> = UseBaseMutationResult<TData, TError, TVariables, TOnMutateResult>\n"
  },
  {
    "path": "packages/solid-query/src/useBaseQuery.ts",
    "content": "// Had to disable the lint rule because isServer type is defined as false\n// in solid-js/web package. I'll create a GitHub issue with them to see\n// why that happens.\nimport { hydrate, notifyManager, shouldThrowError } from '@tanstack/query-core'\nimport { isServer } from 'solid-js/web'\nimport {\n  createComputed,\n  createMemo,\n  createResource,\n  createSignal,\n  on,\n  onCleanup,\n} from 'solid-js'\nimport { createStore, reconcile, unwrap } from 'solid-js/store'\nimport { useQueryClient } from './QueryClientProvider'\nimport { useIsRestoring } from './isRestoring'\nimport type { UseBaseQueryOptions } from './types'\nimport type { Accessor, Signal } from 'solid-js'\nimport type { QueryClient } from './QueryClient'\nimport type {\n  Query,\n  QueryKey,\n  QueryObserver,\n  QueryObserverResult,\n} from '@tanstack/query-core'\n\nfunction reconcileFn<TData, TError>(\n  store: QueryObserverResult<TData, TError>,\n  result: QueryObserverResult<TData, TError>,\n  reconcileOption:\n    | string\n    | false\n    | ((oldData: TData | undefined, newData: TData) => TData),\n  queryHash?: string,\n): QueryObserverResult<TData, TError> {\n  if (reconcileOption === false) return result\n  if (typeof reconcileOption === 'function') {\n    const newData = reconcileOption(store.data, result.data as TData)\n    return { ...result, data: newData } as typeof result\n  }\n  let data = result.data\n  if (store.data === undefined) {\n    try {\n      data = structuredClone(data)\n    } catch (error) {\n      if (process.env.NODE_ENV !== 'production') {\n        if (error instanceof Error) {\n          console.warn(\n            `Unable to correctly reconcile data for query key: ${queryHash}. ` +\n              `Possibly because the query data contains data structures that aren't supported ` +\n              `by the 'structuredClone' algorithm. Consider using a callback function instead ` +\n              `to manage the reconciliation manually.\\n\\n Error Received: ${error.name} - ${error.message}`,\n          )\n        }\n      }\n    }\n  }\n  const newData = reconcile(data, { key: reconcileOption })(store.data)\n  return { ...result, data: newData } as typeof result\n}\n\n/**\n * Solid's `onHydrated` functionality will silently \"fail\" (hydrate with an empty object)\n * if the resource data is not serializable.\n */\nconst hydratableObserverResult = <\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey extends QueryKey,\n  TDataHydratable,\n>(\n  query: Query<TQueryFnData, TError, TData, TQueryKey>,\n  result: QueryObserverResult<TDataHydratable, TError>,\n) => {\n  if (!isServer) return result\n  const obj: any = {\n    ...unwrap(result),\n    // During SSR, functions cannot be serialized, so we need to remove them\n    // This is safe because we will add these functions back when the query is hydrated\n    refetch: undefined,\n  }\n\n  // If the query is an infinite query, we need to remove additional properties\n  if ('fetchNextPage' in result) {\n    obj.fetchNextPage = undefined\n    obj.fetchPreviousPage = undefined\n  }\n\n  // We will also attach the dehydrated state of the query to the result\n  // This will be removed on client after hydration\n  obj.hydrationData = {\n    state: query.state,\n    queryKey: query.queryKey,\n    queryHash: query.queryHash,\n    ...(query.meta && { meta: query.meta }),\n  }\n\n  return obj\n}\n\n// Base Query Function that is used to create the query.\nexport function useBaseQuery<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryData,\n  TQueryKey extends QueryKey,\n>(\n  options: Accessor<\n    UseBaseQueryOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>\n  >,\n  Observer: typeof QueryObserver,\n  queryClient?: Accessor<QueryClient>,\n) {\n  type ResourceData = QueryObserverResult<TData, TError>\n\n  const client = createMemo(() => useQueryClient(queryClient?.()))\n  const isRestoring = useIsRestoring()\n  // There are times when we run a query on the server but the resource is never read\n  // This could lead to times when the queryObserver is unsubscribed before the resource has loaded\n  // Causing a time out error. To prevent this we will queue the unsubscribe if the cleanup is called\n  // before the resource has loaded\n  let unsubscribeQueued = false\n\n  const defaultedOptions = createMemo(() => {\n    const defaultOptions = client().defaultQueryOptions(options())\n    defaultOptions._optimisticResults = isRestoring()\n      ? 'isRestoring'\n      : 'optimistic'\n    defaultOptions.structuralSharing = false\n    if (isServer) {\n      defaultOptions.retry = false\n      defaultOptions.throwOnError = true\n      // Enable prefetch during render for SSR - required for createResource to work\n      // Without this, queries wait for effects which never run on the server\n      defaultOptions.experimental_prefetchInRender = true\n    }\n    return defaultOptions\n  })\n  const initialOptions = defaultedOptions()\n\n  const [observer, setObserver] = createSignal(\n    new Observer(client(), defaultedOptions()),\n  )\n\n  let observerResult = observer().getOptimisticResult(defaultedOptions())\n  const [state, setState] =\n    createStore<QueryObserverResult<TData, TError>>(observerResult)\n\n  const createServerSubscriber = (\n    resolve: (\n      data: ResourceData | PromiseLike<ResourceData | undefined> | undefined,\n    ) => void,\n    reject: (reason?: any) => void,\n  ) => {\n    return observer().subscribe((result) => {\n      notifyManager.batchCalls(() => {\n        const query = observer().getCurrentQuery()\n        const unwrappedResult = hydratableObserverResult(query, result)\n\n        if (result.data !== undefined && unwrappedResult.isError) {\n          reject(unwrappedResult.error)\n          unsubscribeIfQueued()\n        } else {\n          resolve(unwrappedResult)\n          unsubscribeIfQueued()\n        }\n      })()\n    })\n  }\n\n  const unsubscribeIfQueued = () => {\n    if (unsubscribeQueued) {\n      unsubscribe?.()\n      unsubscribeQueued = false\n    }\n  }\n\n  const createClientSubscriber = () => {\n    const obs = observer()\n    return obs.subscribe((result) => {\n      observerResult = result\n      queueMicrotask(() => {\n        if (unsubscribe) {\n          refetch()\n        }\n      })\n    })\n  }\n\n  function setStateWithReconciliation(res: typeof observerResult) {\n    const opts = observer().options\n    // @ts-expect-error - Reconcile option is not correctly typed internally\n    const reconcileOptions = opts.reconcile\n\n    setState((store) => {\n      return reconcileFn(\n        store,\n        res,\n        reconcileOptions === undefined ? false : reconcileOptions,\n        opts.queryHash,\n      )\n    })\n  }\n\n  function createDeepSignal<T>(): Signal<T> {\n    return [\n      () => state,\n      (v: any) => {\n        const unwrapped = unwrap(state)\n        if (typeof v === 'function') {\n          v = v(unwrapped)\n        }\n        // Hydration data exists on first load after SSR,\n        // and should be removed from the observer result\n        if (v?.hydrationData) {\n          const { hydrationData, ...rest } = v\n          v = rest\n        }\n        setStateWithReconciliation(v)\n      },\n    ] as Signal<T>\n  }\n\n  /**\n   * Unsubscribe is set lazily, so that we can subscribe after hydration when needed.\n   */\n  let unsubscribe: (() => void) | null = null\n\n  /*\n    Fixes #7275\n    In a few cases, the observer could unmount before the resource is loaded.\n    This leads to Suspense boundaries to be suspended indefinitely.\n    This resolver will be called when the observer is unmounting\n    but the resource is still in a loading state\n  */\n  let resolver: ((value: ResourceData) => void) | null = null\n  const [queryResource, { refetch }] = createResource<ResourceData | undefined>(\n    () => {\n      const obs = observer()\n      return new Promise((resolve, reject) => {\n        resolver = resolve\n        if (isServer) {\n          unsubscribe = createServerSubscriber(resolve, reject)\n        } else if (!unsubscribe && !isRestoring()) {\n          unsubscribe = createClientSubscriber()\n        }\n        obs.updateResult()\n\n        if (\n          observerResult.isError &&\n          !observerResult.isFetching &&\n          !isRestoring() &&\n          shouldThrowError(obs.options.throwOnError, [\n            observerResult.error,\n            obs.getCurrentQuery(),\n          ])\n        ) {\n          setStateWithReconciliation(observerResult)\n          return reject(observerResult.error)\n        }\n        if (!observerResult.isLoading) {\n          resolver = null\n          return resolve(\n            hydratableObserverResult(obs.getCurrentQuery(), observerResult),\n          )\n        }\n\n        setStateWithReconciliation(observerResult)\n      })\n    },\n    {\n      storage: createDeepSignal,\n\n      get deferStream() {\n        return options().deferStream\n      },\n\n      /**\n       * If this resource was populated on the server (either sync render, or streamed in over time), onHydrated\n       * will be called. This is the point at which we can hydrate the query cache state, and setup the query subscriber.\n       *\n       * Leveraging onHydrated allows us to plug into the async and streaming support that solidjs resources already support.\n       *\n       * Note that this is only invoked on the client, for queries that were originally run on the server.\n       */\n      onHydrated(_k, info) {\n        if (info.value && 'hydrationData' in info.value) {\n          hydrate(client(), {\n            // @ts-expect-error - hydrationData is not correctly typed internally\n            queries: [{ ...info.value.hydrationData }],\n          })\n        }\n\n        if (unsubscribe) return\n        /**\n         * Do not refetch query on mount if query was fetched on server,\n         * even if `staleTime` is not set.\n         */\n        const newOptions = { ...initialOptions }\n        if (\n          (initialOptions.staleTime || !initialOptions.initialData) &&\n          info.value\n        ) {\n          newOptions.refetchOnMount = false\n        }\n        // Setting the options as an immutable object to prevent\n        // wonky behavior with observer subscriptions\n        observer().setOptions(newOptions)\n        setStateWithReconciliation(observer().getOptimisticResult(newOptions))\n        unsubscribe = createClientSubscriber()\n      },\n    },\n  )\n\n  createComputed(\n    on(\n      client,\n      (c) => {\n        if (unsubscribe) {\n          unsubscribe()\n        }\n        const newObserver = new Observer(c, defaultedOptions())\n        unsubscribe = createClientSubscriber()\n        setObserver(newObserver)\n      },\n      {\n        defer: true,\n      },\n    ),\n  )\n\n  createComputed(\n    on(\n      isRestoring,\n      (restoring) => {\n        if (!restoring && !isServer) {\n          refetch()\n        }\n      },\n      { defer: true },\n    ),\n  )\n\n  onCleanup(() => {\n    if (isServer && queryResource.loading) {\n      unsubscribeQueued = true\n      return\n    }\n    if (unsubscribe) {\n      unsubscribe()\n      unsubscribe = null\n    }\n    if (resolver && !isServer) {\n      resolver(observerResult)\n      resolver = null\n    }\n  })\n\n  createComputed(\n    on(\n      [observer, defaultedOptions],\n      ([obs, opts]) => {\n        obs.setOptions(opts)\n        setStateWithReconciliation(obs.getOptimisticResult(opts))\n        refetch()\n      },\n      { defer: true },\n    ),\n  )\n\n  const handler = {\n    get(\n      target: QueryObserverResult<TData, TError>,\n      prop: keyof QueryObserverResult<TData, TError>,\n    ): any {\n      if (prop === 'data') {\n        if (state.data !== undefined) {\n          return queryResource.latest?.data\n        }\n        return queryResource()?.data\n      }\n      return Reflect.get(target, prop)\n    },\n  }\n\n  return new Proxy(state, handler)\n}\n"
  },
  {
    "path": "packages/solid-query/src/useInfiniteQuery.ts",
    "content": "import { InfiniteQueryObserver } from '@tanstack/query-core'\nimport { createMemo } from 'solid-js'\nimport { useBaseQuery } from './useBaseQuery'\nimport type {\n  DefaultError,\n  InfiniteData,\n  QueryKey,\n  QueryObserver,\n} from '@tanstack/query-core'\nimport type { QueryClient } from './QueryClient'\nimport type {\n  DefinedUseInfiniteQueryResult,\n  UseInfiniteQueryOptions,\n  UseInfiniteQueryResult,\n} from './types'\nimport type { Accessor } from 'solid-js'\nimport type {\n  DefinedInitialDataInfiniteOptions,\n  UndefinedInitialDataInfiniteOptions,\n} from './infiniteQueryOptions'\n\nexport function useInfiniteQuery<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: DefinedInitialDataInfiniteOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n  queryClient?: Accessor<QueryClient>,\n): DefinedUseInfiniteQueryResult<TData, TError>\nexport function useInfiniteQuery<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: UndefinedInitialDataInfiniteOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n  queryClient?: Accessor<QueryClient>,\n): UseInfiniteQueryResult<TData, TError>\n\nexport function useInfiniteQuery<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: UseInfiniteQueryOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n  queryClient?: Accessor<QueryClient>,\n): UseInfiniteQueryResult<TData, TError> {\n  return useBaseQuery(\n    createMemo(() => options()),\n    InfiniteQueryObserver as typeof QueryObserver,\n    queryClient,\n  ) as UseInfiniteQueryResult<TData, TError>\n}\n"
  },
  {
    "path": "packages/solid-query/src/useIsFetching.ts",
    "content": "import { createMemo, createSignal, onCleanup } from 'solid-js'\nimport { useQueryClient } from './QueryClientProvider'\nimport type { QueryFilters } from '@tanstack/query-core'\nimport type { QueryClient } from './QueryClient'\nimport type { Accessor } from 'solid-js'\n\nexport function useIsFetching(\n  filters?: Accessor<QueryFilters>,\n  queryClient?: Accessor<QueryClient>,\n): Accessor<number> {\n  const client = createMemo(() => useQueryClient(queryClient?.()))\n  const queryCache = createMemo(() => client().getQueryCache())\n\n  const [fetches, setFetches] = createSignal(client().isFetching(filters?.()))\n\n  const unsubscribe = queryCache().subscribe(() => {\n    setFetches(client().isFetching(filters?.()))\n  })\n\n  onCleanup(unsubscribe)\n\n  return fetches\n}\n"
  },
  {
    "path": "packages/solid-query/src/useIsMutating.ts",
    "content": "import { createMemo, createSignal, onCleanup } from 'solid-js'\nimport { useQueryClient } from './QueryClientProvider'\nimport type { MutationFilters } from '@tanstack/query-core'\nimport type { QueryClient } from './QueryClient'\nimport type { Accessor } from 'solid-js'\n\nexport function useIsMutating(\n  filters?: Accessor<MutationFilters>,\n  queryClient?: Accessor<QueryClient>,\n): Accessor<number> {\n  const client = createMemo(() => useQueryClient(queryClient?.()))\n  const mutationCache = createMemo(() => client().getMutationCache())\n\n  const [mutations, setMutations] = createSignal(\n    client().isMutating(filters?.()),\n  )\n\n  const unsubscribe = mutationCache().subscribe((_result) => {\n    setMutations(client().isMutating(filters?.()))\n  })\n\n  onCleanup(unsubscribe)\n\n  return mutations\n}\n"
  },
  {
    "path": "packages/solid-query/src/useMutation.ts",
    "content": "import { MutationObserver, noop, shouldThrowError } from '@tanstack/query-core'\nimport { createComputed, createMemo, on, onCleanup } from 'solid-js'\nimport { createStore } from 'solid-js/store'\nimport { useQueryClient } from './QueryClientProvider'\nimport type { DefaultError } from '@tanstack/query-core'\nimport type { QueryClient } from './QueryClient'\nimport type {\n  UseMutateFunction,\n  UseMutationOptions,\n  UseMutationResult,\n} from './types'\nimport type { Accessor } from 'solid-js'\n\n// HOOK\nexport function useMutation<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n>(\n  options: UseMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n  queryClient?: Accessor<QueryClient>,\n): UseMutationResult<TData, TError, TVariables, TOnMutateResult> {\n  const client = createMemo(() => useQueryClient(queryClient?.()))\n\n  const observer = new MutationObserver<\n    TData,\n    TError,\n    TVariables,\n    TOnMutateResult\n  >(client(), options())\n\n  const mutate: UseMutateFunction<\n    TData,\n    TError,\n    TVariables,\n    TOnMutateResult\n  > = (variables, mutateOptions) => {\n    observer.mutate(variables, mutateOptions).catch(noop)\n  }\n\n  const [state, setState] = createStore<\n    UseMutationResult<TData, TError, TVariables, TOnMutateResult>\n  >({\n    ...observer.getCurrentResult(),\n    mutate,\n    mutateAsync: observer.getCurrentResult().mutate,\n  })\n\n  createComputed(() => {\n    observer.setOptions(options())\n  })\n\n  createComputed(\n    on(\n      () => state.status,\n      () => {\n        if (\n          state.isError &&\n          shouldThrowError(observer.options.throwOnError, [state.error])\n        ) {\n          throw state.error\n        }\n      },\n    ),\n  )\n\n  const unsubscribe = observer.subscribe((result) => {\n    setState({\n      ...result,\n      mutate,\n      mutateAsync: result.mutate,\n    })\n  })\n\n  onCleanup(unsubscribe)\n\n  return state\n}\n"
  },
  {
    "path": "packages/solid-query/src/useMutationState.ts",
    "content": "import { createEffect, createMemo, createSignal, onCleanup } from 'solid-js'\nimport { replaceEqualDeep } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport type {\n  Mutation,\n  MutationCache,\n  MutationFilters,\n  MutationState,\n} from '@tanstack/query-core'\nimport type { Accessor } from 'solid-js'\nimport type { QueryClient } from './QueryClient'\n\ntype MutationStateOptions<TResult = MutationState> = {\n  filters?: MutationFilters\n  select?: (mutation: Mutation) => TResult\n}\n\nfunction getResult<TResult = MutationState>(\n  mutationCache: MutationCache,\n  options: MutationStateOptions<TResult>,\n): Array<TResult> {\n  return mutationCache\n    .findAll(options.filters)\n    .map(\n      (mutation): TResult =>\n        (options.select ? options.select(mutation) : mutation.state) as TResult,\n    )\n}\n\nexport function useMutationState<TResult = MutationState>(\n  options: Accessor<MutationStateOptions<TResult>> = () => ({}),\n  queryClient?: Accessor<QueryClient>,\n): Accessor<Array<TResult>> {\n  const client = createMemo(() => useQueryClient(queryClient?.()))\n  const mutationCache = createMemo(() => client().getMutationCache())\n\n  const [result, setResult] = createSignal(\n    getResult(mutationCache(), options()),\n  )\n\n  createEffect(() => {\n    const unsubscribe = mutationCache().subscribe(() => {\n      const nextResult = replaceEqualDeep(\n        result(),\n        getResult(mutationCache(), options()),\n      )\n      if (result() !== nextResult) {\n        setResult(nextResult)\n      }\n    })\n\n    onCleanup(unsubscribe)\n  })\n\n  return result\n}\n"
  },
  {
    "path": "packages/solid-query/src/useQueries.ts",
    "content": "import { QueriesObserver, noop } from '@tanstack/query-core'\nimport { createStore, unwrap } from 'solid-js/store'\nimport {\n  batch,\n  createComputed,\n  createMemo,\n  createRenderEffect,\n  createResource,\n  mergeProps,\n  on,\n  onCleanup,\n  onMount,\n} from 'solid-js'\nimport { useQueryClient } from './QueryClientProvider'\nimport { useIsRestoring } from './isRestoring'\nimport type { SolidQueryOptions, UseQueryResult } from './types'\nimport type { Accessor } from 'solid-js'\nimport type { QueryClient } from './QueryClient'\nimport type {\n  DefaultError,\n  OmitKeyof,\n  QueriesObserverOptions,\n  QueriesPlaceholderDataFunction,\n  QueryFunction,\n  QueryKey,\n  QueryObserverOptions,\n  QueryObserverResult,\n  ThrowOnError,\n} from '@tanstack/query-core'\n\n// This defines the `UseQueryOptions` that are accepted in `QueriesOptions` & `GetOptions`.\n// `placeholderData` function does not have a parameter\ntype UseQueryOptionsForUseQueries<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = OmitKeyof<\n  SolidQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  'placeholderData' | 'suspense'\n> & {\n  placeholderData?: TQueryFnData | QueriesPlaceholderDataFunction<TQueryFnData>\n  /**\n   * @deprecated The `suspense` option has been deprecated in v5 and will be removed in the next major version.\n   * The `data` property on useQueries is a plain object and not a SolidJS Resource.\n   * It will not suspend when the data is loading.\n   * Setting `suspense` to `true` will be a no-op.\n   */\n  suspense?: boolean\n}\n\n// Avoid TS depth-limit error in case of large array literal\ntype MAXIMUM_DEPTH = 20\n\n// Widen the type of the symbol to enable type inference even if skipToken is not immutable.\ntype SkipTokenForUseQueries = symbol\n\ntype GetOptions<T> =\n  // Part 1: responsible for applying explicit type parameter to function arguments, if object { queryFnData: TQueryFnData, error: TError, data: TData }\n  T extends {\n    queryFnData: infer TQueryFnData\n    error?: infer TError\n    data: infer TData\n  }\n    ? UseQueryOptionsForUseQueries<TQueryFnData, TError, TData>\n    : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n      ? UseQueryOptionsForUseQueries<TQueryFnData, TError>\n      : T extends { data: infer TData; error?: infer TError }\n        ? UseQueryOptionsForUseQueries<unknown, TError, TData>\n        : // Part 2: responsible for applying explicit type parameter to function arguments, if tuple [TQueryFnData, TError, TData]\n          T extends [infer TQueryFnData, infer TError, infer TData]\n          ? UseQueryOptionsForUseQueries<TQueryFnData, TError, TData>\n          : T extends [infer TQueryFnData, infer TError]\n            ? UseQueryOptionsForUseQueries<TQueryFnData, TError>\n            : T extends [infer TQueryFnData]\n              ? UseQueryOptionsForUseQueries<TQueryFnData>\n              : // Part 3: responsible for inferring and enforcing type if no explicit parameter was provided\n                T extends {\n                    queryFn?:\n                      | QueryFunction<infer TQueryFnData, infer TQueryKey>\n                      | SkipTokenForUseQueries\n                    select?: (data: any) => infer TData\n                    throwOnError?: ThrowOnError<any, infer TError, any, any>\n                  }\n                ? UseQueryOptionsForUseQueries<\n                    TQueryFnData,\n                    unknown extends TError ? DefaultError : TError,\n                    unknown extends TData ? TQueryFnData : TData,\n                    TQueryKey\n                  >\n                : // Fallback\n                  UseQueryOptionsForUseQueries\n\ntype GetResults<T> =\n  // Part 1: responsible for mapping explicit type parameter to function result, if object\n  T extends { queryFnData: any; error?: infer TError; data: infer TData }\n    ? UseQueryResult<TData, TError>\n    : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n      ? UseQueryResult<TQueryFnData, TError>\n      : T extends { data: infer TData; error?: infer TError }\n        ? UseQueryResult<TData, TError>\n        : // Part 2: responsible for mapping explicit type parameter to function result, if tuple\n          T extends [any, infer TError, infer TData]\n          ? UseQueryResult<TData, TError>\n          : T extends [infer TQueryFnData, infer TError]\n            ? UseQueryResult<TQueryFnData, TError>\n            : T extends [infer TQueryFnData]\n              ? UseQueryResult<TQueryFnData>\n              : // Part 3: responsible for mapping inferred type to results, if no explicit parameter was provided\n                T extends {\n                    queryFn?:\n                      | QueryFunction<infer TQueryFnData, any>\n                      | SkipTokenForUseQueries\n                    select?: (data: any) => infer TData\n                    throwOnError?: ThrowOnError<any, infer TError, any, any>\n                  }\n                ? UseQueryResult<\n                    unknown extends TData ? TQueryFnData : TData,\n                    unknown extends TError ? DefaultError : TError\n                  >\n                : // Fallback\n                  UseQueryResult\n\n/**\n * QueriesOptions reducer recursively unwraps function arguments to infer/enforce type param\n */\ntype QueriesOptions<\n  T extends Array<any>,\n  TResult extends Array<any> = [],\n  TDepth extends ReadonlyArray<number> = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n  ? Array<UseQueryOptionsForUseQueries>\n  : T extends []\n    ? []\n    : T extends [infer Head]\n      ? [...TResult, GetOptions<Head>]\n      : T extends [infer Head, ...infer Tail]\n        ? QueriesOptions<\n            [...Tail],\n            [...TResult, GetOptions<Head>],\n            [...TDepth, 1]\n          >\n        : ReadonlyArray<unknown> extends T\n          ? T\n          : // If T is *some* array but we couldn't assign unknown[] to it, then it must hold some known/homogenous type!\n            // use this to infer the param types in the case of Array.map() argument\n            T extends Array<\n                UseQueryOptionsForUseQueries<\n                  infer TQueryFnData,\n                  infer TError,\n                  infer TData,\n                  infer TQueryKey\n                >\n              >\n            ? Array<\n                UseQueryOptionsForUseQueries<\n                  TQueryFnData,\n                  TError,\n                  TData,\n                  TQueryKey\n                >\n              >\n            : // Fallback\n              Array<UseQueryOptionsForUseQueries>\n\n/**\n * QueriesResults reducer recursively maps type param to results\n */\ntype QueriesResults<\n  T extends Array<any>,\n  TResult extends Array<any> = [],\n  TDepth extends ReadonlyArray<number> = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n  ? Array<UseQueryResult>\n  : T extends []\n    ? []\n    : T extends [infer Head]\n      ? [...TResult, GetResults<Head>]\n      : T extends [infer Head, ...infer Tail]\n        ? QueriesResults<\n            [...Tail],\n            [...TResult, GetResults<Head>],\n            [...TDepth, 1]\n          >\n        : { [K in keyof T]: GetResults<T[K]> }\n\nexport function useQueries<\n  T extends Array<any>,\n  TCombinedResult extends QueriesResults<T> = QueriesResults<T>,\n>(\n  queriesOptions: Accessor<{\n    queries:\n      | readonly [...QueriesOptions<T>]\n      | readonly [...{ [K in keyof T]: GetOptions<T[K]> }]\n    combine?: (result: QueriesResults<T>) => TCombinedResult\n  }>,\n  queryClient?: Accessor<QueryClient>,\n): TCombinedResult {\n  const client = createMemo(() => useQueryClient(queryClient?.()))\n  const isRestoring = useIsRestoring()\n\n  const defaultedQueries = createMemo(() =>\n    queriesOptions().queries.map((options) =>\n      mergeProps(\n        client().defaultQueryOptions(options as QueryObserverOptions),\n        {\n          get _optimisticResults() {\n            return isRestoring() ? 'isRestoring' : 'optimistic'\n          },\n        },\n      ),\n    ),\n  )\n\n  const observer = new QueriesObserver(\n    client(),\n    defaultedQueries(),\n    queriesOptions().combine\n      ? ({\n          combine: queriesOptions().combine,\n        } as QueriesObserverOptions<TCombinedResult>)\n      : undefined,\n  )\n\n  const [state, setState] = createStore<TCombinedResult>(\n    observer.getOptimisticResult(\n      defaultedQueries(),\n      (queriesOptions() as QueriesObserverOptions<TCombinedResult>).combine,\n    )[1](),\n  )\n\n  createRenderEffect(\n    on(\n      () => queriesOptions().queries.length,\n      () =>\n        setState(\n          observer.getOptimisticResult(\n            defaultedQueries(),\n            (queriesOptions() as QueriesObserverOptions<TCombinedResult>)\n              .combine,\n          )[1](),\n        ),\n    ),\n  )\n\n  const dataResources = createMemo(\n    on(\n      () => state.length,\n      () =>\n        state.map((queryRes) => {\n          const dataPromise = () =>\n            new Promise((resolve) => {\n              if (queryRes.isFetching && queryRes.isLoading) return\n              resolve(unwrap(queryRes.data))\n            })\n          return createResource(dataPromise)\n        }),\n    ),\n  )\n\n  batch(() => {\n    const dataResources_ = dataResources()\n    for (let index = 0; index < dataResources_.length; index++) {\n      const dataResource = dataResources_[index]!\n      dataResource[1].mutate(() => unwrap(state[index]!.data))\n      dataResource[1].refetch()\n    }\n  })\n\n  let taskQueue: Array<() => void> = []\n  const subscribeToObserver = () =>\n    observer.subscribe((result) => {\n      taskQueue.push(() => {\n        batch(() => {\n          const dataResources_ = dataResources()\n          for (let index = 0; index < dataResources_.length; index++) {\n            const dataResource = dataResources_[index]!\n            const unwrappedResult = { ...unwrap(result[index]) }\n            // @ts-expect-error typescript pedantry regarding the possible range of index\n            setState(index, unwrap(unwrappedResult))\n            dataResource[1].mutate(() => unwrap(state[index]!.data))\n            dataResource[1].refetch()\n          }\n        })\n      })\n\n      queueMicrotask(() => {\n        const taskToRun = taskQueue.pop()\n        if (taskToRun) taskToRun()\n        taskQueue = []\n      })\n    })\n\n  let unsubscribe: () => void = noop\n  createComputed<() => void>((cleanup) => {\n    cleanup?.()\n    unsubscribe = isRestoring() ? noop : subscribeToObserver()\n    // cleanup needs to be scheduled after synchronous effects take place\n    return () => queueMicrotask(unsubscribe)\n  })\n  onCleanup(unsubscribe)\n\n  onMount(() => {\n    observer.setQueries(\n      defaultedQueries(),\n      queriesOptions().combine\n        ? ({\n            combine: queriesOptions().combine,\n          } as QueriesObserverOptions<TCombinedResult>)\n        : undefined,\n    )\n  })\n\n  createComputed(() => {\n    observer.setQueries(\n      defaultedQueries(),\n      queriesOptions().combine\n        ? ({\n            combine: queriesOptions().combine,\n          } as QueriesObserverOptions<TCombinedResult>)\n        : undefined,\n    )\n  })\n\n  const handler = (index: number) => ({\n    get(target: QueryObserverResult, prop: keyof QueryObserverResult): any {\n      if (prop === 'data') {\n        return dataResources()[index]![0]()\n      }\n      return Reflect.get(target, prop)\n    },\n  })\n\n  const getProxies = () =>\n    state.map((s, index) => {\n      return new Proxy(s, handler(index))\n    })\n\n  const [proxyState, setProxyState] = createStore(getProxies())\n  createRenderEffect(() => setProxyState(getProxies()))\n\n  return proxyState as TCombinedResult\n}\n"
  },
  {
    "path": "packages/solid-query/src/useQuery.ts",
    "content": "import { QueryObserver } from '@tanstack/query-core'\nimport { createMemo } from 'solid-js'\nimport { useBaseQuery } from './useBaseQuery'\nimport type { DefaultError, QueryKey } from '@tanstack/query-core'\nimport type { QueryClient } from './QueryClient'\nimport type { Accessor } from 'solid-js'\nimport type {\n  DefinedUseQueryResult,\n  UseQueryOptions,\n  UseQueryResult,\n} from './types'\nimport type {\n  DefinedInitialDataOptions,\n  UndefinedInitialDataOptions,\n} from './queryOptions'\n\nexport function useQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,\n  queryClient?: () => QueryClient,\n): UseQueryResult<TData, TError>\n\nexport function useQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,\n  queryClient?: () => QueryClient,\n): DefinedUseQueryResult<TData, TError>\nexport function useQuery<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  queryClient?: Accessor<QueryClient>,\n) {\n  return useBaseQuery(\n    createMemo(() => options()),\n    QueryObserver,\n    queryClient,\n  )\n}\n"
  },
  {
    "path": "packages/solid-query/test-setup.ts",
    "content": "import '@testing-library/jest-dom/vitest'\nimport { cleanup } from '@solidjs/testing-library'\nimport { afterEach } from 'vitest'\n\n// https://github.com/solidjs/solid-testing-library\nafterEach(() => cleanup())\n"
  },
  {
    "path": "packages/solid-query/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\",\n    \"jsx\": \"preserve\",\n    \"jsxImportSource\": \"solid-js\"\n  },\n  \"include\": [\"src\", \"test-setup.ts\", \"*.config.*\", \"package.json\"],\n  \"references\": [{ \"path\": \"../query-core\" }]\n}\n"
  },
  {
    "path": "packages/solid-query/tsconfig.legacy.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"jsx\": \"preserve\",\n    \"jsxImportSource\": \"solid-js\",\n    \"outDir\": \"./dist-ts/legacy\"\n  },\n  \"include\": [\"src\"],\n  \"exclude\": [\"src/__tests__\"],\n  \"references\": [{ \"path\": \"../query-core\" }]\n}\n"
  },
  {
    "path": "packages/solid-query/tsconfig.prod.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"incremental\": false,\n    \"composite\": false,\n    \"rootDir\": \"../../\"\n  }\n}\n"
  },
  {
    "path": "packages/solid-query/tsup.config.ts",
    "content": "import { defineConfig } from 'tsup'\nimport { generateTsupOptions, parsePresetOptions } from 'tsup-preset-solid'\n\nconst preset_options = {\n  entries: {\n    entry: 'src/index.ts',\n    dev_entry: true,\n  },\n  cjs: true,\n  drop_console: true,\n}\n\nexport default defineConfig(() => {\n  const parsed_data = parsePresetOptions(preset_options)\n  const tsup_options = generateTsupOptions(parsed_data)\n\n  tsup_options.forEach((tsup_option) => {\n    tsup_option.outDir = 'build'\n    tsup_option.experimentalDts = true\n    delete tsup_option.dts\n  })\n\n  return tsup_options\n})\n"
  },
  {
    "path": "packages/solid-query/vite.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\nimport solid from 'vite-plugin-solid'\n\nimport packageJson from './package.json'\n\nexport default defineConfig({\n  plugins: [solid()],\n  // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660\n  resolve: {\n    conditions: ['@tanstack/custom-condition'],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        conditions: ['@tanstack/custom-condition'],\n      },\n    },\n  },\n  test: {\n    name: packageJson.name,\n    dir: './src',\n    watch: false,\n    environment: 'jsdom',\n    setupFiles: ['test-setup.ts'],\n    coverage: {\n      enabled: true,\n      provider: 'istanbul',\n      include: ['src/**/*'],\n      exclude: ['src/__tests__/**'],\n    },\n    typecheck: { enabled: true },\n    restoreMocks: true,\n  },\n})\n"
  },
  {
    "path": "packages/solid-query-devtools/CHANGELOG.md",
    "content": "# @tanstack/solid-query-devtools\n\n## 5.91.3\n\n### Patch Changes\n\n- Updated dependencies [[`83366c4`](https://github.com/TanStack/query/commit/83366c46a6825b5c591399c705d8128743c527dd)]:\n  - @tanstack/query-devtools@5.93.0\n\n## 5.91.2\n\n### Patch Changes\n\n- Updated dependencies [[`f9fc56a`](https://github.com/TanStack/query/commit/f9fc56a9b8724bcfae46f8f6cb229123478eb4db), [`0b29b6f`](https://github.com/TanStack/query/commit/0b29b6f877d4b3a6d05b1c85fb9cb1e6ea736291)]:\n  - @tanstack/query-devtools@5.92.0\n  - @tanstack/solid-query@5.90.17\n\n## 5.91.1\n\n### Patch Changes\n\n- Updated dependencies [[`b261b6f`](https://github.com/TanStack/query/commit/b261b6f29eee2a9bdbe1bc20035fe9b83b15376b)]:\n  - @tanstack/query-devtools@5.91.1\n\n## 5.91.0\n\n### Minor Changes\n\n- feat(devtools): allow passing a theme via prop ([#9887](https://github.com/TanStack/query/pull/9887))\n\n### Patch Changes\n\n- Updated dependencies [[`0e9d5b5`](https://github.com/TanStack/query/commit/0e9d5b565276f0de2a1a14ffbb079b5988581c27)]:\n  - @tanstack/query-devtools@5.91.0\n\n## 5.90.4\n\n### Patch Changes\n\n- Fixed client prop not working on SolidQueryDevtools and SolidQueryDevtoolsPanel ([#9763](https://github.com/TanStack/query/pull/9763))\n"
  },
  {
    "path": "packages/solid-query-devtools/eslint.config.js",
    "content": "// @ts-check\n\nimport rootConfig from './root.eslint.config.js'\n\nexport default [...rootConfig]\n"
  },
  {
    "path": "packages/solid-query-devtools/package.json",
    "content": "{\n  \"name\": \"@tanstack/solid-query-devtools\",\n  \"version\": \"5.91.3\",\n  \"description\": \"Developer tools to interact with and visualize the TanStack/solid-query Query cache\",\n  \"author\": \"tannerlinsley\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/solid-query-devtools\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"scripts\": {\n    \"clean\": \"premove ./build ./coverage ./dist-ts\",\n    \"compile\": \"tsc --build\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:types\": \"npm run compile && npm-run-all --serial test:types:*\",\n    \"test:types:ts54\": \"node ../../node_modules/typescript54/lib/tsc.js --build\",\n    \"test:types:ts55\": \"node ../../node_modules/typescript55/lib/tsc.js --build\",\n    \"test:types:ts56\": \"node ../../node_modules/typescript56/lib/tsc.js --build\",\n    \"test:types:ts57\": \"node ../../node_modules/typescript57/lib/tsc.js --build\",\n    \"test:types:ts58\": \"node ../../node_modules/typescript58/lib/tsc.js --build\",\n    \"test:types:ts59\": \"node ../../node_modules/typescript59/lib/tsc.js --build\",\n    \"test:types:ts60\": \"node ../../node_modules/typescript60/lib/tsc.js --build\",\n    \"test:build\": \"publint --strict && attw --pack\",\n    \"test:lib\": \"vitest --retry=3\",\n    \"test:lib:dev\": \"pnpm run test:lib --watch\",\n    \"build\": \"tsup --tsconfig tsconfig.prod.json\",\n    \"build:dev\": \"tsup --watch\"\n  },\n  \"type\": \"module\",\n  \"main\": \"./build/index.cjs\",\n  \"module\": \"./build/index.js\",\n  \"types\": \"./build/index.d.ts\",\n  \"browser\": {},\n  \"exports\": {\n    \"@tanstack/custom-condition\": \"./src/index.tsx\",\n    \"solid\": {\n      \"development\": \"./build/dev.jsx\",\n      \"import\": \"./build/index.jsx\"\n    },\n    \"development\": {\n      \"import\": {\n        \"types\": \"./build/index.d.ts\",\n        \"default\": \"./build/dev.js\"\n      },\n      \"require\": \"./build/dev.cjs\"\n    },\n    \"import\": {\n      \"types\": \"./build/index.d.ts\",\n      \"default\": \"./build/index.js\"\n    },\n    \"require\": \"./build/index.cjs\"\n  },\n  \"files\": [\n    \"build\",\n    \"src\",\n    \"!src/__tests__\"\n  ],\n  \"dependencies\": {\n    \"@tanstack/query-devtools\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"@solidjs/testing-library\": \"^0.8.10\",\n    \"@tanstack/solid-query\": \"workspace:*\",\n    \"npm-run-all2\": \"^5.0.0\",\n    \"solid-js\": \"^1.9.7\",\n    \"tsup-preset-solid\": \"^2.2.0\",\n    \"vite-plugin-solid\": \"^2.11.6\"\n  },\n  \"peerDependencies\": {\n    \"@tanstack/solid-query\": \"workspace:^\",\n    \"solid-js\": \"^1.6.0\"\n  }\n}\n"
  },
  {
    "path": "packages/solid-query-devtools/src/__tests__/devtools.test.tsx",
    "content": "import { describe, expect, it } from 'vitest'\nimport { render } from '@solidjs/testing-library'\nimport { QueryClient, QueryClientProvider } from '@tanstack/solid-query'\nimport SolidQueryDevtools from '../devtools'\n\ndescribe('SolidQueryDevtools', () => {\n  it('should throw an error if no query client has been set', () => {\n    expect(() => render(() => <SolidQueryDevtools />)).toThrow(\n      'No QueryClient set, use QueryClientProvider to set one',\n    )\n  })\n\n  it('should not throw an error if query client is provided via context', () => {\n    const queryClient = new QueryClient()\n\n    expect(() =>\n      render(() => (\n        <QueryClientProvider client={queryClient}>\n          <SolidQueryDevtools />\n        </QueryClientProvider>\n      )),\n    ).not.toThrow()\n  })\n\n  it('should not throw an error if query client is provided via props', () => {\n    const queryClient = new QueryClient()\n\n    expect(() =>\n      render(() => <SolidQueryDevtools client={queryClient} />),\n    ).not.toThrow()\n  })\n})\n"
  },
  {
    "path": "packages/solid-query-devtools/src/__tests__/devtoolsPanel.test.tsx",
    "content": "import { describe, expect, it } from 'vitest'\nimport { render } from '@solidjs/testing-library'\nimport { QueryClient, QueryClientProvider } from '@tanstack/solid-query'\nimport SolidQueryDevtoolsPanel from '../devtoolsPanel'\n\ndescribe('SolidQueryDevtoolsPanel', () => {\n  it('should throw an error if no query client has been set', () => {\n    expect(() => render(() => <SolidQueryDevtoolsPanel />)).toThrow(\n      'No QueryClient set, use QueryClientProvider to set one',\n    )\n  })\n\n  it('should not throw an error if query client is provided via context', () => {\n    const queryClient = new QueryClient()\n\n    expect(() =>\n      render(() => (\n        <QueryClientProvider client={queryClient}>\n          <SolidQueryDevtoolsPanel />\n        </QueryClientProvider>\n      )),\n    ).not.toThrow()\n  })\n\n  it('should not throw an error if query client is provided via props', () => {\n    const queryClient = new QueryClient()\n\n    expect(() =>\n      render(() => <SolidQueryDevtoolsPanel client={queryClient} />),\n    ).not.toThrow()\n  })\n})\n"
  },
  {
    "path": "packages/solid-query-devtools/src/clientOnly.tsx",
    "content": "import {\n  createMemo,\n  createSignal,\n  onMount,\n  sharedConfig,\n  splitProps,\n  untrack,\n} from 'solid-js'\nimport { isServer } from 'solid-js/web'\nimport type { Component, ComponentProps, JSX } from 'solid-js'\n\n/*\n  This function has been taken from solid-start's codebase\n  This allows the devtools to be loaded only on the client and bypasses any server side rendering\n  https://github.com/solidjs/solid-start/blob/2967fc2db3f0df826f061020231dbdafdfa0746b/packages/start/islands/clientOnly.tsx\n*/\nexport default function clientOnly<T extends Component<any>>(\n  fn: () => Promise<{\n    default: T\n  }>,\n) {\n  if (isServer)\n    return (props: ComponentProps<T> & { fallback?: JSX.Element }) =>\n      props.fallback\n\n  const [comp, setComp] = createSignal<T>()\n  fn().then((m) => setComp(() => m.default))\n  return (props: ComponentProps<T>) => {\n    let Comp: T | undefined\n    let m: boolean\n    const [, rest] = splitProps(props, ['fallback'])\n    if ((Comp = comp()) && !sharedConfig.context) return Comp(rest)\n    const [mounted, setMounted] = createSignal(!sharedConfig.context)\n    onMount(() => setMounted(true))\n    return createMemo(\n      () => (\n        (Comp = comp()),\n        (m = mounted()),\n        untrack(() => (Comp && m ? Comp(rest) : props.fallback))\n      ),\n    )\n  }\n}\n"
  },
  {
    "path": "packages/solid-query-devtools/src/devtools.tsx",
    "content": "import { createEffect, createMemo, onCleanup, onMount } from 'solid-js'\nimport { onlineManager, useQueryClient } from '@tanstack/solid-query'\nimport { TanstackQueryDevtools } from '@tanstack/query-devtools'\nimport type {\n  DevtoolsButtonPosition,\n  DevtoolsErrorType,\n  DevtoolsPosition,\n  Theme,\n} from '@tanstack/query-devtools'\nimport type { QueryClient } from '@tanstack/solid-query'\n\ninterface DevtoolsOptions {\n  /**\n   * Set this true if you want the dev tools to default to being open\n   */\n  initialIsOpen?: boolean\n  /**\n   * The position of the React Query logo to open and close the devtools panel.\n   * 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'\n   * Defaults to 'bottom-right'.\n   */\n  buttonPosition?: DevtoolsButtonPosition\n  /**\n   * The position of the React Query devtools panel.\n   * 'top' | 'bottom' | 'left' | 'right'\n   * Defaults to 'bottom'.\n   */\n  position?: DevtoolsPosition\n  /**\n   * Custom instance of QueryClient\n   */\n  client?: QueryClient\n  /**\n   * Use this so you can define custom errors that can be shown in the devtools.\n   */\n  errorTypes?: Array<DevtoolsErrorType>\n  /**\n   * 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.\n   */\n  styleNonce?: string\n  /**\n   * Use this so you can attach the devtool's styles to specific element in the DOM.\n   */\n  shadowDOMTarget?: ShadowRoot\n  /**\n   * Set this to true to hide disabled queries from the devtools panel.\n   */\n  hideDisabledQueries?: boolean\n  /**\n   * Set this to 'light', 'dark', or 'system' to change the theme of the devtools panel.\n   * Defaults to 'system'.\n   */\n  theme?: Theme\n}\n\nexport default function SolidQueryDevtools(props: DevtoolsOptions) {\n  const queryClient = useQueryClient(props.client)\n  const client = createMemo(() => queryClient)\n  let ref!: HTMLDivElement\n  const devtools = new TanstackQueryDevtools({\n    client: client(),\n    queryFlavor: 'Solid Query',\n    version: '5',\n    onlineManager,\n    buttonPosition: props.buttonPosition,\n    position: props.position,\n    initialIsOpen: props.initialIsOpen,\n    errorTypes: props.errorTypes,\n    styleNonce: props.styleNonce,\n    shadowDOMTarget: props.shadowDOMTarget,\n    hideDisabledQueries: props.hideDisabledQueries,\n    theme: props.theme,\n  })\n\n  createEffect(() => {\n    devtools.setClient(client())\n  })\n\n  createEffect(() => {\n    const buttonPos = props.buttonPosition\n    if (buttonPos) {\n      devtools.setButtonPosition(buttonPos)\n    }\n  })\n\n  createEffect(() => {\n    const pos = props.position\n    if (pos) {\n      devtools.setPosition(pos)\n    }\n  })\n\n  createEffect(() => {\n    devtools.setInitialIsOpen(props.initialIsOpen || false)\n  })\n\n  createEffect(() => {\n    devtools.setErrorTypes(props.errorTypes || [])\n  })\n\n  createEffect(() => {\n    devtools.setTheme(props.theme || 'system')\n  })\n\n  onMount(() => {\n    devtools.mount(ref)\n    onCleanup(() => devtools.unmount())\n  })\n\n  return <div class=\"tsqd-parent-container\" ref={ref}></div>\n}\n"
  },
  {
    "path": "packages/solid-query-devtools/src/devtoolsPanel.tsx",
    "content": "import { createEffect, createMemo, onCleanup, onMount } from 'solid-js'\nimport { onlineManager, useQueryClient } from '@tanstack/solid-query'\nimport { TanstackQueryDevtoolsPanel } from '@tanstack/query-devtools'\nimport type { DevtoolsErrorType, Theme } from '@tanstack/query-devtools'\nimport type { QueryClient } from '@tanstack/solid-query'\nimport type { JSX } from 'solid-js'\n\nexport interface DevtoolsPanelOptions {\n  /**\n   * Custom instance of QueryClient\n   */\n  client?: QueryClient\n  /**\n   * Use this so you can define custom errors that can be shown in the devtools.\n   */\n  errorTypes?: Array<DevtoolsErrorType>\n  /**\n   * 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.\n   */\n  styleNonce?: string\n  /**\n   * Use this so you can attach the devtool's styles to specific element in the DOM.\n   */\n  shadowDOMTarget?: ShadowRoot\n\n  /**\n   * Custom styles for the devtools panel\n   * @default { height: '500px' }\n   * @example { height: '100%' }\n   * @example { height: '100%', width: '100%' }\n   */\n  style?: JSX.CSSProperties\n\n  /**\n   * Callback function that is called when the devtools panel is closed\n   */\n  onClose?: () => unknown\n  /**\n   * Set this to true to hide disabled queries from the devtools panel.\n   */\n  hideDisabledQueries?: boolean\n  /**\n   * Set this to 'light', 'dark', or 'system' to change the theme of the devtools panel.\n   * Defaults to 'system'.\n   */\n  theme?: Theme\n}\n\nexport default function SolidQueryDevtoolsPanel(props: DevtoolsPanelOptions) {\n  const queryClient = useQueryClient(props.client)\n  const client = createMemo(() => queryClient)\n  let ref!: HTMLDivElement\n  const { errorTypes, styleNonce, shadowDOMTarget, hideDisabledQueries } = props\n  const devtools = new TanstackQueryDevtoolsPanel({\n    client: client(),\n    queryFlavor: 'Solid Query',\n    version: '5',\n    onlineManager,\n    buttonPosition: 'bottom-left',\n    position: 'bottom',\n    initialIsOpen: true,\n    errorTypes,\n    styleNonce,\n    shadowDOMTarget,\n    onClose: props.onClose,\n    hideDisabledQueries,\n    theme: props.theme,\n  })\n  createEffect(() => {\n    devtools.setClient(client())\n  })\n  createEffect(() => {\n    devtools.setOnClose(props.onClose ?? (() => {}))\n  })\n\n  createEffect(() => {\n    devtools.setErrorTypes(props.errorTypes || [])\n  })\n\n  createEffect(() => {\n    devtools.setTheme(props.theme || 'system')\n  })\n\n  onMount(() => {\n    devtools.mount(ref)\n    onCleanup(() => devtools.unmount())\n  })\n\n  return (\n    <div\n      style={{ height: '500px', ...props.style }}\n      class=\"tsqd-parent-container\"\n      ref={ref}\n    />\n  )\n}\n"
  },
  {
    "path": "packages/solid-query-devtools/src/index.tsx",
    "content": "import { isDev } from 'solid-js/web'\nimport clientOnly from './clientOnly'\nimport type SolidQueryDevtoolsComp from './devtools'\nimport type SolidQueryDevtoolsCompPanel from './devtoolsPanel'\n\nexport const SolidQueryDevtools: typeof SolidQueryDevtoolsComp = isDev\n  ? clientOnly(() => import('./devtools'))\n  : function () {\n      return null\n    }\n\nexport const SolidQueryDevtoolsPanel: typeof SolidQueryDevtoolsCompPanel = isDev\n  ? clientOnly(() => import('./devtoolsPanel'))\n  : function () {\n      return null\n    }\n\nexport type { DevtoolsPanelOptions } from './devtoolsPanel'\n"
  },
  {
    "path": "packages/solid-query-devtools/test-setup.ts",
    "content": "import '@testing-library/jest-dom/vitest'\nimport { cleanup } from '@solidjs/testing-library'\nimport { afterEach } from 'vitest'\n\n// https://github.com/solidjs/solid-testing-library\nafterEach(() => cleanup())\n"
  },
  {
    "path": "packages/solid-query-devtools/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\",\n    \"jsx\": \"preserve\",\n    \"jsxImportSource\": \"solid-js\"\n  },\n  \"include\": [\"src\", \"*.config.*\", \"package.json\"],\n  \"references\": [{ \"path\": \"../query-devtools\" }, { \"path\": \"../solid-query\" }]\n}\n"
  },
  {
    "path": "packages/solid-query-devtools/tsconfig.prod.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"incremental\": false,\n    \"composite\": false,\n    \"rootDir\": \"../../\"\n  }\n}\n"
  },
  {
    "path": "packages/solid-query-devtools/tsup.config.ts",
    "content": "import { defineConfig } from 'tsup'\nimport { generateTsupOptions, parsePresetOptions } from 'tsup-preset-solid'\n\nconst preset_options = {\n  entries: {\n    entry: 'src/index.tsx',\n    dev_entry: true,\n  },\n  cjs: true,\n  drop_console: true,\n}\n\nexport default defineConfig(() => {\n  const parsed_data = parsePresetOptions(preset_options)\n  const tsup_options = generateTsupOptions(parsed_data)\n\n  tsup_options.forEach((tsup_option) => {\n    tsup_option.outDir = 'build'\n    tsup_option.experimentalDts = true\n    delete tsup_option.dts\n  })\n\n  return tsup_options\n})\n"
  },
  {
    "path": "packages/solid-query-devtools/vite.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\nimport solid from 'vite-plugin-solid'\n\nimport packageJson from './package.json'\n\nexport default defineConfig({\n  plugins: [solid()],\n  // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660\n  resolve: {\n    conditions: ['@tanstack/custom-condition'],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        conditions: ['@tanstack/custom-condition'],\n      },\n    },\n  },\n  test: {\n    name: packageJson.name,\n    dir: './src',\n    watch: false,\n    environment: 'jsdom',\n    setupFiles: ['test-setup.ts'],\n    coverage: {\n      enabled: true,\n      provider: 'istanbul',\n      include: ['src/**/*'],\n      exclude: ['src/__tests__/**'],\n    },\n    typecheck: { enabled: true },\n    restoreMocks: true,\n  },\n})\n"
  },
  {
    "path": "packages/solid-query-persist-client/CHANGELOG.md",
    "content": "# @tanstack/solid-query-persist-client\n\n## 5.90.28\n\n### Patch Changes\n\n- fix(streamedQuery): maintain error state on reset refetch with initialData defined ([#10287](https://github.com/TanStack/query/pull/10287))\n\n- Updated dependencies [[`248975e`](https://github.com/TanStack/query/commit/248975e896f585f6eaa505c796e73fcf7bfd1eec)]:\n  - @tanstack/query-persist-client-core@5.92.4\n  - @tanstack/solid-query@5.91.3\n\n## 5.90.27\n\n### Patch Changes\n\n- Updated dependencies [[`a89aab9`](https://github.com/TanStack/query/commit/a89aab975581c25c113a26c8af486b4cafad272a)]:\n  - @tanstack/solid-query@5.91.2\n  - @tanstack/query-persist-client-core@5.92.3\n\n## 5.90.26\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.92.2\n  - @tanstack/solid-query@5.91.1\n\n## 5.90.25\n\n### Patch Changes\n\n- Updated dependencies [[`e505568`](https://github.com/TanStack/query/commit/e505568f4d51c8281d38e9687091094b7d32a405)]:\n  - @tanstack/query-persist-client-core@5.92.1\n\n## 5.90.24\n\n### Patch Changes\n\n- Updated dependencies [[`978fc52`](https://github.com/TanStack/query/commit/978fc52728a8b9eb33f0a82f4ddf42a95815bd7f)]:\n  - @tanstack/query-persist-client-core@5.92.0\n\n## 5.90.23\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.19\n  - @tanstack/solid-query@5.90.23\n\n## 5.90.22\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.18\n  - @tanstack/solid-query@5.90.22\n\n## 5.90.21\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.17\n  - @tanstack/solid-query@5.90.21\n\n## 5.90.20\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.16\n  - @tanstack/solid-query@5.90.20\n\n## 5.90.19\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.15\n  - @tanstack/solid-query@5.90.19\n\n## 5.90.18\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.14\n  - @tanstack/solid-query@5.90.18\n\n## 5.90.17\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.13\n  - @tanstack/solid-query@5.90.17\n\n## 5.90.16\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.12\n  - @tanstack/solid-query@5.90.16\n\n## 5.90.15\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.11\n  - @tanstack/solid-query@5.90.15\n\n## 5.90.14\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.10\n  - @tanstack/solid-query@5.90.14\n\n## 5.90.13\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.9\n  - @tanstack/solid-query@5.90.13\n\n## 5.90.12\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.8\n  - @tanstack/solid-query@5.90.12\n\n## 5.90.11\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.7\n  - @tanstack/solid-query@5.90.11\n\n## 5.90.10\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.6\n  - @tanstack/solid-query@5.90.10\n\n## 5.90.9\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.5\n  - @tanstack/solid-query@5.90.8\n\n## 5.90.8\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.4\n  - @tanstack/solid-query@5.90.6\n\n## 5.90.7\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.3\n  - @tanstack/solid-query@5.90.5\n\n## 5.90.6\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.2\n  - @tanstack/solid-query@5.90.4\n\n## 5.90.5\n\n### Patch Changes\n\n- Updated dependencies [[`846d53d`](https://github.com/TanStack/query/commit/846d53d98992d50606c40634efa43dea9965b787)]:\n  - @tanstack/query-persist-client-core@5.91.1\n\n## 5.90.4\n\n### Patch Changes\n\n- Updated dependencies [[`5cd86c6`](https://github.com/TanStack/query/commit/5cd86c6ef1720b87b13e1ab70ee823616f1f029a)]:\n  - @tanstack/query-persist-client-core@5.91.0\n"
  },
  {
    "path": "packages/solid-query-persist-client/eslint.config.js",
    "content": "// @ts-check\n\nimport rootConfig from './root.eslint.config.js'\n\nexport default [...rootConfig]\n"
  },
  {
    "path": "packages/solid-query-persist-client/package.json",
    "content": "{\n  \"name\": \"@tanstack/solid-query-persist-client\",\n  \"version\": \"5.90.28\",\n  \"description\": \"Solid.js bindings to work with persisters in TanStack/solid-query\",\n  \"author\": \"tannerlinsley\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/solid-query-persist-client\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"scripts\": {\n    \"clean\": \"premove ./build ./coverage ./dist-ts\",\n    \"compile\": \"tsc --build\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:types\": \"npm run compile && npm-run-all --serial test:types:*\",\n    \"test:types:ts54\": \"node ../../node_modules/typescript54/lib/tsc.js --build\",\n    \"test:types:ts55\": \"node ../../node_modules/typescript55/lib/tsc.js --build\",\n    \"test:types:ts56\": \"node ../../node_modules/typescript56/lib/tsc.js --build\",\n    \"test:types:ts57\": \"node ../../node_modules/typescript57/lib/tsc.js --build\",\n    \"test:types:ts58\": \"node ../../node_modules/typescript58/lib/tsc.js --build\",\n    \"test:types:ts59\": \"node ../../node_modules/typescript59/lib/tsc.js --build\",\n    \"test:types:ts60\": \"node ../../node_modules/typescript60/lib/tsc.js --build\",\n    \"test:lib\": \"vitest\",\n    \"test:lib:dev\": \"pnpm run test:lib --watch\",\n    \"test:build\": \"publint --strict && attw --pack\",\n    \"build\": \"tsup --tsconfig tsconfig.prod.json\"\n  },\n  \"type\": \"module\",\n  \"types\": \"./build/index.d.ts\",\n  \"main\": \"./build/index.cjs\",\n  \"module\": \"./build/index.js\",\n  \"exports\": {\n    \"@tanstack/custom-condition\": \"./src/index.ts\",\n    \"development\": {\n      \"import\": {\n        \"types\": \"./build/index.d.ts\",\n        \"default\": \"./build/dev.js\"\n      },\n      \"require\": {\n        \"types\": \"./build/index.d.cts\",\n        \"default\": \"./build/dev.cjs\"\n      }\n    },\n    \"import\": {\n      \"types\": \"./build/index.d.ts\",\n      \"default\": \"./build/index.js\"\n    },\n    \"require\": {\n      \"types\": \"./build/index.d.cts\",\n      \"default\": \"./build/index.cjs\"\n    }\n  },\n  \"sideEffects\": false,\n  \"files\": [\n    \"build\",\n    \"src\",\n    \"!src/__tests__\"\n  ],\n  \"dependencies\": {\n    \"@tanstack/query-persist-client-core\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"@solidjs/testing-library\": \"^0.8.10\",\n    \"@tanstack/query-test-utils\": \"workspace:*\",\n    \"@tanstack/solid-query\": \"workspace:*\",\n    \"npm-run-all2\": \"^5.0.0\",\n    \"solid-js\": \"^1.9.7\",\n    \"tsup-preset-solid\": \"^2.2.0\",\n    \"vite-plugin-solid\": \"^2.11.6\"\n  },\n  \"peerDependencies\": {\n    \"@tanstack/solid-query\": \"workspace:^\",\n    \"solid-js\": \"^1.6.0\"\n  }\n}\n"
  },
  {
    "path": "packages/solid-query-persist-client/src/PersistQueryClientProvider.tsx",
    "content": "import {\n  persistQueryClientRestore,\n  persistQueryClientSubscribe,\n} from '@tanstack/query-persist-client-core'\nimport { createEffect, createMemo, createSignal, onCleanup } from 'solid-js'\nimport { IsRestoringProvider, QueryClientProvider } from '@tanstack/solid-query'\nimport type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'\nimport type { OmitKeyof, QueryClientProviderProps } from '@tanstack/solid-query'\nimport type { JSX } from 'solid-js'\n\nexport type PersistQueryClientProviderProps = QueryClientProviderProps & {\n  persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>\n  onSuccess?: () => void\n  onError?: () => void\n}\n\nexport const PersistQueryClientProvider = (\n  props: PersistQueryClientProviderProps,\n): JSX.Element => {\n  const [isRestoring, setIsRestoring] = createSignal(true)\n\n  const options = createMemo(() => ({\n    ...props.persistOptions,\n    queryClient: props.client,\n  }))\n\n  createEffect(() => {\n    setIsRestoring(true)\n    persistQueryClientRestore(options())\n      .then(() => props.onSuccess?.())\n      .catch(() => props.onError?.())\n      .finally(() => {\n        setIsRestoring(false)\n      })\n  })\n\n  createEffect(() => {\n    let unsubscribe = () => {}\n    if (!isRestoring()) {\n      unsubscribe = persistQueryClientSubscribe(options())\n    }\n    onCleanup(() => unsubscribe())\n  })\n\n  return (\n    <QueryClientProvider client={props.client}>\n      <IsRestoringProvider value={isRestoring}>\n        {props.children}\n      </IsRestoringProvider>\n    </QueryClientProvider>\n  )\n}\n"
  },
  {
    "path": "packages/solid-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { render, screen } from '@solidjs/testing-library'\nimport { QueryClient, useQueries, useQuery } from '@tanstack/solid-query'\nimport { persistQueryClientSave } from '@tanstack/query-persist-client-core'\nimport { createEffect, createSignal, onMount } from 'solid-js'\nimport { queryKey, sleep } from '@tanstack/query-test-utils'\nimport { PersistQueryClientProvider } from '../PersistQueryClientProvider'\nimport type {\n  PersistedClient,\n  Persister,\n} from '@tanstack/query-persist-client-core'\n\nconst createMockPersister = (): Persister => {\n  let storedState: PersistedClient | undefined\n\n  return {\n    persistClient(persistClient: PersistedClient) {\n      storedState = persistClient\n    },\n    async restoreClient() {\n      return sleep(10).then(() => storedState)\n    },\n    removeClient() {\n      storedState = undefined\n    },\n  }\n}\n\nconst createMockErrorPersister = (\n  removeClient: Persister['removeClient'],\n): [Error, Persister] => {\n  const error = new Error('restore failed')\n  return [\n    error,\n    {\n      async persistClient() {\n        // noop\n      },\n      async restoreClient() {\n        await sleep(10)\n        throw error\n      },\n      removeClient,\n    },\n  ]\n}\n\ndescribe('PersistQueryClientProvider', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('restores cache from persister', async () => {\n    const key = queryKey()\n    const states: Array<{\n      status: string\n      fetchStatus: string\n      data: string | undefined\n    }> = []\n\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createMockPersister()\n\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'fetched'),\n      }))\n      createEffect(() =>\n        states.push({\n          status: state.status,\n          fetchStatus: state.fetchStatus,\n          data: state.data,\n        }),\n      )\n\n      return (\n        <div>\n          <h1>{state.data}</h1>\n          <h2>fetchStatus: {state.fetchStatus}</h2>\n        </div>\n      )\n    }\n\n    render(() => (\n      <PersistQueryClientProvider\n        client={queryClient}\n        persistOptions={{ persister }}\n      >\n        <Page />\n      </PersistQueryClientProvider>\n    ))\n\n    expect(screen.getByText('fetchStatus: idle')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(screen.getByText('hydrated')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(screen.getByText('fetched')).toBeInTheDocument()\n\n    expect(states).toHaveLength(3)\n\n    expect(states[0]).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'idle',\n      data: undefined,\n    })\n\n    expect(states[1]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: 'hydrated',\n    })\n\n    expect(states[2]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: 'fetched',\n    })\n  })\n\n  test('should also put useQueries into idle state', async () => {\n    const key = queryKey()\n    const states: Array<{\n      status: string\n      fetchStatus: string\n      data: string | undefined\n    }> = []\n\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createMockPersister()\n\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    function Page() {\n      const [state] = useQueries(() => ({\n        queries: [\n          {\n            queryKey: key,\n            queryFn: () => sleep(10).then(() => 'fetched'),\n          },\n        ],\n      }))\n\n      createEffect(() =>\n        states.push({\n          status: state.status,\n          fetchStatus: state.fetchStatus,\n          data: state.data,\n        }),\n      )\n\n      return (\n        <div>\n          <h1>{state.data}</h1>\n          <h2>fetchStatus: {state.fetchStatus}</h2>\n        </div>\n      )\n    }\n\n    render(() => (\n      <PersistQueryClientProvider\n        client={queryClient}\n        persistOptions={{ persister }}\n      >\n        <Page />\n      </PersistQueryClientProvider>\n    ))\n\n    expect(screen.getByText('fetchStatus: idle')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(screen.getByText('hydrated')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(screen.getByText('fetched')).toBeInTheDocument()\n\n    expect(states).toHaveLength(3)\n\n    expect(states[0]).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'idle',\n      data: undefined,\n    })\n\n    expect(states[1]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: 'hydrated',\n    })\n\n    expect(states[2]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: 'fetched',\n    })\n  })\n\n  test('should show initialData while restoring', async () => {\n    const key = queryKey()\n    const states: Array<{\n      status: string\n      fetchStatus: string\n      data: string | undefined\n    }> = []\n\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createMockPersister()\n\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'fetched'),\n        initialData: 'initial',\n        // make sure that initial data is older than the hydration data\n        // otherwise initialData would be newer and takes precedence\n        initialDataUpdatedAt: 1,\n      }))\n\n      createEffect(() =>\n        states.push({\n          status: state.status,\n          fetchStatus: state.fetchStatus,\n          data: state.data,\n        }),\n      )\n\n      return (\n        <div>\n          <h1>{state.data}</h1>\n          <h2>fetchStatus: {state.fetchStatus}</h2>\n        </div>\n      )\n    }\n\n    render(() => (\n      <PersistQueryClientProvider\n        client={queryClient}\n        persistOptions={{ persister }}\n      >\n        <Page />\n      </PersistQueryClientProvider>\n    ))\n\n    expect(screen.getByText('initial')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(screen.getByText('hydrated')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(screen.getByText('fetched')).toBeInTheDocument()\n\n    expect(states).toHaveLength(3)\n\n    expect(states[0]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: 'initial',\n    })\n\n    expect(states[1]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: 'hydrated',\n    })\n\n    expect(states[2]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: 'fetched',\n    })\n  })\n\n  test('should not refetch after restoring when data is fresh', async () => {\n    const key = queryKey()\n    const states: Array<{\n      status: string\n      fetchStatus: string\n      data: string | undefined\n    }> = []\n\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createMockPersister()\n\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    let fetched = false\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          fetched = true\n          return 'fetched'\n        },\n        staleTime: Infinity,\n      }))\n\n      createEffect(() =>\n        states.push({\n          status: state.status,\n          fetchStatus: state.fetchStatus,\n          data: state.data,\n        }),\n      )\n\n      return (\n        <div>\n          <h1>data: {state.data ?? 'null'}</h1>\n          <h2>fetchStatus: {state.fetchStatus}</h2>\n        </div>\n      )\n    }\n\n    render(() => (\n      <PersistQueryClientProvider\n        client={queryClient}\n        persistOptions={{ persister }}\n      >\n        <Page />\n      </PersistQueryClientProvider>\n    ))\n\n    expect(screen.getByText('data: null')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(screen.getByText('data: hydrated')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(screen.getByText('data: hydrated')).toBeInTheDocument()\n\n    expect(fetched).toBe(false)\n\n    expect(states).toHaveLength(2)\n\n    expect(states[0]).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'idle',\n      data: undefined,\n    })\n\n    expect(states[1]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: 'hydrated',\n    })\n  })\n\n  test('should call onSuccess after successful restoring', async () => {\n    const key = queryKey()\n\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createMockPersister()\n\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'fetched'),\n      }))\n\n      return (\n        <div>\n          <h1>{state.data}</h1>\n          <h2>fetchStatus: {state.fetchStatus}</h2>\n        </div>\n      )\n    }\n\n    const onSuccess = vi.fn()\n\n    render(() => (\n      <PersistQueryClientProvider\n        client={queryClient}\n        persistOptions={{ persister }}\n        onSuccess={onSuccess}\n      >\n        <Page />\n      </PersistQueryClientProvider>\n    ))\n\n    expect(onSuccess).toHaveBeenCalledTimes(0)\n    await vi.advanceTimersByTimeAsync(10)\n    expect(screen.getByText('hydrated')).toBeInTheDocument()\n    expect(onSuccess).toHaveBeenCalledTimes(1)\n    await vi.advanceTimersByTimeAsync(10)\n    expect(screen.getByText('fetched')).toBeInTheDocument()\n  })\n\n  test('should remove cache after non-successful restoring', async () => {\n    const key = queryKey()\n\n    const onErrorMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const queryClient = new QueryClient()\n    const removeClient = vi.fn()\n    const onSuccess = vi.fn()\n    const onError = vi.fn()\n\n    const [error, persister] = createMockErrorPersister(removeClient)\n\n    function Page() {\n      const state = useQuery(() => ({\n        queryKey: key,\n        queryFn: () => sleep(10).then(() => 'fetched'),\n      }))\n\n      return (\n        <div>\n          <h1>{state.data}</h1>\n          <h2>fetchStatus: {state.fetchStatus}</h2>\n        </div>\n      )\n    }\n\n    render(() => (\n      <PersistQueryClientProvider\n        client={queryClient}\n        persistOptions={{ persister }}\n        onSuccess={onSuccess}\n        onError={onError}\n      >\n        <Page />\n      </PersistQueryClientProvider>\n    ))\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(removeClient).toHaveBeenCalledTimes(1)\n    expect(onSuccess).toHaveBeenCalledTimes(0)\n    expect(onError).toHaveBeenCalledTimes(1)\n    await vi.advanceTimersByTimeAsync(10)\n    expect(screen.getByText('fetched')).toBeInTheDocument()\n\n    expect(onErrorMock).toHaveBeenCalledTimes(1)\n    expect(onErrorMock).toHaveBeenNthCalledWith(1, error)\n    onErrorMock.mockRestore()\n  })\n\n  test('should be able to persist into multiple clients', async () => {\n    const key = queryKey()\n    const states: Array<{\n      status: string\n      fetchStatus: string\n      data: string | undefined\n    }> = []\n\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createMockPersister()\n\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    const onSuccess = vi.fn()\n\n    const queryFn1 = vi\n      .fn()\n      .mockImplementation(() => sleep(10).then(() => 'queryFn1'))\n    const queryFn2 = vi\n      .fn()\n      .mockImplementation(() => sleep(10).then(() => 'queryFn2'))\n\n    function App() {\n      const [client, setClient] = createSignal(\n        new QueryClient({\n          defaultOptions: {\n            queries: {\n              queryFn: queryFn1,\n            },\n          },\n        }),\n      )\n\n      onMount(() => {\n        setClient(\n          new QueryClient({\n            defaultOptions: {\n              queries: {\n                queryFn: queryFn2,\n              },\n            },\n          }),\n        )\n      })\n\n      return (\n        <PersistQueryClientProvider\n          client={client()}\n          persistOptions={{ persister }}\n          onSuccess={onSuccess}\n        >\n          <Page />\n        </PersistQueryClientProvider>\n      )\n    }\n\n    function Page() {\n      const state = useQuery(() => ({ queryKey: key }))\n\n      createEffect(() =>\n        states.push({\n          status: state.status,\n          fetchStatus: state.fetchStatus,\n          data: state.data as string | undefined,\n        }),\n      )\n\n      return (\n        <div>\n          <h1>{String(state.data)}</h1>\n          <h2>fetchStatus: {state.fetchStatus}</h2>\n        </div>\n      )\n    }\n\n    render(() => <App />)\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(screen.getByText('queryFn2')).toBeInTheDocument()\n\n    expect(queryFn1).toHaveBeenCalledTimes(0)\n    expect(queryFn2).toHaveBeenCalledTimes(1)\n    expect(onSuccess).toHaveBeenCalledTimes(1)\n\n    expect(states).toHaveLength(3)\n\n    expect(states[0]).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'idle',\n      data: undefined,\n    })\n\n    expect(states[1]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: 'hydrated',\n    })\n\n    expect(states[2]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: 'queryFn2',\n    })\n  })\n})\n"
  },
  {
    "path": "packages/solid-query-persist-client/src/index.ts",
    "content": "// Re-export core\nexport * from '@tanstack/query-persist-client-core'\n\nexport * from './PersistQueryClientProvider'\n"
  },
  {
    "path": "packages/solid-query-persist-client/test-setup.ts",
    "content": "import '@testing-library/jest-dom/vitest'\nimport { cleanup } from '@solidjs/testing-library'\nimport { afterEach } from 'vitest'\n\n// https://github.com/solidjs/solid-testing-library\nafterEach(() => cleanup())\n"
  },
  {
    "path": "packages/solid-query-persist-client/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\",\n    \"jsx\": \"preserve\",\n    \"jsxImportSource\": \"solid-js\"\n  },\n  \"include\": [\"src\", \"test-setup.ts\", \"*.config.*\", \"package.json\"],\n  \"references\": [\n    { \"path\": \"../query-persist-client-core\" },\n    { \"path\": \"../solid-query\" }\n  ]\n}\n"
  },
  {
    "path": "packages/solid-query-persist-client/tsconfig.prod.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"incremental\": false,\n    \"composite\": false,\n    \"rootDir\": \"../../\"\n  }\n}\n"
  },
  {
    "path": "packages/solid-query-persist-client/tsup.config.ts",
    "content": "import { defineConfig } from 'tsup'\nimport { generateTsupOptions, parsePresetOptions } from 'tsup-preset-solid'\n\nconst preset_options = {\n  entries: {\n    entry: 'src/index.ts',\n    dev_entry: true,\n  },\n  cjs: true,\n  drop_console: true,\n}\n\nexport default defineConfig(() => {\n  const parsed_data = parsePresetOptions(preset_options)\n  const tsup_options = generateTsupOptions(parsed_data)\n\n  tsup_options.forEach((tsup_option) => {\n    tsup_option.outDir = 'build'\n    tsup_option.experimentalDts = true\n    delete tsup_option.dts\n  })\n\n  return tsup_options\n})\n"
  },
  {
    "path": "packages/solid-query-persist-client/vite.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\nimport solid from 'vite-plugin-solid'\n\nimport packageJson from './package.json'\n\nexport default defineConfig({\n  plugins: [solid()],\n  // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660\n  resolve: {\n    conditions: ['@tanstack/custom-condition'],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        conditions: ['@tanstack/custom-condition'],\n      },\n    },\n  },\n  test: {\n    name: packageJson.name,\n    dir: './src',\n    watch: false,\n    environment: 'jsdom',\n    setupFiles: ['test-setup.ts'],\n    coverage: {\n      enabled: true,\n      provider: 'istanbul',\n      include: ['src/**/*'],\n      exclude: ['src/__tests__/**'],\n    },\n    typecheck: { enabled: true },\n    restoreMocks: true,\n  },\n})\n"
  },
  {
    "path": "packages/svelte-query/.attw.json",
    "content": "{\n  \"ignoreRules\": [\"cjs-resolves-to-esm\", \"internal-resolution-error\"]\n}\n"
  },
  {
    "path": "packages/svelte-query/CHANGELOG.md",
    "content": "# @tanstack/svelte-query\n\n## 6.1.3\n\n### Patch Changes\n\n- fix(streamedQuery): maintain error state on reset refetch with initialData defined ([#10287](https://github.com/TanStack/query/pull/10287))\n\n- Updated dependencies [[`248975e`](https://github.com/TanStack/query/commit/248975e896f585f6eaa505c796e73fcf7bfd1eec)]:\n  - @tanstack/query-core@5.91.2\n\n## 6.1.2\n\n### Patch Changes\n\n- Updated dependencies [[`a89aab9`](https://github.com/TanStack/query/commit/a89aab975581c25c113a26c8af486b4cafad272a)]:\n  - @tanstack/query-core@5.91.1\n\n## 6.1.1\n\n### Patch Changes\n\n- Updated dependencies [[`6fa901b`](https://github.com/TanStack/query/commit/6fa901b97a22a80d0fca3f6ed86237ff0cbdd13b)]:\n  - @tanstack/query-core@5.91.0\n\n## 6.1.0\n\n### Minor Changes\n\n- feat(svelte-query): add 'mutationOptions' ([#10175](https://github.com/TanStack/query/pull/10175))\n\n## 6.0.18\n\n### Patch Changes\n\n- Updated dependencies [[`e7258c5`](https://github.com/TanStack/query/commit/e7258c5cb30cafa456cdb4e6bc75b43bf619954d)]:\n  - @tanstack/query-core@5.90.20\n\n## 6.0.17\n\n### Patch Changes\n\n- Updated dependencies [[`53fc74e`](https://github.com/TanStack/query/commit/53fc74ebb16730bd3317f039a69c6821386bae93)]:\n  - @tanstack/query-core@5.90.19\n\n## 6.0.16\n\n### Patch Changes\n\n- Updated dependencies [[`dea1614`](https://github.com/TanStack/query/commit/dea1614aaad5c572cf43cea54b64ac09dc4d5b41)]:\n  - @tanstack/query-core@5.90.18\n\n## 6.0.15\n\n### Patch Changes\n\n- Updated dependencies [[`269351b`](https://github.com/TanStack/query/commit/269351b8ce4b4846da3d320ac5b850ee6aada0d6)]:\n  - @tanstack/query-core@5.90.17\n\n## 6.0.14\n\n### Patch Changes\n\n- Updated dependencies [[`7f47906`](https://github.com/TanStack/query/commit/7f47906eaccc3f3aa5ce24b77a83bd7a620a237b)]:\n  - @tanstack/query-core@5.90.16\n\n## 6.0.13\n\n### Patch Changes\n\n- Updated dependencies [[`fccef79`](https://github.com/TanStack/query/commit/fccef797d57d4a9566517bba87c8377f363920f2)]:\n  - @tanstack/query-core@5.90.15\n\n## 6.0.12\n\n### Patch Changes\n\n- Updated dependencies [[`d576092`](https://github.com/TanStack/query/commit/d576092e2ece4ca3936add3eb0da5234c1d82ed4)]:\n  - @tanstack/query-core@5.90.14\n\n## 6.0.11\n\n### Patch Changes\n\n- Updated dependencies [[`4a0a78a`](https://github.com/TanStack/query/commit/4a0a78afbc2432f8cb6828035965853fa98c86a0)]:\n  - @tanstack/query-core@5.90.13\n\n## 6.0.10\n\n### Patch Changes\n\n- Updated dependencies [[`72d8ac5`](https://github.com/TanStack/query/commit/72d8ac5c592004b8f9c3ee086fcb9c3cd615ca05)]:\n  - @tanstack/query-core@5.90.12\n\n## 6.0.9\n\n### Patch Changes\n\n- Updated dependencies [[`c01b150`](https://github.com/TanStack/query/commit/c01b150e3673e11d6533768529a5e6fe3ebee68c)]:\n  - @tanstack/query-core@5.90.11\n\n## 6.0.8\n\n### Patch Changes\n\n- Updated dependencies [[`8e2e174`](https://github.com/TanStack/query/commit/8e2e174e9fd2e7b94cd232041e49c9d014d74e26), [`eb559a6`](https://github.com/TanStack/query/commit/eb559a66dc0d77dd46435f624fa64fc068bef9ae)]:\n  - @tanstack/query-core@5.90.10\n\n## 6.0.7\n\n### Patch Changes\n\n- Updated dependencies [[`08b211f`](https://github.com/TanStack/query/commit/08b211f8aa475e05d2f13a36517fc556861ef962)]:\n  - @tanstack/query-core@5.90.9\n\n## 6.0.6\n\n### Patch Changes\n\n- Updated dependencies [[`c0ec9fe`](https://github.com/TanStack/query/commit/c0ec9fe0d1426fe3f233adda3ebf23989ffaa110)]:\n  - @tanstack/query-core@5.90.8\n\n## 6.0.5\n\n### Patch Changes\n\n- Updated dependencies [[`b4cd121`](https://github.com/TanStack/query/commit/b4cd121a39d07cefaa3a3411136d342cc54ce8fb)]:\n  - @tanstack/query-core@5.90.7\n\n## 6.0.4\n\n### Patch Changes\n\n- Updated dependencies [[`1638c02`](https://github.com/TanStack/query/commit/1638c028df55648995d04431179904371a189772)]:\n  - @tanstack/query-core@5.90.6\n\n## 6.0.3\n\n### Patch Changes\n\n- Updated dependencies [[`e42ddfe`](https://github.com/TanStack/query/commit/e42ddfe919f34f847ca101aeef162c69845f9a1e)]:\n  - @tanstack/query-core@5.90.5\n\n## 6.0.2\n\n### Patch Changes\n\n- Updated dependencies [[`20ef922`](https://github.com/TanStack/query/commit/20ef922a0a7c3aee00150bf69123c338b0922922)]:\n  - @tanstack/query-core@5.90.4\n\n## 6.0.1\n\n### Patch Changes\n\n- Updated dependencies [[`4e1c433`](https://github.com/TanStack/query/commit/4e1c4338a72f7384600bbda99e44bc1891695df4)]:\n  - @tanstack/query-core@5.90.3\n\n## 6.0.0\n\n### Major Changes\n\n- BREAKING: Migrate to svelte runes (signals). Requires [Svelte v5.25.0](https://github.com/sveltejs/svelte/releases/tag/svelte%405.25.0) or newer. Please see the [migration guide](https://tanstack.com/query/latest/docs/framework/svelte/migrate-from-v5-to-v6). ([#9694](https://github.com/TanStack/query/pull/9694))\n"
  },
  {
    "path": "packages/svelte-query/eslint.config.js",
    "content": "// @ts-check\n\nimport tsParser from '@typescript-eslint/parser'\nimport pluginSvelte from 'eslint-plugin-svelte'\nimport rootConfig from './root.eslint.config.js'\nimport svelteConfig from './svelte.config.js'\n\nexport default [\n  ...rootConfig,\n  ...pluginSvelte.configs['recommended'],\n  {\n    files: ['**/*.svelte', '**/*.svelte.ts', '**/*.svelte.js'],\n    languageOptions: {\n      parserOptions: {\n        parser: tsParser,\n        extraFileExtensions: ['.svelte'],\n        svelteConfig,\n      },\n    },\n  },\n  {\n    rules: {\n      'svelte/block-lang': ['error', { script: ['ts'] }],\n      'svelte/no-svelte-internal': 'error',\n      'svelte/valid-compile': 'off',\n    },\n  },\n]\n"
  },
  {
    "path": "packages/svelte-query/package.json",
    "content": "{\n  \"name\": \"@tanstack/svelte-query\",\n  \"version\": \"6.1.3\",\n  \"description\": \"Primitives for managing, caching and syncing asynchronous and remote data in Svelte\",\n  \"author\": \"Lachlan Collins\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/svelte-query\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"keywords\": [\n    \"tanstack\",\n    \"query\",\n    \"svelte\"\n  ],\n  \"scripts\": {\n    \"clean\": \"premove ./dist ./coverage ./.svelte-kit ./dist-ts\",\n    \"compile\": \"tsc --build\",\n    \"test:types\": \"svelte-check --tsconfig ./tsconfig.json\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:lib\": \"vitest\",\n    \"test:lib:dev\": \"pnpm run test:lib --watch\",\n    \"test:build\": \"publint --strict && attw --pack\",\n    \"build\": \"svelte-package --input ./src --output ./dist\"\n  },\n  \"type\": \"module\",\n  \"types\": \"dist/index.d.ts\",\n  \"module\": \"dist/index.js\",\n  \"svelte\": \"./dist/index.js\",\n  \"exports\": {\n    \".\": {\n      \"@tanstack/custom-condition\": \"./src/index.ts\",\n      \"types\": \"./dist/index.d.ts\",\n      \"svelte\": \"./dist/index.js\",\n      \"import\": \"./dist/index.js\"\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"sideEffects\": false,\n  \"files\": [\n    \"dist\",\n    \"src\",\n    \"!src/__tests__\"\n  ],\n  \"dependencies\": {\n    \"@tanstack/query-core\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"@sveltejs/package\": \"^2.4.0\",\n    \"@sveltejs/vite-plugin-svelte\": \"^5.1.1\",\n    \"@tanstack/query-test-utils\": \"workspace:*\",\n    \"@testing-library/svelte\": \"^5.2.8\",\n    \"@typescript-eslint/parser\": \"^8.48.0\",\n    \"eslint-plugin-svelte\": \"^3.11.0\",\n    \"svelte\": \"^5.39.3\",\n    \"svelte-check\": \"^4.4.5\",\n    \"typescript\": \"5.9.3\"\n  },\n  \"peerDependencies\": {\n    \"svelte\": \"^5.25.0\"\n  }\n}\n"
  },
  {
    "path": "packages/svelte-query/src/HydrationBoundary.svelte",
    "content": "<script lang=\"ts\">\n  import { useHydrate } from './useHydrate.js'\n  import type { Snippet } from 'svelte'\n  import type {\n    DehydratedState,\n    HydrateOptions,\n    QueryClient,\n  } from '@tanstack/query-core'\n\n  type Props = {\n    children: Snippet\n    state: DehydratedState\n    options: HydrateOptions | undefined\n    queryClient: QueryClient | undefined\n  }\n\n  const {\n    children,\n    state,\n    options = undefined,\n    queryClient = undefined,\n  }: Props = $props()\n\n  useHydrate(state, options, queryClient)\n</script>\n\n{@render children()}\n"
  },
  {
    "path": "packages/svelte-query/src/QueryClientProvider.svelte",
    "content": "<script lang=\"ts\">\n  import { onDestroy, onMount } from 'svelte'\n  import { QueryClient } from '@tanstack/query-core'\n  import { setQueryClientContext } from './context.js'\n  import type { QueryClientProviderProps } from './types.js'\n\n  const { client = new QueryClient(), children }: QueryClientProviderProps =\n    $props()\n\n  onMount(() => {\n    client.mount()\n  })\n\n  setQueryClientContext(client)\n\n  onDestroy(() => {\n    client.unmount()\n  })\n</script>\n\n{@render children()}\n"
  },
  {
    "path": "packages/svelte-query/src/containers.svelte.ts",
    "content": "import { SvelteSet, createSubscriber } from 'svelte/reactivity'\n\ntype VoidFn = () => void\ntype Subscriber = (update: VoidFn) => void | VoidFn\n\nexport type Box<T> = { current: T }\n\nexport class ReactiveValue<T> implements Box<T> {\n  #fn\n  #subscribe\n\n  constructor(fn: () => T, onSubscribe: Subscriber) {\n    this.#fn = fn\n    this.#subscribe = createSubscriber((update) => onSubscribe(update))\n  }\n\n  get current() {\n    this.#subscribe()\n    return this.#fn()\n  }\n}\n\n/**\n * Makes all of the top-level keys of an object into $state.raw fields whose initial values\n * are the same as in the original object. Does not mutate the original object. Provides an `update`\n * function that _can_ (but does not have to be) be used to replace all of the object's top-level keys\n * with the values of the new object, while maintaining the original root object's reference.\n */\nexport function createRawRef<T extends {} | Array<unknown>>(\n  init: T,\n): [T, (newValue: T) => void] {\n  const refObj = (Array.isArray(init) ? [] : {}) as T\n  const hiddenKeys = new SvelteSet<PropertyKey>()\n  const out = new Proxy(refObj, {\n    set(target, prop, value, receiver) {\n      hiddenKeys.delete(prop)\n      if (prop in target) {\n        return Reflect.set(target, prop, value, receiver)\n      }\n      let state = $state.raw(value)\n      Object.defineProperty(target, prop, {\n        configurable: true,\n        enumerable: true,\n        get: () => {\n          // If this is a lazy value, we need to call it.\n          // We can't do something like typeof state === 'function'\n          // because the value could actually be a function that we don't want to call.\n          return state && isBranded(state) ? state() : state\n        },\n        set: (v) => {\n          state = v\n        },\n      })\n      return true\n    },\n    has: (target, prop) => {\n      if (hiddenKeys.has(prop)) {\n        return false\n      }\n      return prop in target\n    },\n    ownKeys(target) {\n      return Reflect.ownKeys(target).filter((key) => !hiddenKeys.has(key))\n    },\n    getOwnPropertyDescriptor(target, prop) {\n      if (hiddenKeys.has(prop)) {\n        return undefined\n      }\n      return Reflect.getOwnPropertyDescriptor(target, prop)\n    },\n    deleteProperty(target, prop) {\n      if (prop in target) {\n        // @ts-expect-error\n        // We need to set the value to undefined to signal to the listeners that the value has changed.\n        // If we just deleted it, the reactivity system wouldn't have any idea that the value was gone.\n        target[prop] = undefined\n        hiddenKeys.add(prop)\n        if (Array.isArray(target)) {\n          target.length--\n        }\n        return true\n      }\n      return false\n    },\n  })\n\n  function update(newValue: T) {\n    const existingKeys = Object.keys(out)\n    const newKeys = Object.keys(newValue)\n    const keysToRemove = existingKeys.filter((key) => !newKeys.includes(key))\n    for (const key of keysToRemove) {\n      // @ts-expect-error\n      delete out[key]\n    }\n    for (const key of newKeys) {\n      // @ts-expect-error\n      // This craziness is required because Tanstack Query defines getters for all of the keys on the object.\n      // These getters track property access, so if we access all of them here, we'll end up tracking everything.\n      // So we wrap the property access in a special function that we can identify later to lazily access the value.\n      // (See above)\n      out[key] = brand(() => newValue[key])\n    }\n  }\n\n  // we can't pass `init` directly into the proxy because it'll never set the state fields\n  // (because (prop in target) will always be true)\n  update(init)\n\n  return [out, update]\n}\n\nconst lazyBrand = Symbol('LazyValue')\ntype Branded<T extends () => unknown> = T & { [lazyBrand]: true }\n\nfunction brand<T extends () => unknown>(fn: T): Branded<T> {\n  // @ts-expect-error\n  fn[lazyBrand] = true\n  return fn as Branded<T>\n}\n\nfunction isBranded<T extends () => unknown>(fn: T): fn is Branded<T> {\n  return Boolean((fn as Branded<T>)[lazyBrand])\n}\n"
  },
  {
    "path": "packages/svelte-query/src/context.ts",
    "content": "import { getContext, setContext } from 'svelte'\nimport type { QueryClient } from '@tanstack/query-core'\nimport type { Box } from './containers.svelte'\n\nconst _contextKey = Symbol('QueryClient')\n\n/** Retrieves a Client from Svelte's context */\nexport const getQueryClientContext = (): QueryClient => {\n  const client = getContext<QueryClient | undefined>(_contextKey)\n  if (!client) {\n    throw new Error(\n      'No QueryClient was found in Svelte context. Did you forget to wrap your component with QueryClientProvider?',\n    )\n  }\n\n  return client\n}\n\n/** Sets a QueryClient on Svelte's context */\nexport const setQueryClientContext = (client: QueryClient): void => {\n  setContext(_contextKey, client)\n}\n\nconst _isRestoringContextKey = Symbol('isRestoring')\n\n/** Retrieves a `isRestoring` from Svelte's context */\nexport const getIsRestoringContext = (): Box<boolean> => {\n  try {\n    const isRestoring = getContext<Box<boolean> | undefined>(\n      _isRestoringContextKey,\n    )\n    return isRestoring ?? { current: false }\n  } catch (error) {\n    return { current: false }\n  }\n}\n\n/** Sets a `isRestoring` on Svelte's context */\nexport const setIsRestoringContext = (isRestoring: Box<boolean>): void => {\n  setContext(_isRestoringContextKey, isRestoring)\n}\n"
  },
  {
    "path": "packages/svelte-query/src/createBaseQuery.svelte.ts",
    "content": "import { useIsRestoring } from './useIsRestoring.js'\nimport { useQueryClient } from './useQueryClient.js'\nimport { createRawRef } from './containers.svelte.js'\nimport { watchChanges } from './utils.svelte.js'\nimport type { QueryClient, QueryKey, QueryObserver } from '@tanstack/query-core'\nimport type {\n  Accessor,\n  CreateBaseQueryOptions,\n  CreateBaseQueryResult,\n} from './types.js'\n\n/**\n * Base implementation for `createQuery` and `createInfiniteQuery`\n * @param options - A function that returns query options\n * @param Observer - The observer from query-core\n * @param queryClient - Custom query client which overrides provider\n */\nexport function createBaseQuery<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryData,\n  TQueryKey extends QueryKey,\n>(\n  options: Accessor<\n    CreateBaseQueryOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>\n  >,\n  Observer: typeof QueryObserver,\n  queryClient?: Accessor<QueryClient>,\n): CreateBaseQueryResult<TData, TError> {\n  /** Load query client */\n  const client = $derived(useQueryClient(queryClient?.()))\n  const isRestoring = useIsRestoring()\n\n  const resolvedOptions = $derived.by(() => {\n    const opts = client.defaultQueryOptions(options())\n    opts._optimisticResults = isRestoring.current ? 'isRestoring' : 'optimistic'\n    return opts\n  })\n\n  /** Creates the observer */\n  // svelte-ignore state_referenced_locally - intentional, initial value\n  let observer = $state(\n    new Observer<TQueryFnData, TError, TData, TQueryData, TQueryKey>(\n      client,\n      resolvedOptions,\n    ),\n  )\n  watchChanges(\n    () => client,\n    'pre',\n    () => {\n      observer = new Observer<\n        TQueryFnData,\n        TError,\n        TData,\n        TQueryData,\n        TQueryKey\n      >(client, resolvedOptions)\n    },\n  )\n\n  function createResult() {\n    const result = observer.getOptimisticResult(resolvedOptions)\n    return !resolvedOptions.notifyOnChangeProps\n      ? observer.trackResult(result)\n      : result\n  }\n  const [query, update] = createRawRef(\n    // svelte-ignore state_referenced_locally - intentional, initial value\n    createResult(),\n  )\n\n  $effect(() => {\n    const unsubscribe = isRestoring.current\n      ? () => undefined\n      : observer.subscribe(() => update(createResult()))\n    observer.updateResult()\n    return unsubscribe\n  })\n\n  watchChanges(\n    () => resolvedOptions,\n    'pre',\n    () => {\n      observer.setOptions(resolvedOptions)\n    },\n  )\n  watchChanges(\n    () => [resolvedOptions, observer],\n    'pre',\n    () => {\n      // The only reason this is necessary is because of `isRestoring`.\n      // Because we don't subscribe while restoring, the following can occur:\n      // - `isRestoring` is true\n      // - `isRestoring` becomes false\n      // - `observer.subscribe` and `observer.updateResult` is called in the above effect,\n      //   but the subsequent `fetch` has already completed\n      // - `result` misses the intermediate restored-but-not-fetched state\n      //\n      // this could technically be its own effect but that doesn't seem necessary\n      update(createResult())\n    },\n  )\n\n  return query\n}\n"
  },
  {
    "path": "packages/svelte-query/src/createInfiniteQuery.ts",
    "content": "import { InfiniteQueryObserver } from '@tanstack/query-core'\nimport { createBaseQuery } from './createBaseQuery.svelte.js'\nimport type {\n  DefaultError,\n  InfiniteData,\n  QueryClient,\n  QueryKey,\n  QueryObserver,\n} from '@tanstack/query-core'\nimport type {\n  Accessor,\n  CreateInfiniteQueryOptions,\n  CreateInfiniteQueryResult,\n} from './types.js'\n\nexport function createInfiniteQuery<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: Accessor<\n    CreateInfiniteQueryOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey,\n      TPageParam\n    >\n  >,\n  queryClient?: Accessor<QueryClient>,\n): CreateInfiniteQueryResult<TData, TError> {\n  return createBaseQuery(\n    options,\n    InfiniteQueryObserver as typeof QueryObserver,\n    queryClient,\n  ) as CreateInfiniteQueryResult<TData, TError>\n}\n"
  },
  {
    "path": "packages/svelte-query/src/createMutation.svelte.ts",
    "content": "import { MutationObserver, noop, notifyManager } from '@tanstack/query-core'\nimport { useQueryClient } from './useQueryClient.js'\nimport { watchChanges } from './utils.svelte.js'\nimport type {\n  Accessor,\n  CreateMutateFunction,\n  CreateMutationOptions,\n  CreateMutationResult,\n} from './types.js'\n\nimport type { DefaultError, QueryClient } from '@tanstack/query-core'\n\n/**\n * @param options - A function that returns mutation options\n * @param queryClient - Custom query client which overrides provider\n */\nexport function createMutation<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TContext = unknown,\n>(\n  options: Accessor<CreateMutationOptions<TData, TError, TVariables, TContext>>,\n  queryClient?: Accessor<QueryClient>,\n): CreateMutationResult<TData, TError, TVariables, TContext> {\n  const client = $derived(useQueryClient(queryClient?.()))\n\n  // svelte-ignore state_referenced_locally - intentional, initial value\n  let observer = $state(\n    // svelte-ignore state_referenced_locally - intentional, initial value\n    new MutationObserver<TData, TError, TVariables, TContext>(\n      client,\n      options(),\n    ),\n  )\n\n  watchChanges(\n    () => client,\n    'pre',\n    () => {\n      observer = new MutationObserver(client, options())\n    },\n  )\n\n  $effect.pre(() => {\n    observer.setOptions(options())\n  })\n\n  const mutate = <CreateMutateFunction<TData, TError, TVariables, TContext>>((\n    variables,\n    mutateOptions,\n  ) => {\n    observer.mutate(variables, mutateOptions).catch(noop)\n  })\n\n  let result = $state(observer.getCurrentResult())\n  watchChanges(\n    () => observer,\n    'pre',\n    () => {\n      result = observer.getCurrentResult()\n    },\n  )\n\n  $effect.pre(() => {\n    const unsubscribe = observer.subscribe((val) => {\n      notifyManager.batchCalls(() => {\n        Object.assign(result, val)\n      })()\n    })\n    return unsubscribe\n  })\n\n  const resultProxy = $derived(\n    new Proxy(result, {\n      get: (_, prop) => {\n        const r = {\n          ...result,\n          mutate,\n          mutateAsync: result.mutate,\n        }\n        if (prop == 'value') return r\n        // @ts-expect-error\n        return r[prop]\n      },\n    }),\n  )\n\n  // @ts-expect-error\n  return resultProxy\n}\n"
  },
  {
    "path": "packages/svelte-query/src/createQueries.svelte.ts",
    "content": "import { QueriesObserver } from '@tanstack/query-core'\nimport { useIsRestoring } from './useIsRestoring.js'\nimport { createRawRef } from './containers.svelte.js'\nimport { useQueryClient } from './useQueryClient.js'\nimport type {\n  Accessor,\n  CreateQueryOptions,\n  CreateQueryResult,\n  DefinedCreateQueryResult,\n} from './types.js'\nimport type {\n  DefaultError,\n  OmitKeyof,\n  QueriesObserverOptions,\n  QueriesPlaceholderDataFunction,\n  QueryClient,\n  QueryFunction,\n  QueryKey,\n  ThrowOnError,\n} from '@tanstack/query-core'\n\n// This defines the `CreateQueryOptions` that are accepted in `QueriesOptions` & `GetOptions`.\n// `placeholderData` function always gets undefined passed\ntype CreateQueryOptionsForCreateQueries<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = OmitKeyof<\n  CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  'placeholderData'\n> & {\n  placeholderData?: TQueryFnData | QueriesPlaceholderDataFunction<TQueryFnData>\n}\n\n// Avoid TS depth-limit error in case of large array literal\ntype MAXIMUM_DEPTH = 20\n\n// Widen the type of the symbol to enable type inference even if skipToken is not immutable.\ntype SkipTokenForCreateQueries = symbol\n\ntype GetCreateQueryOptionsForCreateQueries<T> =\n  // Part 1: responsible for applying explicit type parameter to function arguments, if object { queryFnData: TQueryFnData, error: TError, data: TData }\n  T extends {\n    queryFnData: infer TQueryFnData\n    error?: infer TError\n    data: infer TData\n  }\n    ? CreateQueryOptionsForCreateQueries<TQueryFnData, TError, TData>\n    : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n      ? CreateQueryOptionsForCreateQueries<TQueryFnData, TError>\n      : T extends { data: infer TData; error?: infer TError }\n        ? CreateQueryOptionsForCreateQueries<unknown, TError, TData>\n        : // Part 2: responsible for applying explicit type parameter to function arguments, if tuple [TQueryFnData, TError, TData]\n          T extends [infer TQueryFnData, infer TError, infer TData]\n          ? CreateQueryOptionsForCreateQueries<TQueryFnData, TError, TData>\n          : T extends [infer TQueryFnData, infer TError]\n            ? CreateQueryOptionsForCreateQueries<TQueryFnData, TError>\n            : T extends [infer TQueryFnData]\n              ? CreateQueryOptionsForCreateQueries<TQueryFnData>\n              : // Part 3: responsible for inferring and enforcing type if no explicit parameter was provided\n                T extends {\n                    queryFn?:\n                      | QueryFunction<infer TQueryFnData, infer TQueryKey>\n                      | SkipTokenForCreateQueries\n                    select?: (data: any) => infer TData\n                    throwOnError?: ThrowOnError<any, infer TError, any, any>\n                  }\n                ? CreateQueryOptionsForCreateQueries<\n                    TQueryFnData,\n                    unknown extends TError ? DefaultError : TError,\n                    unknown extends TData ? TQueryFnData : TData,\n                    TQueryKey\n                  >\n                : // Fallback\n                  CreateQueryOptionsForCreateQueries\n\n// A defined initialData setting should return a DefinedCreateQueryResult rather than CreateQueryResult\ntype GetDefinedOrUndefinedQueryResult<T, TData, TError = unknown> = T extends {\n  initialData?: infer TInitialData\n}\n  ? unknown extends TInitialData\n    ? CreateQueryResult<TData, TError>\n    : TInitialData extends TData\n      ? DefinedCreateQueryResult<TData, TError>\n      : TInitialData extends () => infer TInitialDataResult\n        ? unknown extends TInitialDataResult\n          ? CreateQueryResult<TData, TError>\n          : TInitialDataResult extends TData\n            ? DefinedCreateQueryResult<TData, TError>\n            : CreateQueryResult<TData, TError>\n        : CreateQueryResult<TData, TError>\n  : CreateQueryResult<TData, TError>\n\ntype GetCreateQueryResult<T> =\n  // Part 1: responsible for mapping explicit type parameter to function result, if object\n  T extends { queryFnData: any; error?: infer TError; data: infer TData }\n    ? GetDefinedOrUndefinedQueryResult<T, TData, TError>\n    : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n      ? GetDefinedOrUndefinedQueryResult<T, TQueryFnData, TError>\n      : T extends { data: infer TData; error?: infer TError }\n        ? GetDefinedOrUndefinedQueryResult<T, TData, TError>\n        : // Part 2: responsible for mapping explicit type parameter to function result, if tuple\n          T extends [any, infer TError, infer TData]\n          ? GetDefinedOrUndefinedQueryResult<T, TData, TError>\n          : T extends [infer TQueryFnData, infer TError]\n            ? GetDefinedOrUndefinedQueryResult<T, TQueryFnData, TError>\n            : T extends [infer TQueryFnData]\n              ? GetDefinedOrUndefinedQueryResult<T, TQueryFnData>\n              : // Part 3: responsible for mapping inferred type to results, if no explicit parameter was provided\n                T extends {\n                    queryFn?:\n                      | QueryFunction<infer TQueryFnData, any>\n                      | SkipTokenForCreateQueries\n                    select?: (data: any) => infer TData\n                    throwOnError?: ThrowOnError<any, infer TError, any, any>\n                  }\n                ? GetDefinedOrUndefinedQueryResult<\n                    T,\n                    unknown extends TData ? TQueryFnData : TData,\n                    unknown extends TError ? DefaultError : TError\n                  >\n                : // Fallback\n                  CreateQueryResult\n\n/**\n * QueriesOptions reducer recursively unwraps function arguments to infer/enforce type param\n */\nexport type QueriesOptions<\n  T extends Array<any>,\n  TResults extends Array<any> = [],\n  TDepth extends ReadonlyArray<number> = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n  ? Array<CreateQueryOptionsForCreateQueries>\n  : T extends []\n    ? []\n    : T extends [infer Head]\n      ? [...TResults, GetCreateQueryOptionsForCreateQueries<Head>]\n      : T extends [infer Head, ...infer Tails]\n        ? QueriesOptions<\n            [...Tails],\n            [...TResults, GetCreateQueryOptionsForCreateQueries<Head>],\n            [...TDepth, 1]\n          >\n        : ReadonlyArray<unknown> extends T\n          ? T\n          : // If T is *some* array but we couldn't assign unknown[] to it, then it must hold some known/homogenous type!\n            // use this to infer the param types in the case of Array.map() argument\n            T extends Array<\n                CreateQueryOptionsForCreateQueries<\n                  infer TQueryFnData,\n                  infer TError,\n                  infer TData,\n                  infer TQueryKey\n                >\n              >\n            ? Array<\n                CreateQueryOptionsForCreateQueries<\n                  TQueryFnData,\n                  TError,\n                  TData,\n                  TQueryKey\n                >\n              >\n            : // Fallback\n              Array<CreateQueryOptionsForCreateQueries>\n\n/**\n * QueriesResults reducer recursively maps type param to results\n */\nexport type QueriesResults<\n  T extends Array<any>,\n  TResults extends Array<any> = [],\n  TDepth extends ReadonlyArray<number> = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n  ? Array<CreateQueryResult>\n  : T extends []\n    ? []\n    : T extends [infer Head]\n      ? [...TResults, GetCreateQueryResult<Head>]\n      : T extends [infer Head, ...infer Tails]\n        ? QueriesResults<\n            [...Tails],\n            [...TResults, GetCreateQueryResult<Head>],\n            [...TDepth, 1]\n          >\n        : { [K in keyof T]: GetCreateQueryResult<T[K]> }\n\nexport function createQueries<\n  T extends Array<any>,\n  TCombinedResult = QueriesResults<T>,\n>(\n  createQueriesOptions: Accessor<{\n    queries:\n      | readonly [...QueriesOptions<T>]\n      | readonly [\n          ...{ [K in keyof T]: GetCreateQueryOptionsForCreateQueries<T[K]> },\n        ]\n    combine?: (result: QueriesResults<T>) => TCombinedResult\n  }>,\n  queryClient?: Accessor<QueryClient>,\n): TCombinedResult {\n  const client = $derived(useQueryClient(queryClient?.()))\n  const isRestoring = useIsRestoring()\n\n  const { queries, combine } = $derived.by(createQueriesOptions)\n  const resolvedQueryOptions = $derived(\n    queries.map((opts) => {\n      const resolvedOptions = client.defaultQueryOptions(opts)\n      // Make sure the results are already in fetching state before subscribing or updating options\n      resolvedOptions._optimisticResults = isRestoring.current\n        ? 'isRestoring'\n        : 'optimistic'\n      return resolvedOptions\n    }),\n  )\n\n  // can't do same as createMutation, as QueriesObserver has no `setOptions` method\n  const observer = $derived(\n    new QueriesObserver<TCombinedResult>(\n      client,\n      resolvedQueryOptions,\n      combine as QueriesObserverOptions<TCombinedResult>,\n    ),\n  )\n\n  function createResult() {\n    const [_, getCombinedResult, trackResult] = observer.getOptimisticResult(\n      resolvedQueryOptions,\n      combine as QueriesObserverOptions<TCombinedResult>['combine'],\n    )\n    return getCombinedResult(trackResult())\n  }\n\n  // @ts-expect-error - the crazy-complex TCombinedResult type doesn't like being called an array\n  // svelte-ignore state_referenced_locally\n  const [results, update] = createRawRef<TCombinedResult>(createResult())\n\n  $effect(() => {\n    const unsubscribe = isRestoring.current\n      ? () => undefined\n      : observer.subscribe(() => update(createResult()))\n    return unsubscribe\n  })\n\n  $effect.pre(() => {\n    observer.setQueries(resolvedQueryOptions, {\n      combine,\n    } as QueriesObserverOptions<TCombinedResult>)\n    update(createResult())\n  })\n\n  return results\n}\n"
  },
  {
    "path": "packages/svelte-query/src/createQuery.ts",
    "content": "import { QueryObserver } from '@tanstack/query-core'\nimport { createBaseQuery } from './createBaseQuery.svelte.js'\nimport type { DefaultError, QueryClient, QueryKey } from '@tanstack/query-core'\nimport type {\n  Accessor,\n  CreateQueryOptions,\n  CreateQueryResult,\n  DefinedCreateQueryResult,\n} from './types.js'\nimport type {\n  DefinedInitialDataOptions,\n  UndefinedInitialDataOptions,\n} from './queryOptions.js'\n\nexport function createQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: Accessor<\n    UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>\n  >,\n  queryClient?: Accessor<QueryClient>,\n): CreateQueryResult<TData, TError>\n\nexport function createQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: Accessor<\n    DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>\n  >,\n  queryClient?: Accessor<QueryClient>,\n): DefinedCreateQueryResult<TData, TError>\n\nexport function createQuery<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: Accessor<CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>>,\n  queryClient?: Accessor<QueryClient>,\n): CreateQueryResult<TData, TError>\n\nexport function createQuery(\n  options: Accessor<CreateQueryOptions>,\n  queryClient?: Accessor<QueryClient>,\n) {\n  return createBaseQuery(options, QueryObserver, queryClient)\n}\n"
  },
  {
    "path": "packages/svelte-query/src/index.ts",
    "content": "/* istanbul ignore file */\n\n// Re-export core\nexport * from '@tanstack/query-core'\n\n// Svelte Query\nexport * from './types.js'\nexport * from './context.js'\n\nexport { createQuery } from './createQuery.js'\nexport type { QueriesResults, QueriesOptions } from './createQueries.svelte.js'\nexport type {\n  DefinedInitialDataOptions,\n  UndefinedInitialDataOptions,\n} from './queryOptions.js'\nexport { queryOptions } from './queryOptions.js'\nexport { createQueries } from './createQueries.svelte.js'\nexport { createInfiniteQuery } from './createInfiniteQuery.js'\nexport { infiniteQueryOptions } from './infiniteQueryOptions.js'\nexport { mutationOptions } from './mutationOptions.js'\nexport { createMutation } from './createMutation.svelte.js'\nexport { useMutationState } from './useMutationState.svelte.js'\nexport { useQueryClient } from './useQueryClient.js'\nexport { useIsFetching } from './useIsFetching.svelte.js'\nexport { useIsMutating } from './useIsMutating.svelte.js'\nexport { useIsRestoring } from './useIsRestoring.js'\nexport { useHydrate } from './useHydrate.js'\nexport { default as HydrationBoundary } from './HydrationBoundary.svelte'\nexport { default as QueryClientProvider } from './QueryClientProvider.svelte'\n"
  },
  {
    "path": "packages/svelte-query/src/infiniteQueryOptions.ts",
    "content": "import type { DefaultError, InfiniteData, QueryKey } from '@tanstack/query-core'\nimport type { CreateInfiniteQueryOptions } from './types.js'\n\nexport function infiniteQueryOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: CreateInfiniteQueryOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n): CreateInfiniteQueryOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey,\n  TPageParam\n> {\n  return options\n}\n"
  },
  {
    "path": "packages/svelte-query/src/mutationOptions.ts",
    "content": "import type { DefaultError, WithRequired } from '@tanstack/query-core'\nimport type { CreateMutationOptions } from './types.js'\n\nexport function mutationOptions<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n>(\n  options: WithRequired<\n    CreateMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n    'mutationKey'\n  >,\n): WithRequired<\n  CreateMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n  'mutationKey'\n>\nexport function mutationOptions<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n>(\n  options: Omit<\n    CreateMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n    'mutationKey'\n  >,\n): Omit<\n  CreateMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n  'mutationKey'\n>\nexport function mutationOptions<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n>(\n  options: CreateMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n): CreateMutationOptions<TData, TError, TVariables, TOnMutateResult> {\n  return options\n}\n"
  },
  {
    "path": "packages/svelte-query/src/queryOptions.ts",
    "content": "import type {\n  DataTag,\n  DefaultError,\n  InitialDataFunction,\n  NonUndefinedGuard,\n  QueryKey,\n} from '@tanstack/query-core'\nimport type { CreateQueryOptions } from './types.js'\n\nexport type UndefinedInitialDataOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey> & {\n  initialData?: undefined | InitialDataFunction<NonUndefinedGuard<TQueryFnData>>\n}\n\nexport type DefinedInitialDataOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey> & {\n  initialData:\n    | NonUndefinedGuard<TQueryFnData>\n    | (() => NonUndefinedGuard<TQueryFnData>)\n}\n\nexport function queryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,\n): DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> & {\n  queryKey: DataTag<TQueryKey, TQueryFnData>\n}\n\nexport function queryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,\n): UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> & {\n  queryKey: DataTag<TQueryKey, TQueryFnData>\n}\n\nexport function queryOptions(options: unknown) {\n  return options\n}\n"
  },
  {
    "path": "packages/svelte-query/src/types.ts",
    "content": "import type { Snippet } from 'svelte'\nimport type {\n  DefaultError,\n  DefinedQueryObserverResult,\n  InfiniteQueryObserverOptions,\n  InfiniteQueryObserverResult,\n  MutateFunction,\n  Mutation,\n  MutationFilters,\n  MutationObserverOptions,\n  MutationObserverResult,\n  MutationState,\n  OmitKeyof,\n  Override,\n  QueryClient,\n  QueryKey,\n  QueryObserverOptions,\n  QueryObserverResult,\n} from '@tanstack/query-core'\n\nexport type Accessor<T> = () => T\n\n/** Options for createBaseQuery */\nexport type CreateBaseQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = QueryObserverOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>\n\n/** Result from createBaseQuery */\nexport type CreateBaseQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = QueryObserverResult<TData, TError>\n\n/** Options for createQuery */\nexport type CreateQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = CreateBaseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>\n\n/** Result from createQuery */\nexport type CreateQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = CreateBaseQueryResult<TData, TError>\n\n/** Options for createInfiniteQuery */\nexport type CreateInfiniteQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> = InfiniteQueryObserverOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey,\n  TPageParam\n>\n\n/** Result from createInfiniteQuery */\nexport type CreateInfiniteQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = InfiniteQueryObserverResult<TData, TError>\n\n/** Options for createBaseQuery with initialData */\nexport type DefinedCreateBaseQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = DefinedQueryObserverResult<TData, TError>\n\n/** Options for createQuery with initialData */\nexport type DefinedCreateQueryResult<\n  TData = unknown,\n  TError = DefaultError,\n> = DefinedCreateBaseQueryResult<TData, TError>\n\n/** Options for createMutation */\nexport type CreateMutationOptions<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> = OmitKeyof<\n  MutationObserverOptions<TData, TError, TVariables, TOnMutateResult>,\n  '_defaulted'\n>\n\nexport type CreateMutateFunction<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> = (\n  ...args: Parameters<\n    MutateFunction<TData, TError, TVariables, TOnMutateResult>\n  >\n) => void\n\nexport type CreateMutateAsyncFunction<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> = MutateFunction<TData, TError, TVariables, TOnMutateResult>\n\nexport type CreateBaseMutationResult<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = unknown,\n  TOnMutateResult = unknown,\n> = Override<\n  MutationObserverResult<TData, TError, TVariables, TOnMutateResult>,\n  { mutate: CreateMutateFunction<TData, TError, TVariables, TOnMutateResult> }\n> & {\n  mutateAsync: CreateMutateAsyncFunction<\n    TData,\n    TError,\n    TVariables,\n    TOnMutateResult\n  >\n}\n\n/** Result from createMutation */\nexport type CreateMutationResult<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = unknown,\n  TOnMutateResult = unknown,\n> = CreateBaseMutationResult<TData, TError, TVariables, TOnMutateResult>\n\n/** Options for useMutationState */\nexport type MutationStateOptions<TResult = MutationState> = {\n  filters?: MutationFilters\n  select?: (\n    mutation: Mutation<unknown, DefaultError, unknown, unknown>,\n  ) => TResult\n}\n\nexport type QueryClientProviderProps = {\n  client: QueryClient\n  children: Snippet\n}\n"
  },
  {
    "path": "packages/svelte-query/src/useHydrate.ts",
    "content": "import { hydrate } from '@tanstack/query-core'\nimport { useQueryClient } from './useQueryClient.js'\nimport type { HydrateOptions, QueryClient } from '@tanstack/query-core'\n\nexport function useHydrate(\n  state?: unknown,\n  options?: HydrateOptions,\n  queryClient?: QueryClient,\n) {\n  const client = useQueryClient(queryClient)\n\n  if (state) {\n    hydrate(client, state, options)\n  }\n}\n"
  },
  {
    "path": "packages/svelte-query/src/useIsFetching.svelte.ts",
    "content": "import { ReactiveValue } from './containers.svelte.js'\nimport { useQueryClient } from './useQueryClient.js'\nimport type { QueryClient, QueryFilters } from '@tanstack/query-core'\n\nexport function useIsFetching(\n  filters?: QueryFilters,\n  queryClient?: QueryClient,\n): ReactiveValue<number> {\n  const client = useQueryClient(queryClient)\n  const queryCache = client.getQueryCache()\n\n  return new ReactiveValue(\n    () => client.isFetching(filters),\n    (update) => queryCache.subscribe(update),\n  )\n}\n"
  },
  {
    "path": "packages/svelte-query/src/useIsMutating.svelte.ts",
    "content": "import { useQueryClient } from './useQueryClient.js'\nimport { ReactiveValue } from './containers.svelte.js'\nimport type { MutationFilters, QueryClient } from '@tanstack/query-core'\n\nexport function useIsMutating(\n  filters?: MutationFilters,\n  queryClient?: QueryClient,\n): ReactiveValue<number> {\n  const client = useQueryClient(queryClient)\n  const cache = client.getMutationCache()\n\n  return new ReactiveValue(\n    () => client.isMutating(filters),\n    (update) => cache.subscribe(update),\n  )\n}\n"
  },
  {
    "path": "packages/svelte-query/src/useIsRestoring.ts",
    "content": "import { getIsRestoringContext } from './context.js'\nimport type { Box } from './containers.svelte.js'\n\nexport function useIsRestoring(): Box<boolean> {\n  return getIsRestoringContext()\n}\n"
  },
  {
    "path": "packages/svelte-query/src/useMutationState.svelte.ts",
    "content": "import { replaceEqualDeep } from '@tanstack/query-core'\nimport { useQueryClient } from './useQueryClient.js'\nimport type {\n  MutationCache,\n  MutationState,\n  QueryClient,\n} from '@tanstack/query-core'\nimport type { MutationStateOptions } from './types.js'\n\nfunction getResult<TResult = MutationState>(\n  mutationCache: MutationCache,\n  options: MutationStateOptions<TResult>,\n): Array<TResult> {\n  return mutationCache\n    .findAll(options.filters)\n    .map(\n      (mutation): TResult =>\n        (options.select ? options.select(mutation) : mutation.state) as TResult,\n    )\n}\n\nexport function useMutationState<TResult = MutationState>(\n  options: MutationStateOptions<TResult> = {},\n  queryClient?: QueryClient,\n): Array<TResult> {\n  const mutationCache = useQueryClient(queryClient).getMutationCache()\n  const result = $state(getResult(mutationCache, options))\n\n  $effect(() => {\n    const unsubscribe = mutationCache.subscribe(() => {\n      const nextResult = replaceEqualDeep(\n        result,\n        getResult(mutationCache, options),\n      )\n      if (result !== nextResult) {\n        Object.assign(result, nextResult)\n      }\n    })\n\n    return unsubscribe\n  })\n\n  /*  $effect(() => {\n    mutationCache.subscribe(() => {\n      const nextResult = replaceEqualDeep(\n        result.current,\n        getResult(mutationCache, optionsRef),\n      )\n      if (result.current !== nextResult) {\n        result = nextResult\n        //notifyManager.schedule(onStoreChange)\n      }\n    })\n  }) */\n  return result\n}\n"
  },
  {
    "path": "packages/svelte-query/src/useQueryClient.ts",
    "content": "import { getQueryClientContext } from './context.js'\nimport type { QueryClient } from '@tanstack/query-core'\n\nexport function useQueryClient(queryClient?: QueryClient): QueryClient {\n  if (queryClient) return queryClient\n  return getQueryClientContext()\n}\n"
  },
  {
    "path": "packages/svelte-query/src/utils.svelte.ts",
    "content": "import { untrack } from 'svelte'\n// modified from the great https://github.com/svecosystem/runed\nfunction runEffect(\n  flush: 'post' | 'pre',\n  effect: () => void | VoidFunction,\n): void {\n  switch (flush) {\n    case 'post':\n      $effect(effect)\n      break\n    case 'pre':\n      $effect.pre(effect)\n      break\n  }\n}\ntype Getter<T> = () => T\nexport const watchChanges = <T>(\n  sources: Getter<T> | Array<Getter<T>>,\n  flush: 'post' | 'pre',\n  effect: (\n    values: T | Array<T>,\n    previousValues: T | undefined | Array<T | undefined>,\n  ) => void,\n) => {\n  let active = false\n  let previousValues: T | undefined | Array<T | undefined> = Array.isArray(\n    sources,\n  )\n    ? []\n    : undefined\n  runEffect(flush, () => {\n    const values = Array.isArray(sources)\n      ? sources.map((source) => source())\n      : sources()\n    if (!active) {\n      active = true\n      previousValues = values\n      return\n    }\n    const cleanup = untrack(() => effect(values, previousValues))\n    previousValues = values\n    return cleanup\n  })\n}\n"
  },
  {
    "path": "packages/svelte-query/svelte.config.js",
    "content": "import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'\n\nconst config = {\n  preprocess: vitePreprocess(),\n  compilerOptions: {\n    runes: true,\n  },\n}\n\nexport default config\n"
  },
  {
    "path": "packages/svelte-query/tests/HydrationBoundary/BaseExample.svelte",
    "content": "<script lang=\"ts\">\n  import { QueryClient } from '@tanstack/query-core'\n  import {\n    HydrationBoundary,\n    createQuery,\n    setQueryClientContext,\n  } from '../../src/index.js'\n  import type { DehydratedState } from '@tanstack/query-core'\n\n  let {\n    dehydratedState,\n    queryFn,\n  }: {\n    dehydratedState: DehydratedState\n    queryFn: () => Promise<string>\n  } = $props()\n\n  const queryClient = new QueryClient()\n  setQueryClientContext(queryClient)\n\n  const query = createQuery(() => ({\n    queryKey: ['string'],\n    queryFn,\n  }))\n</script>\n\n<HydrationBoundary\n  state={dehydratedState}\n  options={undefined}\n  queryClient={undefined}\n>\n  <div>data: {query.data ?? 'undefined'}</div>\n</HydrationBoundary>\n"
  },
  {
    "path": "packages/svelte-query/tests/HydrationBoundary/HydrationBoundary.svelte.test.ts",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { render } from '@testing-library/svelte'\nimport { QueryClient, dehydrate } from '@tanstack/query-core'\nimport { sleep } from '@tanstack/query-test-utils'\nimport BaseExample from './BaseExample.svelte'\n\ndescribe('HydrationBoundary', () => {\n  let stringifiedState: string\n\n  beforeEach(async () => {\n    vi.useFakeTimers()\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: ['string'],\n      queryFn: () => sleep(10).then(() => 'stringCached'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n    const dehydrated = dehydrate(queryClient)\n    stringifiedState = JSON.stringify(dehydrated)\n    queryClient.clear()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should hydrate queries to the cache on context', async () => {\n    const dehydratedState = JSON.parse(stringifiedState)\n\n    const rendered = render(BaseExample, {\n      props: {\n        dehydratedState,\n        queryFn: () => sleep(20).then(() => 'string'),\n      },\n    })\n\n    expect(rendered.getByText('data: stringCached')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(21)\n    expect(rendered.getByText('data: string')).toBeInTheDocument()\n  })\n})\n"
  },
  {
    "path": "packages/svelte-query/tests/ProviderWrapper.svelte",
    "content": "<script lang=\"ts\">\n  import { QueryClient } from '@tanstack/query-core'\n  import { QueryClientProvider } from '../src/index.js'\n  import { Snippet } from 'svelte'\n\n  const {\n    queryClient = new QueryClient(),\n    children,\n  }: { queryClient?: QueryClient; children: Snippet } = $props()\n</script>\n\n<QueryClientProvider client={queryClient}>\n  {@render children()}\n</QueryClientProvider>\n"
  },
  {
    "path": "packages/svelte-query/tests/QueryClientProvider/ChildComponent.svelte",
    "content": "<script lang=\"ts\">\n  import { createQuery } from '../../src/index.js'\n  import { sleep } from '@tanstack/query-test-utils'\n\n  const query = createQuery(() => ({\n    queryKey: ['hello'],\n    queryFn: () => sleep(10).then(() => 'test'),\n  }))\n</script>\n\n<div>Data: {query.data ?? 'undefined'}</div>\n"
  },
  {
    "path": "packages/svelte-query/tests/QueryClientProvider/ParentComponent.svelte",
    "content": "<script lang=\"ts\">\n  import { QueryClientProvider } from '../../src/index.js'\n  import ChildComponent from './ChildComponent.svelte'\n  import type { QueryClient } from '@tanstack/query-core'\n\n  let { queryClient }: { queryClient: QueryClient } = $props()\n</script>\n\n<QueryClientProvider client={queryClient}>\n  <ChildComponent />\n</QueryClientProvider>\n"
  },
  {
    "path": "packages/svelte-query/tests/QueryClientProvider/QueryClientProvider.svelte.test.ts",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { render } from '@testing-library/svelte'\nimport { QueryClient } from '@tanstack/query-core'\nimport ParentComponent from './ParentComponent.svelte'\n\ndescribe('QueryClientProvider', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('Sets a specific cache for all queries to use', async () => {\n    const queryClient = new QueryClient()\n    const queryCache = queryClient.getQueryCache()\n\n    const rendered = render(ParentComponent, {\n      props: {\n        queryClient: queryClient,\n      },\n    })\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Data: test')).toBeInTheDocument()\n\n    expect(queryCache.find({ queryKey: ['hello'] })).toBeDefined()\n  })\n})\n"
  },
  {
    "path": "packages/svelte-query/tests/containers.svelte.test.ts",
    "content": "import { flushSync } from 'svelte'\nimport { describe, expect, it } from 'vitest'\nimport { createRawRef } from '../src/containers.svelte.js'\nimport { withEffectRoot } from './utils.svelte.js'\n\ndescribe('createRawRef', () => {\n  it('should create a reactive reference', () => {\n    const [ref, update] = createRawRef({ a: 1, b: 2 })\n\n    expect(ref).toEqual({ a: 1, b: 2 })\n\n    update({ a: 3, b: 4 })\n    expect(ref).toEqual({ a: 3, b: 4 })\n\n    ref.a = 5\n    expect(ref).toEqual({ a: 5, b: 4 })\n  })\n\n  it('should handle nested objects', () => {\n    const [ref, update] = createRawRef<{ a: any }>({ a: { b: { c: 1 } } })\n\n    expect(ref).toEqual({ a: { b: { c: 1 } } })\n\n    // update with same structure\n    update({ a: { b: { c: 2 } } })\n    expect(ref).toEqual({ a: { b: { c: 2 } } })\n\n    ref.a.b.c = 3\n    expect(ref).toEqual({ a: { b: { c: 3 } } })\n\n    // update with different structure should wipe out everything below the first level\n    update({ a: { b: 3 } })\n    expect(ref).toEqual({ a: { b: 3 } })\n  })\n\n  it('should remove properties when a new object is assigned', () => {\n    const [ref, update] = createRawRef<Record<string, number>>({\n      a: 1,\n      b: 2,\n    })\n\n    expect(ref).toEqual({ a: 1, b: 2 })\n\n    update({ a: 3 })\n    expect(ref).toEqual({ a: 3 })\n  })\n\n  it(\n    'should not break reactivity when removing keys',\n    withEffectRoot(() => {\n      const [ref, update] = createRawRef<Record<string, number>>({ a: 1, b: 2 })\n      const states: Array<number | undefined> = []\n      $effect(() => {\n        states.push(ref.b)\n      })\n\n      // these flushSync calls force the effect to run and push the value to the states array\n      flushSync()\n      update({ a: 3 }) // should remove b, and should rerun the effect\n      flushSync()\n      update({ a: 3, b: 4 }) // should add b back, and should rerun the effect\n      flushSync()\n      delete ref.b // should remove b, and should rerun the effect\n      flushSync()\n      delete ref.a // should remove a, and should _not_ rerun the effect\n      expect(states).toEqual([2, undefined, 4, undefined])\n    }),\n  )\n\n  it(\n    'should correctly trap calls to `in`',\n    withEffectRoot(() => {\n      const [ref, update] = createRawRef<Record<string, number>>({\n        a: 1,\n        b: 2,\n      })\n\n      expect('b' in ref).toBe(true)\n      delete ref.b\n      expect('b' in ref).toBe(false)\n      update({})\n      expect('a' in ref).toBe(false)\n      update({ a: 1, b: 2 })\n      expect('b' in ref).toBe(true)\n      expect('a' in ref).toBe(true)\n    }),\n  )\n\n  it('should correctly trap calls to `ownKeys`', () => {\n    const [ref, update] = createRawRef<Record<string, number>>({\n      a: 1,\n      b: 2,\n    })\n\n    expect(Object.keys(ref)).toEqual(['a', 'b'])\n\n    delete ref.b\n    expect(Reflect.ownKeys(ref)).toEqual(['a'])\n\n    update({})\n    expect(Object.keys(ref)).toEqual([])\n\n    update({ a: 1, b: 2 })\n    expect(Object.keys(ref)).toEqual(['a', 'b'])\n  })\n\n  it('should correctly trap calls to `getOwnPropertyDescriptor`', () => {\n    const [ref, update] = createRawRef<Record<string, number>>({\n      a: 1,\n      b: 2,\n    })\n\n    expect(Reflect.getOwnPropertyDescriptor(ref, 'b')).toEqual({\n      configurable: true,\n      enumerable: true,\n      get: expect.any(Function),\n      set: expect.any(Function),\n    })\n\n    delete ref.b\n    expect(Reflect.getOwnPropertyDescriptor(ref, 'b')).toEqual(undefined)\n\n    update({})\n    expect(Reflect.getOwnPropertyDescriptor(ref, 'a')).toEqual(undefined)\n\n    update({ a: 1, b: 2 })\n    expect(Reflect.getOwnPropertyDescriptor(ref, 'a')).toEqual({\n      configurable: true,\n      enumerable: true,\n      get: expect.any(Function),\n      set: expect.any(Function),\n    })\n    expect(Reflect.getOwnPropertyDescriptor(ref, 'b')).toEqual({\n      configurable: true,\n      enumerable: true,\n      get: expect.any(Function),\n      set: expect.any(Function),\n    })\n  })\n\n  it('should lazily access values when using `update`', () => {\n    let aAccessed = false\n    let bAccessed = false\n    const [ref, update] = createRawRef({\n      get a() {\n        aAccessed = true\n        return 1\n      },\n      get b() {\n        bAccessed = true\n        return 2\n      },\n    })\n\n    expect(aAccessed).toBe(false)\n    expect(bAccessed).toBe(false)\n\n    expect(ref.a).toBe(1)\n\n    expect(aAccessed).toBe(true)\n    expect(bAccessed).toBe(false)\n\n    aAccessed = false\n    bAccessed = false\n\n    update({\n      get a() {\n        aAccessed = true\n        return 2\n      },\n      get b() {\n        bAccessed = true\n        return 3\n      },\n    })\n\n    expect(aAccessed).toBe(false)\n    expect(bAccessed).toBe(false)\n\n    expect(ref.a).toBe(2)\n\n    expect(aAccessed).toBe(true)\n    expect(bAccessed).toBe(false)\n  })\n\n  it('should handle arrays', () => {\n    const [ref, update] = createRawRef([1, 2, 3])\n\n    expect(ref).toEqual([1, 2, 3])\n\n    ref[0] = 4\n    expect(ref).toEqual([4, 2, 3])\n\n    update([5, 6])\n    expect(ref).toEqual([5, 6])\n\n    update([7, 8, 9])\n    expect(ref).toEqual([7, 8, 9])\n  })\n\n  it('should behave like a regular object when not using `update`', () => {\n    const [ref] = createRawRef<Record<string, unknown>>({ a: 1, b: 2 })\n\n    expect(ref).toEqual({ a: 1, b: 2 })\n\n    ref.a = 3\n    expect(ref).toEqual({ a: 3, b: 2 })\n\n    ref.b = 4\n    expect(ref).toEqual({ a: 3, b: 4 })\n\n    ref.c = 5\n    expect(ref).toEqual({ a: 3, b: 4, c: 5 })\n\n    ref.fn = () => 6\n    expect(ref).toEqual({ a: 3, b: 4, c: 5, fn: expect.any(Function) })\n    expect((ref.fn as () => number)()).toBe(6)\n  })\n})\n"
  },
  {
    "path": "packages/svelte-query/tests/context/BaseExample.svelte",
    "content": "<script lang=\"ts\">\n  import { getQueryClientContext } from '../../src/index.js'\n\n  getQueryClientContext()\n</script>\n"
  },
  {
    "path": "packages/svelte-query/tests/context/context.svelte.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { render } from '@testing-library/svelte'\nimport { getIsRestoringContext } from '../../src/index.js'\nimport BaseExample from './BaseExample.svelte'\n\ndescribe('getQueryClientContext', () => {\n  test('Throw when called without a client in context', () => {\n    expect(() => render(BaseExample)).toThrowError(\n      'No QueryClient was found in Svelte context. Did you forget to wrap your component with QueryClientProvider?',\n    )\n  })\n})\n\ndescribe('getIsRestoringContext', () => {\n  test('Do not throw when called outside of a component', () => {\n    expect(() => getIsRestoringContext()).not.toThrowError()\n  })\n})\n"
  },
  {
    "path": "packages/svelte-query/tests/createInfiniteQuery/BaseExample.svelte",
    "content": "<script lang=\"ts\">\n  import { untrack } from 'svelte'\n  import { QueryClient } from '@tanstack/query-core'\n  import { sleep } from '@tanstack/query-test-utils'\n  import { createInfiniteQuery } from '../../src/index.js'\n  import type { QueryObserverResult } from '@tanstack/query-core'\n\n  let { states }: { states: { value: Array<QueryObserverResult> } } = $props()\n\n  const queryClient = new QueryClient()\n\n  const query = createInfiniteQuery(\n    () => ({\n      queryKey: ['test'],\n      queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n      getNextPageParam: (lastPage) => lastPage + 1,\n      initialPageParam: 0,\n    }),\n    () => queryClient,\n  )\n\n  $effect(() => {\n    // @ts-expect-error\n    // svelte-ignore state_snapshot_uncloneable\n    states.value = [...untrack(() => states.value), $state.snapshot(query)]\n  })\n</script>\n\n<div>Status: {query.status}</div>\n"
  },
  {
    "path": "packages/svelte-query/tests/createInfiniteQuery/ChangeClient.svelte",
    "content": "<script lang=\"ts\">\n  import { QueryClient } from '@tanstack/query-core'\n  import { createInfiniteQuery } from '../../src/index.js'\n  import { sleep } from '@tanstack/query-test-utils'\n\n  let { queryClient }: { queryClient: QueryClient } = $props()\n\n  const queryKey = ['test']\n\n  let firstPage = $state(0)\n\n  const query = createInfiniteQuery(\n    () => ({\n      queryKey: queryKey,\n      queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),\n      getNextPageParam: (lastPage) => lastPage + 1,\n      initialPageParam: firstPage,\n    }),\n    () => queryClient,\n  )\n</script>\n\n<button\n  onclick={() => {\n    queryClient.setQueryData(queryKey, {\n      pages: [7, 8],\n      pageParams: [7, 8],\n    })\n    firstPage = 7\n  }}\n>\n  setPages\n</button>\n\n<div>Data: {JSON.stringify(query.data)}</div>\n"
  },
  {
    "path": "packages/svelte-query/tests/createInfiniteQuery/SelectExample.svelte",
    "content": "<script lang=\"ts\">\n  import { untrack } from 'svelte'\n  import { QueryClient } from '@tanstack/query-core'\n  import { createInfiniteQuery } from '../../src/index.js'\n  import type { QueryObserverResult } from '@tanstack/query-core'\n  import { sleep } from '@tanstack/query-test-utils'\n\n  let { states }: { states: { value: Array<QueryObserverResult> } } = $props()\n\n  const queryClient = new QueryClient()\n\n  const query = createInfiniteQuery(\n    () => ({\n      queryKey: ['test'],\n      queryFn: () => sleep(10).then(() => ({ count: 1 })),\n      select: (data) => ({\n        pages: data.pages.map((x) => `count: ${x.count}`),\n        pageParams: data.pageParams,\n      }),\n      getNextPageParam: () => undefined,\n      initialPageParam: 0,\n    }),\n    () => queryClient,\n  )\n\n  $effect(() => {\n    // @ts-expect-error\n    // svelte-ignore state_snapshot_uncloneable\n    states.value = [...untrack(() => states.value), $state.snapshot(query)]\n  })\n</script>\n\n<div>{query.data?.pages.join(',')}</div>\n"
  },
  {
    "path": "packages/svelte-query/tests/createInfiniteQuery/createInfiniteQuery.svelte.test.ts",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { fireEvent, render } from '@testing-library/svelte'\nimport { QueryClient } from '@tanstack/query-core'\nimport { ref } from '../utils.svelte.js'\nimport BaseExample from './BaseExample.svelte'\nimport SelectExample from './SelectExample.svelte'\nimport ChangeClient from './ChangeClient.svelte'\nimport type { QueryObserverResult } from '@tanstack/query-core'\n\ndescribe('createInfiniteQuery', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should return the correct states for a successful query', async () => {\n    let states = ref<Array<QueryObserverResult>>([])\n\n    const rendered = render(BaseExample, {\n      props: {\n        states,\n      },\n    })\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Status: success')).toBeInTheDocument()\n\n    expect(states.value).toHaveLength(2)\n\n    expect(states.value[0]).toEqual({\n      data: undefined,\n      dataUpdatedAt: 0,\n      error: null,\n      errorUpdatedAt: 0,\n      failureCount: 0,\n      failureReason: null,\n      errorUpdateCount: 0,\n      fetchNextPage: expect.any(Function),\n      fetchPreviousPage: expect.any(Function),\n      hasNextPage: false,\n      hasPreviousPage: false,\n      isError: false,\n      isFetched: false,\n      isFetchedAfterMount: false,\n      isFetching: true,\n      isPaused: false,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isLoading: true,\n      isPending: true,\n      isInitialLoading: true,\n      isLoadingError: false,\n      isPlaceholderData: false,\n      isRefetchError: false,\n      isRefetching: false,\n      isStale: true,\n      isSuccess: false,\n      isEnabled: true,\n      refetch: expect.any(Function),\n      status: 'pending',\n      fetchStatus: 'fetching',\n      promise: expect.any(Promise),\n    })\n\n    expect(states.value[1]).toEqual({\n      data: { pages: [0], pageParams: [0] },\n      dataUpdatedAt: expect.any(Number),\n      error: null,\n      errorUpdatedAt: 0,\n      failureCount: 0,\n      failureReason: null,\n      errorUpdateCount: 0,\n      fetchNextPage: expect.any(Function),\n      fetchPreviousPage: expect.any(Function),\n      hasNextPage: true,\n      hasPreviousPage: false,\n      isError: false,\n      isFetched: true,\n      isFetchedAfterMount: true,\n      isFetching: false,\n      isPaused: false,\n      isFetchNextPageError: false,\n      isFetchingNextPage: false,\n      isFetchPreviousPageError: false,\n      isFetchingPreviousPage: false,\n      isLoading: false,\n      isPending: false,\n      isInitialLoading: false,\n      isLoadingError: false,\n      isPlaceholderData: false,\n      isRefetchError: false,\n      isRefetching: false,\n      isStale: true,\n      isSuccess: true,\n      isEnabled: true,\n      refetch: expect.any(Function),\n      status: 'success',\n      fetchStatus: 'idle',\n      promise: expect.any(Promise),\n    })\n  })\n\n  it('should be able to select a part of the data', async () => {\n    let states = ref<Array<QueryObserverResult>>([])\n\n    const rendered = render(SelectExample, {\n      props: {\n        states,\n      },\n    })\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('count: 1')).toBeInTheDocument()\n\n    expect(states.value).toHaveLength(2)\n\n    expect(states.value[0]).toMatchObject({\n      data: undefined,\n      isSuccess: false,\n    })\n\n    expect(states.value[1]).toMatchObject({\n      data: { pages: ['count: 1'] },\n      isSuccess: true,\n    })\n  })\n\n  it('should be able to set new pages with the query client', async () => {\n    const queryClient = new QueryClient()\n\n    const rendered = render(ChangeClient, {\n      props: {\n        queryClient,\n      },\n    })\n\n    await vi.advanceTimersByTimeAsync(11)\n    expect(\n      rendered.getByText('Data: {\"pages\":[0],\"pageParams\":[0]}'),\n    ).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /setPages/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(\n      rendered.getByText('Data: {\"pages\":[7,8],\"pageParams\":[7,8]}'),\n    ).toBeInTheDocument()\n  })\n})\n"
  },
  {
    "path": "packages/svelte-query/tests/createMutation/FailureExample.svelte",
    "content": "<script lang=\"ts\">\n  import { QueryClient } from '@tanstack/query-core'\n  import { createMutation, setQueryClientContext } from '../../src/index.js'\n\n  let {\n    mutationFn,\n  }: { mutationFn: (value: { count: number }) => Promise<{ count: number }> } =\n    $props()\n\n  let count = $state(0)\n\n  const queryClient = new QueryClient()\n  setQueryClientContext(queryClient)\n\n  const mutation = createMutation(() => ({ mutationFn }))\n</script>\n\n<button onclick={() => mutation.mutate({ count: ++count })}>Mutate</button>\n\n<div>Data: {mutation.data?.count ?? 'undefined'}</div>\n<div>Status: {mutation.status}</div>\n<div>Failure Count: {mutation.failureCount}</div>\n<div>Failure Reason: {mutation.failureReason ?? 'undefined'}</div>\n"
  },
  {
    "path": "packages/svelte-query/tests/createMutation/OnSuccessExample.svelte",
    "content": "<script lang=\"ts\">\n  import { QueryClient } from '@tanstack/query-core'\n  import { createMutation, setQueryClientContext } from '../../src/index.js'\n  import { sleep } from '@tanstack/query-test-utils'\n\n  type Props = {\n    onSuccessMock: any\n    onSettledMock: any\n  }\n\n  const { onSettledMock, onSuccessMock }: Props = $props()\n\n  let count = $state(0)\n\n  const queryClient = new QueryClient()\n  setQueryClientContext(queryClient)\n\n  const mutation = createMutation(() => ({\n    mutationFn: (vars: { count: number }) => sleep(10).then(() => vars.count),\n    onSuccess: (data) => {\n      onSuccessMock(data)\n    },\n    onSettled: (data) => {\n      onSettledMock(data)\n    },\n  }))\n</script>\n\n<button onclick={() => mutation.mutate({ count: ++count })}>Mutate</button>\n\n<div>Count: {count}</div>\n"
  },
  {
    "path": "packages/svelte-query/tests/createMutation/ResetExample.svelte",
    "content": "<script lang=\"ts\">\n  import { QueryClient } from '@tanstack/query-core'\n  import { createMutation, setQueryClientContext } from '../../src/index.js'\n  import { sleep } from '@tanstack/query-test-utils'\n\n  const queryClient = new QueryClient()\n  setQueryClientContext(queryClient)\n\n  const mutation = createMutation(() => ({\n    mutationFn: () =>\n      sleep(10).then(() => Promise.reject(new Error('Expected mock error'))),\n  }))\n</script>\n\n<button onclick={() => mutation.reset()}>Reset</button>\n<button onclick={() => mutation.mutate()}>Mutate</button>\n\n<div>Error: {mutation.error?.message ?? 'undefined'}</div>\n"
  },
  {
    "path": "packages/svelte-query/tests/createMutation/createMutation.svelte.test.ts",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { flushSync } from 'svelte'\nimport { fireEvent, render } from '@testing-library/svelte'\nimport { QueryClient } from '@tanstack/query-core'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { createMutation } from '../../src/index.js'\nimport { withEffectRoot } from '../utils.svelte.js'\nimport ResetExample from './ResetExample.svelte'\nimport OnSuccessExample from './OnSuccessExample.svelte'\nimport FailureExample from './FailureExample.svelte'\n\ndescribe('createMutation', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('Able to reset `error`', async () => {\n    const rendered = render(ResetExample)\n\n    expect(rendered.queryByText('Error: undefined')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /Mutate/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Error: Expected mock error')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /Reset/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Error: undefined')).toBeInTheDocument()\n  })\n\n  test('Able to call `onSuccess` and `onSettled` after each successful mutate', async () => {\n    const onSuccessMock = vi.fn()\n    const onSettledMock = vi.fn()\n\n    const rendered = render(OnSuccessExample, {\n      props: {\n        onSuccessMock,\n        onSettledMock,\n      },\n    })\n\n    expect(rendered.queryByText('Count: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /Mutate/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /Mutate/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /Mutate/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.queryByText('Count: 3')).toBeInTheDocument()\n\n    expect(onSuccessMock).toHaveBeenCalledTimes(3)\n    expect(onSuccessMock).toHaveBeenNthCalledWith(1, 1)\n    expect(onSuccessMock).toHaveBeenNthCalledWith(2, 2)\n    expect(onSuccessMock).toHaveBeenNthCalledWith(3, 3)\n\n    expect(onSettledMock).toHaveBeenCalledTimes(3)\n    expect(onSettledMock).toHaveBeenNthCalledWith(1, 1)\n    expect(onSettledMock).toHaveBeenNthCalledWith(2, 2)\n    expect(onSettledMock).toHaveBeenNthCalledWith(3, 3)\n  })\n\n  test('Set correct values for `failureReason` and `failureCount` on multiple mutate calls', async () => {\n    type Value = { count: number }\n\n    const mutationFn = vi.fn<(value: Value) => Promise<Value>>()\n\n    mutationFn.mockImplementationOnce(() =>\n      sleep(20).then(() => Promise.reject(`Expected mock error`)),\n    )\n\n    mutationFn.mockImplementation((value) => sleep(10).then(() => value))\n\n    const rendered = render(FailureExample, {\n      props: {\n        mutationFn,\n      },\n    })\n\n    expect(rendered.queryByText('Data: undefined')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /Mutate/i }))\n    expect(rendered.getByText('Data: undefined')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(21)\n    expect(rendered.getByText('Status: error')).toBeInTheDocument()\n    expect(rendered.getByText('Failure Count: 1')).toBeInTheDocument()\n    expect(\n      rendered.getByText('Failure Reason: Expected mock error'),\n    ).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /Mutate/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Status: pending')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('Status: success')).toBeInTheDocument()\n    expect(rendered.getByText('Data: 2')).toBeInTheDocument()\n    expect(rendered.getByText('Failure Count: 0')).toBeInTheDocument()\n    expect(rendered.getByText('Failure Reason: undefined')).toBeInTheDocument()\n  })\n\n  test(\n    'should recreate observer when queryClient changes',\n    withEffectRoot(async () => {\n      const queryClient1 = new QueryClient()\n      const queryClient2 = new QueryClient()\n\n      let queryClient = $state(queryClient1)\n\n      const mutation = createMutation(\n        () => ({\n          mutationFn: (params: string) => sleep(10).then(() => params),\n        }),\n        () => queryClient,\n      )\n\n      mutation.mutate('first')\n      await vi.advanceTimersByTimeAsync(11)\n\n      expect(mutation.status).toBe('success')\n      expect(mutation.data).toBe('first')\n\n      queryClient = queryClient2\n      flushSync()\n\n      expect(mutation.status).toBe('idle')\n      expect(mutation.data).toBeUndefined()\n    }),\n  )\n})\n"
  },
  {
    "path": "packages/svelte-query/tests/createQueries.svelte.test.ts",
    "content": "import { afterEach, describe, expect, expectTypeOf, it, vi } from 'vitest'\nimport { QueryClient, createQueries } from '../src/index.js'\nimport { promiseWithResolvers, withEffectRoot } from './utils.svelte.js'\nimport type {\n  CreateQueryOptions,\n  CreateQueryResult,\n  QueryFunction,\n  QueryFunctionContext,\n  QueryKey,\n  skipToken,\n} from '../src/index.js'\n\ndescribe('createQueries', () => {\n  const queryClient = new QueryClient()\n\n  afterEach(() => {\n    queryClient.clear()\n  })\n\n  it(\n    'should return the correct states',\n    withEffectRoot(async () => {\n      const key1 = ['test-1']\n      const key2 = ['test-2']\n      const results: Array<Array<CreateQueryResult>> = []\n      const { promise: promise1, resolve: resolve1 } = promiseWithResolvers()\n      const { promise: promise2, resolve: resolve2 } = promiseWithResolvers()\n\n      const result = createQueries(\n        () => ({\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: () => promise1,\n            },\n            {\n              queryKey: key2,\n              queryFn: () => promise2,\n            },\n          ],\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        results.push([{ ...result[0] }, { ...result[1] }])\n      })\n\n      resolve1(1)\n\n      await vi.waitFor(() => expect(result[0].data).toBe(1))\n\n      resolve2(2)\n      await vi.waitFor(() => expect(result[1].data).toBe(2))\n\n      expect(results.length).toBe(3)\n      expect(results[0]).toMatchObject([\n        { data: undefined },\n        { data: undefined },\n      ])\n      expect(results[1]).toMatchObject([{ data: 1 }, { data: undefined }])\n      expect(results[2]).toMatchObject([{ data: 1 }, { data: 2 }])\n    }),\n  )\n\n  it(\n    'handles type parameter - tuple of tuples',\n    withEffectRoot(() => {\n      const key1 = ['test-key-1']\n      const key2 = ['test-key-2']\n      const key3 = ['test-key-3']\n\n      const result1 = createQueries<\n        [[number], [string], [Array<string>, boolean]]\n      >(\n        () => ({\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: () => 1,\n            },\n            {\n              queryKey: key2,\n              queryFn: () => 'string',\n            },\n            {\n              queryKey: key3,\n              queryFn: () => ['string[]'],\n            },\n          ],\n        }),\n        () => queryClient,\n      )\n\n      expectTypeOf(result1[0]).toEqualTypeOf<\n        CreateQueryResult<number, unknown>\n      >()\n      expectTypeOf(result1[1]).toEqualTypeOf<\n        CreateQueryResult<string, unknown>\n      >()\n      expectTypeOf(result1[2]).toEqualTypeOf<\n        CreateQueryResult<Array<string>, boolean>\n      >()\n      expectTypeOf(result1[0].data).toEqualTypeOf<number | undefined>()\n      expectTypeOf(result1[1].data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(result1[2].data).toEqualTypeOf<Array<string> | undefined>()\n      expectTypeOf(result1[2].error).toEqualTypeOf<boolean | null>()\n\n      // TData (3rd element) takes precedence over TQueryFnData (1st element)\n      const result2 = createQueries<\n        [[string, unknown, string], [string, unknown, number]]\n      >(\n        () => ({\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: () => 'string',\n              select: (a) => {\n                expectTypeOf(a).toEqualTypeOf<string>()\n                return a.toLowerCase()\n              },\n            },\n            {\n              queryKey: key2,\n              queryFn: () => 'string',\n              select: (a) => {\n                expectTypeOf(a).toEqualTypeOf<string>()\n                return parseInt(a)\n              },\n            },\n          ],\n        }),\n        () => queryClient,\n      )\n\n      expectTypeOf(result2[0]).toEqualTypeOf<\n        CreateQueryResult<string, unknown>\n      >()\n      expectTypeOf(result2[1]).toEqualTypeOf<\n        CreateQueryResult<number, unknown>\n      >()\n      expectTypeOf(result2[0].data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(result2[1].data).toEqualTypeOf<number | undefined>()\n\n      // types should be enforced\n      createQueries<[[string, unknown, string], [string, boolean, number]]>(\n        () => ({\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: () => 'string',\n              select: (a) => {\n                expectTypeOf(a).toEqualTypeOf<string>()\n                return a.toLowerCase()\n              },\n              placeholderData: 'string',\n              // @ts-expect-error (initialData: string)\n              initialData: 123,\n            },\n            {\n              queryKey: key2,\n              queryFn: () => 'string',\n              select: (a) => {\n                expectTypeOf(a).toEqualTypeOf<string>()\n                return parseInt(a)\n              },\n              placeholderData: 'string',\n              // @ts-expect-error (initialData: string)\n              initialData: 123,\n            },\n          ],\n        }),\n        () => queryClient,\n      )\n\n      // field names should be enforced\n      createQueries<[[string]]>(\n        () => ({\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: () => 'string',\n            },\n          ],\n        }),\n        () => queryClient,\n      )\n    }),\n  )\n\n  it(\n    'handles type parameter - tuple of objects',\n    withEffectRoot(() => {\n      const key1 = ['test-key-1']\n      const key2 = ['test-key-2']\n      const key3 = ['test-key-3']\n\n      const result1 = createQueries<\n        [\n          { queryFnData: number },\n          { queryFnData: string },\n          { queryFnData: Array<string>; error: boolean },\n        ]\n      >(\n        () => ({\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: () => 1,\n            },\n            {\n              queryKey: key2,\n              queryFn: () => 'string',\n            },\n            {\n              queryKey: key3,\n              queryFn: () => ['string[]'],\n            },\n          ],\n        }),\n        () => queryClient,\n      )\n\n      expectTypeOf(result1[0]).toEqualTypeOf<\n        CreateQueryResult<number, unknown>\n      >()\n      expectTypeOf(result1[1]).toEqualTypeOf<\n        CreateQueryResult<string, unknown>\n      >()\n      expectTypeOf(result1[2]).toEqualTypeOf<\n        CreateQueryResult<Array<string>, boolean>\n      >()\n      expectTypeOf(result1[0].data).toEqualTypeOf<number | undefined>()\n      expectTypeOf(result1[1].data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(result1[2].data).toEqualTypeOf<Array<string> | undefined>()\n      expectTypeOf(result1[2].error).toEqualTypeOf<boolean | null>()\n\n      // TData (data prop) takes precedence over TQueryFnData (queryFnData prop)\n      const result2 = createQueries<\n        [\n          { queryFnData: string; data: string },\n          { queryFnData: string; data: number },\n        ]\n      >(\n        () => ({\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: () => 'string',\n              select: (a) => {\n                expectTypeOf(a).toEqualTypeOf<string>()\n                return a.toLowerCase()\n              },\n            },\n            {\n              queryKey: key2,\n              queryFn: () => 'string',\n              select: (a) => {\n                expectTypeOf(a).toEqualTypeOf<string>()\n                return parseInt(a)\n              },\n            },\n          ],\n        }),\n        () => queryClient,\n      )\n\n      expectTypeOf(result2[0]).toEqualTypeOf<\n        CreateQueryResult<string, unknown>\n      >()\n      expectTypeOf(result2[1]).toEqualTypeOf<\n        CreateQueryResult<number, unknown>\n      >()\n      expectTypeOf(result2[0].data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(result2[1].data).toEqualTypeOf<number | undefined>()\n\n      // can pass only TData (data prop) although TQueryFnData will be left unknown\n      const result3 = createQueries<[{ data: string }, { data: number }]>(\n        () => ({\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: () => 'string',\n              select: (a) => {\n                expectTypeOf(a).toEqualTypeOf<unknown>()\n                return a as string\n              },\n            },\n            {\n              queryKey: key2,\n              queryFn: () => 'string',\n              select: (a) => {\n                expectTypeOf(a).toEqualTypeOf<unknown>()\n                return a as number\n              },\n            },\n          ],\n        }),\n        () => queryClient,\n      )\n\n      expectTypeOf(result3[0]).toEqualTypeOf<\n        CreateQueryResult<string, unknown>\n      >()\n      expectTypeOf(result3[1]).toEqualTypeOf<\n        CreateQueryResult<number, unknown>\n      >()\n      expectTypeOf(result3[0].data).toEqualTypeOf<string | undefined>()\n      expectTypeOf(result3[1].data).toEqualTypeOf<number | undefined>()\n\n      // types should be enforced\n      createQueries<\n        [\n          { queryFnData: string; data: string },\n          { queryFnData: string; data: number; error: boolean },\n        ]\n      >(\n        () => ({\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: () => 'string',\n              select: (a) => {\n                expectTypeOf(a).toEqualTypeOf<string>()\n                return a.toLowerCase()\n              },\n              placeholderData: 'string',\n              // @ts-expect-error (initialData: string)\n              initialData: 123,\n            },\n            {\n              queryKey: key2,\n              queryFn: () => 'string',\n              select: (a) => {\n                expectTypeOf(a).toEqualTypeOf<string>()\n                return parseInt(a)\n              },\n              placeholderData: 'string',\n              // @ts-expect-error (initialData: string)\n              initialData: 123,\n            },\n          ],\n        }),\n        () => queryClient,\n      )\n\n      // field names should be enforced\n      createQueries<[{ queryFnData: string }]>(\n        () => ({\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: () => 'string',\n            },\n          ],\n        }),\n        () => queryClient,\n      )\n    }),\n  )\n\n  it(\n    'handles array literal without type parameter to infer result type',\n    withEffectRoot(() => {\n      const key1 = ['test-key-1']\n      const key2 = ['test-key-2']\n      const key3 = ['test-key-3']\n      const key4 = ['test-key-4']\n\n      // Array.map preserves TQueryFnData\n      const result1 = createQueries(\n        () => ({\n          queries: Array(50).map((_, i) => ({\n            queryKey: ['key', i] as const,\n            queryFn: () => i + 10,\n          })),\n        }),\n        () => queryClient,\n      )\n\n      expectTypeOf(result1).toEqualTypeOf<\n        Array<CreateQueryResult<number, Error>>\n      >()\n      if (result1[0]) {\n        expectTypeOf(result1[0].data).toEqualTypeOf<number | undefined>()\n      }\n\n      // Array.map preserves TData\n      const result2 = createQueries(\n        () => ({\n          queries: Array(50).map((_, i) => ({\n            queryKey: ['key', i] as const,\n            queryFn: () => i + 10,\n            select: (data: number) => data.toString(),\n          })),\n        }),\n        () => queryClient,\n      )\n\n      expectTypeOf(result2).toEqualTypeOf<\n        Array<CreateQueryResult<string, Error>>\n      >()\n\n      const result3 = createQueries(\n        () => ({\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: () => 1,\n            },\n            {\n              queryKey: key2,\n              queryFn: () => 'string',\n            },\n            {\n              queryKey: key3,\n              queryFn: () => ['string[]'],\n              select: () => 123,\n            },\n          ],\n        }),\n        () => queryClient,\n      )\n\n      expectTypeOf(result3[0]).toEqualTypeOf<CreateQueryResult<number, Error>>()\n      expectTypeOf(result3[1]).toEqualTypeOf<CreateQueryResult<string, Error>>()\n      expectTypeOf(result3[2]).toEqualTypeOf<CreateQueryResult<number, Error>>()\n      expectTypeOf(result3[0].data).toEqualTypeOf<number | undefined>()\n      expectTypeOf(result3[1].data).toEqualTypeOf<string | undefined>()\n      // select takes precedence over queryFn\n      expectTypeOf(result3[2].data).toEqualTypeOf<number | undefined>()\n\n      // initialData/placeholderData are enforced\n      createQueries(\n        () => ({\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: () => 'string',\n              placeholderData: 'string',\n              // @ts-expect-error (initialData: string)\n              initialData: 123,\n            },\n            {\n              queryKey: key2,\n              queryFn: () => 123,\n              // @ts-expect-error (placeholderData: number)\n              placeholderData: 'string',\n              initialData: 123,\n            },\n          ],\n        }),\n        () => queryClient,\n      )\n\n      // select params are \"indirectly\" enforced\n      createQueries(\n        () => ({\n          queries: [\n            // unfortunately TS will not suggest the type for you\n            {\n              queryKey: key1,\n              queryFn: () => 'string',\n            },\n            // however you can add a type to the callback\n            {\n              queryKey: key2,\n              queryFn: () => 'string',\n            },\n            // the type you do pass is enforced\n            {\n              queryKey: key3,\n              queryFn: () => 'string',\n            },\n            {\n              queryKey: key4,\n              queryFn: () => 'string',\n              select: (a: string) => parseInt(a),\n            },\n          ],\n        }),\n        () => queryClient,\n      )\n\n      // callbacks are also indirectly enforced with Array.map\n      createQueries(\n        () => ({\n          queries: Array(50).map((_, i) => ({\n            queryKey: ['key', i] as const,\n            queryFn: () => i + 10,\n            select: (data: number) => data.toString(),\n          })),\n        }),\n        () => queryClient,\n      )\n\n      // results inference works when all the handlers are defined\n      const result4 = createQueries(\n        () => ({\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: () => 'string',\n            },\n            {\n              queryKey: key2,\n              queryFn: () => 'string',\n            },\n            {\n              queryKey: key4,\n              queryFn: () => 'string',\n              select: (a: string) => parseInt(a),\n            },\n          ],\n        }),\n        () => queryClient,\n      )\n\n      expectTypeOf(result4[0]).toEqualTypeOf<CreateQueryResult<string, Error>>()\n      expectTypeOf(result4[1]).toEqualTypeOf<CreateQueryResult<string, Error>>()\n      expectTypeOf(result4[2]).toEqualTypeOf<CreateQueryResult<number, Error>>()\n\n      // handles when queryFn returns a Promise\n      const result5 = createQueries(\n        () => ({\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: () => Promise.resolve('string'),\n            },\n          ],\n        }),\n        () => queryClient,\n      )\n\n      expectTypeOf(result5[0]).toEqualTypeOf<CreateQueryResult<string, Error>>()\n\n      // Array as const does not throw error\n      const result6 = createQueries(\n        () =>\n          ({\n            queries: [\n              {\n                queryKey: ['key1'],\n                queryFn: () => 'string',\n              },\n              {\n                queryKey: ['key1'],\n                queryFn: () => 123,\n              },\n            ],\n          }) as const,\n        () => queryClient,\n      )\n\n      expectTypeOf(result6[0]).toEqualTypeOf<CreateQueryResult<string, Error>>()\n      expectTypeOf(result6[1]).toEqualTypeOf<CreateQueryResult<number, Error>>()\n\n      // field names should be enforced - array literal\n      createQueries(\n        () => ({\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: () => 'string',\n            },\n          ],\n        }),\n        () => queryClient,\n      )\n\n      // field names should be enforced - Array.map() result\n      createQueries(\n        () => ({\n          // @ts-expect-error (invalidField)\n          queries: Array(10).map(() => ({\n            someInvalidField: '',\n          })),\n        }),\n        () => queryClient,\n      )\n\n      // supports queryFn using fetch() to return Promise<any> - Array.map() result\n      createQueries(\n        () => ({\n          queries: Array(50).map((_, i) => ({\n            queryKey: ['key', i] as const,\n            queryFn: () =>\n              fetch('return Promise<any>').then((resp) => resp.json()),\n          })),\n        }),\n        () => queryClient,\n      )\n\n      // supports queryFn using fetch() to return Promise<any> - array literal\n      createQueries(\n        () => ({\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: () =>\n                fetch('return Promise<any>').then((resp) => resp.json()),\n            },\n          ],\n        }),\n        () => queryClient,\n      )\n    }),\n  )\n\n  it(\n    'handles strongly typed queryFn factories and createQueries wrappers',\n    withEffectRoot(() => {\n      // QueryKey + queryFn factory\n      type QueryKeyA = ['queryA']\n      const getQueryKeyA = (): QueryKeyA => ['queryA']\n      type GetQueryFunctionA = () => QueryFunction<number, QueryKeyA>\n      const getQueryFunctionA: GetQueryFunctionA = () => () => {\n        return 1\n      }\n      type SelectorA = (data: number) => [number, string]\n      const getSelectorA = (): SelectorA => (data) => [data, data.toString()]\n\n      type QueryKeyB = ['queryB', string]\n      const getQueryKeyB = (id: string): QueryKeyB => ['queryB', id]\n      type GetQueryFunctionB = () => QueryFunction<string, QueryKeyB>\n      const getQueryFunctionB: GetQueryFunctionB = () => () => {\n        return '1'\n      }\n      type SelectorB = (data: string) => [string, number]\n      const getSelectorB = (): SelectorB => (data) => [data, +data]\n\n      // Wrapper with strongly typed array-parameter\n      function useWrappedQueries<\n        TQueryFnData,\n        TError,\n        TData,\n        TQueryKey extends QueryKey,\n      >(\n        queries: Array<\n          CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>\n        >,\n      ) {\n        return createQueries(\n          () => ({\n            queries: queries.map(\n              // no need to type the mapped query\n              (query) => {\n                const { queryFn: fn, queryKey: key } = query\n                expectTypeOf(fn).toEqualTypeOf<\n                  | typeof skipToken\n                  | QueryFunction<TQueryFnData, TQueryKey, never>\n                  | undefined\n                >()\n                return {\n                  queryKey: key,\n                  queryFn: fn\n                    ? (ctx: QueryFunctionContext<TQueryKey>) => {\n                        // eslint-disable-next-line vitest/valid-expect\n                        expectTypeOf<TQueryKey>(ctx.queryKey)\n                        return (\n                          fn as QueryFunction<TQueryFnData, TQueryKey>\n                        ).call({}, ctx)\n                      }\n                    : undefined,\n                }\n              },\n            ),\n          }),\n          () => queryClient,\n        )\n      }\n\n      const result = createQueries(\n        () => ({\n          queries: [\n            {\n              queryKey: getQueryKeyA(),\n              queryFn: getQueryFunctionA(),\n            },\n            {\n              queryKey: getQueryKeyB('id'),\n              queryFn: getQueryFunctionB(),\n            },\n          ],\n        }),\n        () => queryClient,\n      )\n\n      expectTypeOf(result[0]).toEqualTypeOf<CreateQueryResult<number, Error>>()\n      expectTypeOf(result[1]).toEqualTypeOf<CreateQueryResult<string, Error>>()\n\n      const withSelector = createQueries(\n        () => ({\n          queries: [\n            {\n              queryKey: getQueryKeyA(),\n              queryFn: getQueryFunctionA(),\n              select: getSelectorA(),\n            },\n            {\n              queryKey: getQueryKeyB('id'),\n              queryFn: getQueryFunctionB(),\n              select: getSelectorB(),\n            },\n          ],\n        }),\n        () => queryClient,\n      )\n\n      expectTypeOf(withSelector[0]).toEqualTypeOf<\n        CreateQueryResult<[number, string], Error>\n      >()\n      expectTypeOf(withSelector[1]).toEqualTypeOf<\n        CreateQueryResult<[string, number], Error>\n      >()\n\n      const withWrappedQueries = useWrappedQueries(\n        Array(10).map(() => ({\n          queryKey: getQueryKeyA(),\n          queryFn: getQueryFunctionA(),\n          select: getSelectorA(),\n        })),\n      )\n\n      expectTypeOf(withWrappedQueries).toEqualTypeOf<\n        Array<CreateQueryResult<number, Error>>\n      >()\n    }),\n  )\n\n  it(\n    'should track results',\n    withEffectRoot(async () => {\n      const key1 = ['test-track-results']\n      const results: Array<Array<CreateQueryResult>> = []\n      let count = 0\n\n      const result = createQueries(\n        () => ({\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: () => Promise.resolve(++count),\n            },\n          ],\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        results.push([result[0]])\n      })\n\n      await vi.waitFor(() => expect(result[0].data).toBe(1))\n\n      expect(results.length).toBe(2)\n      expect(results[0]).toMatchObject([{ data: undefined }])\n      expect(results[1]).toMatchObject([{ data: 1 }])\n\n      // Trigger refetch\n      result[0].refetch()\n\n      await vi.waitFor(() => expect(result[0].data).toBe(2))\n\n      // Only one render for data update, no render for isFetching transition\n      expect(results.length).toBe(3)\n      expect(results[2]).toMatchObject([{ data: 2 }])\n    }),\n  )\n\n  it(\n    'should combine queries',\n    withEffectRoot(async () => {\n      const key1 = ['test-combine-1']\n      const key2 = ['test-combine-2']\n\n      const { promise: promise1, resolve: resolve1 } =\n        promiseWithResolvers<string>()\n      const { promise: promise2, resolve: resolve2 } =\n        promiseWithResolvers<string>()\n\n      const queries = createQueries(\n        () => ({\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: () => promise1,\n            },\n            {\n              queryKey: key2,\n              queryFn: () => promise2,\n            },\n          ],\n          combine: (results) => {\n            return {\n              combined: true,\n              res: results\n                .flatMap((res) => (res.data ? [res.data] : []))\n                .join(','),\n            }\n          },\n        }),\n        () => queryClient,\n      )\n\n      // Initially both queries are loading\n      expect(queries).toEqual({\n        combined: true,\n        res: '',\n      })\n\n      // Resolve the first query\n      resolve1('first result')\n      await vi.waitFor(() => expect(queries.res).toBe('first result'))\n\n      // Resolve the second query\n      resolve2('second result')\n      await vi.waitFor(() =>\n        expect(queries.res).toBe('first result,second result'),\n      )\n\n      expect(queries).toEqual({\n        combined: true,\n        res: 'first result,second result',\n      })\n    }),\n  )\n\n  it(\n    'should track property access through combine function',\n    withEffectRoot(async () => {\n      const key1 = ['test-track-combine-1']\n      const key2 = ['test-track-combine-2']\n      let count = 0\n      const results: Array<unknown> = []\n\n      const { promise: promise1, resolve: resolve1 } =\n        promiseWithResolvers<string>()\n      const { promise: promise2, resolve: resolve2 } =\n        promiseWithResolvers<string>()\n      const { promise: promise3, resolve: resolve3 } =\n        promiseWithResolvers<string>()\n      const { promise: promise4, resolve: resolve4 } =\n        promiseWithResolvers<string>()\n\n      const queries = createQueries(\n        () => ({\n          queries: [\n            {\n              queryKey: key1,\n              queryFn: () => (count === 0 ? promise1 : promise3),\n            },\n            {\n              queryKey: key2,\n              queryFn: () => (count === 0 ? promise2 : promise4),\n            },\n          ],\n          combine: (queryResults) => {\n            return {\n              combined: true,\n              refetch: () =>\n                Promise.all(queryResults.map((res) => res.refetch())),\n              res: queryResults\n                .flatMap((res) => (res.data ? [res.data] : []))\n                .join(','),\n            }\n          },\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        results.push({ ...queries })\n      })\n\n      // Initially both queries are loading\n      await vi.waitFor(() =>\n        expect(results[0]).toStrictEqual({\n          combined: true,\n          refetch: expect.any(Function),\n          res: '',\n        }),\n      )\n\n      // Resolve the first query\n      resolve1('first result ' + count)\n      await vi.waitFor(() => expect(queries.res).toBe('first result 0'))\n\n      expect(results[1]).toStrictEqual({\n        combined: true,\n        refetch: expect.any(Function),\n        res: 'first result 0',\n      })\n\n      // Resolve the second query\n      resolve2('second result ' + count)\n      await vi.waitFor(() =>\n        expect(queries.res).toBe('first result 0,second result 0'),\n      )\n\n      expect(results[2]).toStrictEqual({\n        combined: true,\n        refetch: expect.any(Function),\n        res: 'first result 0,second result 0',\n      })\n\n      // Increment count and refetch\n      count++\n      queries.refetch()\n\n      // Resolve the refetched queries\n      resolve3('first result ' + count)\n      resolve4('second result ' + count)\n\n      await vi.waitFor(() =>\n        expect(queries.res).toBe('first result 1,second result 1'),\n      )\n\n      const length = results.length\n      expect(results.at(-1)).toStrictEqual({\n        combined: true,\n        refetch: expect.any(Function),\n        res: 'first result 1,second result 1',\n      })\n\n      // Refetch again but with the same data\n      await queries.refetch()\n\n      // No further re-render because data didn't change\n      expect(results.length).toBe(length)\n    }),\n  )\n})\n"
  },
  {
    "path": "packages/svelte-query/tests/createQueries.test-d.ts",
    "content": "import { describe, expectTypeOf, it } from 'vitest'\nimport { createQueries, queryOptions } from '../src/index.js'\nimport type { CreateQueryResult } from '../src/index.js'\n\ndescribe('createQueries', () => {\n  it('should return correct data for dynamic queries with mixed result types', () => {\n    const Queries1 = {\n      get: () =>\n        queryOptions({\n          queryKey: ['key1'],\n          queryFn: () => Promise.resolve(1),\n        }),\n    }\n    const Queries2 = {\n      get: () =>\n        queryOptions({\n          queryKey: ['key2'],\n          queryFn: () => Promise.resolve(true),\n        }),\n    }\n\n    const queries1List = [1, 2, 3].map(() => ({ ...Queries1.get() }))\n    const result = createQueries(() => ({\n      queries: [...queries1List, { ...Queries2.get() }],\n    }))\n\n    expectTypeOf(result).toEqualTypeOf<\n      [\n        ...Array<CreateQueryResult<number, Error>>,\n        CreateQueryResult<boolean, Error>,\n      ]\n    >()\n  })\n})\n"
  },
  {
    "path": "packages/svelte-query/tests/createQuery.svelte.test.ts",
    "content": "import { flushSync } from 'svelte'\nimport { afterEach, describe, expect, expectTypeOf, it, vi } from 'vitest'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { QueryClient, createQuery, keepPreviousData } from '../src/index.js'\nimport { promiseWithResolvers, withEffectRoot } from './utils.svelte.js'\nimport type { CreateQueryResult } from '../src/index.js'\n\ndescribe('createQuery', () => {\n  const queryClient = new QueryClient()\n  const queryCache = queryClient.getQueryCache()\n\n  afterEach(() => {\n    queryClient.clear()\n  })\n\n  it(\n    'should return the correct states for a successful query',\n    withEffectRoot(async () => {\n      const { promise, resolve } = promiseWithResolvers<string>()\n\n      const query = createQuery<string, Error>(\n        () => ({\n          queryKey: ['test'],\n          queryFn: () => promise,\n        }),\n        () => queryClient,\n      )\n\n      if (query.isPending) {\n        expectTypeOf(query.data).toEqualTypeOf<undefined>()\n        expectTypeOf(query.error).toEqualTypeOf<null>()\n      } else if (query.isLoadingError) {\n        expectTypeOf(query.data).toEqualTypeOf<undefined>()\n        expectTypeOf(query.error).toEqualTypeOf<Error>()\n      } else {\n        expectTypeOf(query.data).toEqualTypeOf<string>()\n        expectTypeOf(query.error).toEqualTypeOf<Error | null>()\n      }\n\n      const promise1 = query.promise\n\n      expect(query).toEqual({\n        data: undefined,\n        dataUpdatedAt: 0,\n        error: null,\n        errorUpdatedAt: 0,\n        failureCount: 0,\n        failureReason: null,\n        errorUpdateCount: 0,\n        isEnabled: true,\n        isError: false,\n        isFetched: false,\n        isFetchedAfterMount: false,\n        isFetching: true,\n        isPaused: false,\n        isPending: true,\n        isInitialLoading: true,\n        isLoading: true,\n        isLoadingError: false,\n        isPlaceholderData: false,\n        isRefetchError: false,\n        isRefetching: false,\n        isStale: true,\n        isSuccess: false,\n        refetch: expect.any(Function),\n        status: 'pending',\n        fetchStatus: 'fetching',\n        promise: expect.any(Promise),\n      })\n      resolve('resolved')\n      await vi.waitFor(() =>\n        expect(query).toEqual({\n          data: 'resolved',\n          dataUpdatedAt: expect.any(Number),\n          error: null,\n          errorUpdatedAt: 0,\n          failureCount: 0,\n          failureReason: null,\n          errorUpdateCount: 0,\n          isEnabled: true,\n          isError: false,\n          isFetched: true,\n          isFetchedAfterMount: true,\n          isFetching: false,\n          isPaused: false,\n          isPending: false,\n          isInitialLoading: false,\n          isLoading: false,\n          isLoadingError: false,\n          isPlaceholderData: false,\n          isRefetchError: false,\n          isRefetching: false,\n          isStale: true,\n          isSuccess: true,\n          refetch: expect.any(Function),\n          status: 'success',\n          fetchStatus: 'idle',\n          promise: expect.any(Promise),\n        }),\n      )\n\n      expect(promise1).toBe(query.promise)\n    }),\n  )\n\n  it(\n    'should return the correct states for an unsuccessful query',\n    withEffectRoot(async () => {\n      let count = 0\n      const states: Array<CreateQueryResult> = []\n      const query = createQuery<string, Error>(\n        () => ({\n          queryKey: ['test'],\n          queryFn: () => {\n            return Promise.reject(new Error('rejected #' + ++count))\n          },\n          retry: 1,\n          retryDelay: 1,\n        }),\n        () => queryClient,\n      )\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      await vi.waitFor(() => expect(query.isError).toBe(true))\n\n      expect(states[0]).toEqual({\n        data: undefined,\n        dataUpdatedAt: 0,\n        error: null,\n        errorUpdatedAt: 0,\n        failureCount: 0,\n        failureReason: null,\n        errorUpdateCount: 0,\n        isEnabled: true,\n        isError: false,\n        isFetched: false,\n        isFetchedAfterMount: false,\n        isFetching: true,\n        isPaused: false,\n        isPending: true,\n        isInitialLoading: true,\n        isLoading: true,\n        isLoadingError: false,\n        isPlaceholderData: false,\n        isRefetchError: false,\n        isRefetching: false,\n        isStale: true,\n        isSuccess: false,\n        refetch: expect.any(Function),\n        status: 'pending',\n        fetchStatus: 'fetching',\n        promise: expect.any(Promise),\n      })\n\n      expect(states[1]).toEqual({\n        data: undefined,\n        dataUpdatedAt: 0,\n        error: null,\n        errorUpdatedAt: 0,\n        failureCount: 1,\n        failureReason: new Error('rejected #1'),\n        errorUpdateCount: 0,\n        isEnabled: true,\n        isError: false,\n        isFetched: false,\n        isFetchedAfterMount: false,\n        isFetching: true,\n        isPaused: false,\n        isPending: true,\n        isInitialLoading: true,\n        isLoading: true,\n        isLoadingError: false,\n        isPlaceholderData: false,\n        isRefetchError: false,\n        isRefetching: false,\n        isStale: true,\n        isSuccess: false,\n        refetch: expect.any(Function),\n        status: 'pending',\n        fetchStatus: 'fetching',\n        promise: expect.any(Promise),\n      })\n\n      expect(states[2]).toEqual({\n        data: undefined,\n        dataUpdatedAt: 0,\n        error: new Error('rejected #2'),\n        errorUpdatedAt: expect.any(Number),\n        failureCount: 2,\n        failureReason: new Error('rejected #2'),\n        errorUpdateCount: 1,\n        isEnabled: true,\n        isError: true,\n        isFetched: true,\n        isFetchedAfterMount: true,\n        isFetching: false,\n        isPaused: false,\n        isPending: false,\n        isInitialLoading: false,\n        isLoading: false,\n        isLoadingError: true,\n        isPlaceholderData: false,\n        isRefetchError: false,\n        isRefetching: false,\n        isStale: true,\n        isSuccess: false,\n        refetch: expect.any(Function),\n        status: 'error',\n        fetchStatus: 'idle',\n        promise: expect.any(Promise),\n      })\n    }),\n  )\n\n  it('should set isFetchedAfterMount to true after a query has been fetched', async () => {\n    const key = ['test']\n\n    await queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => Promise.resolve('prefetched'),\n    })\n\n    await withEffectRoot(async () => {\n      const { promise, resolve } = promiseWithResolvers<string>()\n\n      const query = createQuery<string, Error>(\n        () => ({\n          queryKey: key,\n          queryFn: () => promise,\n        }),\n        () => queryClient,\n      )\n\n      expect(query).toEqual(\n        expect.objectContaining({\n          data: 'prefetched',\n          isFetched: true,\n          isFetchedAfterMount: false,\n        }),\n      )\n      resolve('resolved')\n      await vi.waitFor(() =>\n        expect(query).toEqual(\n          expect.objectContaining({\n            data: 'resolved',\n            isFetched: true,\n            isFetchedAfterMount: true,\n          }),\n        ),\n      )\n    })()\n  })\n\n  it(\n    'should not cancel an ongoing fetch when refetch is called with cancelRefetch=false if we have data already',\n    withEffectRoot(async () => {\n      const key = ['test']\n      let fetchCount = 0\n\n      const { promise, resolve } = promiseWithResolvers<string>()\n\n      const { refetch } = createQuery<string, Error>(\n        () => ({\n          queryKey: key,\n          queryFn: () => {\n            fetchCount++\n            return promise\n          },\n          enabled: false,\n          initialData: 'initial',\n        }),\n        () => queryClient,\n      )\n\n      refetch()\n      refetch({ cancelRefetch: false })\n\n      resolve('resolved')\n      await promise\n\n      expect(fetchCount).toBe(1)\n    }),\n  )\n\n  it(\n    'should cancel an ongoing fetch when refetch is called (cancelRefetch=true) if we have data already',\n    withEffectRoot(async () => {\n      const key = ['test']\n      let fetchCount = 0\n\n      const { promise, resolve } = promiseWithResolvers<string>()\n\n      const query = createQuery<string, Error>(\n        () => ({\n          queryKey: key,\n          queryFn: async () => {\n            fetchCount++\n            return promise\n          },\n          enabled: false,\n          initialData: 'initialData',\n        }),\n        () => queryClient,\n      )\n\n      // Trigger two refetch close together\n      query.refetch()\n      query.refetch()\n\n      resolve('resolved')\n      await promise\n\n      expect(fetchCount).toBe(2)\n    }),\n  )\n\n  it(\n    'should not cancel an ongoing fetch when refetch is called (cancelRefetch=true) if we do not have data yet',\n    withEffectRoot(async () => {\n      const key = ['test']\n      let fetchCount = 0\n\n      const { promise, resolve } = promiseWithResolvers<string>()\n\n      const query = createQuery<string, Error>(\n        () => ({\n          queryKey: key,\n          queryFn: async () => {\n            fetchCount++\n            return promise\n          },\n          enabled: false,\n        }),\n        () => queryClient,\n      )\n\n      // Trigger two refetch close together\n      query.refetch()\n      query.refetch()\n\n      resolve('resolved')\n      await promise\n\n      expect(fetchCount).toBe(1)\n    }),\n  )\n\n  it(\n    'should be able to watch a query without providing a query function',\n    withEffectRoot(async () => {\n      const key = ['test']\n      const states: Array<CreateQueryResult<string>> = []\n\n      queryClient.setQueryDefaults(key, {\n        queryFn: () => 'data',\n      })\n\n      const query = createQuery<string>(\n        () => ({ queryKey: key }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      await vi.waitFor(() => {\n        expect(query.data).toBe('data')\n      })\n\n      expect(states.length).toBe(2)\n      expect(states[0]).toMatchObject({ data: undefined })\n      expect(states[1]).toMatchObject({ data: 'data' })\n    }),\n  )\n\n  it('should pick up a query when re-mounting with gcTime 0', async () => {\n    // this needs to be split into two different effect roots because\n    // effects won't pick up dependencies created after the first `await`\n    // -- the two roots effectively emulate two consecutive components being rendered\n    await withEffectRoot(async () => {\n      const { promise, resolve } = promiseWithResolvers<string>()\n\n      const query = createQuery<string>(\n        () => ({\n          queryKey: ['test'],\n          queryFn: () => promise,\n          gcTime: 0,\n          notifyOnChangeProps: 'all',\n        }),\n        () => queryClient,\n      )\n\n      expect(query).toMatchObject({\n        isPending: true,\n        isSuccess: false,\n        isFetching: true,\n      })\n\n      resolve('resolved: 1')\n      await vi.waitFor(() => expect(query.data).toBe('resolved: 1'))\n\n      expect(query).toMatchObject({\n        isPending: false,\n        isSuccess: true,\n        isFetching: false,\n      })\n    })()\n\n    await withEffectRoot(async () => {\n      const { promise, resolve } = promiseWithResolvers<string>()\n\n      const query = createQuery<string>(\n        () => ({\n          queryKey: ['test'],\n          queryFn: () => promise,\n          gcTime: 0,\n          notifyOnChangeProps: 'all',\n        }),\n        () => queryClient,\n      )\n\n      expect(query).toMatchObject({\n        data: 'resolved: 1',\n        isPending: false,\n        isSuccess: true,\n        isFetching: true,\n      })\n\n      resolve('resolved: 2')\n      await vi.waitFor(() => expect(query.data).toBe('resolved: 2'))\n\n      expect(query).toMatchObject({\n        data: 'resolved: 2',\n        isPending: false,\n        isSuccess: true,\n        isFetching: false,\n      })\n    })()\n  })\n\n  it('should not get into an infinite loop when removing a query with gcTime 0 and rerendering', async () => {\n    const key = ['test']\n    const states: Array<CreateQueryResult<string>> = []\n\n    // First mount: render the query and let it fetch\n    await withEffectRoot(async () => {\n      const query = createQuery<string>(\n        () => ({\n          queryKey: key,\n          queryFn: () => Promise.resolve('data'),\n          gcTime: 0,\n          notifyOnChangeProps: ['isPending', 'isSuccess', 'data'],\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      await vi.waitFor(() => {\n        expect(query.data).toBe('data')\n      })\n    })()\n\n    // Simulate rerender by removing the query and mounting again\n    await withEffectRoot(async () => {\n      queryClient.removeQueries({ queryKey: key })\n\n      const query = createQuery<string>(\n        () => ({\n          queryKey: key,\n          queryFn: () => Promise.resolve('data'),\n          gcTime: 0,\n          notifyOnChangeProps: ['isPending', 'isSuccess', 'data'],\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      await vi.waitFor(() => {\n        expect(query.data).toBe('data')\n      })\n\n      // Give it time to catch any accidental infinite updates\n      await new Promise((r) => setTimeout(r, 100))\n    })()\n\n    expect(states.length).toBe(4)\n    expect(states[0]).toMatchObject({\n      isPending: true,\n      isSuccess: false,\n      data: undefined,\n    })\n    expect(states[1]).toMatchObject({\n      isPending: false,\n      isSuccess: true,\n      data: 'data',\n    })\n    expect(states[2]).toMatchObject({\n      isPending: true,\n      isSuccess: false,\n      data: undefined,\n    })\n    expect(states[3]).toMatchObject({\n      isPending: false,\n      isSuccess: true,\n      data: 'data',\n    })\n  })\n\n  it(\n    'should fetch when refetchOnMount is false and nothing has been fetched yet',\n    withEffectRoot(async () => {\n      const key = ['test']\n      const states: Array<CreateQueryResult<string>> = []\n\n      const query = createQuery<string>(\n        () => ({\n          queryKey: key,\n          queryFn: () => 'test',\n          refetchOnMount: false,\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      await vi.waitFor(() => {\n        expect(query.data).toBe('test')\n      })\n\n      expect(states.length).toBe(2)\n      expect(states[0]).toMatchObject({ data: undefined })\n      expect(states[1]).toMatchObject({ data: 'test' })\n    }),\n  )\n\n  it(\n    'should not fetch when refetchOnMount is false and data has been fetched already',\n    withEffectRoot(async () => {\n      const key = ['test']\n      const states: Array<CreateQueryResult<string>> = []\n\n      queryClient.setQueryData(key, 'prefetched')\n\n      const query = createQuery<string>(\n        () => ({\n          queryKey: key,\n          queryFn: () => 'test',\n          refetchOnMount: false,\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      await vi.waitFor(() => {\n        expect(query.data).toBe('prefetched')\n      })\n\n      expect(states.length).toBe(1)\n      expect(states[0]).toMatchObject({ data: 'prefetched' })\n    }),\n  )\n\n  it(\n    'should be able to select a part of the data with select',\n    withEffectRoot(async () => {\n      const key = ['test']\n      const states: Array<CreateQueryResult<string>> = []\n\n      const query = createQuery<{ name: string }, Error, string>(\n        () => ({\n          queryKey: key,\n          queryFn: () => ({ name: 'test' }),\n          select: (data) => data.name,\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      await vi.waitFor(() => {\n        expect(query.data).toBe('test')\n      })\n\n      expect(states.length).toBe(2)\n      expect(states[0]).toMatchObject({ data: undefined })\n      expect(states[1]).toMatchObject({ data: 'test' })\n    }),\n  )\n\n  it(\n    'should throw an error when a selector throws',\n    withEffectRoot(async () => {\n      const key = ['test']\n      const error = new Error('Select Error')\n      const states: Array<CreateQueryResult<string>> = []\n\n      const query = createQuery<{ name: string }, Error, string>(\n        () => ({\n          queryKey: key,\n          queryFn: () => ({ name: 'test' }),\n          select: () => {\n            throw error\n          },\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      await vi.waitFor(() => {\n        expect(query.status).toBe('error')\n      })\n\n      expect(states.length).toBe(2)\n      expect(states[0]).toMatchObject({ status: 'pending', data: undefined })\n      expect(states[1]).toMatchObject({ status: 'error', error })\n    }),\n  )\n\n  it(\n    'should be able to remove a query',\n    withEffectRoot(async () => {\n      const key = ['test']\n      const states: Array<CreateQueryResult<number>> = []\n      let count = 0\n      const query = createQuery<number>(\n        () => ({\n          queryKey: key,\n          queryFn: () => ++count,\n          notifyOnChangeProps: 'all',\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      await vi.waitFor(() => expect(query.data).toBe(1))\n\n      queryClient.removeQueries({ queryKey: key })\n      await query.refetch()\n\n      await vi.waitFor(() => expect(query.data).toBe(2))\n\n      expect(states.length).toBe(4)\n      expect(states[0]).toMatchObject({\n        status: 'pending',\n        data: undefined,\n        dataUpdatedAt: 0,\n      })\n      expect(states[1]).toMatchObject({ status: 'success', data: 1 })\n      expect(states[2]).toMatchObject({\n        status: 'pending',\n        data: undefined,\n        dataUpdatedAt: 0,\n      })\n      expect(states[3]).toMatchObject({ status: 'success', data: 2 })\n    }),\n  )\n\n  it(\n    'keeps up-to-date with query key changes',\n    withEffectRoot(async () => {\n      let search = $state('')\n      const states: Array<CreateQueryResult<string>> = []\n\n      const query = createQuery(\n        () => ({\n          queryKey: ['products', search],\n          queryFn: async () => Promise.resolve(search),\n          placeholderData: keepPreviousData,\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      await vi.waitFor(() => expect(query.data).toBe(''))\n      search = 'phone'\n      await vi.waitFor(() => expect(query.data).toBe('phone'))\n\n      expect(states.length).toBe(4)\n      expect(states[0]).toMatchObject({\n        status: 'pending',\n        fetchStatus: 'fetching',\n        data: undefined,\n      })\n      expect(states[1]).toMatchObject({\n        status: 'success',\n        fetchStatus: 'idle',\n        data: '',\n      })\n      expect(states[2]).toMatchObject({\n        status: 'success',\n        fetchStatus: 'fetching',\n        data: '',\n      })\n      expect(states[3]).toMatchObject({\n        status: 'success',\n        fetchStatus: 'idle',\n        data: 'phone',\n      })\n    }),\n  )\n\n  it(\n    'should create a new query when refetching a removed query',\n    withEffectRoot(async () => {\n      const key = ['test']\n      const states: Array<CreateQueryResult<number>> = []\n      let count = 0\n\n      const query = createQuery(\n        () => ({\n          queryKey: key,\n          queryFn: () => Promise.resolve(++count),\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      await vi.waitFor(() => {\n        expect(query.data).toBe(1)\n      })\n\n      queryClient.removeQueries({ queryKey: key })\n      await query.refetch()\n      await vi.waitFor(() => {\n        expect(query.data).toBe(2)\n      })\n\n      expect(states.length).toBe(4)\n      // Initial\n      expect(states[0]).toMatchObject({ data: undefined, dataUpdatedAt: 0 })\n      // Fetched\n      expect(states[1]).toMatchObject({ data: 1 })\n      // Switch\n      expect(states[2]).toMatchObject({ data: undefined, dataUpdatedAt: 0 })\n      // Fetched\n      expect(states[3]).toMatchObject({ data: 2 })\n    }),\n  )\n\n  it(\n    'should share equal data structures between query results',\n    withEffectRoot(async () => {\n      const key = ['test']\n\n      const result1 = [\n        { id: '1', done: false },\n        { id: '2', done: false },\n      ]\n\n      const result2 = [\n        { id: '1', done: false },\n        { id: '2', done: true },\n      ]\n\n      const states: Array<CreateQueryResult<typeof result1>> = []\n\n      let count = 0\n\n      const query = createQuery<typeof result1>(\n        () => ({\n          queryKey: key,\n          queryFn: () => {\n            count++\n            return Promise.resolve(count === 1 ? result1 : result2)\n          },\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      await vi.waitFor(() => expect(query.data?.[1]?.done).toBe(false))\n      await query.refetch()\n      await vi.waitFor(() => expect(query.data?.[1]?.done).toBe(true))\n\n      expect(states.length).toBe(4)\n\n      const todos = states[1]?.data\n      const todo1 = todos?.[0]\n      const todo2 = todos?.[1]\n\n      const newTodos = states[3]?.data\n      const newTodo1 = newTodos?.[0]\n      const newTodo2 = newTodos?.[1]\n\n      expect(todos).toEqual(result1)\n      expect(newTodos).toEqual(result2)\n      expect(newTodos).not.toBe(todos)\n      expect(newTodo1).toBe(todo1)\n      expect(newTodo2).not.toBe(todo2)\n    }),\n  )\n\n  it(\n    'should use query function from hook when the existing query does not have a query function',\n    withEffectRoot(async () => {\n      const key = ['test']\n\n      queryClient.setQueryData(key, 'set')\n\n      const query = createQuery(\n        () => ({\n          queryKey: key,\n          queryFn: () => Promise.resolve('fetched'),\n          initialData: 'initial',\n          staleTime: Infinity,\n        }),\n        () => queryClient,\n      )\n\n      await vi.waitFor(() => expect(query.data).toBe('set'))\n      queryClient.refetchQueries({ queryKey: key })\n      await vi.waitFor(() => expect(query.data).toBe('fetched'))\n    }),\n  )\n\n  it(\n    'should update query stale state and refetch when invalidated with invalidateQueries',\n    withEffectRoot(async () => {\n      const key = ['test']\n      let count = 0\n\n      const query = createQuery<number>(\n        () => ({\n          queryKey: key,\n          queryFn: () => Promise.resolve(++count),\n          staleTime: Infinity,\n        }),\n        () => queryClient,\n      )\n\n      await vi.waitFor(() =>\n        expect(query).toEqual(\n          expect.objectContaining({\n            data: 1,\n            isStale: false,\n            isFetching: false,\n          }),\n        ),\n      )\n      queryClient.invalidateQueries({ queryKey: key })\n      await vi.waitFor(() =>\n        expect(query).toEqual(\n          expect.objectContaining({\n            data: 1,\n            isStale: true,\n            isFetching: true,\n          }),\n        ),\n      )\n      await vi.waitFor(() =>\n        expect(query).toEqual(\n          expect.objectContaining({\n            data: 2,\n            isStale: false,\n            isFetching: false,\n          }),\n        ),\n      )\n    }),\n  )\n\n  it(\n    'should not update disabled query when refetching with refetchQueries',\n    withEffectRoot(async () => {\n      const key = ['test']\n      const states: Array<CreateQueryResult<number>> = []\n      let count = 0\n\n      const query = createQuery<number>(\n        () => ({\n          queryKey: key,\n          queryFn: () => Promise.resolve(++count),\n          enabled: false,\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      await sleep(50)\n\n      expect(states.length).toBe(1)\n      expect(states[0]).toMatchObject({\n        data: undefined,\n        isSuccess: false,\n        isFetching: false,\n        isStale: false,\n      })\n    }),\n  )\n\n  it(\n    'should not refetch disabled query when invalidated with invalidateQueries',\n    withEffectRoot(async () => {\n      const key = ['test-key']\n      const states: Array<CreateQueryResult<number>> = []\n      let count = 0\n\n      const query = createQuery<number>(\n        () => ({\n          queryKey: key,\n          queryFn: () => Promise.resolve(++count),\n          enabled: false,\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      queryClient.invalidateQueries({ queryKey: key })\n\n      // Wait long enough for the invalidation and potential refetch\n      await sleep(100)\n\n      expect(states.length).toBe(1)\n      expect(states[0]).toMatchObject({\n        data: undefined,\n        isFetching: false,\n        isSuccess: false,\n        isStale: false,\n      })\n    }),\n  )\n\n  it(\n    'should not fetch when switching to a disabled query',\n    withEffectRoot(async () => {\n      const key = ['test-key']\n      const states: Array<CreateQueryResult<number>> = []\n      let count = $state<number>(0)\n\n      const query = createQuery<number>(\n        () => ({\n          queryKey: [key, count],\n          queryFn: () => Promise.resolve(count),\n          enabled: count === 0,\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      await vi.waitFor(() => expect(query.data).toBe(0))\n      count = 1\n      await vi.waitFor(() => expect(states.length).toBe(3))\n\n      // Fetch query\n      expect(states[0]).toMatchObject({\n        isFetching: true,\n        isSuccess: false,\n      })\n      // Fetched query\n      expect(states[1]).toMatchObject({\n        data: 0,\n        isFetching: false,\n        isSuccess: true,\n      })\n      // Switch to disabled query\n      expect(states[2]).toMatchObject({\n        isFetching: false,\n        isSuccess: false,\n      })\n    }),\n  )\n\n  it(\n    'should keep the previous data when placeholderData is set',\n    withEffectRoot(async () => {\n      const key = ['test-key']\n      const states: Array<CreateQueryResult<number>> = []\n      let count = $state(0)\n\n      const query = createQuery<number>(\n        () => ({\n          queryKey: [key, count],\n          queryFn: () => Promise.resolve(count),\n          placeholderData: keepPreviousData,\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      // Wait for the initial fetch to complete\n      await vi.waitFor(() => expect(query.data).toBe(0))\n\n      // Update count to trigger a new fetch\n      count = 1\n\n      // Wait for all state updates to complete\n      await vi.waitFor(() => expect(states.length).toBe(4))\n\n      // Initial\n      expect(states[0]).toMatchObject({\n        data: undefined,\n        isFetching: true,\n        isSuccess: false,\n        isPlaceholderData: false,\n      })\n      // Fetched\n      expect(states[1]).toMatchObject({\n        data: 0,\n        isFetching: false,\n        isSuccess: true,\n        isPlaceholderData: false,\n      })\n      // Set state\n      expect(states[2]).toMatchObject({\n        data: 0,\n        isFetching: true,\n        isSuccess: true,\n        isPlaceholderData: true,\n      })\n      // New data\n      expect(states[3]).toMatchObject({\n        data: 1,\n        isFetching: false,\n        isSuccess: true,\n        isPlaceholderData: false,\n      })\n    }),\n  )\n\n  it(\n    'should not show initial data from next query if placeholderData is set',\n    withEffectRoot(async () => {\n      const key = ['test-key']\n      const states: Array<CreateQueryResult<number>> = []\n      let count = $state<number>(0)\n\n      const query = createQuery<number>(\n        () => ({\n          queryKey: [key, count],\n          queryFn: () => Promise.resolve(count),\n          initialData: 99,\n          placeholderData: keepPreviousData,\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      // Wait for the initial fetch to complete\n      await vi.waitFor(() => expect(query.data).toBe(0))\n\n      // Update count to trigger a new fetch\n      count = 1\n\n      // Wait for the new fetch to complete\n      await vi.waitFor(() => expect(query.data).toBe(1))\n\n      // Wait for all state updates to complete\n      await vi.waitFor(() => expect(states.length).toBe(4))\n\n      // Initial\n      expect(states[0]).toMatchObject({\n        data: 99,\n        isFetching: true,\n        isSuccess: true,\n        isPlaceholderData: false,\n      })\n      // Fetched\n      expect(states[1]).toMatchObject({\n        data: 0,\n        isFetching: false,\n        isSuccess: true,\n        isPlaceholderData: false,\n      })\n      // Set state\n      expect(states[2]).toMatchObject({\n        data: 99,\n        isFetching: true,\n        isSuccess: true,\n        isPlaceholderData: false,\n      })\n      // New data\n      expect(states[3]).toMatchObject({\n        data: 1,\n        isFetching: false,\n        isSuccess: true,\n        isPlaceholderData: false,\n      })\n    }),\n  )\n\n  it(\n    'should keep the previous data on disabled query when placeholderData is set and switching query key multiple times',\n    withEffectRoot(async () => {\n      const key = ['test-key']\n      const states: Array<CreateQueryResult<number>> = []\n\n      // Set initial query data\n      queryClient.setQueryData([key, 10], 10)\n\n      let count = $state(10)\n\n      const query = createQuery<number>(\n        () => ({\n          queryKey: [key, count],\n          queryFn: () => Promise.resolve(count),\n          enabled: false,\n          placeholderData: keepPreviousData,\n          notifyOnChangeProps: 'all',\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      // let that effect ^ run to push the initial state\n      flushSync()\n      flushSync(() => (count = 11))\n      flushSync(() => (count = 12))\n      await query.refetch()\n      // Wait for all operations to complete\n      await vi.waitFor(() => expect(query.data).toBe(12))\n\n      // Disabled query\n      expect(states[0]).toMatchObject({\n        data: 10,\n        isFetching: false,\n        isSuccess: true,\n        isPlaceholderData: false,\n      })\n      // Set state (11)\n      expect(states[1]).toMatchObject({\n        data: 10,\n        isFetching: false,\n        isSuccess: true,\n        isPlaceholderData: true,\n      })\n      // Set state (12)\n      expect(states[2]).toMatchObject({\n        data: 10,\n        isFetching: false,\n        isSuccess: true,\n        isPlaceholderData: true,\n      })\n      // Refetch\n      expect(states[3]).toMatchObject({\n        data: 10,\n        isFetching: true,\n        isSuccess: true,\n        isPlaceholderData: true,\n      })\n      // Refetch done\n      expect(states[4]).toMatchObject({\n        data: 12,\n        isFetching: false,\n        isSuccess: true,\n        isPlaceholderData: false,\n      })\n    }),\n  )\n\n  it(\n    'should use the correct query function when components use different configurations',\n    withEffectRoot(async () => {\n      const key = ['test-key']\n      const states: Array<CreateQueryResult<number>> = []\n      const { promise, resolve } = promiseWithResolvers<number>()\n\n      // Simulate FirstComponent\n      const firstQuery = createQuery<number>(\n        () => ({\n          queryKey: key,\n          queryFn: () => promise,\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...firstQuery })\n      })\n\n      // Simulate SecondComponent\n      createQuery<number>(\n        () => ({\n          queryKey: key,\n          queryFn: () => 2,\n        }),\n        () => queryClient,\n      )\n\n      // Resolve the first query\n      resolve(1)\n\n      // Wait for the first query to complete\n      await vi.waitFor(() => expect(firstQuery.data).toBe(1))\n\n      // Refetch the first query\n      await firstQuery.refetch()\n\n      // Wait for all state updates to complete\n      await vi.waitFor(() => expect(states.length).toBe(4))\n\n      expect(states[0]).toMatchObject({\n        data: undefined,\n      })\n      expect(states[1]).toMatchObject({\n        data: 1,\n      })\n      expect(states[2]).toMatchObject({\n        data: 1,\n      })\n      // This state should be 1 instead of 2\n      expect(states[3]).toMatchObject({\n        data: 1,\n      })\n    }),\n  )\n\n  it.todo(\n    'should be able to set different stale times for a query',\n    async () => {\n      /**\n       * TODO: There's a super weird bug with this test, and I think it's caused by a race condition in query-core.\n       *\n       * If you add this to the top `updateResult` in `packages/query-core/src/queryObserver.ts:647`:\n       * ```\n       * for (let i = 0; i < 10_000_000; i++) {\n       *   continue\n       * }\n       * ```\n       *\n       * This test will miraculously start to pass. I'm suspicious that there's some race condition between props\n       * being tracked and `updateResult` being called, but that _should_ be fixed by `notifyOnChangeProps: 'all'`,\n       * and that's not doing anything.\n       *\n       * This test will also start to magically pass if you put `$inspect(firstQuery)` before `vi.waitFor` near\n       * the end of the test.\n       */\n\n      const key = ['test-key']\n      const states1: Array<CreateQueryResult<string>> = []\n      const states2: Array<CreateQueryResult<string>> = []\n\n      // Prefetch the query\n      await queryClient.prefetchQuery({\n        queryKey: key,\n        queryFn: async () => {\n          await sleep(10)\n          return 'prefetch'\n        },\n      })\n\n      await vi.waitFor(() =>\n        expect(queryClient.getQueryState(key)?.data).toBe('prefetch'),\n      )\n\n      await withEffectRoot(async () => {\n        const firstQuery = createQuery<string>(\n          () => ({\n            queryKey: key,\n            queryFn: () => Promise.resolve('one'),\n            staleTime: 100,\n          }),\n          () => queryClient,\n        )\n\n        $effect(() => {\n          states1.push({ ...firstQuery })\n        })\n\n        const secondQuery = createQuery<string>(\n          () => ({\n            queryKey: key,\n            queryFn: () => Promise.resolve('two'),\n            staleTime: 10,\n          }),\n          () => queryClient,\n        )\n\n        $effect(() => {\n          states2.push({ ...secondQuery })\n        })\n\n        await vi.waitFor(() => {\n          expect(firstQuery).toMatchObject({ data: 'two', isStale: true })\n          expect(secondQuery).toMatchObject({ data: 'two', isStale: true })\n        })\n\n        expect(states1).toMatchObject([\n          // First render\n          {\n            data: 'prefetch',\n            isStale: false,\n          },\n          // Second createQuery started fetching\n          {\n            data: 'prefetch',\n            isStale: false,\n          },\n          // Second createQuery data came in\n          {\n            data: 'two',\n            isStale: false,\n          },\n          // Data became stale after 100ms\n          {\n            data: 'two',\n            isStale: true,\n          },\n        ])\n\n        expect(states2).toMatchObject([\n          // First render, data is stale and starts fetching\n          {\n            data: 'prefetch',\n            isStale: true,\n          },\n          // Second createQuery data came in\n          {\n            data: 'two',\n            isStale: false,\n          },\n          // Data became stale after 10ms\n          {\n            data: 'two',\n            isStale: true,\n          },\n        ])\n      })()\n    },\n  )\n\n  it(\n    'should re-render when a query becomes stale',\n    withEffectRoot(async () => {\n      const key = ['test-key']\n      const states: Array<CreateQueryResult<string>> = []\n\n      const query = createQuery<string>(\n        () => ({\n          queryKey: key,\n          queryFn: () => 'test',\n          staleTime: 50,\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      // Wait for the query to become stale\n      await sleep(100)\n\n      expect(states.length).toBe(3)\n      expect(states[0]).toMatchObject({ isStale: true })\n      expect(states[1]).toMatchObject({ isStale: false })\n      expect(states[2]).toMatchObject({ isStale: true })\n    }),\n  )\n\n  it(\n    'should not re-render when it should only re-render on data changes and the data did not change',\n    withEffectRoot(async () => {\n      const key = ['test-key']\n      const states: Array<CreateQueryResult<string>> = []\n      const { promise, resolve } = promiseWithResolvers<string>()\n\n      const query = createQuery<string>(\n        () => ({\n          queryKey: key,\n          queryFn: () => promise,\n          notifyOnChangeProps: ['data'],\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      resolve('test')\n\n      // Refetch the query\n      setTimeout(() => {\n        query.refetch()\n      }, 10)\n\n      await vi.waitFor(() => {\n        expect(states.length).toBe(2)\n      })\n\n      expect(states[0]).toMatchObject({\n        data: undefined,\n        status: 'pending',\n        isFetching: true,\n      })\n      expect(states[1]).toMatchObject({\n        data: 'test',\n        status: 'success',\n        isFetching: false,\n      })\n    }),\n  )\n\n  it(\n    'should track properties and only re-render when a tracked property changes',\n    withEffectRoot(async () => {\n      const key = ['test-key']\n      const states: Array<string | undefined> = []\n      const { promise, resolve } = promiseWithResolvers<string>()\n\n      const query = createQuery<string>(\n        () => ({\n          queryKey: key,\n          queryFn: () => promise,\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push(query.data)\n      })\n\n      // Resolve the promise after a delay\n      setTimeout(() => {\n        resolve('test')\n      }, 10)\n\n      await vi.waitFor(() => expect(query.data).toBe('test'))\n\n      // Refetch after data is available\n      setTimeout(() => {\n        if (query.data) {\n          query.refetch()\n        }\n      }, 20)\n\n      // Wait for refetch to complete\n      await sleep(30)\n\n      expect(states.length).toBe(2)\n      expect(states[0]).toBe(undefined)\n      expect(states[1]).toBe('test')\n    }),\n  )\n\n  it(\n    'should always re-render if we are tracking props but not using any',\n    withEffectRoot(async () => {\n      const key = ['test-key']\n      let renderCount = 0\n      const states: Array<CreateQueryResult<string>> = []\n\n      const query = createQuery<string>(\n        () => ({\n          queryKey: key,\n          queryFn: () => Promise.resolve('test'),\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      // Track changes to the query state\n      $effect(() => {\n        // @ts-expect-error\n        const _ = { ...query }\n        renderCount++\n      })\n\n      await vi.waitFor(() => expect(query.data).toBe('test'))\n\n      expect(renderCount).toBe(2)\n      expect(states.length).toBe(2)\n      expect(states[0]).toMatchObject({ data: undefined })\n      expect(states[1]).toMatchObject({ data: 'test' })\n    }),\n  )\n\n  it(\n    'should update query options',\n    withEffectRoot(() => {\n      const key = ['test-key']\n\n      const queryFn = async () => {\n        await sleep(10)\n        return 'data1'\n      }\n\n      // Create two queries with the same key but different options\n      createQuery(\n        () => ({ queryKey: key, queryFn, retryDelay: 10 }),\n        () => queryClient,\n      )\n\n      createQuery(\n        () => ({ queryKey: key, queryFn, retryDelay: 20 }),\n        () => queryClient,\n      )\n\n      // The last options should win\n      expect(queryCache.find({ queryKey: key })!.options.retryDelay).toBe(20)\n    }),\n  )\n\n  it(\n    'should start with status pending, fetchStatus idle if enabled is false',\n    withEffectRoot(async () => {\n      const key1 = ['test-key-1']\n      const key2 = ['test-key-2']\n      const states1: Array<CreateQueryResult<string>> = []\n      const states2: Array<CreateQueryResult<string>> = []\n\n      const query1 = createQuery<string>(\n        () => ({\n          queryKey: key1,\n          queryFn: () => 'data',\n          enabled: false,\n        }),\n        () => queryClient,\n      )\n\n      const query2 = createQuery<string>(\n        () => ({\n          queryKey: key2,\n          queryFn: () => 'data',\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states1.push({ ...query1 })\n      })\n\n      $effect(() => {\n        states2.push({ ...query2 })\n      })\n\n      // Check initial states\n      expect(query1.status).toBe('pending')\n      expect(query1.fetchStatus).toBe('idle')\n\n      // Wait for second query to complete\n      await vi.waitFor(() => {\n        expect(query2.status).toBe('success')\n        expect(query2.fetchStatus).toBe('idle')\n      })\n\n      // Verify the state transitions for the second query\n      expect(states2[0]?.status).toBe('pending')\n      expect(states2[0]?.fetchStatus).toBe('fetching')\n    }),\n  )\n\n  it(\n    'should be in \"pending\" state by default',\n    withEffectRoot(() => {\n      const key = ['test-key']\n\n      const query = createQuery<string>(\n        () => ({\n          queryKey: key,\n          queryFn: () => new Promise(() => {}),\n        }),\n        () => queryClient,\n      )\n\n      expect(query.status).toBe('pending')\n    }),\n  )\n\n  it(\n    'should not refetch query on focus when `enabled` is set to `false`',\n    withEffectRoot(async () => {\n      const key = ['test-key']\n      const queryFn = vi.fn().mockReturnValue('data')\n\n      const query = createQuery<string>(\n        () => ({\n          queryKey: key,\n          queryFn,\n          enabled: false,\n        }),\n        () => queryClient,\n      )\n\n      // Wait a bit to ensure the query has time to settle\n      await sleep(10)\n\n      // Simulate window focus\n      window.dispatchEvent(new Event('visibilitychange'))\n\n      // Wait a bit more to ensure no refetch happens\n      await sleep(10)\n\n      // The query function should not have been called\n      expect(queryFn).not.toHaveBeenCalled()\n\n      // Data should be undefined since the query is disabled\n      expect(query.data).toBeUndefined()\n    }),\n  )\n\n  it(\n    'should not refetch stale query on focus when `refetchOnWindowFocus` is set to `false`',\n    withEffectRoot(async () => {\n      const key = ['test-key']\n      const states: Array<CreateQueryResult<number>> = []\n      let count = 0\n\n      const query = createQuery<number>(\n        () => ({\n          queryKey: key,\n          queryFn: () => count++,\n          staleTime: 0,\n          refetchOnWindowFocus: false,\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      // Wait for the initial fetch to complete\n      await vi.waitFor(() => expect(query.data).toBe(0))\n\n      // Simulate window focus\n      window.dispatchEvent(new Event('visibilitychange'))\n\n      // Wait a bit to ensure no refetch happens\n      await sleep(10)\n\n      // Should only have 2 states: initial and after fetch\n      expect(states.length).toBe(2)\n      expect(states[0]).toMatchObject({ data: undefined, isFetching: true })\n      expect(states[1]).toMatchObject({ data: 0, isFetching: false })\n\n      // Count should still be 0 since no refetch occurred\n      expect(count).toBe(1)\n    }),\n  )\n\n  it(\n    'should not refetch stale query on focus when `refetchOnWindowFocus` is set to a function that returns `false`',\n    withEffectRoot(async () => {\n      const key = ['test-key']\n      const states: Array<CreateQueryResult<number>> = []\n      let count = 0\n\n      const query = createQuery<number>(\n        () => ({\n          queryKey: key,\n          queryFn: () => count++,\n          staleTime: 0,\n          refetchOnWindowFocus: () => false,\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      // Wait for the initial fetch to complete\n      await vi.waitFor(() => expect(query.data).toBe(0))\n\n      // Simulate window focus\n      window.dispatchEvent(new Event('visibilitychange'))\n\n      // Wait a bit to ensure no refetch happens\n      await sleep(10)\n\n      // Should only have 2 states: initial and after fetch\n      expect(states.length).toBe(2)\n      expect(states[0]).toMatchObject({ data: undefined, isFetching: true })\n      expect(states[1]).toMatchObject({ data: 0, isFetching: false })\n\n      // Count should still be 0 since no refetch occurred\n      expect(count).toBe(1)\n    }),\n  )\n\n  it(\n    'should not refetch fresh query on focus when `refetchOnWindowFocus` is set to `true`',\n    withEffectRoot(async () => {\n      const key = ['test-key']\n      const states: Array<CreateQueryResult<number>> = []\n      let count = 0\n\n      const query = createQuery<number>(\n        () => ({\n          queryKey: key,\n          queryFn: () => count++,\n          staleTime: Infinity,\n          refetchOnWindowFocus: true,\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      // Wait for the initial fetch to complete\n      await vi.waitFor(() => expect(query.data).toBe(0))\n\n      // Simulate window focus\n      window.dispatchEvent(new Event('visibilitychange'))\n\n      // Wait a bit to ensure no refetch happens\n      await sleep(10)\n\n      // Should only have 2 states: initial and after fetch\n      expect(states.length).toBe(2)\n      expect(states[0]).toMatchObject({ data: undefined, isFetching: true })\n      expect(states[1]).toMatchObject({ data: 0, isFetching: false })\n\n      // Count should still be 0 since no refetch occurred\n      expect(count).toBe(1)\n    }),\n  )\n\n  it('should refetch fresh query when refetchOnMount is set to always', async () => {\n    const key = ['test-key']\n    const states: Array<CreateQueryResult<string>> = []\n\n    // Prefetch the query\n    await queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => 'prefetched',\n    })\n\n    await withEffectRoot(async () => {\n      const query = createQuery<string>(\n        () => ({\n          queryKey: key,\n          queryFn: () => 'data',\n          refetchOnMount: 'always',\n          staleTime: Infinity,\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      // Wait for the refetch to complete\n      await vi.waitFor(() => expect(query.data).toBe('data'))\n\n      // Should have 2 states: initial (with prefetched data) and after refetch\n      expect(states.length).toBe(2)\n      expect(states[0]).toMatchObject({\n        data: 'prefetched',\n        isStale: false,\n        isFetching: true,\n      })\n      expect(states[1]).toMatchObject({\n        data: 'data',\n        isStale: false,\n        isFetching: false,\n      })\n    })()\n  })\n\n  it('should refetch stale query when refetchOnMount is set to true', async () => {\n    const key = ['test-key']\n    const states: Array<CreateQueryResult<string>> = []\n\n    // Prefetch the query\n    await queryClient.prefetchQuery({\n      queryKey: key,\n      queryFn: () => 'prefetched',\n    })\n\n    await withEffectRoot(async () => {\n      const query = createQuery<string>(\n        () => ({\n          queryKey: key,\n          queryFn: () => 'data',\n          refetchOnMount: true,\n          staleTime: 0,\n        }),\n        () => queryClient,\n      )\n\n      $effect(() => {\n        states.push({ ...query })\n      })\n\n      // Wait for the refetch to complete\n      await vi.waitFor(() => expect(query.data).toBe('data'))\n\n      // Should have 2 states: initial (with prefetched data) and after refetch\n      expect(states.length).toBe(2)\n      expect(states[0]).toMatchObject({\n        data: 'prefetched',\n        isStale: true,\n        isFetching: true,\n      })\n      expect(states[1]).toMatchObject({\n        data: 'data',\n        isStale: true,\n        isFetching: false,\n      })\n    })()\n  })\n\n  it(\n    'should set status to error if queryFn throws',\n    withEffectRoot(async () => {\n      const key = ['test-key'] // Declare key variable\n      const consoleMock = vi\n        .spyOn(console, 'error')\n        .mockImplementation(() => undefined)\n\n      const query = createQuery<string, Error>(\n        () => ({\n          queryKey: key,\n          queryFn: () => Promise.reject(new Error('Error test')),\n          retry: false,\n        }),\n        () => queryClient,\n      )\n\n      await vi.waitFor(() => expect(query.status).toBe('error'))\n      expect(query.error?.message).toBe('Error test')\n\n      consoleMock.mockRestore()\n    }),\n  )\n\n  it(\n    'should set status to error instead of throwing when error should not be thrown',\n    withEffectRoot(async () => {\n      const key = ['test-key'] // Declare key variable\n\n      const query = createQuery<string, Error>(\n        () => ({\n          queryKey: key,\n          queryFn: () => Promise.reject(new Error('Local Error')),\n          retry: false,\n          throwOnError: (err) => err.message !== 'Local Error',\n        }),\n        () => queryClient,\n      )\n\n      await vi.waitFor(() => expect(query.status).toBe('error'))\n      expect(query.error?.message).toBe('Local Error')\n    }),\n  )\n\n  it(\n    'should support changing provided query client',\n    withEffectRoot(async () => {\n      const queryClient1 = new QueryClient()\n      const queryClient2 = new QueryClient()\n\n      let queryClient = $state(queryClient1)\n\n      const key = ['test']\n\n      createQuery(\n        () => ({\n          queryKey: key,\n          queryFn: () => Promise.resolve('prefetched'),\n        }),\n        () => queryClient,\n      )\n\n      expect(queryClient1.getQueryCache().find({ queryKey: key })).toBeDefined()\n\n      queryClient = queryClient2\n      flushSync()\n\n      expect(queryClient2.getQueryCache().find({ queryKey: key })).toBeDefined()\n    }),\n  )\n})\n"
  },
  {
    "path": "packages/svelte-query/tests/createQuery.test-d.ts",
    "content": "import { describe, expectTypeOf, it } from 'vitest'\nimport { createQuery, queryOptions } from '../src/index.js'\n\ndescribe('initialData', () => {\n  describe('Config object overload', () => {\n    it('TData should always be defined when initialData is provided as an object', () => {\n      const { data } = createQuery(() => ({\n        queryKey: ['key'],\n        queryFn: () => ({ wow: true }),\n        initialData: { wow: true },\n      }))\n\n      expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n    })\n\n    it('TData should be defined when passed through queryOptions', () => {\n      const options = queryOptions({\n        queryKey: ['key'],\n        queryFn: () => ({ wow: true }),\n        initialData: { wow: true },\n      })\n      const { data } = createQuery(() => options)\n\n      expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n    })\n\n    it('TData should have undefined in the union when initialData is NOT provided', () => {\n      const { data } = createQuery(() => ({\n        queryKey: ['key'],\n        queryFn: () => ({ wow: true }),\n      }))\n\n      expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()\n    })\n\n    it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => {\n      const { data } = createQuery(() => ({\n        queryKey: ['key'],\n        queryFn: () => ({ wow: true }),\n        initialData: () => undefined as { wow: boolean } | undefined,\n      }))\n\n      expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()\n    })\n  })\n\n  describe('Query key overload', () => {\n    it('TData should always be defined when initialData is provided', () => {\n      const { data } = createQuery(() => ({\n        queryKey: ['key'],\n        queryFn: () => ({ wow: true }),\n        initialData: { wow: true },\n      }))\n\n      expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n    })\n\n    it('TData should have undefined in the union when initialData is NOT provided', () => {\n      const { data } = createQuery(() => ({\n        queryKey: ['key'],\n        queryFn: () => ({ wow: true }),\n      }))\n\n      expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()\n    })\n  })\n\n  describe('Query key and func', () => {\n    it('TData should always be defined when initialData is provided', () => {\n      const { data } = createQuery(() => ({\n        queryKey: ['key'],\n        queryFn: () => ({ wow: true }),\n        initialData: { wow: true },\n      }))\n\n      expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n    })\n\n    it('TData should have undefined in the union when initialData is NOT provided', () => {\n      const { data } = createQuery(() => ({\n        queryKey: ['key'],\n        queryFn: () => ({ wow: true }),\n      }))\n\n      expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/svelte-query/tests/infiniteQueryOptions.svelte.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\nimport { infiniteQueryOptions } from '../src/index.js'\nimport type { CreateInfiniteQueryOptions } from '../src/types.js'\n\ndescribe('infiniteQueryOptions', () => {\n  it('should return the object received as a parameter without any modification.', () => {\n    const object: CreateInfiniteQueryOptions = {\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n      getNextPageParam: () => null,\n      initialPageParam: null,\n    } as const\n\n    expect(infiniteQueryOptions(object)).toBe(object)\n  })\n})\n"
  },
  {
    "path": "packages/svelte-query/tests/infiniteQueryOptions.test-d.ts",
    "content": "import { describe, expectTypeOf, test } from 'vitest'\nimport { QueryClient } from '@tanstack/query-core'\nimport { createInfiniteQuery, infiniteQueryOptions } from '../src/index.js'\nimport type { InfiniteData } from '@tanstack/query-core'\n\ndescribe('queryOptions', () => {\n  test('Should not allow excess properties', () => {\n    infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('data'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n      // @ts-expect-error this is a good error, because stallTime does not exist!\n      stallTime: 1000,\n    })\n  })\n\n  test('Should infer types for callbacks', () => {\n    infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('data'),\n      staleTime: 1000,\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n      select: (data) => {\n        expectTypeOf(data).toEqualTypeOf<InfiniteData<string, number>>()\n      },\n    })\n  })\n\n  test('Should work when passed to createInfiniteQuery', () => {\n    const options = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    const query = createInfiniteQuery(() => options)\n\n    // known issue: type of pageParams is unknown when returned from useInfiniteQuery\n    expectTypeOf(query.data).toEqualTypeOf<\n      InfiniteData<string, unknown> | undefined\n    >()\n  })\n\n  test('Should work when passed to fetchInfiniteQuery', async () => {\n    const options = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    const data = await new QueryClient().fetchInfiniteQuery(options)\n\n    expectTypeOf(data).toEqualTypeOf<InfiniteData<string, number>>()\n  })\n})\n"
  },
  {
    "path": "packages/svelte-query/tests/mutationOptions/BaseExample.svelte",
    "content": "<script lang=\"ts\">\n  import { QueryClient } from '@tanstack/query-core'\n  import {\n    createMutation,\n    setQueryClientContext,\n    useIsMutating,\n    useMutationState,\n  } from '../../src/index.js'\n  import type {\n    Accessor,\n    CreateMutationOptions,\n    MutationStateOptions,\n  } from '../../src/index.js'\n  import type { MutationFilters } from '@tanstack/query-core'\n\n  let {\n    mutationOpts,\n    isMutatingFilters,\n    mutationStateOpts,\n  }: {\n    mutationOpts: Accessor<CreateMutationOptions<string, Error, void, unknown>>\n    isMutatingFilters?: MutationFilters\n    mutationStateOpts?: MutationStateOptions\n  } = $props()\n\n  const queryClient = new QueryClient()\n  setQueryClientContext(queryClient)\n\n  const mutation = createMutation(mutationOpts)\n  const isMutating = useIsMutating(isMutatingFilters)\n  const mutationState = useMutationState(mutationStateOpts)\n\n  let clientIsMutating = $state(0)\n\n  $effect(() => {\n    const mutationCache = queryClient.getMutationCache()\n    clientIsMutating = isMutatingFilters\n      ? queryClient.isMutating(isMutatingFilters)\n      : queryClient.isMutating()\n\n    const unsubscribe = mutationCache.subscribe(() => {\n      clientIsMutating = isMutatingFilters\n        ? queryClient.isMutating(isMutatingFilters)\n        : queryClient.isMutating()\n    })\n\n    return unsubscribe\n  })\n</script>\n\n<button onclick={() => mutation.mutate()}>mutate</button>\n\n<div>isMutating: {isMutating.current}</div>\n<div>clientIsMutating: {clientIsMutating}</div>\n<div>\n  mutationState: {JSON.stringify(mutationState.map((state) => state.data))}\n</div>\n"
  },
  {
    "path": "packages/svelte-query/tests/mutationOptions/MultiExample.svelte",
    "content": "<script lang=\"ts\">\n  import { QueryClient } from '@tanstack/query-core'\n  import {\n    createMutation,\n    setQueryClientContext,\n    useIsMutating,\n    useMutationState,\n  } from '../../src/index.js'\n  import type {\n    Accessor,\n    CreateMutationOptions,\n    MutationStateOptions,\n  } from '../../src/index.js'\n  import type { MutationFilters } from '@tanstack/query-core'\n\n  let {\n    mutationOpts1,\n    mutationOpts2,\n    isMutatingFilters,\n    mutationStateOpts,\n  }: {\n    mutationOpts1: Accessor<CreateMutationOptions<string, Error, void, unknown>>\n    mutationOpts2: Accessor<CreateMutationOptions<string, Error, void, unknown>>\n    isMutatingFilters?: MutationFilters\n    mutationStateOpts?: MutationStateOptions\n  } = $props()\n\n  const queryClient = new QueryClient()\n  setQueryClientContext(queryClient)\n\n  const mutation1 = createMutation(mutationOpts1)\n  const mutation2 = createMutation(mutationOpts2)\n  const isMutating = useIsMutating(isMutatingFilters)\n  const mutationState = useMutationState(mutationStateOpts)\n\n  let clientIsMutating = $state(0)\n\n  $effect(() => {\n    const mutationCache = queryClient.getMutationCache()\n    clientIsMutating = isMutatingFilters\n      ? queryClient.isMutating(isMutatingFilters)\n      : queryClient.isMutating()\n\n    const unsubscribe = mutationCache.subscribe(() => {\n      clientIsMutating = isMutatingFilters\n        ? queryClient.isMutating(isMutatingFilters)\n        : queryClient.isMutating()\n    })\n\n    return unsubscribe\n  })\n</script>\n\n<button onclick={() => mutation1.mutate()}>mutate1</button>\n<button onclick={() => mutation2.mutate()}>mutate2</button>\n\n<div>isMutating: {isMutating.current}</div>\n<div>clientIsMutating: {clientIsMutating}</div>\n<div>\n  mutationState: {JSON.stringify(mutationState.map((state) => state.data))}\n</div>\n"
  },
  {
    "path": "packages/svelte-query/tests/mutationOptions/mutationOptions.svelte.test.ts",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { fireEvent, render } from '@testing-library/svelte'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { mutationOptions } from '../../src/index.js'\nimport BaseExample from './BaseExample.svelte'\nimport MultiExample from './MultiExample.svelte'\n\ndescribe('mutationOptions', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should return the object received as a parameter without any modification (with mutationKey in mutationOptions)', () => {\n    const object = {\n      mutationKey: ['key'],\n      mutationFn: () => sleep(10).then(() => 5),\n    } as const\n\n    expect(mutationOptions(object)).toStrictEqual(object)\n  })\n\n  it('should return the object received as a parameter without any modification (without mutationKey in mutationOptions)', () => {\n    const object = {\n      mutationFn: () => sleep(10).then(() => 5),\n    } as const\n\n    expect(mutationOptions(object)).toStrictEqual(object)\n  })\n\n  it('should return the number of fetching mutations when used with useIsMutating (with mutationKey in mutationOptions)', async () => {\n    const mutationOpts = mutationOptions({\n      mutationKey: ['key'],\n      mutationFn: () => sleep(50).then(() => 'data'),\n    })\n\n    const rendered = render(BaseExample, {\n      props: { mutationOpts: () => mutationOpts },\n    })\n\n    expect(rendered.getByText('isMutating: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('isMutating: 1')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(51)\n    expect(rendered.getByText('isMutating: 0')).toBeInTheDocument()\n  })\n\n  it('should return the number of fetching mutations when used with useIsMutating (without mutationKey in mutationOptions)', async () => {\n    const mutationOpts = mutationOptions({\n      mutationFn: () => sleep(50).then(() => 'data'),\n    })\n\n    const rendered = render(BaseExample, {\n      props: { mutationOpts: () => mutationOpts },\n    })\n\n    expect(rendered.getByText('isMutating: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('isMutating: 1')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(51)\n    expect(rendered.getByText('isMutating: 0')).toBeInTheDocument()\n  })\n\n  it('should return the number of fetching mutations when used with useIsMutating', async () => {\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['key'],\n      mutationFn: () => sleep(50).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(50).then(() => 'data2'),\n    })\n\n    const rendered = render(MultiExample, {\n      props: {\n        mutationOpts1: () => mutationOpts1,\n        mutationOpts2: () => mutationOpts2,\n      },\n    })\n\n    expect(rendered.getByText('isMutating: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('isMutating: 2')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(51)\n    expect(rendered.getByText('isMutating: 0')).toBeInTheDocument()\n  })\n\n  it('should return the number of fetching mutations when used with useIsMutating (filter mutationOpts1.mutationKey)', async () => {\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['key'],\n      mutationFn: () => sleep(50).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(50).then(() => 'data2'),\n    })\n\n    const rendered = render(MultiExample, {\n      props: {\n        mutationOpts1: () => mutationOpts1,\n        mutationOpts2: () => mutationOpts2,\n        isMutatingFilters: { mutationKey: mutationOpts1.mutationKey },\n      },\n    })\n\n    expect(rendered.getByText('isMutating: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('isMutating: 1')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(51)\n    expect(rendered.getByText('isMutating: 0')).toBeInTheDocument()\n  })\n\n  it('should return the number of fetching mutations when used with queryClient.isMutating (with mutationKey in mutationOptions)', async () => {\n    const mutationOpts = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(500).then(() => 'data'),\n    })\n\n    const rendered = render(BaseExample, {\n      props: {\n        mutationOpts: () => mutationOpts,\n        isMutatingFilters: { mutationKey: mutationOpts.mutationKey },\n      },\n    })\n\n    expect(rendered.getByText('clientIsMutating: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('clientIsMutating: 1')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(501)\n    expect(rendered.getByText('clientIsMutating: 0')).toBeInTheDocument()\n  })\n\n  it('should return the number of fetching mutations when used with queryClient.isMutating (without mutationKey in mutationOptions)', async () => {\n    const mutationOpts = mutationOptions({\n      mutationFn: () => sleep(500).then(() => 'data'),\n    })\n\n    const rendered = render(BaseExample, {\n      props: { mutationOpts: () => mutationOpts },\n    })\n\n    expect(rendered.getByText('clientIsMutating: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('clientIsMutating: 1')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(501)\n    expect(rendered.getByText('clientIsMutating: 0')).toBeInTheDocument()\n  })\n\n  it('should return the number of fetching mutations when used with queryClient.isMutating', async () => {\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(500).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(500).then(() => 'data2'),\n    })\n\n    const rendered = render(MultiExample, {\n      props: {\n        mutationOpts1: () => mutationOpts1,\n        mutationOpts2: () => mutationOpts2,\n      },\n    })\n\n    expect(rendered.getByText('clientIsMutating: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('clientIsMutating: 2')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(501)\n    expect(rendered.getByText('clientIsMutating: 0')).toBeInTheDocument()\n  })\n\n  it('should return the number of fetching mutations when used with queryClient.isMutating (filter mutationOpts1.mutationKey)', async () => {\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(500).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(500).then(() => 'data2'),\n    })\n\n    const rendered = render(MultiExample, {\n      props: {\n        mutationOpts1: () => mutationOpts1,\n        mutationOpts2: () => mutationOpts2,\n        isMutatingFilters: { mutationKey: mutationOpts1.mutationKey },\n      },\n    })\n\n    expect(rendered.getByText('clientIsMutating: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('clientIsMutating: 1')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(501)\n    expect(rendered.getByText('clientIsMutating: 0')).toBeInTheDocument()\n  })\n\n  it('should return mutation states when used with useMutationState (with mutationKey in mutationOptions)', async () => {\n    const mutationOpts = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(10).then(() => 'data'),\n    })\n\n    const rendered = render(BaseExample, {\n      props: {\n        mutationOpts: () => mutationOpts,\n        mutationStateOpts: {\n          filters: {\n            mutationKey: mutationOpts.mutationKey,\n            status: 'success',\n          },\n        },\n      },\n    })\n\n    expect(rendered.getByText('mutationState: []')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('mutationState: [\"data\"]')).toBeInTheDocument()\n  })\n\n  it('should return mutation states when used with useMutationState (without mutationKey in mutationOptions)', async () => {\n    const mutationOpts = mutationOptions({\n      mutationFn: () => sleep(10).then(() => 'data'),\n    })\n\n    const rendered = render(BaseExample, {\n      props: {\n        mutationOpts: () => mutationOpts,\n        mutationStateOpts: {\n          filters: { status: 'success' },\n        },\n      },\n    })\n\n    expect(rendered.getByText('mutationState: []')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('mutationState: [\"data\"]')).toBeInTheDocument()\n  })\n\n  it('should return mutation states when used with useMutationState', async () => {\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(10).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(10).then(() => 'data2'),\n    })\n\n    const rendered = render(MultiExample, {\n      props: {\n        mutationOpts1: () => mutationOpts1,\n        mutationOpts2: () => mutationOpts2,\n        mutationStateOpts: {\n          filters: { status: 'success' },\n        },\n      },\n    })\n\n    expect(rendered.getByText('mutationState: []')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(\n      rendered.getByText('mutationState: [\"data1\",\"data2\"]'),\n    ).toBeInTheDocument()\n  })\n\n  it('should return mutation states when used with useMutationState (filter mutationOpts1.mutationKey)', async () => {\n    const mutationOpts1 = mutationOptions({\n      mutationKey: ['mutation'],\n      mutationFn: () => sleep(10).then(() => 'data1'),\n    })\n    const mutationOpts2 = mutationOptions({\n      mutationFn: () => sleep(10).then(() => 'data2'),\n    })\n\n    const rendered = render(MultiExample, {\n      props: {\n        mutationOpts1: () => mutationOpts1,\n        mutationOpts2: () => mutationOpts2,\n        mutationStateOpts: {\n          filters: {\n            mutationKey: mutationOpts1.mutationKey,\n            status: 'success',\n          },\n        },\n      },\n    })\n\n    expect(rendered.getByText('mutationState: []')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate1/i }))\n    fireEvent.click(rendered.getByRole('button', { name: /mutate2/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('mutationState: [\"data1\"]')).toBeInTheDocument()\n  })\n})\n"
  },
  {
    "path": "packages/svelte-query/tests/mutationOptions/mutationOptions.test-d.ts",
    "content": "import { assertType, describe, expectTypeOf, test } from 'vitest'\nimport { QueryClient } from '@tanstack/query-core'\nimport {\n  createMutation,\n  mutationOptions,\n  useIsMutating,\n  useMutationState,\n} from '../../src/index.js'\nimport type {\n  DefaultError,\n  MutationFunctionContext,\n  MutationState,\n  WithRequired,\n} from '@tanstack/query-core'\nimport type {\n  CreateMutationOptions,\n  CreateMutationResult,\n} from '../../src/types.js'\n\ndescribe('mutationOptions', () => {\n  test('Should not allow excess properties', () => {\n    // @ts-expect-error this is a good error, because onMutates does not exist!\n    mutationOptions({\n      mutationFn: () => Promise.resolve(5),\n      mutationKey: ['key'],\n      onMutates: 1000,\n      onSuccess: (data) => {\n        expectTypeOf(data).toEqualTypeOf<number>()\n      },\n    })\n  })\n\n  test('Should infer types for callbacks', () => {\n    mutationOptions({\n      mutationFn: () => Promise.resolve(5),\n      mutationKey: ['key'],\n      onSuccess: (data) => {\n        expectTypeOf(data).toEqualTypeOf<number>()\n      },\n    })\n  })\n\n  test('Should infer types for onError callback', () => {\n    mutationOptions({\n      mutationFn: () => {\n        throw new Error('fail')\n      },\n      mutationKey: ['key'],\n      onError: (error) => {\n        expectTypeOf(error).toEqualTypeOf<DefaultError>()\n      },\n    })\n  })\n\n  test('Should infer types for variables', () => {\n    mutationOptions<number, DefaultError, { id: string }>({\n      mutationFn: (vars) => {\n        expectTypeOf(vars).toEqualTypeOf<{ id: string }>()\n        return Promise.resolve(5)\n      },\n      mutationKey: ['with-vars'],\n    })\n  })\n\n  test('Should infer result type correctly', () => {\n    mutationOptions<number, DefaultError, void, { name: string }>({\n      mutationFn: () => Promise.resolve(5),\n      mutationKey: ['key'],\n      onMutate: () => {\n        return { name: 'onMutateResult' }\n      },\n      onSuccess: (_data, _variables, onMutateResult) => {\n        expectTypeOf(onMutateResult).toEqualTypeOf<{ name: string }>()\n      },\n    })\n  })\n\n  test('Should infer context type correctly', () => {\n    mutationOptions<number>({\n      mutationFn: (_variables, context) => {\n        expectTypeOf(context).toEqualTypeOf<MutationFunctionContext>()\n        return Promise.resolve(5)\n      },\n      mutationKey: ['key'],\n      onMutate: (_variables, context) => {\n        expectTypeOf(context).toEqualTypeOf<MutationFunctionContext>()\n      },\n      onSuccess: (_data, _variables, _onMutateResult, context) => {\n        expectTypeOf(context).toEqualTypeOf<MutationFunctionContext>()\n      },\n      onError: (_error, _variables, _onMutateResult, context) => {\n        expectTypeOf(context).toEqualTypeOf<MutationFunctionContext>()\n      },\n      onSettled: (_data, _error, _variables, _onMutateResult, context) => {\n        expectTypeOf(context).toEqualTypeOf<MutationFunctionContext>()\n      },\n    })\n  })\n\n  test('Should error if mutationFn return type mismatches TData', () => {\n    assertType(\n      mutationOptions<number>({\n        // @ts-expect-error this is a good error, because return type is string, not number\n        mutationFn: async () => Promise.resolve('wrong return'),\n      }),\n    )\n  })\n\n  test('Should allow mutationKey to be omitted', () => {\n    return mutationOptions({\n      mutationFn: () => Promise.resolve(123),\n      onSuccess: (data) => {\n        expectTypeOf(data).toEqualTypeOf<number>()\n      },\n    })\n  })\n\n  test('Should infer all types when not explicitly provided', () => {\n    expectTypeOf(\n      mutationOptions({\n        mutationFn: (id: string) => Promise.resolve(id.length),\n        mutationKey: ['key'],\n        onSuccess: (data) => {\n          expectTypeOf(data).toEqualTypeOf<number>()\n        },\n      }),\n    ).toEqualTypeOf<\n      WithRequired<\n        CreateMutationOptions<number, DefaultError, string>,\n        'mutationKey'\n      >\n    >()\n    expectTypeOf(\n      mutationOptions({\n        mutationFn: (id: string) => Promise.resolve(id.length),\n        onSuccess: (data) => {\n          expectTypeOf(data).toEqualTypeOf<number>()\n        },\n      }),\n    ).toEqualTypeOf<\n      Omit<CreateMutationOptions<number, DefaultError, string>, 'mutationKey'>\n    >()\n  })\n\n  test('Should work when used with createMutation', () => {\n    const mutation = createMutation(() =>\n      mutationOptions({\n        mutationKey: ['key'],\n        mutationFn: () => Promise.resolve('data'),\n        onSuccess: (data) => {\n          expectTypeOf(data).toEqualTypeOf<string>()\n        },\n      }),\n    )\n    expectTypeOf(mutation).toEqualTypeOf<\n      CreateMutationResult<string, DefaultError, void, unknown>\n    >()\n\n    createMutation(() =>\n      // should allow when used with createMutation without mutationKey\n      mutationOptions({\n        mutationFn: () => Promise.resolve('data'),\n        onSuccess: (data) => {\n          expectTypeOf(data).toEqualTypeOf<string>()\n        },\n      }),\n    )\n  })\n\n  test('Should work when used with useIsMutating', () => {\n    const isMutating = useIsMutating(\n      mutationOptions({\n        mutationKey: ['key'],\n        mutationFn: () => Promise.resolve(5),\n      }),\n    )\n    expectTypeOf(isMutating.current).toEqualTypeOf<number>()\n\n    useIsMutating(\n      // @ts-expect-error filters should have mutationKey\n      mutationOptions({\n        mutationFn: () => Promise.resolve(5),\n      }),\n    )\n  })\n\n  test('Should work when used with queryClient.isMutating', () => {\n    const queryClient = new QueryClient()\n\n    const isMutating = queryClient.isMutating(\n      mutationOptions({\n        mutationKey: ['key'],\n        mutationFn: () => Promise.resolve(5),\n      }),\n    )\n    expectTypeOf(isMutating).toEqualTypeOf<number>()\n\n    queryClient.isMutating(\n      // @ts-expect-error filters should have mutationKey\n      mutationOptions({\n        mutationFn: () => Promise.resolve(5),\n      }),\n    )\n  })\n\n  test('Should work when used with useMutationState', () => {\n    const mutationState = useMutationState({\n      filters: mutationOptions({\n        mutationKey: ['key'],\n        mutationFn: () => Promise.resolve(5),\n      }),\n    })\n    expectTypeOf(mutationState).toEqualTypeOf<\n      Array<MutationState<unknown, Error, unknown, unknown>>\n    >()\n\n    useMutationState({\n      // @ts-expect-error filters should have mutationKey\n      filters: mutationOptions({\n        mutationFn: () => Promise.resolve(5),\n      }),\n    })\n  })\n})\n"
  },
  {
    "path": "packages/svelte-query/tests/queryOptions.svelte.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\nimport { queryOptions } from '../src/index.js'\n\ndescribe('queryOptions', () => {\n  it('should return the object received as a parameter without any modification.', () => {\n    const object = {\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    } as const\n\n    expect(queryOptions(object)).toBe(object)\n  })\n})\n"
  },
  {
    "path": "packages/svelte-query/tests/queryOptions.test-d.ts",
    "content": "import { describe, expectTypeOf, test } from 'vitest'\nimport {\n  QueriesObserver,\n  QueryClient,\n  dataTagSymbol,\n  skipToken,\n} from '@tanstack/query-core'\nimport { createQueries, queryOptions } from '../src/index.js'\nimport type { QueryObserverResult } from '@tanstack/query-core'\n\ndescribe('queryOptions', () => {\n  test('Should not allow excess properties', () => {\n    queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n      // @ts-expect-error this is a good error, because stallTime does not exist!\n      stallTime: 1000,\n    })\n  })\n\n  test('Should infer types for callbacks', () => {\n    queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n      staleTime: 1000,\n      select: (data) => {\n        expectTypeOf(data).toEqualTypeOf<number>()\n      },\n    })\n  })\n\n  test('Should work when passed to fetchQuery', async () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const data = await new QueryClient().fetchQuery(options)\n    expectTypeOf(data).toEqualTypeOf<number>()\n  })\n\n  test('Should work when passed to createQueries', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const queries = createQueries(() => ({\n      queries: [options],\n    }))\n\n    expectTypeOf(queries[0].data).toEqualTypeOf<number | undefined>()\n  })\n\n  test('Should tag the queryKey with the result type of the QueryFn', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<number>()\n  })\n\n  test('Should tag the queryKey even if no promise is returned', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => 5,\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<number>()\n  })\n\n  test('Should tag the queryKey with unknown if there is no queryFn', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<unknown>()\n  })\n\n  test('Should tag the queryKey with the result type of the QueryFn if select is used', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n      select: (data) => data.toString(),\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<number>()\n  })\n\n  test('Should return the proper type when passed to getQueryData', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryData(queryKey)\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n\n  test('Should return the proper type when passed to getQueryState', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n    const state = queryClient.getQueryState(queryKey)\n    expectTypeOf(state?.data).toEqualTypeOf<number | undefined>()\n  })\n\n  test('Should properly type updaterFn when passed to setQueryData', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.setQueryData(queryKey, (prev) => {\n      expectTypeOf(prev).toEqualTypeOf<number | undefined>()\n      return prev\n    })\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n\n  test('Should properly type value when passed to setQueryData', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n\n    // @ts-expect-error value should be a number\n    queryClient.setQueryData(queryKey, '5')\n    // @ts-expect-error value should be a number\n    queryClient.setQueryData(queryKey, () => '5')\n\n    const data = queryClient.setQueryData(queryKey, 5)\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n\n  test('Should infer even if there is a conditional skipToken', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryData(options.queryKey)\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n\n  test('Should infer to unknown if we disable a query with just a skipToken', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: skipToken,\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryData(options.queryKey)\n    expectTypeOf(data).toEqualTypeOf<unknown>()\n  })\n\n  test('Should return the proper type when passed to QueriesObserver', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n    const queriesObserver = new QueriesObserver(queryClient, [options])\n    expectTypeOf(queriesObserver).toEqualTypeOf<\n      QueriesObserver<Array<QueryObserverResult>>\n    >()\n  })\n\n  test('Should allow undefined response in initialData', () => {\n    return (id: string | null) =>\n      queryOptions({\n        queryKey: ['todo', id],\n        queryFn: () =>\n          Promise.resolve({\n            id: '1',\n            title: 'Do Laundry',\n          }),\n        initialData: () =>\n          !id\n            ? undefined\n            : {\n                id,\n                title: 'Initial Data',\n              },\n      })\n  })\n})\n"
  },
  {
    "path": "packages/svelte-query/tests/test-setup.ts",
    "content": "import '@testing-library/jest-dom/vitest'\n"
  },
  {
    "path": "packages/svelte-query/tests/useIsFetching/BaseExample.svelte",
    "content": "<script lang=\"ts\">\n  import ProviderWrapper from '../ProviderWrapper.svelte'\n  import FetchStatus from './FetchStatus.svelte'\n  import Query from './Query.svelte'\n</script>\n\n<ProviderWrapper>\n  <FetchStatus />\n\n  <Query />\n</ProviderWrapper>\n"
  },
  {
    "path": "packages/svelte-query/tests/useIsFetching/FetchStatus.svelte",
    "content": "<script lang=\"ts\">\n  import { useIsFetching } from '../../src/index.js'\n  const isFetching = useIsFetching()\n</script>\n\n<div>isFetching: {isFetching.current}</div>\n"
  },
  {
    "path": "packages/svelte-query/tests/useIsFetching/Query.svelte",
    "content": "<script lang=\"ts\">\n  import { createQuery } from '../../src/index.js'\n  import { sleep } from '@tanstack/query-test-utils'\n\n  let ready = $state(false)\n\n  const query = createQuery(() => ({\n    queryKey: ['test'],\n    queryFn: async () => {\n      await sleep(10)\n      return 'test'\n    },\n    enabled: ready,\n  }))\n</script>\n\n<button onclick={() => (ready = true)}>setReady</button>\n\n<div>Data: {query.data ?? 'undefined'}</div>\n"
  },
  {
    "path": "packages/svelte-query/tests/useIsFetching/useIsFetching.svelte.test.ts",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { fireEvent, render } from '@testing-library/svelte'\nimport BaseExample from './BaseExample.svelte'\n\ndescribe('useIsFetching', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('should update as queries start and stop fetching', async () => {\n    const rendered = render(BaseExample)\n\n    expect(rendered.getByText('isFetching: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /setReady/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('isFetching: 1')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('isFetching: 0')).toBeInTheDocument()\n  })\n})\n"
  },
  {
    "path": "packages/svelte-query/tests/useIsMutating/BaseExample.svelte",
    "content": "<script lang=\"ts\">\n  import ProviderWrapper from '../ProviderWrapper.svelte'\n  import MutatingStatus from './MutatingStatus.svelte'\n  import Query from './Query.svelte'\n</script>\n\n<ProviderWrapper>\n  <MutatingStatus />\n\n  <Query />\n</ProviderWrapper>\n"
  },
  {
    "path": "packages/svelte-query/tests/useIsMutating/MutatingStatus.svelte",
    "content": "<script lang=\"ts\">\n  import { useIsMutating } from '../../src/index.js'\n  const isMutating = useIsMutating()\n</script>\n\n<div>isMutating: {isMutating.current}</div>\n"
  },
  {
    "path": "packages/svelte-query/tests/useIsMutating/Query.svelte",
    "content": "<script lang=\"ts\">\n  import { createMutation } from '../../src/index.js'\n  import { sleep } from '@tanstack/query-test-utils'\n\n  const mutation = createMutation(() => ({\n    mutationKey: ['mutation-1'],\n    mutationFn: async () => {\n      await sleep(10)\n      return 'data'\n    },\n  }))\n</script>\n\n<button onclick={() => mutation.mutate()}>Trigger</button>\n"
  },
  {
    "path": "packages/svelte-query/tests/useIsMutating/useIsMutating.svelte.test.ts",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { fireEvent, render } from '@testing-library/svelte'\nimport BaseExample from './BaseExample.svelte'\n\ndescribe('useIsMutating', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('should update as queries start and stop mutating', async () => {\n    const rendered = render(BaseExample)\n\n    expect(rendered.getByText('isMutating: 0')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /Trigger/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('isMutating: 1')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(11)\n    expect(rendered.getByText('isMutating: 0')).toBeInTheDocument()\n  })\n})\n"
  },
  {
    "path": "packages/svelte-query/tests/useMutationState/BaseExample.svelte",
    "content": "<script lang=\"ts\">\n  import { QueryClient } from '@tanstack/query-core'\n  import {\n    createMutation,\n    setQueryClientContext,\n    useMutationState,\n  } from '../../src/index.js'\n  import type {\n    Accessor,\n    CreateMutationOptions,\n    MutationStateOptions,\n  } from '../../src/index.js'\n\n  let {\n    successMutationOpts,\n    errorMutationOpts,\n    mutationStateOpts,\n  }: {\n    successMutationOpts: Accessor<CreateMutationOptions>\n    errorMutationOpts: Accessor<CreateMutationOptions>\n    mutationStateOpts?: MutationStateOptions | undefined\n  } = $props()\n\n  const queryClient = new QueryClient()\n  setQueryClientContext(queryClient)\n\n  const successMutation = createMutation(successMutationOpts)\n  const errorMutation = createMutation(errorMutationOpts)\n\n  const mutationState = useMutationState(mutationStateOpts)\n</script>\n\n<button onclick={() => successMutation.mutate()}>Success</button>\n<button onclick={() => errorMutation.mutate()}>Error</button>\n\n<div>\n  Data: {JSON.stringify(mutationState.map((state) => state.status))}\n</div>\n"
  },
  {
    "path": "packages/svelte-query/tests/useMutationState/SelectExample.svelte",
    "content": "<script lang=\"ts\">\n  import { QueryClient } from '@tanstack/query-core'\n  import {\n    createMutation,\n    setQueryClientContext,\n    useMutationState,\n  } from '../../src/index.js'\n  import type {\n    Accessor,\n    CreateMutationOptions,\n    MutationStateOptions,\n  } from '../../src/index.js'\n\n  let {\n    mutationOpts,\n    mutationStateOpts,\n  }: {\n    mutationOpts: Accessor<CreateMutationOptions>\n    mutationStateOpts: MutationStateOptions<any>\n  } = $props()\n\n  const queryClient = new QueryClient()\n  setQueryClientContext(queryClient)\n\n  const mutation = createMutation(mutationOpts)\n\n  const variables = useMutationState(mutationStateOpts)\n</script>\n\n<button onclick={() => mutation.mutate()}>mutate</button>\n\n<div>\n  Variables: {JSON.stringify(variables)}\n</div>\n"
  },
  {
    "path": "packages/svelte-query/tests/useMutationState/useMutationState.svelte.test.ts",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { fireEvent, render } from '@testing-library/svelte'\nimport { sleep } from '@tanstack/query-test-utils'\nimport BaseExample from './BaseExample.svelte'\nimport SelectExample from './SelectExample.svelte'\nimport type { Mutation } from '@tanstack/query-core'\n\ndescribe('useMutationState', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('Run few mutation functions and check from useMutationState', async () => {\n    const successMutationFn = vi.fn(() => sleep(10).then(() => 'data'))\n    const errorMutationFn = vi\n      .fn()\n      .mockImplementation(() =>\n        sleep(20).then(() => Promise.reject(new Error('error'))),\n      )\n\n    const rendered = render(BaseExample, {\n      props: {\n        successMutationOpts: () => ({\n          mutationKey: ['success'],\n          mutationFn: successMutationFn,\n        }),\n        errorMutationOpts: () => ({\n          mutationKey: ['error'],\n          mutationFn: errorMutationFn,\n        }),\n      },\n    })\n\n    fireEvent.click(rendered.getByRole('button', { name: /Success/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(successMutationFn).toHaveBeenCalledTimes(1)\n    expect(rendered.getByText('Data: [\"success\"]')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /Error/i }))\n    await vi.advanceTimersByTimeAsync(21)\n    expect(errorMutationFn).toHaveBeenCalledTimes(1)\n    expect(rendered.getByText('Data: [\"success\",\"error\"]')).toBeInTheDocument()\n  })\n\n  test('Can select specific type of mutation ( i.e: error only )', async () => {\n    const successMutationFn = vi.fn(() => sleep(10).then(() => 'data'))\n    const errorMutationFn = vi\n      .fn()\n      .mockImplementation(() =>\n        sleep(20).then(() => Promise.reject(new Error('error'))),\n      )\n\n    const rendered = render(BaseExample, {\n      props: {\n        successMutationOpts: () => ({\n          mutationKey: ['success'],\n          mutationFn: successMutationFn,\n        }),\n        errorMutationOpts: () => ({\n          mutationKey: ['error'],\n          mutationFn: errorMutationFn,\n        }),\n        mutationStateOpts: {\n          filters: { status: 'error' },\n        },\n      },\n    })\n\n    fireEvent.click(rendered.getByRole('button', { name: /Success/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(successMutationFn).toHaveBeenCalledTimes(1)\n    expect(rendered.getByText('Data: []')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /Error/i }))\n    await vi.advanceTimersByTimeAsync(21)\n    expect(errorMutationFn).toHaveBeenCalledTimes(1)\n    expect(rendered.getByText('Data: [\"error\"]')).toBeInTheDocument()\n  })\n\n  test('should return selected value when using select option', async () => {\n    const mutationKey = ['select']\n\n    const rendered = render(SelectExample, {\n      props: {\n        mutationOpts: () => ({\n          mutationKey,\n          mutationFn: () => sleep(10).then(() => 'data'),\n        }),\n        mutationStateOpts: {\n          filters: { mutationKey },\n          select: (mutation: Mutation) => mutation.state.status,\n        },\n      },\n    })\n\n    expect(rendered.getByText('Variables: []')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))\n    await vi.advanceTimersByTimeAsync(0)\n    expect(rendered.getByText('Variables: [\"pending\"]')).toBeInTheDocument()\n\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('Variables: [\"success\"]')).toBeInTheDocument()\n  })\n\n  test('Can select specific mutation using mutation key', async () => {\n    const successMutationFn = vi.fn(() => sleep(10).then(() => 'data'))\n    const errorMutationFn = vi\n      .fn()\n      .mockImplementation(() =>\n        sleep(20).then(() => Promise.reject(new Error('error'))),\n      )\n\n    const rendered = render(BaseExample, {\n      props: {\n        successMutationOpts: () => ({\n          mutationKey: ['success'],\n          mutationFn: successMutationFn,\n        }),\n        errorMutationOpts: () => ({\n          mutationKey: ['error'],\n          mutationFn: errorMutationFn,\n        }),\n        mutationStateOpts: {\n          filters: { mutationKey: ['success'] },\n        },\n      },\n    })\n\n    fireEvent.click(rendered.getByRole('button', { name: /Success/i }))\n    await vi.advanceTimersByTimeAsync(11)\n    expect(successMutationFn).toHaveBeenCalledTimes(1)\n    expect(rendered.getByText('Data: [\"success\"]')).toBeInTheDocument()\n\n    fireEvent.click(rendered.getByRole('button', { name: /Error/i }))\n    await vi.advanceTimersByTimeAsync(21)\n    expect(errorMutationFn).toHaveBeenCalledTimes(1)\n    expect(rendered.getByText('Data: [\"success\"]')).toBeInTheDocument()\n  })\n})\n"
  },
  {
    "path": "packages/svelte-query/tests/utils.svelte.ts",
    "content": "export function ref<T>(initial: T) {\n  let value = $state(initial)\n\n  return {\n    get value() {\n      return value\n    },\n    set value(newValue) {\n      value = newValue\n    },\n  }\n}\n\nexport function promiseWithResolvers<T>() {\n  let resolve: (value: T) => void\n  let reject: (reason?: any) => void\n  const promise = new Promise<T>((res, rej) => {\n    resolve = res\n    reject = rej\n  })\n  return { promise, resolve: resolve!, reject: reject! }\n}\n\nexport function withEffectRoot(fn: () => void | Promise<void>) {\n  return async () => {\n    let promise: void | Promise<void> = Promise.resolve()\n    const cleanup = $effect.root(() => {\n      promise = fn()\n    })\n    await promise\n    cleanup()\n  }\n}\n"
  },
  {
    "path": "packages/svelte-query/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\"\n  },\n  \"include\": [\"src\", \"tests\", \"*.config.*\", \"package.json\"],\n  \"references\": [{ \"path\": \"../query-core\" }]\n}\n"
  },
  {
    "path": "packages/svelte-query/vite.config.ts",
    "content": "import { svelte } from '@sveltejs/vite-plugin-svelte'\nimport { defineConfig } from 'vitest/config'\nimport { svelteTesting } from '@testing-library/svelte/vite'\n\nimport packageJson from './package.json'\n\nexport default defineConfig({\n  plugins: [svelte(), svelteTesting()],\n  // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660\n  resolve: {\n    conditions: ['@tanstack/custom-condition'],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        conditions: ['@tanstack/custom-condition'],\n      },\n    },\n  },\n  test: {\n    name: packageJson.name,\n    dir: './tests',\n    watch: false,\n    environment: 'jsdom',\n    setupFiles: ['./tests/test-setup.ts'],\n    coverage: { enabled: true, provider: 'istanbul', include: ['src/**/*'] },\n    typecheck: { enabled: true },\n  },\n})\n"
  },
  {
    "path": "packages/svelte-query-devtools/.attw.json",
    "content": "{\n  \"ignoreRules\": [\"cjs-resolves-to-esm\", \"internal-resolution-error\"]\n}\n"
  },
  {
    "path": "packages/svelte-query-devtools/CHANGELOG.md",
    "content": "# @tanstack/svelte-query-devtools\n\n## 6.0.4\n\n### Patch Changes\n\n- Updated dependencies [[`83366c4`](https://github.com/TanStack/query/commit/83366c46a6825b5c591399c705d8128743c527dd)]:\n  - @tanstack/query-devtools@5.93.0\n\n## 6.0.3\n\n### Patch Changes\n\n- Updated dependencies [[`f9fc56a`](https://github.com/TanStack/query/commit/f9fc56a9b8724bcfae46f8f6cb229123478eb4db), [`0b29b6f`](https://github.com/TanStack/query/commit/0b29b6f877d4b3a6d05b1c85fb9cb1e6ea736291)]:\n  - @tanstack/query-devtools@5.92.0\n  - @tanstack/svelte-query@6.0.12\n\n## 6.0.2\n\n### Patch Changes\n\n- Updated dependencies [[`b261b6f`](https://github.com/TanStack/query/commit/b261b6f29eee2a9bdbe1bc20035fe9b83b15376b)]:\n  - @tanstack/query-devtools@5.91.1\n\n## 6.0.1\n\n### Patch Changes\n\n- Updated dependencies [[`0e9d5b5`](https://github.com/TanStack/query/commit/0e9d5b565276f0de2a1a14ffbb079b5988581c27)]:\n  - @tanstack/query-devtools@5.91.0\n\n## 6.0.0\n\n### Major Changes\n\n- BREAKING: Migrate to svelte runes (signals). Requires [Svelte v5.25.0](https://github.com/sveltejs/svelte/releases/tag/svelte%405.25.0) or newer. Please see the [migration guide](https://tanstack.com/query/latest/docs/framework/svelte/migrate-from-v5-to-v6). ([#9694](https://github.com/TanStack/query/pull/9694))\n\n### Patch Changes\n\n- Updated dependencies [[`1056ba6`](https://github.com/TanStack/query/commit/1056ba63b30b9d9a66fa813c7d7fb1395e377c55)]:\n  - @tanstack/svelte-query@6.0.0\n"
  },
  {
    "path": "packages/svelte-query-devtools/eslint.config.js",
    "content": "// @ts-check\n\nimport tsParser from '@typescript-eslint/parser'\nimport pluginSvelte from 'eslint-plugin-svelte'\nimport rootConfig from './root.eslint.config.js'\nimport svelteConfig from './svelte.config.js'\n\nexport default [\n  ...rootConfig,\n  ...pluginSvelte.configs['recommended'],\n  {\n    files: ['**/*.svelte', '**/*.svelte.ts', '**/*.svelte.js'],\n    languageOptions: {\n      parserOptions: {\n        parser: tsParser,\n        extraFileExtensions: ['.svelte'],\n        svelteConfig,\n      },\n    },\n  },\n  {\n    rules: {\n      'svelte/block-lang': ['error', { script: ['ts'] }],\n      'svelte/no-svelte-internal': 'error',\n      'svelte/valid-compile': 'off',\n    },\n  },\n]\n"
  },
  {
    "path": "packages/svelte-query-devtools/package.json",
    "content": "{\n  \"name\": \"@tanstack/svelte-query-devtools\",\n  \"version\": \"6.0.4\",\n  \"description\": \"Developer tools to interact with and visualize the TanStack/svelte-query cache\",\n  \"author\": \"Lachlan Collins\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/svelte-query-devtools\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"keywords\": [\n    \"tanstack\",\n    \"query\",\n    \"svelte\"\n  ],\n  \"scripts\": {\n    \"clean\": \"premove ./dist ./coverage ./.svelte-kit ./dist-ts\",\n    \"compile\": \"tsc --build\",\n    \"test:types\": \"svelte-check --tsconfig ./tsconfig.json\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:build\": \"publint --strict && attw --pack\",\n    \"build\": \"svelte-package --input ./src --output ./dist\"\n  },\n  \"type\": \"module\",\n  \"types\": \"dist/index.d.ts\",\n  \"module\": \"dist/index.js\",\n  \"svelte\": \"./dist/index.js\",\n  \"exports\": {\n    \".\": {\n      \"@tanstack/custom-condition\": \"./src/index.ts\",\n      \"types\": \"./dist/index.d.ts\",\n      \"svelte\": \"./dist/index.js\",\n      \"import\": \"./dist/index.js\"\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"files\": [\n    \"dist\",\n    \"src\",\n    \"!src/__tests__\"\n  ],\n  \"dependencies\": {\n    \"@tanstack/query-devtools\": \"workspace:*\",\n    \"esm-env\": \"^1.2.1\"\n  },\n  \"devDependencies\": {\n    \"@sveltejs/package\": \"^2.4.0\",\n    \"@sveltejs/vite-plugin-svelte\": \"^5.1.1\",\n    \"@tanstack/svelte-query\": \"workspace:*\",\n    \"@typescript-eslint/parser\": \"^8.48.0\",\n    \"eslint-plugin-svelte\": \"^3.11.0\",\n    \"svelte\": \"^5.39.3\",\n    \"svelte-check\": \"^4.4.5\",\n    \"typescript\": \"5.9.3\"\n  },\n  \"peerDependencies\": {\n    \"@tanstack/svelte-query\": \"workspace:^\",\n    \"svelte\": \"^5.25.0\"\n  }\n}\n"
  },
  {
    "path": "packages/svelte-query-devtools/src/Devtools.svelte",
    "content": "<script lang=\"ts\">\n  import { onMount } from 'svelte'\n  import { BROWSER, DEV } from 'esm-env'\n  import { onlineManager, useQueryClient } from '@tanstack/svelte-query'\n  import type { QueryClient } from '@tanstack/svelte-query'\n  import type {\n    DevtoolsButtonPosition,\n    DevtoolsErrorType,\n    DevtoolsPosition,\n    TanstackQueryDevtools,\n  } from '@tanstack/query-devtools'\n\n  interface DevtoolsOptions {\n    /**\n     * Set this true if you want the dev tools to default to being open\n     */\n    initialIsOpen?: boolean\n    /**\n     * The position of the TanStack Query logo to open and close the devtools panel.\n     * 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'\n     * Defaults to 'bottom-right'.\n     */\n    buttonPosition?: DevtoolsButtonPosition\n    /**\n     * The position of the TanStack Query devtools panel.\n     * 'top' | 'bottom' | 'left' | 'right'\n     * Defaults to 'bottom'.\n     */\n    position?: DevtoolsPosition\n    /**\n     * Custom instance of QueryClient\n     */\n    client?: QueryClient\n    /**\n     * Use this so you can define custom errors that can be shown in the devtools.\n     */\n    errorTypes?: Array<DevtoolsErrorType>\n    /**\n     * 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.\n     */\n    styleNonce?: string\n    /**\n     * Use this so you can attach the devtool's styles to specific element in the DOM.\n     */\n    shadowDOMTarget?: ShadowRoot\n    /**\n     * Set this to true to hide disabled queries from the devtools panel.\n     */\n    hideDisabledQueries?: boolean\n  }\n\n  let {\n    initialIsOpen = false,\n    buttonPosition = 'bottom-right',\n    position = 'bottom',\n    client = useQueryClient(),\n    errorTypes = [],\n    styleNonce = undefined,\n    shadowDOMTarget = undefined,\n    hideDisabledQueries = false,\n  }: DevtoolsOptions = $props()\n\n  let ref: HTMLDivElement\n  let devtools: TanstackQueryDevtools | undefined\n\n  if (DEV && BROWSER) {\n    onMount(() => {\n      import('@tanstack/query-devtools').then((m) => {\n        const QueryDevtools = m.TanstackQueryDevtools\n\n        devtools = new QueryDevtools({\n          client,\n          queryFlavor: 'Svelte Query',\n          version: '5',\n          onlineManager,\n          buttonPosition,\n          position,\n          initialIsOpen,\n          errorTypes,\n          styleNonce,\n          shadowDOMTarget,\n          hideDisabledQueries,\n        })\n\n        devtools.mount(ref)\n      })\n      return () => devtools?.unmount()\n    })\n\n    $effect(() => {\n      devtools?.setButtonPosition(buttonPosition)\n    })\n\n    $effect(() => {\n      devtools?.setPosition(position)\n    })\n\n    $effect(() => {\n      devtools?.setInitialIsOpen(initialIsOpen)\n    })\n\n    $effect(() => {\n      devtools?.setErrorTypes(errorTypes)\n    })\n  }\n</script>\n\n<div class=\"tsqd-parent-container\" bind:this={ref}></div>\n"
  },
  {
    "path": "packages/svelte-query-devtools/src/index.ts",
    "content": "export { default as SvelteQueryDevtools } from './Devtools.svelte'\n"
  },
  {
    "path": "packages/svelte-query-devtools/svelte.config.js",
    "content": "import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'\n\nconst config = {\n  preprocess: vitePreprocess(),\n  compilerOptions: {\n    runes: true,\n  },\n}\n\nexport default config\n"
  },
  {
    "path": "packages/svelte-query-devtools/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\"\n  },\n  \"include\": [\"src\", \"*.config.*\", \"package.json\"],\n  \"references\": [{ \"path\": \"../query-devtools\" }, { \"path\": \"../svelte-query\" }]\n}\n"
  },
  {
    "path": "packages/svelte-query-devtools/vite.config.ts",
    "content": "import { svelte } from '@sveltejs/vite-plugin-svelte'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  plugins: [svelte()],\n  // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660\n  resolve: {\n    conditions: ['@tanstack/custom-condition'],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        conditions: ['@tanstack/custom-condition'],\n      },\n    },\n  },\n})\n"
  },
  {
    "path": "packages/svelte-query-persist-client/.attw.json",
    "content": "{\n  \"ignoreRules\": [\"cjs-resolves-to-esm\", \"internal-resolution-error\"]\n}\n"
  },
  {
    "path": "packages/svelte-query-persist-client/CHANGELOG.md",
    "content": "# @tanstack/svelte-query-persist-client\n\n## 6.0.25\n\n### Patch Changes\n\n- fix(streamedQuery): maintain error state on reset refetch with initialData defined ([#10287](https://github.com/TanStack/query/pull/10287))\n\n- Updated dependencies [[`248975e`](https://github.com/TanStack/query/commit/248975e896f585f6eaa505c796e73fcf7bfd1eec)]:\n  - @tanstack/query-persist-client-core@5.92.4\n  - @tanstack/svelte-query@6.1.3\n\n## 6.0.24\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.92.3\n  - @tanstack/svelte-query@6.1.2\n\n## 6.0.23\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.92.2\n  - @tanstack/svelte-query@6.1.1\n\n## 6.0.22\n\n### Patch Changes\n\n- Updated dependencies [[`e505568`](https://github.com/TanStack/query/commit/e505568f4d51c8281d38e9687091094b7d32a405)]:\n  - @tanstack/query-persist-client-core@5.92.1\n\n## 6.0.21\n\n### Patch Changes\n\n- Updated dependencies [[`978fc52`](https://github.com/TanStack/query/commit/978fc52728a8b9eb33f0a82f4ddf42a95815bd7f)]:\n  - @tanstack/query-persist-client-core@5.92.0\n\n## 6.0.20\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.19\n  - @tanstack/svelte-query@6.0.18\n\n## 6.0.19\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.18\n  - @tanstack/svelte-query@6.0.17\n\n## 6.0.18\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.17\n  - @tanstack/svelte-query@6.0.16\n\n## 6.0.17\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.16\n  - @tanstack/svelte-query@6.0.15\n\n## 6.0.16\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.15\n  - @tanstack/svelte-query@6.0.14\n\n## 6.0.15\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.14\n  - @tanstack/svelte-query@6.0.13\n\n## 6.0.14\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.13\n  - @tanstack/svelte-query@6.0.12\n\n## 6.0.13\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.12\n  - @tanstack/svelte-query@6.0.11\n\n## 6.0.12\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.11\n  - @tanstack/svelte-query@6.0.10\n\n## 6.0.11\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.10\n  - @tanstack/svelte-query@6.0.9\n\n## 6.0.10\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.9\n  - @tanstack/svelte-query@6.0.8\n\n## 6.0.9\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.8\n  - @tanstack/svelte-query@6.0.7\n\n## 6.0.8\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.7\n  - @tanstack/svelte-query@6.0.6\n\n## 6.0.7\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.6\n  - @tanstack/svelte-query@6.0.5\n\n## 6.0.6\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.5\n  - @tanstack/svelte-query@6.0.4\n\n## 6.0.5\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.4\n  - @tanstack/svelte-query@6.0.3\n\n## 6.0.4\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.3\n  - @tanstack/svelte-query@6.0.2\n\n## 6.0.3\n\n### Patch Changes\n\n- Updated dependencies []:\n  - @tanstack/query-persist-client-core@5.91.2\n  - @tanstack/svelte-query@6.0.1\n\n## 6.0.2\n\n### Patch Changes\n\n- Updated dependencies [[`846d53d`](https://github.com/TanStack/query/commit/846d53d98992d50606c40634efa43dea9965b787)]:\n  - @tanstack/query-persist-client-core@5.91.1\n\n## 6.0.1\n\n### Patch Changes\n\n- Updated dependencies [[`5cd86c6`](https://github.com/TanStack/query/commit/5cd86c6ef1720b87b13e1ab70ee823616f1f029a)]:\n  - @tanstack/query-persist-client-core@5.91.0\n\n## 6.0.0\n\n### Major Changes\n\n- BREAKING: Migrate to svelte runes (signals). Requires [Svelte v5.25.0](https://github.com/sveltejs/svelte/releases/tag/svelte%405.25.0) or newer. Please see the [migration guide](https://tanstack.com/query/latest/docs/framework/svelte/migrate-from-v5-to-v6). ([#9694](https://github.com/TanStack/query/pull/9694))\n\n### Patch Changes\n\n- Updated dependencies [[`1056ba6`](https://github.com/TanStack/query/commit/1056ba63b30b9d9a66fa813c7d7fb1395e377c55)]:\n  - @tanstack/svelte-query@6.0.0\n"
  },
  {
    "path": "packages/svelte-query-persist-client/eslint.config.js",
    "content": "// @ts-check\n\nimport tsParser from '@typescript-eslint/parser'\nimport pluginSvelte from 'eslint-plugin-svelte'\nimport rootConfig from './root.eslint.config.js'\nimport svelteConfig from './svelte.config.js'\n\nexport default [\n  ...rootConfig,\n  ...pluginSvelte.configs['recommended'],\n  {\n    files: ['**/*.svelte', '**/*.svelte.ts', '**/*.svelte.js'],\n    languageOptions: {\n      parserOptions: {\n        parser: tsParser,\n        extraFileExtensions: ['.svelte'],\n        svelteConfig,\n      },\n    },\n  },\n  {\n    rules: {\n      'svelte/block-lang': ['error', { script: ['ts'] }],\n      'svelte/no-svelte-internal': 'error',\n      'svelte/valid-compile': 'off',\n    },\n  },\n]\n"
  },
  {
    "path": "packages/svelte-query-persist-client/package.json",
    "content": "{\n  \"name\": \"@tanstack/svelte-query-persist-client\",\n  \"version\": \"6.0.25\",\n  \"description\": \"Svelte bindings to work with persisters in TanStack/svelte-query\",\n  \"author\": \"Lachlan Collins\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/svelte-query-persist-client\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"keywords\": [\n    \"tanstack\",\n    \"query\",\n    \"svelte\"\n  ],\n  \"scripts\": {\n    \"clean\": \"premove ./dist ./coverage ./.svelte-kit ./dist-ts\",\n    \"compile\": \"tsc --build\",\n    \"test:types\": \"svelte-check --tsconfig ./tsconfig.json\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:lib\": \"vitest\",\n    \"test:lib:dev\": \"pnpm run test:lib --watch\",\n    \"test:build\": \"publint --strict && attw --pack\",\n    \"build\": \"svelte-package --input ./src --output ./dist\"\n  },\n  \"type\": \"module\",\n  \"types\": \"dist/index.d.ts\",\n  \"module\": \"dist/index.js\",\n  \"svelte\": \"./dist/index.js\",\n  \"exports\": {\n    \".\": {\n      \"@tanstack/custom-condition\": \"./src/index.ts\",\n      \"types\": \"./dist/index.d.ts\",\n      \"svelte\": \"./dist/index.js\",\n      \"import\": \"./dist/index.js\"\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"sideEffects\": false,\n  \"files\": [\n    \"dist\",\n    \"src\",\n    \"!src/__tests__\"\n  ],\n  \"dependencies\": {\n    \"@tanstack/query-persist-client-core\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"@sveltejs/package\": \"^2.4.0\",\n    \"@sveltejs/vite-plugin-svelte\": \"^5.1.1\",\n    \"@tanstack/query-test-utils\": \"workspace:*\",\n    \"@tanstack/svelte-query\": \"workspace:*\",\n    \"@testing-library/svelte\": \"^5.2.8\",\n    \"@typescript-eslint/parser\": \"^8.48.0\",\n    \"eslint-plugin-svelte\": \"^3.11.0\",\n    \"svelte\": \"^5.39.3\",\n    \"svelte-check\": \"^4.4.5\",\n    \"typescript\": \"5.9.3\"\n  },\n  \"peerDependencies\": {\n    \"@tanstack/svelte-query\": \"workspace:^\",\n    \"svelte\": \"^5.25.0\"\n  }\n}\n"
  },
  {
    "path": "packages/svelte-query-persist-client/src/PersistQueryClientProvider.svelte",
    "content": "<script lang=\"ts\">\n  import {\n    persistQueryClientRestore,\n    persistQueryClientSubscribe,\n  } from '@tanstack/query-persist-client-core'\n  import {\n    QueryClientProvider,\n    setIsRestoringContext,\n  } from '@tanstack/svelte-query'\n  import { box } from './utils.svelte.js'\n  import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'\n  import type {\n    OmitKeyof,\n    QueryClientProviderProps,\n  } from '@tanstack/svelte-query'\n\n  type PersistQueryClientProviderProps = QueryClientProviderProps & {\n    persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>\n    onSuccess?: () => void\n    onError?: () => void\n  }\n\n  let {\n    client,\n    children,\n    persistOptions,\n    ...props\n  }: PersistQueryClientProviderProps = $props()\n\n  let isRestoring = box(true)\n\n  setIsRestoringContext(isRestoring)\n\n  const options = $derived({\n    ...persistOptions,\n    queryClient: client,\n  })\n\n  $effect(() => {\n    return isRestoring.current ? () => {} : persistQueryClientSubscribe(options)\n  })\n\n  $effect(() => {\n    isRestoring.current = true\n    persistQueryClientRestore(options)\n      .then(() => props.onSuccess?.())\n      .catch(() => props.onError?.())\n      .finally(() => {\n        isRestoring.current = false\n      })\n  })\n</script>\n\n<QueryClientProvider {client} {...props}>\n  {@render children()}\n</QueryClientProvider>\n"
  },
  {
    "path": "packages/svelte-query-persist-client/src/index.ts",
    "content": "// Re-export core\nexport * from '@tanstack/query-persist-client-core'\nexport { default as PersistQueryClientProvider } from './PersistQueryClientProvider.svelte'\n"
  },
  {
    "path": "packages/svelte-query-persist-client/src/utils.svelte.ts",
    "content": "type Box<T> = { current: T }\n\nexport function box<T>(initial: T): Box<T> {\n  let current = $state(initial)\n\n  return {\n    get current() {\n      return current\n    },\n    set current(newValue) {\n      current = newValue\n    },\n  }\n}\n"
  },
  {
    "path": "packages/svelte-query-persist-client/svelte.config.js",
    "content": "import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'\n\nconst config = {\n  preprocess: vitePreprocess(),\n  compilerOptions: {\n    runes: true,\n  },\n}\n\nexport default config\n"
  },
  {
    "path": "packages/svelte-query-persist-client/tests/AwaitOnSuccess/AwaitOnSuccess.svelte",
    "content": "<script lang=\"ts\">\n  import { createQuery } from '@tanstack/svelte-query'\n  import { sleep } from '@tanstack/query-test-utils'\n  import { StatelessRef } from '../utils.svelte.js'\n\n  let { states }: { states: StatelessRef<Array<string>> } = $props()\n\n  const query = createQuery(() => ({\n    queryKey: ['test'],\n    queryFn: async () => {\n      states.current.push('fetching')\n      await sleep(10)\n      states.current.push('fetched')\n      return 'fetched'\n    },\n  }))\n</script>\n\n<div>{query.data}</div>\n<div>fetchStatus: {query.fetchStatus}</div>\n"
  },
  {
    "path": "packages/svelte-query-persist-client/tests/AwaitOnSuccess/Provider.svelte",
    "content": "<script lang=\"ts\">\n  import PersistQueryClientProvider from '../../src/PersistQueryClientProvider.svelte'\n  import AwaitOnSuccess from './AwaitOnSuccess.svelte'\n  import type { OmitKeyof, QueryClient } from '@tanstack/svelte-query'\n  import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'\n  import { StatelessRef } from '../utils.svelte'\n\n  interface Props {\n    queryClient: QueryClient\n    persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>\n    onSuccess: () => Promise<void>\n    states: StatelessRef<Array<string>>\n  }\n\n  let { queryClient, persistOptions, onSuccess, states }: Props = $props()\n</script>\n\n<PersistQueryClientProvider client={queryClient} {persistOptions} {onSuccess}>\n  <AwaitOnSuccess {states} />\n</PersistQueryClientProvider>\n"
  },
  {
    "path": "packages/svelte-query-persist-client/tests/FreshData/FreshData.svelte",
    "content": "<script lang=\"ts\">\n  import { createQuery } from '@tanstack/svelte-query'\n  import { sleep } from '@tanstack/query-test-utils'\n  import type { StatelessRef, StatusResult } from '../utils.svelte.js'\n\n  let {\n    states,\n    onFetch,\n  }: {\n    states: StatelessRef<Array<StatusResult<string>>>\n    onFetch: () => void\n  } = $props()\n\n  const query = createQuery(() => ({\n    queryKey: ['test'],\n    queryFn: async () => {\n      await sleep(10)\n      onFetch()\n      return 'fetched'\n    },\n    staleTime: Infinity,\n  }))\n\n  $effect(() => {\n    // svelte-ignore state_snapshot_uncloneable\n    const snapshot = $state.snapshot(query)\n    states.current.push(snapshot)\n  })\n</script>\n\n<div>data: {query.data ?? 'null'}</div>\n<div>fetchStatus: {query.fetchStatus}</div>\n"
  },
  {
    "path": "packages/svelte-query-persist-client/tests/FreshData/Provider.svelte",
    "content": "<script lang=\"ts\">\n  import PersistQueryClientProvider from '../../src/PersistQueryClientProvider.svelte'\n  import FreshData from './FreshData.svelte'\n  import type { OmitKeyof, QueryClient } from '@tanstack/svelte-query'\n  import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'\n  import type { StatelessRef, StatusResult } from '../utils.svelte.js'\n\n  interface Props {\n    queryClient: QueryClient\n    persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>\n    states: StatelessRef<Array<StatusResult<string>>>\n    onFetch: () => void\n  }\n\n  let { queryClient, persistOptions, states, onFetch }: Props = $props()\n</script>\n\n<PersistQueryClientProvider client={queryClient} {persistOptions}>\n  <FreshData {states} {onFetch} />\n</PersistQueryClientProvider>\n"
  },
  {
    "path": "packages/svelte-query-persist-client/tests/InitialData/InitialData.svelte",
    "content": "<script lang=\"ts\">\n  import { createQuery } from '@tanstack/svelte-query'\n  import { sleep } from '@tanstack/query-test-utils'\n  import type { StatelessRef, StatusResult } from '../utils.svelte.js'\n\n  let { states }: { states: StatelessRef<Array<StatusResult<string>>> } =\n    $props()\n\n  const query = createQuery(() => ({\n    queryKey: ['test'],\n    queryFn: () => sleep(10).then(() => 'fetched'),\n    initialData: 'initial',\n    // make sure that initial data is older than the hydration data\n    // otherwise initialData would be newer and takes precedence\n    initialDataUpdatedAt: 1,\n  }))\n\n  $effect(() => {\n    // svelte-ignore state_snapshot_uncloneable\n    const snapshot = $state.snapshot(query)\n    states.current.push(snapshot)\n  })\n</script>\n\n<div>{query.data}</div>\n<div>fetchStatus: {query.fetchStatus}</div>\n"
  },
  {
    "path": "packages/svelte-query-persist-client/tests/InitialData/Provider.svelte",
    "content": "<script lang=\"ts\">\n  import PersistQueryClientProvider from '../../src/PersistQueryClientProvider.svelte'\n  import InitialData from './InitialData.svelte'\n  import type { OmitKeyof, QueryClient } from '@tanstack/svelte-query'\n  import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'\n  import type { StatelessRef, StatusResult } from '../utils.svelte.js'\n\n  interface Props {\n    queryClient: QueryClient\n    persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>\n    states: StatelessRef<Array<StatusResult<string>>>\n  }\n\n  let { queryClient, persistOptions, states }: Props = $props()\n</script>\n\n<PersistQueryClientProvider client={queryClient} {persistOptions}>\n  <InitialData {states} />\n</PersistQueryClientProvider>\n"
  },
  {
    "path": "packages/svelte-query-persist-client/tests/OnSuccess/OnSuccess.svelte",
    "content": "<script lang=\"ts\">\n  import { createQuery } from '@tanstack/svelte-query'\n  import { sleep } from '@tanstack/query-test-utils'\n\n  const query = createQuery(() => ({\n    queryKey: ['test'],\n    queryFn: () => sleep(10).then(() => 'fetched'),\n  }))\n</script>\n\n<div>{query.data}</div>\n<div>fetchStatus: {query.fetchStatus}</div>\n"
  },
  {
    "path": "packages/svelte-query-persist-client/tests/OnSuccess/Provider.svelte",
    "content": "<script lang=\"ts\">\n  import PersistQueryClientProvider from '../../src/PersistQueryClientProvider.svelte'\n  import OnSuccess from './OnSuccess.svelte'\n  import type { OmitKeyof, QueryClient } from '@tanstack/svelte-query'\n  import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'\n\n  interface Props {\n    queryClient: QueryClient\n    persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>\n    onSuccess: () => void\n  }\n\n  let { queryClient, persistOptions, onSuccess }: Props = $props()\n</script>\n\n<PersistQueryClientProvider client={queryClient} {persistOptions} {onSuccess}>\n  <OnSuccess />\n</PersistQueryClientProvider>\n"
  },
  {
    "path": "packages/svelte-query-persist-client/tests/PersistQueryClientProvider.svelte.test.ts",
    "content": "import { render } from '@testing-library/svelte'\nimport { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { QueryClient } from '@tanstack/svelte-query'\nimport { persistQueryClientSave } from '@tanstack/query-persist-client-core'\nimport { sleep } from '@tanstack/query-test-utils'\nimport AwaitOnSuccess from './AwaitOnSuccess/Provider.svelte'\nimport FreshData from './FreshData/Provider.svelte'\nimport OnSuccess from './OnSuccess/Provider.svelte'\nimport InitialData from './InitialData/Provider.svelte'\nimport RemoveCache from './RemoveCache/Provider.svelte'\nimport RestoreCache from './RestoreCache/Provider.svelte'\nimport UseQueries from './UseQueries/Provider.svelte'\nimport { StatelessRef } from './utils.svelte.js'\nimport type {\n  PersistedClient,\n  Persister,\n} from '@tanstack/query-persist-client-core'\nimport type { StatusResult } from './utils.svelte.js'\n\nbeforeEach(() => {\n  vi.useFakeTimers()\n})\n\nafterEach(() => {\n  vi.useRealTimers()\n})\n\nconst createMockPersister = (): Persister => {\n  let storedState: PersistedClient | undefined\n\n  return {\n    persistClient(persistClient: PersistedClient) {\n      storedState = persistClient\n    },\n    async restoreClient() {\n      return sleep(10).then(() => storedState)\n    },\n    removeClient() {\n      storedState = undefined\n    },\n  }\n}\n\nconst createMockErrorPersister = (\n  removeClient: Persister['removeClient'],\n): [Error, Persister] => {\n  const error = new Error('restore failed')\n  return [\n    error,\n    {\n      async persistClient() {\n        // noop\n      },\n      async restoreClient() {\n        return sleep(10).then(() => Promise.reject(error))\n      },\n      removeClient,\n    },\n  ]\n}\n\ndescribe('PersistQueryClientProvider', () => {\n  test('restores cache from persister', async () => {\n    const states = new StatelessRef<Array<StatusResult<string>>>([])\n\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: ['test'],\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createMockPersister()\n\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    const rendered = render(RestoreCache, {\n      props: {\n        queryClient,\n        persistOptions: { persister },\n        states,\n      },\n    })\n\n    expect(rendered.getByText('fetchStatus: idle')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('hydrated')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('fetched')).toBeInTheDocument()\n\n    expect(states.current).toHaveLength(3)\n\n    expect(states.current[0]).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'idle',\n      data: undefined,\n    })\n\n    expect(states.current[1]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: 'hydrated',\n    })\n\n    expect(states.current[2]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: 'fetched',\n    })\n  })\n\n  test('should also put useQueries into idle state', async () => {\n    const states = new StatelessRef<Array<StatusResult<string>>>([])\n\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: ['test'],\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createMockPersister()\n\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    const rendered = render(UseQueries, {\n      props: {\n        queryClient,\n        persistOptions: { persister },\n        states,\n      },\n    })\n\n    expect(rendered.getByText('fetchStatus: idle')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('hydrated')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('fetched')).toBeInTheDocument()\n\n    expect(states.current).toHaveLength(3)\n\n    expect(states.current[0]).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'idle',\n      data: undefined,\n    })\n\n    expect(states.current[1]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: 'hydrated',\n    })\n\n    expect(states.current[2]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: 'fetched',\n    })\n  })\n\n  test('should show initialData while restoring', async () => {\n    const states = new StatelessRef<Array<StatusResult<string>>>([])\n\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: ['test'],\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createMockPersister()\n\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    const rendered = render(InitialData, {\n      props: {\n        queryClient,\n        persistOptions: { persister },\n        states,\n      },\n    })\n\n    expect(rendered.getByText('initial')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('hydrated')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('fetched')).toBeInTheDocument()\n\n    expect(states.current).toHaveLength(3)\n\n    expect(states.current[0]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: 'initial',\n    })\n\n    expect(states.current[1]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'fetching',\n      data: 'hydrated',\n    })\n\n    expect(states.current[2]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: 'fetched',\n    })\n  })\n\n  test('should not refetch after restoring when data is fresh', async () => {\n    const states = new StatelessRef<Array<StatusResult<string>>>([])\n\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: ['test'],\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createMockPersister()\n\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    let fetched = false\n\n    const rendered = render(FreshData, {\n      props: {\n        queryClient,\n        persistOptions: { persister },\n        states,\n        onFetch: () => {\n          fetched = true\n        },\n      },\n    })\n\n    expect(rendered.getByText('data: null')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: hydrated')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('data: hydrated')).toBeInTheDocument()\n\n    expect(states.current).toHaveLength(2)\n\n    expect(fetched).toBe(false)\n\n    expect(states.current[0]).toMatchObject({\n      status: 'pending',\n      fetchStatus: 'idle',\n      data: undefined,\n    })\n\n    expect(states.current[1]).toMatchObject({\n      status: 'success',\n      fetchStatus: 'idle',\n      data: 'hydrated',\n    })\n  })\n\n  test('should call onSuccess after successful restoring', async () => {\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: ['test'],\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createMockPersister()\n\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    const onSuccess = vi.fn()\n\n    const rendered = render(OnSuccess, {\n      props: {\n        queryClient,\n        persistOptions: { persister },\n        onSuccess,\n      },\n    })\n\n    expect(onSuccess).toHaveBeenCalledTimes(0)\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('hydrated')).toBeInTheDocument()\n    expect(onSuccess).toHaveBeenCalledTimes(1)\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('fetched')).toBeInTheDocument()\n  })\n\n  test('should await onSuccess after successful restoring', async () => {\n    const queryClient = new QueryClient()\n    queryClient.prefetchQuery({\n      queryKey: ['test'],\n      queryFn: () => sleep(10).then(() => 'hydrated'),\n    })\n    await vi.advanceTimersByTimeAsync(10)\n\n    const persister = createMockPersister()\n\n    persistQueryClientSave({ queryClient, persister })\n    await vi.advanceTimersByTimeAsync(0)\n\n    queryClient.clear()\n\n    const states = new StatelessRef<Array<string>>([])\n\n    const rendered = render(AwaitOnSuccess, {\n      props: {\n        queryClient,\n        persistOptions: { persister },\n        states,\n        onSuccess: async () => {\n          states.current.push('onSuccess')\n          await sleep(5)\n          states.current.push('onSuccess done')\n        },\n      },\n    })\n\n    await vi.advanceTimersByTimeAsync(15)\n    expect(rendered.getByText('hydrated')).toBeInTheDocument()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('fetched')).toBeInTheDocument()\n\n    expect(states.current).toEqual([\n      'onSuccess',\n      'onSuccess done',\n      'fetching',\n      'fetched',\n    ])\n  })\n\n  test('should remove cache after non-successful restoring', async () => {\n    const consoleMock = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => undefined)\n    const consoleWarn = vi\n      .spyOn(console, 'warn')\n      .mockImplementation(() => undefined)\n\n    const queryClient = new QueryClient()\n    const removeClient = vi.fn()\n    const onSuccess = vi.fn()\n    const onError = vi.fn()\n\n    const [error, persister] = createMockErrorPersister(removeClient)\n\n    const rendered = render(RemoveCache, {\n      props: { queryClient, persistOptions: { persister }, onError, onSuccess },\n    })\n\n    await vi.advanceTimersByTimeAsync(10)\n    await vi.advanceTimersByTimeAsync(10)\n    expect(rendered.getByText('fetched')).toBeInTheDocument()\n    expect(removeClient).toHaveBeenCalledTimes(1)\n    expect(onSuccess).toHaveBeenCalledTimes(0)\n    expect(onError).toHaveBeenCalledTimes(1)\n    expect(consoleMock).toHaveBeenCalledTimes(1)\n    expect(consoleMock).toHaveBeenNthCalledWith(1, error)\n    consoleMock.mockRestore()\n    consoleWarn.mockRestore()\n  })\n})\n"
  },
  {
    "path": "packages/svelte-query-persist-client/tests/RemoveCache/Provider.svelte",
    "content": "<script lang=\"ts\">\n  import PersistQueryClientProvider from '../../src/PersistQueryClientProvider.svelte'\n  import RemoveCache from './RemoveCache.svelte'\n  import type { OmitKeyof, QueryClient } from '@tanstack/svelte-query'\n  import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'\n\n  interface Props {\n    queryClient: QueryClient\n    persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>\n    onSuccess: () => void\n    onError: () => void\n  }\n\n  let { queryClient, persistOptions, onError, onSuccess }: Props = $props()\n</script>\n\n<PersistQueryClientProvider\n  client={queryClient}\n  {persistOptions}\n  {onSuccess}\n  {onError}\n>\n  <RemoveCache />\n</PersistQueryClientProvider>\n"
  },
  {
    "path": "packages/svelte-query-persist-client/tests/RemoveCache/RemoveCache.svelte",
    "content": "<script lang=\"ts\">\n  import { createQuery } from '@tanstack/svelte-query'\n  import { sleep } from '@tanstack/query-test-utils'\n\n  const query = createQuery(() => ({\n    queryKey: ['test'],\n    queryFn: () => sleep(10).then(() => 'fetched'),\n  }))\n</script>\n\n<div>{query.data}</div>\n<div>fetchStatus: {query.fetchStatus}</div>\n"
  },
  {
    "path": "packages/svelte-query-persist-client/tests/RestoreCache/Provider.svelte",
    "content": "<script lang=\"ts\">\n  import PersistQueryClientProvider from '../../src/PersistQueryClientProvider.svelte'\n  import RestoreCache from './RestoreCache.svelte'\n  import type { OmitKeyof, QueryClient } from '@tanstack/svelte-query'\n  import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'\n  import type { StatelessRef, StatusResult } from '../utils.svelte.js'\n\n  interface Props {\n    queryClient: QueryClient\n    persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>\n    states: StatelessRef<Array<StatusResult<string>>>\n  }\n\n  let { queryClient, persistOptions, states }: Props = $props()\n</script>\n\n<PersistQueryClientProvider client={queryClient} {persistOptions}>\n  <RestoreCache {states} />\n</PersistQueryClientProvider>\n"
  },
  {
    "path": "packages/svelte-query-persist-client/tests/RestoreCache/RestoreCache.svelte",
    "content": "<script lang=\"ts\">\n  import { createQuery } from '@tanstack/svelte-query'\n  import { sleep } from '@tanstack/query-test-utils'\n  import type { StatelessRef, StatusResult } from '../utils.svelte.js'\n\n  let { states }: { states: StatelessRef<Array<StatusResult<string>>> } =\n    $props()\n\n  const query = createQuery(() => ({\n    queryKey: ['test'],\n    queryFn: () => sleep(10).then(() => 'fetched'),\n  }))\n\n  $effect(() => {\n    // svelte-ignore state_snapshot_uncloneable\n    const snapshot = $state.snapshot(query)\n    states.current.push(snapshot)\n  })\n</script>\n\n<div>{query.data}</div>\n<div>fetchStatus: {query.fetchStatus}</div>\n"
  },
  {
    "path": "packages/svelte-query-persist-client/tests/UseQueries/Provider.svelte",
    "content": "<script lang=\"ts\">\n  import PersistQueryClientProvider from '../../src/PersistQueryClientProvider.svelte'\n  import UseQueries from './UseQueries.svelte'\n  import type { OmitKeyof, QueryClient } from '@tanstack/svelte-query'\n  import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'\n  import type { StatelessRef, StatusResult } from '../utils.svelte.js'\n\n  interface Props {\n    queryClient: QueryClient\n    persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>\n    states: StatelessRef<Array<StatusResult<string>>>\n  }\n\n  let { queryClient, persistOptions, states }: Props = $props()\n</script>\n\n<PersistQueryClientProvider client={queryClient} {persistOptions}>\n  <UseQueries {states} />\n</PersistQueryClientProvider>\n"
  },
  {
    "path": "packages/svelte-query-persist-client/tests/UseQueries/UseQueries.svelte",
    "content": "<script lang=\"ts\">\n  import { createQueries } from '@tanstack/svelte-query'\n  import { sleep } from '@tanstack/query-test-utils'\n  import type { StatelessRef, StatusResult } from '../utils.svelte.js'\n\n  let { states }: { states: StatelessRef<Array<StatusResult<string>>> } =\n    $props()\n\n  const queries = createQueries(() => ({\n    queries: [\n      {\n        queryKey: ['test'],\n        queryFn: () => sleep(10).then(() => 'fetched'),\n      },\n    ],\n  }))\n\n  $effect(() => {\n    // svelte-ignore state_snapshot_uncloneable\n    const snapshot = $state.snapshot(queries[0])\n    states.current.push(snapshot)\n  })\n</script>\n\n<div>{queries[0].data}</div>\n<div>fetchStatus: {queries[0].fetchStatus}</div>\n"
  },
  {
    "path": "packages/svelte-query-persist-client/tests/test-setup.ts",
    "content": "import '@testing-library/jest-dom/vitest'\n"
  },
  {
    "path": "packages/svelte-query-persist-client/tests/utils.svelte.ts",
    "content": "export type StatusResult<T = unknown> = {\n  status: string\n  fetchStatus: string\n  data: T | undefined\n}\n\nexport class StatelessRef<T> {\n  current: T\n  constructor(value: T) {\n    this.current = value\n  }\n}\n"
  },
  {
    "path": "packages/svelte-query-persist-client/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\"\n  },\n  \"include\": [\"src\", \"tests\", \"*.config.*\", \"package.json\"],\n  \"references\": [\n    { \"path\": \"../query-persist-client-core\" },\n    { \"path\": \"../svelte-query\" }\n  ]\n}\n"
  },
  {
    "path": "packages/svelte-query-persist-client/vite.config.ts",
    "content": "import { svelte } from '@sveltejs/vite-plugin-svelte'\nimport { defineConfig } from 'vitest/config'\nimport { svelteTesting } from '@testing-library/svelte/vite'\n\nimport packageJson from './package.json'\n\nexport default defineConfig({\n  plugins: [svelte(), svelteTesting()],\n  // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660\n  resolve: {\n    conditions: ['@tanstack/custom-condition'],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        conditions: ['@tanstack/custom-condition'],\n      },\n    },\n  },\n  test: {\n    name: packageJson.name,\n    dir: './tests',\n    watch: false,\n    environment: 'jsdom',\n    setupFiles: ['./tests/test-setup.ts'],\n    typecheck: { enabled: true },\n    restoreMocks: true,\n  },\n})\n"
  },
  {
    "path": "packages/vue-query/CHANGELOG.md",
    "content": "# @tanstack/vue-query\n\n## 5.92.12\n\n### Patch Changes\n\n- fix(streamedQuery): maintain error state on reset refetch with initialData defined ([#10287](https://github.com/TanStack/query/pull/10287))\n\n- Updated dependencies [[`248975e`](https://github.com/TanStack/query/commit/248975e896f585f6eaa505c796e73fcf7bfd1eec)]:\n  - @tanstack/query-core@5.91.2\n\n## 5.92.11\n\n### Patch Changes\n\n- Updated dependencies [[`a89aab9`](https://github.com/TanStack/query/commit/a89aab975581c25c113a26c8af486b4cafad272a)]:\n  - @tanstack/query-core@5.91.1\n\n## 5.92.10\n\n### Patch Changes\n\n- fix(vue-query/useMutation): add missing '\\_defaulted' omit in 'UseMutationOptionsBase' ([#10215](https://github.com/TanStack/query/pull/10215))\n\n- Updated dependencies [[`6fa901b`](https://github.com/TanStack/query/commit/6fa901b97a22a80d0fca3f6ed86237ff0cbdd13b)]:\n  - @tanstack/query-core@5.91.0\n\n## 5.92.9\n\n### Patch Changes\n\n- Updated dependencies [[`e7258c5`](https://github.com/TanStack/query/commit/e7258c5cb30cafa456cdb4e6bc75b43bf619954d)]:\n  - @tanstack/query-core@5.90.20\n\n## 5.92.8\n\n### Patch Changes\n\n- Updated dependencies [[`53fc74e`](https://github.com/TanStack/query/commit/53fc74ebb16730bd3317f039a69c6821386bae93)]:\n  - @tanstack/query-core@5.90.19\n\n## 5.92.7\n\n### Patch Changes\n\n- Updated dependencies [[`dea1614`](https://github.com/TanStack/query/commit/dea1614aaad5c572cf43cea54b64ac09dc4d5b41)]:\n  - @tanstack/query-core@5.90.18\n\n## 5.92.6\n\n### Patch Changes\n\n- Updated dependencies [[`269351b`](https://github.com/TanStack/query/commit/269351b8ce4b4846da3d320ac5b850ee6aada0d6)]:\n  - @tanstack/query-core@5.90.17\n\n## 5.92.5\n\n### Patch Changes\n\n- Updated dependencies [[`7f47906`](https://github.com/TanStack/query/commit/7f47906eaccc3f3aa5ce24b77a83bd7a620a237b)]:\n  - @tanstack/query-core@5.90.16\n\n## 5.92.4\n\n### Patch Changes\n\n- Updated dependencies [[`fccef79`](https://github.com/TanStack/query/commit/fccef797d57d4a9566517bba87c8377f363920f2)]:\n  - @tanstack/query-core@5.90.15\n\n## 5.92.3\n\n### Patch Changes\n\n- Updated dependencies [[`d576092`](https://github.com/TanStack/query/commit/d576092e2ece4ca3936add3eb0da5234c1d82ed4)]:\n  - @tanstack/query-core@5.90.14\n\n## 5.92.2\n\n### Patch Changes\n\n- Updated dependencies [[`4a0a78a`](https://github.com/TanStack/query/commit/4a0a78afbc2432f8cb6828035965853fa98c86a0)]:\n  - @tanstack/query-core@5.90.13\n\n## 5.92.1\n\n### Patch Changes\n\n- Updated dependencies [[`72d8ac5`](https://github.com/TanStack/query/commit/72d8ac5c592004b8f9c3ee086fcb9c3cd615ca05)]:\n  - @tanstack/query-core@5.90.12\n\n## 5.92.0\n\n### Minor Changes\n\n- feat(vue-query): allow options getters in additional composables ([#9914](https://github.com/TanStack/query/pull/9914))\n\n## 5.91.4\n\n### Patch Changes\n\n- Updated dependencies [[`c01b150`](https://github.com/TanStack/query/commit/c01b150e3673e11d6533768529a5e6fe3ebee68c)]:\n  - @tanstack/query-core@5.90.11\n\n## 5.91.3\n\n### Patch Changes\n\n- Include TPageParam in enabled of InfiniteQueryObserverOptions ([#9898](https://github.com/TanStack/query/pull/9898))\n\n## 5.91.2\n\n### Patch Changes\n\n- Updated dependencies [[`8e2e174`](https://github.com/TanStack/query/commit/8e2e174e9fd2e7b94cd232041e49c9d014d74e26), [`eb559a6`](https://github.com/TanStack/query/commit/eb559a66dc0d77dd46435f624fa64fc068bef9ae)]:\n  - @tanstack/query-core@5.90.10\n\n## 5.91.1\n\n### Patch Changes\n\n- Updated dependencies [[`08b211f`](https://github.com/TanStack/query/commit/08b211f8aa475e05d2f13a36517fc556861ef962)]:\n  - @tanstack/query-core@5.90.9\n\n## 5.91.0\n\n### Minor Changes\n\n- feat(vue-query): support useQuery options getter ([#9866](https://github.com/TanStack/query/pull/9866))\n\n## 5.90.8\n\n### Patch Changes\n\n- Updated dependencies [[`c0ec9fe`](https://github.com/TanStack/query/commit/c0ec9fe0d1426fe3f233adda3ebf23989ffaa110)]:\n  - @tanstack/query-core@5.90.8\n\n## 5.90.7\n\n### Patch Changes\n\n- Updated dependencies [[`b4cd121`](https://github.com/TanStack/query/commit/b4cd121a39d07cefaa3a3411136d342cc54ce8fb)]:\n  - @tanstack/query-core@5.90.7\n\n## 5.90.6\n\n### Patch Changes\n\n- Updated dependencies [[`1638c02`](https://github.com/TanStack/query/commit/1638c028df55648995d04431179904371a189772)]:\n  - @tanstack/query-core@5.90.6\n\n## 5.90.5\n\n### Patch Changes\n\n- Updated dependencies [[`e42ddfe`](https://github.com/TanStack/query/commit/e42ddfe919f34f847ca101aeef162c69845f9a1e)]:\n  - @tanstack/query-core@5.90.5\n\n## 5.90.4\n\n### Patch Changes\n\n- Updated dependencies [[`20ef922`](https://github.com/TanStack/query/commit/20ef922a0a7c3aee00150bf69123c338b0922922)]:\n  - @tanstack/query-core@5.90.4\n\n## 5.90.3\n\n### Patch Changes\n\n- Updated dependencies [[`4e1c433`](https://github.com/TanStack/query/commit/4e1c4338a72f7384600bbda99e44bc1891695df4)]:\n  - @tanstack/query-core@5.90.3\n"
  },
  {
    "path": "packages/vue-query/README.md",
    "content": "[![Vue Query logo](https://raw.githubusercontent.com/TanStack/query/main/packages/vue-query/media/vue-query.png)](https://github.com/TanStack/query/tree/main/packages/vue-query)\n\n[![npm version](https://img.shields.io/npm/v/@tanstack/vue-query)](https://www.npmjs.com/package/@tanstack/vue-query)\n[![npm license](https://img.shields.io/npm/l/@tanstack/vue-query)](https://github.com/TanStack/query/blob/main/LICENSE)\n[![bundle size](https://img.shields.io/bundlephobia/minzip/@tanstack/vue-query)](https://bundlephobia.com/package/@tanstack/vue-query)\n[![npm](https://img.shields.io/npm/dm/@tanstack/vue-query)](https://www.npmjs.com/package/@tanstack/vue-query)\n\n# Vue Query\n\nHooks for fetching, caching and updating asynchronous data in Vue.\n\nSupport for Vue 2.x via [vue-demi](https://github.com/vueuse/vue-demi)\n\n# Documentation\n\nVisit https://tanstack.com/query/latest/docs/vue/overview\n\n# Quick Features\n\n- Transport/protocol/backend agnostic data fetching (REST, GraphQL, promises, whatever!)\n- Auto Caching + Refetching (stale-while-revalidate, Window Refocus, Polling/Realtime)\n- Parallel + Dependent Queries\n- Mutations + Reactive Query Refetching\n- Multi-layer Cache + Automatic Garbage Collection\n- Paginated + Cursor-based Queries\n- Load-More + Infinite Scroll Queries w/ Scroll Recovery\n- Request Cancellation\n- (experimental) [Suspense](https://v3.vuejs.org/guide/migration/suspense.html#introduction) + Fetch-As-You-Render Query Prefetching\n- (experimental) SSR support\n- Dedicated Devtools\n- [![npm bundle size](https://img.shields.io/bundlephobia/minzip/@tanstack/vue-query)](https://bundlephobia.com/package/@tanstack/vue-query) (depending on features imported)\n\n# Quick Start\n\n1. Install `vue-query`\n\n   ```bash\n   $ npm i @tanstack/vue-query\n   ```\n\n   or\n\n   ```bash\n   $ pnpm add @tanstack/vue-query\n   ```\n\n   or\n\n   ```bash\n   $ yarn add @tanstack/vue-query\n   ```\n\n   or\n\n   ```bash\n   $ bun add @tanstack/vue-query\n   ```\n\n   > If you are using Vue 2.6, make sure to also setup [@vue/composition-api](https://github.com/vuejs/composition-api)\n\n2. Initialize **Vue Query** via **VueQueryPlugin**\n\n   ```tsx\n   import { createApp } from 'vue'\n   import { VueQueryPlugin } from '@tanstack/vue-query'\n\n   import App from './App.vue'\n\n   createApp(App).use(VueQueryPlugin).mount('#app')\n   ```\n\n3. Use query\n\n   ```tsx\n   import { defineComponent } from 'vue'\n   import { useQuery } from '@tanstack/vue-query'\n\n   export default defineComponent({\n     name: 'MyComponent',\n     setup() {\n       const query = useQuery({ queryKey: ['todos'], queryFn: getTodos })\n\n       return {\n         query,\n       }\n     },\n   })\n   ```\n\n4. If you need to update options on your query dynamically, make sure to pass them as reactive variables\n\n   ```tsx\n   const id = ref(1)\n   const enabled = ref(false)\n\n   const query = useQuery({\n     queryKey: ['todos', id],\n     queryFn: () => getTodos(id),\n     enabled,\n   })\n   ```\n"
  },
  {
    "path": "packages/vue-query/eslint.config.js",
    "content": "// @ts-check\n\nimport pluginVue from 'eslint-plugin-vue'\nimport rootConfig from './root.eslint.config.js'\n\nexport default [...rootConfig, ...pluginVue.configs['flat/base']]\n"
  },
  {
    "path": "packages/vue-query/package.json",
    "content": "{\n  \"name\": \"@tanstack/vue-query\",\n  \"version\": \"5.92.12\",\n  \"description\": \"Hooks for managing, caching and syncing asynchronous and remote data in Vue\",\n  \"author\": \"Damian Osipiuk\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/vue-query\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"scripts\": {\n    \"clean\": \"premove ./build ./coverage ./dist-ts\",\n    \"compile\": \"tsc --build\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:types\": \"vue-demi-switch 3 && pnpm run \\\"/^test:types:ts[0-9]{2}$/\\\"\",\n    \"test:types:ts54\": \"node ../../node_modules/typescript54/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts55\": \"node ../../node_modules/typescript55/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts56\": \"node ../../node_modules/typescript56/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts57\": \"node ../../node_modules/typescript57/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts58\": \"node ../../node_modules/typescript58/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:ts59\": \"node ../../node_modules/typescript59/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:types:tscurrent\": \"tsc --build\",\n    \"test:types:ts60\": \"node ../../node_modules/typescript60/lib/tsc.js --build tsconfig.legacy.json\",\n    \"test:lib\": \"pnpm run test:lib:2 && pnpm run test:lib:2.7 && pnpm run test:lib:3\",\n    \"test:lib:2\": \"vue-demi-switch 2 vue2 && vitest\",\n    \"test:lib:2.7\": \"vue-demi-switch 2.7 vue2.7 && vitest\",\n    \"test:lib:3\": \"vue-demi-switch 3 && vitest\",\n    \"test:lib:dev\": \"pnpm run test:lib --watch\",\n    \"test:build\": \"publint --strict && attw --pack\",\n    \"build\": \"tsup --tsconfig tsconfig.prod.json\"\n  },\n  \"type\": \"module\",\n  \"types\": \"build/legacy/index.d.ts\",\n  \"main\": \"build/legacy/index.cjs\",\n  \"module\": \"build/legacy/index.js\",\n  \"exports\": {\n    \".\": {\n      \"@tanstack/custom-condition\": \"./src/index.ts\",\n      \"import\": {\n        \"types\": \"./build/modern/index.d.ts\",\n        \"default\": \"./build/modern/index.js\"\n      },\n      \"require\": {\n        \"types\": \"./build/modern/index.d.cts\",\n        \"default\": \"./build/modern/index.cjs\"\n      }\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"sideEffects\": false,\n  \"files\": [\n    \"build\",\n    \"src\",\n    \"!src/__tests__\"\n  ],\n  \"dependencies\": {\n    \"@tanstack/match-sorter-utils\": \"^8.19.4\",\n    \"@tanstack/query-core\": \"workspace:*\",\n    \"@vue/devtools-api\": \"^6.6.3\",\n    \"vue-demi\": \"^0.14.10\"\n  },\n  \"devDependencies\": {\n    \"@tanstack/query-test-utils\": \"workspace:*\",\n    \"@vitejs/plugin-vue\": \"^5.2.4\",\n    \"@vue/composition-api\": \"1.7.2\",\n    \"eslint-plugin-vue\": \"^10.5.0\",\n    \"vue\": \"^3.4.27\",\n    \"vue2\": \"npm:vue@2.6\",\n    \"vue2.7\": \"npm:vue@2.7\"\n  },\n  \"peerDependencies\": {\n    \"@vue/composition-api\": \"^1.1.2\",\n    \"vue\": \"^2.6.0 || ^3.3.0\"\n  },\n  \"peerDependenciesMeta\": {\n    \"@vue/composition-api\": {\n      \"optional\": true\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vue-query/src/__mocks__/useBaseQuery.ts",
    "content": "import { vi } from 'vitest'\nimport type * as UseBaseQueryModule from '../useBaseQuery'\n\nconst { useBaseQuery: originImpl } =\n  await vi.importActual<typeof UseBaseQueryModule>('../useBaseQuery')\n\nexport const useBaseQuery = vi.fn(originImpl)\n"
  },
  {
    "path": "packages/vue-query/src/__mocks__/useQueryClient.ts",
    "content": "import { vi } from 'vitest'\nimport { QueryClient } from '../queryClient'\n\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: { retry: false, gcTime: Infinity },\n  },\n})\n\nexport const useQueryClient = vi.fn(() => queryClient)\n"
  },
  {
    "path": "packages/vue-query/src/__tests__/infiniteQueryOptions.test-d.ts",
    "content": "import { assertType, describe, expectTypeOf, it } from 'vitest'\nimport { QueryClient, dataTagSymbol } from '@tanstack/query-core'\nimport { reactive } from 'vue-demi'\nimport { infiniteQueryOptions } from '../infiniteQueryOptions'\nimport { useInfiniteQuery } from '../useInfiniteQuery'\nimport type { InfiniteData } from '@tanstack/query-core'\n\ndescribe('infiniteQueryOptions', () => {\n  it('should not allow excess properties', () => {\n    assertType(\n      infiniteQueryOptions({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve('data'),\n        getNextPageParam: () => 1,\n        initialPageParam: 1,\n        // @ts-expect-error this is a good error, because stallTime does not exist!\n        stallTime: 1000,\n      }),\n    )\n  })\n  it('should infer types for callbacks', () => {\n    infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('data'),\n      staleTime: 1000,\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n      select: (data) => {\n        expectTypeOf(data).toEqualTypeOf<InfiniteData<string, number>>()\n      },\n    })\n  })\n  it('should work when passed to useInfiniteQuery', () => {\n    const options = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    const { data } = reactive(useInfiniteQuery(options))\n\n    expectTypeOf(data).toEqualTypeOf<\n      InfiniteData<string, unknown> | undefined\n    >()\n  })\n  it('should tag the queryKey with the result type of the QueryFn', () => {\n    const { queryKey } = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<InfiniteData<string>>()\n  })\n  it('should tag the queryKey even if no promise is returned', () => {\n    const { queryKey } = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => 'string',\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<InfiniteData<string>>()\n  })\n  it('should tag the queryKey with the result type of the QueryFn if select is used', () => {\n    const { queryKey } = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      select: (data) => data.pages,\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<InfiniteData<string>>()\n  })\n  it('should return the proper type when passed to getQueryData', () => {\n    const { queryKey } = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryData(queryKey)\n\n    expectTypeOf(data).toEqualTypeOf<\n      InfiniteData<string, unknown> | undefined\n    >()\n  })\n  it('should properly type when passed to setQueryData', () => {\n    const { queryKey } = infiniteQueryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.setQueryData(queryKey, (prev) => {\n      expectTypeOf(prev).toEqualTypeOf<\n        InfiniteData<string, unknown> | undefined\n      >()\n      return prev\n    })\n\n    expectTypeOf(data).toEqualTypeOf<\n      InfiniteData<string, unknown> | undefined\n    >()\n  })\n})\n"
  },
  {
    "path": "packages/vue-query/src/__tests__/mutationCache.test.ts",
    "content": "import { beforeAll, describe, expect, test, vi } from 'vitest'\nimport { ref } from 'vue-demi'\nimport { MutationCache as MutationCacheOrigin } from '@tanstack/query-core'\nimport { MutationCache } from '../mutationCache'\n\ndescribe('MutationCache', () => {\n  beforeAll(() => {\n    vi.spyOn(MutationCacheOrigin.prototype, 'find')\n    vi.spyOn(MutationCacheOrigin.prototype, 'findAll')\n  })\n\n  describe('find', () => {\n    test('should properly unwrap parameters', () => {\n      const mutationCache = new MutationCache()\n\n      mutationCache.find({\n        mutationKey: ref(['baz']),\n      })\n\n      expect(MutationCacheOrigin.prototype.find).toBeCalledWith({\n        mutationKey: ['baz'],\n      })\n    })\n  })\n\n  describe('findAll', () => {\n    test('should properly unwrap parameters', () => {\n      const mutationCache = new MutationCache()\n\n      mutationCache.findAll({\n        mutationKey: ref(['baz']),\n      })\n\n      expect(MutationCacheOrigin.prototype.findAll).toBeCalledWith({\n        mutationKey: ['baz'],\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/vue-query/src/__tests__/queryCache.test.ts",
    "content": "import { beforeAll, describe, expect, test, vi } from 'vitest'\nimport { ref } from 'vue-demi'\nimport { QueryCache as QueryCacheOrigin } from '@tanstack/query-core'\nimport { QueryCache } from '../queryCache'\n\ndescribe('QueryCache', () => {\n  beforeAll(() => {\n    vi.spyOn(QueryCacheOrigin.prototype, 'find')\n    vi.spyOn(QueryCacheOrigin.prototype, 'findAll')\n  })\n\n  describe('find', () => {\n    test('should properly unwrap parameters', () => {\n      const queryCache = new QueryCache()\n\n      queryCache.find({\n        queryKey: ['foo', ref('bar')],\n      })\n\n      expect(QueryCacheOrigin.prototype.find).toBeCalledWith({\n        queryKey: ['foo', 'bar'],\n      })\n    })\n  })\n\n  describe('findAll', () => {\n    test('should properly unwrap two parameters', () => {\n      const queryCache = new QueryCache()\n\n      queryCache.findAll({\n        queryKey: ['foo', ref('bar')],\n      })\n\n      expect(QueryCacheOrigin.prototype.findAll).toBeCalledWith({\n        queryKey: ['foo', 'bar'],\n      })\n    })\n\n    test('should default to empty filters', () => {\n      const queryCache = new QueryCache()\n\n      queryCache.findAll()\n\n      expect(QueryCacheOrigin.prototype.findAll).toBeCalledWith({})\n    })\n  })\n})\n"
  },
  {
    "path": "packages/vue-query/src/__tests__/queryClient.test-d.ts",
    "content": "import { assertType, describe, expectTypeOf, it } from 'vitest'\nimport { QueryClient } from '../queryClient'\nimport type { DataTag, InfiniteData } from '@tanstack/query-core'\n\ndescribe('getQueryData', () => {\n  it('should be typed if key is tagged', () => {\n    const queryKey = ['key'] as DataTag<Array<string>, number>\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryData(queryKey)\n\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n\n  it('should infer unknown if key is not tagged', () => {\n    const queryKey = ['key'] as const\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryData(queryKey)\n\n    expectTypeOf(data).toEqualTypeOf<unknown>()\n  })\n\n  it('should infer passed generic if passed', () => {\n    const queryKey = ['key'] as const\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryData<number>(queryKey)\n\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n\n  it('should only allow Arrays to be passed', () => {\n    assertType<Parameters<QueryClient['getQueryData']>>([\n      // @ts-expect-error TS2345: Argument of type 'string' is not assignable to parameter of type 'QueryKey'\n      { queryKey: 'key' },\n    ])\n  })\n})\n\ndescribe('setQueryData', () => {\n  it('updater should be typed if key is tagged', () => {\n    const queryKey = ['key'] as DataTag<Array<string>, number>\n    const queryClient = new QueryClient()\n    const data = queryClient.setQueryData(queryKey, (prev) => {\n      expectTypeOf(prev).toEqualTypeOf<number | undefined>()\n      return prev\n    })\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n\n  it('value should be typed if key is tagged', () => {\n    const queryKey = ['key'] as DataTag<Array<string>, number>\n    const queryClient = new QueryClient()\n\n    // @ts-expect-error value should be a number\n    queryClient.setQueryData(queryKey, '1')\n\n    // @ts-expect-error value should be a number\n    queryClient.setQueryData(queryKey, () => '1')\n\n    const data = queryClient.setQueryData(queryKey, 1)\n\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n\n  it('should infer unknown for updater if key is not tagged', () => {\n    const queryKey = ['key'] as const\n    const queryClient = new QueryClient()\n    const data = queryClient.setQueryData(queryKey, (prev) => {\n      expectTypeOf(prev).toEqualTypeOf<unknown>()\n      return prev\n    })\n    expectTypeOf(data).toEqualTypeOf<unknown>()\n  })\n\n  it('should infer unknown for value if key is not tagged', () => {\n    const queryKey = ['key'] as const\n    const queryClient = new QueryClient()\n    const data = queryClient.setQueryData(queryKey, 'foo')\n\n    expectTypeOf(data).toEqualTypeOf<unknown>()\n  })\n\n  it('should infer passed generic if passed', () => {\n    const queryKey = ['key'] as const\n    const queryClient = new QueryClient()\n    const data = queryClient.setQueryData<string>(queryKey, (prev) => {\n      expectTypeOf(prev).toEqualTypeOf<string | undefined>()\n      return prev\n    })\n    expectTypeOf(data).toEqualTypeOf<string | undefined>()\n  })\n\n  it('should infer passed generic for value', () => {\n    const queryKey = ['key'] as const\n    const queryClient = new QueryClient()\n    const data = queryClient.setQueryData<string>(queryKey, 'foo')\n\n    expectTypeOf(data).toEqualTypeOf<string | undefined>()\n  })\n\n  it('should preserve updater parameter type inference when used in functions with explicit return types', () => {\n    const queryKey = ['key'] as DataTag<Array<string>, number>\n    const queryClient = new QueryClient()\n\n    // Simulate usage inside a function with explicit return type\n    // The outer function returns 'unknown' but this shouldn't affect the updater's type inference\n    ;(() =>\n      queryClient.setQueryData(queryKey, (data) => {\n        expectTypeOf(data).toEqualTypeOf<number | undefined>()\n        return data\n      })) satisfies () => unknown\n  })\n})\n\ndescribe('fetchInfiniteQuery', () => {\n  it('should allow passing pages', async () => {\n    const data = await new QueryClient().fetchInfiniteQuery({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve('string'),\n      getNextPageParam: () => 1,\n      initialPageParam: 1,\n      pages: 5,\n    })\n\n    expectTypeOf(data).toEqualTypeOf<InfiniteData<string, number>>()\n  })\n\n  it('should not allow passing getNextPageParam without pages', () => {\n    assertType<Parameters<QueryClient['fetchInfiniteQuery']>>([\n      {\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve('string'),\n        initialPageParam: 1,\n        getNextPageParam: () => 1,\n      },\n    ])\n  })\n\n  it('should not allow passing pages without getNextPageParam', () => {\n    assertType<Parameters<QueryClient['fetchInfiniteQuery']>>([\n      // @ts-expect-error Property 'getNextPageParam' is missing\n      {\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve('string'),\n        initialPageParam: 1,\n        pages: 5,\n      },\n    ])\n  })\n})\n"
  },
  {
    "path": "packages/vue-query/src/__tests__/queryClient.test.ts",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { ref } from 'vue-demi'\nimport { QueryClient as QueryClientOrigin } from '@tanstack/query-core'\nimport { QueryClient } from '../queryClient'\nimport { infiniteQueryOptions } from '../infiniteQueryOptions'\n\nvi.mock('@tanstack/query-core', async () => {\n  const actual = await vi.importActual<{\n    QueryClient: typeof QueryClientOrigin\n  }>('@tanstack/query-core')\n\n  // Get the prototype methods dynamically\n  const prototypeMethods = Object.getOwnPropertyNames(\n    actual.QueryClient.prototype,\n  ).filter((prop): prop is keyof typeof actual.QueryClient.prototype => {\n    const descriptor = Object.getOwnPropertyDescriptor(\n      actual.QueryClient.prototype,\n      prop,\n    )\n    return typeof descriptor?.value === 'function' && prop !== 'constructor'\n  })\n\n  // Spy on all methods in the prototype\n  prototypeMethods.forEach((method) => {\n    vi.spyOn(actual.QueryClient.prototype, method)\n  })\n\n  return actual\n})\n\nconst queryKeyRef = ['foo', ref('bar')]\nconst queryKeyUnref = ['foo', 'bar']\n\nconst fn = () => 'mock'\n\ndescribe('QueryCache', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n    vi.clearAllMocks()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  describe('isFetching', () => {\n    test('should properly unwrap 1 parameter', () => {\n      const queryClient = new QueryClient()\n\n      queryClient.isFetching({\n        queryKey: queryKeyRef,\n      })\n\n      expect(QueryClientOrigin.prototype.isFetching).toBeCalledWith({\n        queryKey: queryKeyUnref,\n      })\n    })\n  })\n\n  describe('isMutating', () => {\n    test('should properly unwrap 1 parameter', () => {\n      const queryClient = new QueryClient()\n\n      queryClient.isMutating({\n        mutationKey: queryKeyRef,\n      })\n\n      expect(QueryClientOrigin.prototype.isMutating).toBeCalledWith({\n        mutationKey: queryKeyUnref,\n      })\n    })\n  })\n\n  describe('getQueryData', () => {\n    test('should properly unwrap 1 parameter', () => {\n      const queryClient = new QueryClient()\n\n      queryClient.getQueryData(queryKeyRef)\n\n      expect(QueryClientOrigin.prototype.getQueryData).toBeCalledWith(\n        queryKeyUnref,\n      )\n    })\n  })\n\n  describe('ensureQueryData', () => {\n    test('should properly unwrap parameter', () => {\n      const queryClient = new QueryClient()\n\n      queryClient.ensureQueryData({\n        queryKey: queryKeyRef,\n        queryFn: fn,\n      })\n\n      expect(QueryClientOrigin.prototype.ensureQueryData).toBeCalledWith({\n        queryKey: queryKeyUnref,\n        queryFn: fn,\n      })\n    })\n  })\n\n  describe('getQueriesData', () => {\n    test('should properly unwrap queryKey param', () => {\n      const queryClient = new QueryClient()\n\n      queryClient.getQueriesData({ queryKey: queryKeyRef })\n\n      expect(QueryClientOrigin.prototype.getQueriesData).toBeCalledWith({\n        queryKey: queryKeyUnref,\n      })\n    })\n\n    test('should properly unwrap filters param', () => {\n      const queryClient = new QueryClient()\n\n      queryClient.getQueriesData({ queryKey: queryKeyRef })\n\n      expect(QueryClientOrigin.prototype.getQueriesData).toBeCalledWith({\n        queryKey: queryKeyUnref,\n      })\n    })\n  })\n\n  describe('setQueryData', () => {\n    test('should properly unwrap 3 parameter', () => {\n      const queryClient = new QueryClient()\n\n      queryClient.setQueryData(queryKeyRef, fn, {\n        updatedAt: ref(3),\n      })\n\n      expect(QueryClientOrigin.prototype.setQueryData).toBeCalledWith(\n        queryKeyUnref,\n        fn,\n        { updatedAt: 3 },\n      )\n    })\n  })\n\n  describe('setQueriesData', () => {\n    test('should properly unwrap params with queryKey', () => {\n      const queryClient = new QueryClient()\n\n      queryClient.setQueriesData({ queryKey: queryKeyRef }, fn, {\n        updatedAt: ref(3),\n      })\n\n      expect(QueryClientOrigin.prototype.setQueriesData).toBeCalledWith(\n        { queryKey: queryKeyUnref },\n        fn,\n        { updatedAt: 3 },\n      )\n    })\n\n    test('should properly unwrap params with filters', () => {\n      const queryClient = new QueryClient()\n\n      queryClient.setQueriesData({ queryKey: queryKeyRef }, fn, {\n        updatedAt: ref(3),\n      })\n\n      expect(QueryClientOrigin.prototype.setQueriesData).toBeCalledWith(\n        { queryKey: queryKeyUnref },\n        fn,\n        { updatedAt: 3 },\n      )\n    })\n  })\n\n  describe('getQueryState', () => {\n    test('should properly unwrap 1 parameter', () => {\n      const queryClient = new QueryClient()\n\n      queryClient.getQueryState(queryKeyRef)\n\n      expect(QueryClientOrigin.prototype.getQueryState).toBeCalledWith(\n        queryKeyUnref,\n      )\n    })\n  })\n\n  describe('removeQueries', () => {\n    test('should properly unwrap 1 parameter', () => {\n      const queryClient = new QueryClient()\n\n      queryClient.removeQueries({\n        queryKey: queryKeyRef,\n      })\n\n      expect(QueryClientOrigin.prototype.removeQueries).toBeCalledWith({\n        queryKey: queryKeyUnref,\n      })\n    })\n  })\n\n  describe('resetQueries', () => {\n    test('should properly unwrap 2 parameter', () => {\n      const queryClient = new QueryClient()\n\n      queryClient.resetQueries(\n        {\n          queryKey: queryKeyRef,\n        },\n        { cancelRefetch: ref(false) },\n      )\n\n      expect(QueryClientOrigin.prototype.resetQueries).toBeCalledWith(\n        {\n          queryKey: queryKeyUnref,\n        },\n        { cancelRefetch: false },\n      )\n    })\n  })\n\n  describe('cancelQueries', () => {\n    test('should properly unwrap 2 parameter', () => {\n      const queryClient = new QueryClient()\n\n      queryClient.cancelQueries(\n        {\n          queryKey: queryKeyRef,\n        },\n        { revert: ref(false) },\n      )\n\n      expect(QueryClientOrigin.prototype.cancelQueries).toBeCalledWith(\n        {\n          queryKey: queryKeyUnref,\n        },\n        { revert: false },\n      )\n    })\n  })\n\n  describe('invalidateQueries', () => {\n    test('should properly unwrap 2 parameter', () => {\n      const queryClient = new QueryClient()\n\n      queryClient.invalidateQueries(\n        {\n          queryKey: queryKeyRef,\n        },\n        { cancelRefetch: ref(false) },\n      )\n\n      expect(QueryClientOrigin.prototype.invalidateQueries).toBeCalledWith(\n        {\n          queryKey: queryKeyUnref,\n          refetchType: 'none',\n        },\n        { cancelRefetch: false },\n      )\n    })\n\n    // #7694\n    test('should call invalidateQueries immediately and refetchQueries after sleep', async () => {\n      const invalidateQueries = vi.spyOn(\n        QueryClientOrigin.prototype,\n        'invalidateQueries',\n      )\n      const refetchQueries = vi.spyOn(\n        QueryClientOrigin.prototype,\n        'refetchQueries',\n      )\n\n      const queryClient = new QueryClient()\n\n      queryClient.invalidateQueries({\n        queryKey: queryKeyRef,\n      })\n\n      expect(invalidateQueries).toBeCalled()\n      expect(refetchQueries).not.toBeCalled()\n\n      await vi.advanceTimersByTimeAsync(0)\n\n      expect(refetchQueries).toBeCalled()\n    })\n\n    test('should call invalidateQueries immediately and not call refetchQueries', async () => {\n      const invalidateQueries = vi.spyOn(\n        QueryClientOrigin.prototype,\n        'invalidateQueries',\n      )\n      const refetchQueries = vi.spyOn(\n        QueryClientOrigin.prototype,\n        'refetchQueries',\n      )\n\n      const queryClient = new QueryClient()\n\n      queryClient.invalidateQueries({\n        queryKey: queryKeyRef,\n        refetchType: 'none',\n      })\n\n      expect(invalidateQueries).toBeCalled()\n      expect(refetchQueries).not.toBeCalled()\n\n      await vi.advanceTimersByTimeAsync(0)\n\n      expect(refetchQueries).not.toBeCalled()\n    })\n  })\n\n  describe('refetchQueries', () => {\n    test('should properly unwrap 2 parameter', () => {\n      const queryClient = new QueryClient()\n\n      queryClient.refetchQueries(\n        {\n          queryKey: queryKeyRef,\n        },\n        { cancelRefetch: ref(false) },\n      )\n\n      expect(QueryClientOrigin.prototype.refetchQueries).toBeCalledWith(\n        {\n          queryKey: queryKeyUnref,\n        },\n        { cancelRefetch: false },\n      )\n    })\n  })\n\n  describe('fetchQuery', () => {\n    test('should properly unwrap parameter', () => {\n      const queryClient = new QueryClient()\n\n      queryClient.fetchQuery({\n        queryKey: queryKeyRef,\n      })\n\n      expect(QueryClientOrigin.prototype.fetchQuery).toBeCalledWith({\n        queryKey: queryKeyUnref,\n      })\n    })\n  })\n\n  describe('prefetchQuery', () => {\n    test('should properly unwrap parameters', () => {\n      const queryClient = new QueryClient()\n\n      queryClient.prefetchQuery({ queryKey: queryKeyRef, queryFn: fn })\n\n      expect(QueryClientOrigin.prototype.prefetchQuery).toBeCalledWith({\n        queryKey: queryKeyUnref,\n        queryFn: fn,\n      })\n    })\n  })\n\n  describe('fetchInfiniteQuery', () => {\n    test('should properly unwrap parameter', () => {\n      const queryClient = new QueryClient()\n\n      queryClient.fetchInfiniteQuery({\n        queryKey: queryKeyRef,\n        initialPageParam: 0,\n      })\n\n      expect(QueryClientOrigin.prototype.fetchInfiniteQuery).toBeCalledWith(\n        expect.objectContaining({\n          initialPageParam: 0,\n          queryKey: queryKeyUnref,\n        }),\n      )\n    })\n    test('should properly unwrap parameter using infiniteQueryOptions with unref', () => {\n      const queryClient = new QueryClient()\n\n      const options = infiniteQueryOptions({\n        queryKey: queryKeyUnref,\n        initialPageParam: 0,\n        getNextPageParam: () => 12,\n      })\n\n      queryClient.fetchInfiniteQuery(options)\n\n      expect(QueryClientOrigin.prototype.fetchInfiniteQuery).toBeCalledWith(\n        expect.objectContaining({\n          initialPageParam: 0,\n          queryKey: queryKeyUnref,\n        }),\n      )\n    })\n  })\n\n  describe('prefetchInfiniteQuery', () => {\n    test('should properly unwrap parameters', () => {\n      const queryClient = new QueryClient()\n\n      queryClient.prefetchInfiniteQuery({\n        queryKey: queryKeyRef,\n        queryFn: fn,\n        initialPageParam: 0,\n      })\n\n      expect(QueryClientOrigin.prototype.prefetchInfiniteQuery).toBeCalledWith({\n        initialPageParam: 0,\n        queryKey: queryKeyUnref,\n        queryFn: fn,\n      })\n    })\n  })\n\n  describe('setDefaultOptions', () => {\n    test('should properly unwrap parameters', () => {\n      const queryClient = new QueryClient()\n\n      queryClient.setDefaultOptions({\n        queries: {\n          enabled: ref(false),\n        },\n      })\n\n      expect(QueryClientOrigin.prototype.setDefaultOptions).toBeCalledWith({\n        queries: {\n          enabled: false,\n        },\n      })\n    })\n  })\n\n  describe('setQueryDefaults', () => {\n    test('should properly unwrap parameters', () => {\n      const queryClient = new QueryClient()\n\n      queryClient.setQueryDefaults(queryKeyRef, {\n        enabled: ref(false),\n      })\n\n      expect(QueryClientOrigin.prototype.setQueryDefaults).toBeCalledWith(\n        queryKeyUnref,\n        {\n          enabled: false,\n        },\n      )\n    })\n  })\n\n  describe('getQueryDefaults', () => {\n    test('should properly unwrap parameters', () => {\n      const queryClient = new QueryClient()\n\n      queryClient.getQueryDefaults(queryKeyRef)\n\n      expect(QueryClientOrigin.prototype.getQueryDefaults).toBeCalledWith(\n        queryKeyUnref,\n      )\n    })\n  })\n\n  describe('setMutationDefaults', () => {\n    test('should properly unwrap parameters', () => {\n      const queryClient = new QueryClient()\n\n      queryClient.setMutationDefaults(queryKeyRef, {\n        mutationKey: queryKeyRef,\n      })\n\n      expect(QueryClientOrigin.prototype.setMutationDefaults).toBeCalledWith(\n        queryKeyUnref,\n        {\n          mutationKey: queryKeyUnref,\n        },\n      )\n    })\n  })\n\n  describe('getMutationDefaults', () => {\n    test('should properly unwrap parameters', () => {\n      const queryClient = new QueryClient()\n\n      queryClient.getMutationDefaults(queryKeyRef)\n\n      expect(QueryClientOrigin.prototype.getMutationDefaults).toBeCalledWith(\n        queryKeyUnref,\n      )\n    })\n  })\n})\n"
  },
  {
    "path": "packages/vue-query/src/__tests__/queryOptions.test-d.ts",
    "content": "import { assertType, describe, expectTypeOf, it } from 'vitest'\nimport { reactive, ref } from 'vue-demi'\nimport { dataTagSymbol } from '@tanstack/query-core'\nimport { QueryClient } from '../queryClient'\nimport { queryOptions } from '../queryOptions'\nimport { useQuery } from '../useQuery'\n\ndescribe('queryOptions', () => {\n  it('should not allow excess properties', () => {\n    assertType(\n      queryOptions({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(5),\n        // @ts-expect-error this is a good error, because stallTime does not exist!\n        stallTime: 1000,\n      }),\n    )\n  })\n  it('should infer types for callbacks', () => {\n    queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n      staleTime: 1000,\n      select: (data) => {\n        expectTypeOf(data).toEqualTypeOf<number>()\n      },\n    })\n  })\n  it('should work when passed to useQuery', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const { data } = reactive(useQuery(options))\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n  it('should tag the queryKey with the result type of the QueryFn', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<number>()\n  })\n  it('should tag the queryKey even if no promise is returned', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => 5,\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<number>()\n  })\n  it('should tag the queryKey with unknown if there is no queryFn', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<unknown>()\n  })\n  it('should tag the queryKey with the result type of the QueryFn if select is used', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n      select: (data) => data.toString(),\n    })\n\n    expectTypeOf(queryKey[dataTagSymbol]).toEqualTypeOf<number>()\n  })\n  it('should return the proper type when passed to getQueryData', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.getQueryData(queryKey)\n\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n  it('should properly type updaterFn when passed to setQueryData', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n    const data = queryClient.setQueryData(queryKey, (prev) => {\n      expectTypeOf(prev).toEqualTypeOf<number | undefined>()\n      return prev\n    })\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n  it('should properly type value when passed to setQueryData', () => {\n    const { queryKey } = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n\n    // @ts-expect-error value should be a number\n    queryClient.setQueryData(queryKey, '5')\n    // @ts-expect-error value should be a number\n    queryClient.setQueryData(queryKey, () => '5')\n\n    const data = queryClient.setQueryData(queryKey, 5)\n\n    expectTypeOf(data).toEqualTypeOf<number | undefined>()\n  })\n  it('should allow to be passed to QueryClient methods while containing ref in queryKey', () => {\n    const options = queryOptions({\n      queryKey: ['key', ref(1), { nested: ref(2) }],\n      queryFn: () => Promise.resolve(5),\n    })\n\n    const queryClient = new QueryClient()\n\n    // Should not error\n    const data = queryClient.invalidateQueries(options)\n    // Should not error\n    const data2 = queryClient.fetchQuery(options)\n\n    expectTypeOf(data).toEqualTypeOf<Promise<void>>()\n    expectTypeOf(data2).toEqualTypeOf<Promise<number>>()\n  })\n\n  it('TData should always be defined when initialData is provided as a function which ALWAYS returns the data', () => {\n    const { data } = reactive(\n      useQuery(\n        queryOptions({\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n          initialData: () => ({\n            wow: true,\n          }),\n        }),\n      ),\n    )\n\n    expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n  })\n\n  it('TData should have undefined in the union when initialData is NOT provided', () => {\n    const { data } = reactive(\n      useQuery(\n        queryOptions({\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n        }),\n      ),\n    )\n\n    expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()\n  })\n\n  it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => {\n    const { data } = reactive(\n      useQuery(\n        queryOptions({\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n          initialData: () => undefined as { wow: boolean } | undefined,\n        }),\n      ),\n    )\n\n    expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()\n  })\n\n  it('TData should be narrowed after an isSuccess check when initialData is provided as a function which can return undefined', () => {\n    const { data, isSuccess } = reactive(\n      useQuery(\n        queryOptions({\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n          initialData: () => undefined as { wow: boolean } | undefined,\n        }),\n      ),\n    )\n\n    if (isSuccess) {\n      expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n    }\n  })\n\n  it('data should not have undefined when initialData is provided', () => {\n    const { data } = reactive(\n      useQuery(\n        queryOptions({\n          queryKey: ['query-key'],\n          initialData: 42,\n        }),\n      ),\n    )\n\n    expectTypeOf(data).toEqualTypeOf<number>()\n  })\n})\n"
  },
  {
    "path": "packages/vue-query/src/__tests__/queryOptions.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\nimport { queryOptions } from '../queryOptions'\nimport type { UseQueryOptions } from '../useQuery'\n\ndescribe('queryOptions', () => {\n  it('should return the object received as a parameter without any modification.', () => {\n    const object: UseQueryOptions = {\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(5),\n    } as const\n\n    expect(queryOptions(object)).toBe(object)\n  })\n})\n"
  },
  {
    "path": "packages/vue-query/src/__tests__/useInfiniteQuery.test-d.tsx",
    "content": "import { describe, expectTypeOf, it } from 'vitest'\nimport { computed, reactive } from 'vue-demi'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { useInfiniteQuery } from '../useInfiniteQuery'\nimport { infiniteQueryOptions } from '../infiniteQueryOptions'\nimport type { InfiniteData } from '@tanstack/query-core'\n\ndescribe('Discriminated union return type', () => {\n  it('data should be possibly undefined by default', () => {\n    const query = reactive(\n      useInfiniteQuery({\n        queryKey: ['infiniteQuery'],\n        queryFn: () => sleep(0).then(() => 'Some data'),\n        getNextPageParam: () => undefined,\n        initialPageParam: 0,\n      }),\n    )\n\n    // TODO: Order of generics prevents pageParams to be typed correctly. Using `unknown` for now\n    expectTypeOf(query.data).toEqualTypeOf<\n      InfiniteData<string, unknown> | undefined\n    >()\n  })\n\n  it('data should be defined when query is success', () => {\n    const query = reactive(\n      useInfiniteQuery({\n        queryKey: ['infiniteQuery'],\n        queryFn: () => sleep(0).then(() => 'Some data'),\n        getNextPageParam: () => undefined,\n        initialPageParam: 0,\n      }),\n    )\n\n    if (query.isSuccess) {\n      // TODO: Order of generics prevents pageParams to be typed correctly. Using `unknown` for now\n      expectTypeOf(query.data).toEqualTypeOf<InfiniteData<string, unknown>>()\n    }\n  })\n\n  it('error should be null when query is success', () => {\n    const query = reactive(\n      useInfiniteQuery({\n        queryKey: ['infiniteQuery'],\n        queryFn: () => sleep(0).then(() => 'Some data'),\n        getNextPageParam: () => undefined,\n        initialPageParam: 0,\n      }),\n    )\n\n    if (query.isSuccess) {\n      expectTypeOf(query.error).toEqualTypeOf<null>()\n    }\n  })\n\n  it('data should be undefined when query is pending', () => {\n    const query = reactive(\n      useInfiniteQuery({\n        queryKey: ['infiniteQuery'],\n        queryFn: () => sleep(0).then(() => 'Some data'),\n        getNextPageParam: () => undefined,\n        initialPageParam: 0,\n      }),\n    )\n\n    if (query.isPending) {\n      expectTypeOf(query.data).toEqualTypeOf<undefined>()\n    }\n  })\n\n  it('error should be defined when query is error', () => {\n    const query = reactive(\n      useInfiniteQuery({\n        queryKey: ['infiniteQuery'],\n        queryFn: () => sleep(0).then(() => 'Some data'),\n        getNextPageParam: () => undefined,\n        initialPageParam: 0,\n      }),\n    )\n\n    if (query.isError) {\n      expectTypeOf(query.error).toEqualTypeOf<Error>()\n    }\n  })\n\n  it('should accept computed options', () => {\n    const options = computed(() => ({\n      queryKey: ['infiniteQuery'],\n      queryFn: () => sleep(0).then(() => 'Some data'),\n      getNextPageParam: () => undefined,\n      initialPageParam: 0,\n    }))\n    const query = reactive(useInfiniteQuery(options))\n\n    if (query.isSuccess) {\n      expectTypeOf(query.data).toEqualTypeOf<InfiniteData<string, unknown>>()\n    }\n  })\n\n  it('should accept computed options using infiniteQueryOptions', () => {\n    const options = computed(() =>\n      infiniteQueryOptions({\n        queryKey: ['infiniteQuery'],\n        queryFn: () => sleep(0).then(() => 'Some data'),\n        getNextPageParam: () => undefined,\n        initialPageParam: 0,\n      }),\n    )\n    const query = reactive(useInfiniteQuery(options))\n\n    if (query.isSuccess) {\n      expectTypeOf(query.data).toEqualTypeOf<InfiniteData<string, unknown>>()\n    }\n  })\n\n  it('should accept plain options using infiniteQueryOptions', () => {\n    const options = () =>\n      infiniteQueryOptions({\n        queryKey: ['infiniteQuery'],\n        queryFn: () => sleep(0).then(() => 'Some data'),\n        getNextPageParam: () => undefined,\n        initialPageParam: 0,\n      })\n    const query = reactive(useInfiniteQuery(options))\n\n    if (query.isSuccess) {\n      expectTypeOf(query.data).toEqualTypeOf<InfiniteData<string, unknown>>()\n    }\n  })\n})\n"
  },
  {
    "path": "packages/vue-query/src/__tests__/useInfiniteQuery.test.ts",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { useInfiniteQuery } from '../useInfiniteQuery'\nimport { infiniteQueryOptions } from '../infiniteQueryOptions'\n\nvi.mock('../useQueryClient')\n\ndescribe('useInfiniteQuery', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('should properly execute infinite query', async () => {\n    const { data, fetchNextPage, status } = useInfiniteQuery({\n      queryKey: ['infiniteQuery'],\n      queryFn: ({ pageParam }) =>\n        sleep(0).then(() => 'data on page ' + pageParam),\n      initialPageParam: 0,\n      getNextPageParam: () => 12,\n    })\n\n    expect(data.value).toStrictEqual(undefined)\n    expect(status.value).toStrictEqual('pending')\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(data.value).toStrictEqual({\n      pageParams: [0],\n      pages: ['data on page 0'],\n    })\n    expect(status.value).toStrictEqual('success')\n\n    fetchNextPage()\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(data.value).toStrictEqual({\n      pageParams: [0, 12],\n      pages: ['data on page 0', 'data on page 12'],\n    })\n    expect(status.value).toStrictEqual('success')\n  })\n  test('should properly execute infinite query using infiniteQueryOptions', async () => {\n    const options = infiniteQueryOptions({\n      queryKey: ['infiniteQueryOptions'],\n      queryFn: ({ pageParam }) =>\n        sleep(0).then(() => 'data on page ' + pageParam),\n      initialPageParam: 0,\n      getNextPageParam: () => 12,\n    })\n\n    const { data, fetchNextPage, status } = useInfiniteQuery(options)\n\n    expect(data.value).toStrictEqual(undefined)\n    expect(status.value).toStrictEqual('pending')\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(data.value).toStrictEqual({\n      pageParams: [0],\n      pages: ['data on page 0'],\n    })\n    expect(status.value).toStrictEqual('success')\n\n    fetchNextPage()\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(data.value).toStrictEqual({\n      pageParams: [0, 12],\n      pages: ['data on page 0', 'data on page 12'],\n    })\n    expect(status.value).toStrictEqual('success')\n  })\n})\n"
  },
  {
    "path": "packages/vue-query/src/__tests__/useIsFetching.test.ts",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { onScopeDispose, reactive, ref } from 'vue-demi'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { useQuery } from '../useQuery'\nimport { useIsFetching } from '../useIsFetching'\nimport type { MockedFunction } from 'vitest'\n\nvi.mock('../useQueryClient')\n\ndescribe('useIsFetching', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('should properly return isFetching state', async () => {\n    const { isFetching: isFetchingQuery } = useQuery({\n      queryKey: ['isFetching1'],\n      queryFn: () => sleep(0).then(() => 'Some data'),\n    })\n    useQuery({\n      queryKey: ['isFetching2'],\n      queryFn: () => sleep(0).then(() => 'Some data'),\n    })\n    const isFetching = useIsFetching()\n\n    expect(isFetchingQuery.value).toStrictEqual(true)\n    expect(isFetching.value).toStrictEqual(2)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(isFetchingQuery.value).toStrictEqual(false)\n    expect(isFetching.value).toStrictEqual(0)\n  })\n\n  test('should stop listening to changes on onScopeDispose', async () => {\n    const onScopeDisposeMock = onScopeDispose as MockedFunction<\n      typeof onScopeDispose\n    >\n    onScopeDisposeMock.mockImplementation((fn) => fn())\n\n    const { status } = useQuery({\n      queryKey: ['onScopeDispose'],\n      queryFn: () => sleep(0).then(() => 'Some data'),\n    })\n    const isFetching = useIsFetching()\n\n    expect(status.value).toStrictEqual('pending')\n    expect(isFetching.value).toStrictEqual(1)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(status.value).toStrictEqual('pending')\n    expect(isFetching.value).toStrictEqual(1)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(status.value).toStrictEqual('pending')\n    expect(isFetching.value).toStrictEqual(1)\n\n    onScopeDisposeMock.mockReset()\n  })\n\n  test('should properly update filters', async () => {\n    const filter = reactive({ stale: false, queryKey: ['isFetchingFilter'] })\n    useQuery({\n      queryKey: ['isFetchingFilter'],\n      queryFn: () => sleep(10).then(() => 'Some data'),\n    })\n    const isFetching = useIsFetching(filter)\n\n    expect(isFetching.value).toStrictEqual(0)\n\n    filter.stale = true\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(isFetching.value).toStrictEqual(1)\n  })\n\n  test('should work with options getter and be reactive', async () => {\n    const staleRef = ref(false)\n    useQuery({\n      queryKey: ['isFetchingGetter'],\n      queryFn: () => sleep(10).then(() => 'Some data'),\n    })\n    const isFetching = useIsFetching(() => ({\n      stale: staleRef.value,\n      queryKey: ['isFetchingGetter'],\n    }))\n\n    expect(isFetching.value).toStrictEqual(0)\n\n    staleRef.value = true\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(isFetching.value).toStrictEqual(1)\n  })\n\n  test('should warn when used outside of setup function in development mode', () => {\n    vi.stubEnv('NODE_ENV', 'development')\n    const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})\n\n    try {\n      useIsFetching()\n\n      expect(warnSpy).toHaveBeenCalledWith(\n        'vue-query composable like \"useQuery()\" should only be used inside a \"setup()\" function or a running effect scope. They might otherwise lead to memory leaks.',\n      )\n    } finally {\n      warnSpy.mockRestore()\n      vi.unstubAllEnvs()\n    }\n  })\n})\n"
  },
  {
    "path": "packages/vue-query/src/__tests__/useIsMutating.test.ts",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { onScopeDispose, reactive, ref } from 'vue-demi'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { useMutation } from '../useMutation'\nimport { useIsMutating } from '../useMutationState'\nimport type { MockedFunction } from 'vitest'\n\nvi.mock('../useQueryClient')\n\ndescribe('useIsMutating', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('should properly return isMutating state', async () => {\n    const mutation = useMutation({\n      mutationFn: (params: string) => sleep(10).then(() => params),\n    })\n    const mutation2 = useMutation({\n      mutationFn: (params: string) => sleep(10).then(() => params),\n    })\n    const isMutating = useIsMutating()\n\n    expect(isMutating.value).toStrictEqual(0)\n\n    mutation.mutateAsync('a')\n    mutation2.mutateAsync('b')\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(isMutating.value).toStrictEqual(2)\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(isMutating.value).toStrictEqual(0)\n  })\n\n  test('should stop listening to changes on onScopeDispose', async () => {\n    const onScopeDisposeMock = onScopeDispose as MockedFunction<\n      typeof onScopeDispose\n    >\n    onScopeDisposeMock.mockImplementation((fn) => fn())\n\n    const mutation = useMutation({\n      mutationFn: (params: string) => sleep(0).then(() => params),\n    })\n    const mutation2 = useMutation({\n      mutationFn: (params: string) => sleep(0).then(() => params),\n    })\n    const isMutating = useIsMutating()\n\n    expect(isMutating.value).toStrictEqual(0)\n\n    mutation.mutateAsync('a')\n    mutation2.mutateAsync('b')\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(isMutating.value).toStrictEqual(0)\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(isMutating.value).toStrictEqual(0)\n\n    onScopeDisposeMock.mockReset()\n  })\n\n  test('should properly update filters', async () => {\n    const filter = reactive({ mutationKey: ['foo'] })\n    const { mutate } = useMutation({\n      mutationKey: ['isMutating'],\n      mutationFn: (params: string) => sleep(10).then(() => params),\n    })\n    mutate('foo')\n\n    const isMutating = useIsMutating(filter)\n\n    expect(isMutating.value).toStrictEqual(0)\n\n    filter.mutationKey = ['isMutating']\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(isMutating.value).toStrictEqual(1)\n  })\n\n  test('should work with options getter and be reactive', async () => {\n    const keyRef = ref('isMutatingGetter2')\n    const { mutate } = useMutation({\n      mutationKey: ['isMutatingGetter'],\n      mutationFn: (params: string) => sleep(10).then(() => params),\n    })\n    mutate('foo')\n\n    const isMutating = useIsMutating(() => ({\n      mutationKey: [keyRef.value],\n    }))\n\n    expect(isMutating.value).toStrictEqual(0)\n\n    keyRef.value = 'isMutatingGetter'\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(isMutating.value).toStrictEqual(1)\n  })\n})\n"
  },
  {
    "path": "packages/vue-query/src/__tests__/useMutation.test-d.tsx",
    "content": "import { describe, expectTypeOf, it } from 'vitest'\nimport { reactive } from 'vue-demi'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { useMutation } from '../useMutation'\n\ndescribe('Discriminated union return type', () => {\n  it('data should be possibly undefined by default', () => {\n    const mutation = reactive(\n      useMutation({\n        mutationFn: (params: string) => sleep(0).then(() => params),\n      }),\n    )\n\n    expectTypeOf(mutation.data).toEqualTypeOf<string | undefined>()\n  })\n\n  it('data should be defined when mutation is success', () => {\n    const mutation = reactive(\n      useMutation({\n        mutationFn: (params: string) => sleep(0).then(() => params),\n      }),\n    )\n\n    if (mutation.isSuccess) {\n      expectTypeOf(mutation.data).toEqualTypeOf<string>()\n    }\n  })\n\n  it('error should be null when mutation is success', () => {\n    const mutation = reactive(\n      useMutation({\n        mutationFn: (params: string) => sleep(0).then(() => params),\n      }),\n    )\n\n    if (mutation.isSuccess) {\n      expectTypeOf(mutation.error).toEqualTypeOf<null>()\n    }\n  })\n\n  it('data should be undefined when mutation is pending', () => {\n    const mutation = reactive(\n      useMutation({\n        mutationFn: (params: string) => sleep(0).then(() => params),\n      }),\n    )\n\n    if (mutation.isPending) {\n      expectTypeOf(mutation.data).toEqualTypeOf<undefined>()\n    }\n  })\n\n  it('error should be defined when mutation is error', () => {\n    const mutation = reactive(\n      useMutation({\n        mutationFn: (params: string) => sleep(0).then(() => params),\n      }),\n    )\n\n    if (mutation.isError) {\n      expectTypeOf(mutation.error).toEqualTypeOf<Error>()\n    }\n  })\n\n  it('should narrow variables', () => {\n    const mutation = reactive(\n      useMutation({\n        mutationFn: (params: string) => sleep(0).then(() => params),\n      }),\n    )\n\n    if (mutation.isIdle) {\n      expectTypeOf(mutation.variables).toEqualTypeOf<undefined>()\n      return\n    }\n    if (mutation.isPending) {\n      expectTypeOf(mutation.variables).toEqualTypeOf<string>()\n      return\n    }\n    if (mutation.isSuccess) {\n      expectTypeOf(mutation.variables).toEqualTypeOf<string>()\n      return\n    }\n    expectTypeOf(mutation.variables).toEqualTypeOf<string>()\n  })\n})\n"
  },
  {
    "path": "packages/vue-query/src/__tests__/useMutation.test.ts",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { reactive, ref } from 'vue-demi'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { useMutation } from '../useMutation'\nimport { useQueryClient } from '../useQueryClient'\n\nvi.mock('../useQueryClient')\n\ndescribe('useMutation', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('should be in idle state initially', () => {\n    const mutation = useMutation({\n      mutationFn: (params) => sleep(0).then(() => params),\n    })\n\n    expect(mutation).toMatchObject({\n      isIdle: { value: true },\n      isPending: { value: false },\n      isError: { value: false },\n      isSuccess: { value: false },\n    })\n  })\n\n  test('should change state after invoking mutate', () => {\n    const result = 'Mock data'\n    const mutation = useMutation({\n      mutationFn: (params: string) => sleep(0).then(() => params),\n    })\n\n    mutation.mutate(result)\n\n    expect(mutation).toMatchObject({\n      isIdle: { value: false },\n      isPending: { value: true },\n      isError: { value: false },\n      isSuccess: { value: false },\n      data: { value: undefined },\n      error: { value: null },\n    })\n  })\n\n  test('should return error when request fails', async () => {\n    const mutation = useMutation({\n      mutationFn: () =>\n        sleep(10).then(() => Promise.reject(new Error('Some error'))),\n    })\n    mutation.mutate()\n    await vi.advanceTimersByTimeAsync(10)\n    expect(mutation).toMatchObject({\n      isIdle: { value: false },\n      isPending: { value: false },\n      isError: { value: true },\n      isSuccess: { value: false },\n      data: { value: undefined },\n      error: { value: Error('Some error') },\n    })\n  })\n\n  test('should return data when request succeeds', async () => {\n    const result = 'Mock data'\n    const mutation = useMutation({\n      mutationFn: (params: string) => sleep(10).then(() => params),\n    })\n\n    mutation.mutate(result)\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(mutation).toMatchObject({\n      isIdle: { value: false },\n      isPending: { value: false },\n      isError: { value: false },\n      isSuccess: { value: true },\n      data: { value: 'Mock data' },\n      error: { value: null },\n    })\n  })\n\n  test('should work with options getter and be reactive', async () => {\n    const result = 'Mock data'\n    const keyRef = ref('key01')\n    const fnMock = vi.fn((params: string) => sleep(10).then(() => params))\n    const mutation = useMutation(() => ({\n      mutationKey: [keyRef.value],\n      mutationFn: fnMock,\n    }))\n\n    mutation.mutate(result)\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(fnMock).toHaveBeenCalledTimes(1)\n    expect(fnMock).toHaveBeenNthCalledWith(\n      1,\n      result,\n      expect.objectContaining({ mutationKey: ['key01'] }),\n    )\n\n    keyRef.value = 'key02'\n    await vi.advanceTimersByTimeAsync(0)\n    mutation.mutate(result)\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(fnMock).toHaveBeenCalledTimes(2)\n    expect(fnMock).toHaveBeenNthCalledWith(\n      2,\n      result,\n      expect.objectContaining({ mutationKey: ['key02'] }),\n    )\n  })\n\n  test('should update reactive options', async () => {\n    const queryClient = useQueryClient()\n    const mutationCache = queryClient.getMutationCache()\n    const options = reactive({\n      mutationKey: ['foo'],\n      mutationFn: (params: string) => sleep(10).then(() => params),\n    })\n    const mutation = useMutation(options)\n\n    options.mutationKey = ['bar']\n    await vi.advanceTimersByTimeAsync(10)\n    mutation.mutate('xyz')\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    const mutations = mutationCache.find({ mutationKey: ['bar'] })\n\n    expect(mutations?.options.mutationKey).toEqual(['bar'])\n  })\n\n  test('should update reactive options deeply', async () => {\n    type MutationKeyTest = {\n      entity: string\n      otherObject: {\n        name: string\n      }\n    }\n    const mutationKey = ref<Array<MutationKeyTest>>([\n      {\n        entity: 'test',\n        otherObject: { name: 'objectName' },\n      },\n    ])\n    const queryClient = useQueryClient()\n    const mutationCache = queryClient.getMutationCache()\n    const options = reactive({\n      mutationKey,\n      mutationFn: (params: string) => sleep(10).then(() => params),\n    })\n    const mutation = useMutation(options)\n\n    mutationKey.value[0]!.otherObject.name = 'someOtherObjectName'\n    await vi.advanceTimersByTimeAsync(10)\n    mutation.mutate('xyz')\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    const mutations = mutationCache.getAll()\n    const relevantMutation = mutations.find((m) => {\n      return (\n        Array.isArray(m.options.mutationKey) &&\n        !!m.options.mutationKey[0].otherObject\n      )\n    })\n\n    expect(\n      (relevantMutation?.options.mutationKey as Array<MutationKeyTest>)[0]\n        ?.otherObject.name === 'someOtherObjectName',\n    ).toBe(true)\n  })\n\n  test('should allow for non-options object (mutationFn or mutationKey) passed as arg1 & arg2 to trigger reactive updates', async () => {\n    const mutationKey = ref<Array<string>>(['foo2'])\n    const mutationFn = ref((params: string) => sleep(0).then(() => params))\n    const queryClient = useQueryClient()\n    const mutationCache = queryClient.getMutationCache()\n    const mutation = useMutation({ mutationKey, mutationFn })\n\n    mutationKey.value = ['bar2']\n    let proof = false\n    mutationFn.value = (params: string) => {\n      proof = true\n      return sleep(10).then(() => params)\n    }\n    await vi.advanceTimersByTimeAsync(10)\n\n    mutation.mutate('xyz')\n    await vi.advanceTimersByTimeAsync(10)\n\n    const mutations = mutationCache.find({ mutationKey: ['bar2'] })\n    expect(mutations?.options.mutationKey).toEqual(['bar2'])\n    expect(proof).toEqual(true)\n  })\n\n  test('should reset state after invoking mutation.reset', async () => {\n    const mutation = useMutation({\n      mutationFn: () =>\n        sleep(10).then(() => Promise.reject(new Error('Some error'))),\n    })\n\n    mutation.mutate()\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    mutation.reset()\n\n    expect(mutation).toMatchObject({\n      isIdle: { value: true },\n      isPending: { value: false },\n      isError: { value: false },\n      isSuccess: { value: false },\n      data: { value: undefined },\n      error: { value: null },\n    })\n  })\n\n  describe('side effects', () => {\n    beforeEach(() => {\n      vi.clearAllMocks()\n    })\n\n    test('should call onMutate when passed as an option', async () => {\n      const onMutate = vi.fn()\n      const mutation = useMutation({\n        mutationFn: (params: string) => sleep(10).then(() => params),\n        onMutate,\n      })\n\n      mutation.mutate('')\n\n      await vi.advanceTimersByTimeAsync(10)\n\n      expect(onMutate).toHaveBeenCalledTimes(1)\n    })\n\n    test('should call onError when passed as an option', async () => {\n      const onError = vi.fn()\n      const mutation = useMutation({\n        mutationFn: () =>\n          sleep(10).then(() => Promise.reject(new Error('Some error'))),\n        onError,\n      })\n\n      mutation.mutate('')\n\n      await vi.advanceTimersByTimeAsync(10)\n\n      expect(onError).toHaveBeenCalledTimes(1)\n    })\n\n    test('should call onSuccess when passed as an option', async () => {\n      const onSuccess = vi.fn()\n      const mutation = useMutation({\n        mutationFn: (params: string) => sleep(10).then(() => params),\n        onSuccess,\n      })\n\n      mutation.mutate('')\n\n      await vi.advanceTimersByTimeAsync(10)\n\n      expect(onSuccess).toHaveBeenCalledTimes(1)\n    })\n\n    test('should call onSettled when passed as an option', async () => {\n      const onSettled = vi.fn()\n      const mutation = useMutation({\n        mutationFn: (params: string) => sleep(10).then(() => params),\n        onSettled,\n      })\n\n      mutation.mutate('')\n\n      await vi.advanceTimersByTimeAsync(10)\n\n      expect(onSettled).toHaveBeenCalledTimes(1)\n    })\n\n    test('should call onError when passed as an argument of mutate function', async () => {\n      const onError = vi.fn()\n      const mutation = useMutation({\n        mutationFn: () =>\n          sleep(10).then(() => Promise.reject(new Error('Some error'))),\n      })\n\n      mutation.mutate(undefined, { onError })\n\n      await vi.advanceTimersByTimeAsync(10)\n\n      expect(onError).toHaveBeenCalledTimes(1)\n    })\n\n    test('should call onSuccess when passed as an argument of mutate function', async () => {\n      const onSuccess = vi.fn()\n      const mutation = useMutation({\n        mutationFn: (params: string) => sleep(10).then(() => params),\n      })\n\n      mutation.mutate('', { onSuccess })\n\n      await vi.advanceTimersByTimeAsync(10)\n\n      expect(onSuccess).toHaveBeenCalledTimes(1)\n    })\n\n    test('should call onSettled when passed as an argument of mutate function', async () => {\n      const onSettled = vi.fn()\n      const mutation = useMutation({\n        mutationFn: (params: string) => sleep(10).then(() => params),\n      })\n\n      mutation.mutate('', { onSettled })\n\n      await vi.advanceTimersByTimeAsync(10)\n\n      expect(onSettled).toHaveBeenCalledTimes(1)\n    })\n\n    test('should fire both onSettled functions', async () => {\n      const onSettled = vi.fn()\n      const onSettledOnFunction = vi.fn()\n      const mutation = useMutation({\n        mutationFn: (params: string) => sleep(10).then(() => params),\n        onSettled,\n      })\n\n      mutation.mutate('', { onSettled: onSettledOnFunction })\n\n      await vi.advanceTimersByTimeAsync(10)\n\n      expect(onSettled).toHaveBeenCalledTimes(1)\n      expect(onSettledOnFunction).toHaveBeenCalledTimes(1)\n    })\n  })\n\n  describe('async', () => {\n    beforeEach(() => {\n      vi.clearAllMocks()\n    })\n\n    test('should resolve properly', async () => {\n      const result = 'Mock data'\n      const mutation = useMutation({\n        mutationFn: (params: string) => sleep(10).then(() => params),\n      })\n\n      await vi.waitFor(() =>\n        expect(mutation.mutateAsync(result)).resolves.toBe(result),\n      )\n\n      expect(mutation).toMatchObject({\n        isIdle: { value: false },\n        isPending: { value: false },\n        isError: { value: false },\n        isSuccess: { value: true },\n        data: { value: 'Mock data' },\n        error: { value: null },\n      })\n    })\n\n    test('should throw on error', async () => {\n      const mutation = useMutation({\n        mutationFn: () =>\n          sleep(10).then(() => Promise.reject(new Error('Some error'))),\n      })\n\n      await vi.waitFor(() =>\n        expect(mutation.mutateAsync()).rejects.toThrowError('Some error'),\n      )\n\n      expect(mutation).toMatchObject({\n        isIdle: { value: false },\n        isPending: { value: false },\n        isError: { value: true },\n        isSuccess: { value: false },\n        data: { value: undefined },\n        error: { value: Error('Some error') },\n      })\n    })\n  })\n\n  test('should warn when used outside of setup function in development mode', () => {\n    vi.stubEnv('NODE_ENV', 'development')\n    const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})\n\n    try {\n      useMutation({\n        mutationFn: (params: string) => sleep(0).then(() => params),\n      })\n\n      expect(warnSpy).toHaveBeenCalledWith(\n        'vue-query composable like \"useQuery()\" should only be used inside a \"setup()\" function or a running effect scope. They might otherwise lead to memory leaks.',\n      )\n    } finally {\n      warnSpy.mockRestore()\n      vi.unstubAllEnvs()\n    }\n  })\n\n  describe('throwOnError', () => {\n    test('should evaluate throwOnError when mutation is expected to throw', async () => {\n      const err = new Error('Expected mock error. All is well!')\n      const boundaryFn = vi.fn()\n      const { mutate } = useMutation({\n        mutationFn: () => sleep(10).then(() => Promise.reject(err)),\n        throwOnError: boundaryFn,\n      })\n\n      mutate()\n\n      await vi.advanceTimersByTimeAsync(10)\n\n      expect(boundaryFn).toHaveBeenCalledTimes(1)\n      expect(boundaryFn).toHaveBeenCalledWith(err)\n    })\n\n    test('should throw from error watcher when throwOnError returns true', async () => {\n      const throwOnErrorFn = vi.fn().mockReturnValue(true)\n      const { mutate } = useMutation({\n        mutationFn: () =>\n          sleep(10).then(() => Promise.reject(new Error('Some error'))),\n        throwOnError: throwOnErrorFn,\n      })\n\n      mutate()\n\n      // Suppress the Unhandled Rejection caused by watcher throw in Vue 3\n      const rejectionHandler = () => {}\n      process.on('unhandledRejection', rejectionHandler)\n\n      await vi.advanceTimersByTimeAsync(10)\n\n      process.off('unhandledRejection', rejectionHandler)\n\n      expect(throwOnErrorFn).toHaveBeenCalledTimes(1)\n      expect(throwOnErrorFn).toHaveBeenCalledWith(Error('Some error'))\n    })\n  })\n})\n"
  },
  {
    "path": "packages/vue-query/src/__tests__/useMutationState.test.ts",
    "content": "import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { ref } from 'vue-demi'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { useMutation } from '../useMutation'\nimport { useMutationState } from '../useMutationState'\nimport { useQueryClient } from '../useQueryClient'\n\nvi.mock('../useQueryClient')\n\ndescribe('useMutationState', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should return variables after calling mutate 1', () => {\n    const mutationKey = ['mutation']\n    const variables = 'foo123'\n\n    const { mutate } = useMutation({\n      mutationKey: mutationKey,\n      mutationFn: (params: string) => sleep(0).then(() => params),\n    })\n\n    mutate(variables)\n\n    const mutationState = useMutationState({\n      filters: { mutationKey, status: 'pending' },\n      select: (mutation) => mutation.state.variables,\n    })\n\n    expect(mutationState.value).toEqual([variables])\n  })\n\n  it('should return variables after calling mutate 2', () => {\n    const queryClient = useQueryClient()\n    queryClient.clear()\n    const mutationKey = ['mutation']\n    const variables = 'bar234'\n\n    const { mutate } = useMutation({\n      mutationKey: mutationKey,\n      mutationFn: (params: string) => sleep(0).then(() => params),\n    })\n\n    mutate(variables)\n\n    const mutationState = useMutationState()\n\n    expect(mutationState.value[0]?.variables).toEqual(variables)\n  })\n\n  it('should work with options getter and be reactive', async () => {\n    const keyRef = ref('useMutationStateGetter2')\n    const variables = 'foo123'\n\n    const { mutate } = useMutation({\n      mutationKey: ['useMutationStateGetter'],\n      mutationFn: (params: string) => sleep(10).then(() => params),\n    })\n\n    mutate(variables)\n\n    const mutationState = useMutationState(() => ({\n      filters: { mutationKey: [keyRef.value], status: 'pending' },\n      select: (mutation) => mutation.state.variables,\n    }))\n\n    expect(mutationState.value).toEqual([])\n\n    keyRef.value = 'useMutationStateGetter'\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(mutationState.value).toEqual([variables])\n  })\n})\n"
  },
  {
    "path": "packages/vue-query/src/__tests__/useQueries.test-d.ts",
    "content": "import { describe, expectTypeOf, it } from 'vitest'\nimport { reactive } from 'vue'\nimport { skipToken, useQueries } from '..'\nimport { queryOptions } from '../queryOptions'\nimport type { OmitKeyof, QueryObserverResult } from '..'\nimport type { UseQueryOptions } from '../useQuery'\n\ndescribe('UseQueries config object overload', () => {\n  it('TData should always be defined when initialData is provided as an object', () => {\n    const query1 = {\n      queryKey: ['key1'],\n      queryFn: () => {\n        return {\n          wow: true,\n        }\n      },\n      initialData: {\n        wow: false,\n      },\n    }\n\n    const query2 = queryOptions({\n      queryKey: ['key2'],\n      queryFn: () => 'Query Data',\n      initialData: 'initial data',\n    })\n\n    const query3 = {\n      queryKey: ['key2'],\n      queryFn: () => 'Query Data',\n    }\n\n    const { value: queriesState } = useQueries({\n      queries: [query1, query2, query3],\n    })\n\n    expectTypeOf(queriesState[0].data).toEqualTypeOf<{ wow: boolean }>()\n    expectTypeOf(queriesState[1].data).toEqualTypeOf<string>()\n    expectTypeOf(queriesState[2].data).toEqualTypeOf<string | undefined>()\n  })\n\n  it('TData should be defined when passed through queryOptions', () => {\n    const options = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => {\n        return {\n          wow: true,\n        }\n      },\n      initialData: {\n        wow: true,\n      },\n    })\n\n    const { value: queriesState } = useQueries({ queries: [options] })\n\n    expectTypeOf(queriesState[0].data).toEqualTypeOf<{ wow: boolean }>()\n  })\n\n  it('should be possible to define a different TData than TQueryFnData using select with queryOptions spread into useQueries', () => {\n    const query1 = queryOptions({\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(1),\n      select: (data) => data > 1,\n    })\n\n    const query2 = {\n      queryKey: ['key'],\n      queryFn: () => Promise.resolve(1),\n      select: (data: any) => data > 1,\n    }\n\n    const queriesState = reactive(useQueries({ queries: [query1, query2] }))\n\n    expectTypeOf(queriesState.value[0].data).toEqualTypeOf<\n      boolean | undefined\n    >()\n    expectTypeOf(queriesState.value[1].data).toEqualTypeOf<\n      boolean | undefined\n    >()\n  })\n\n  it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => {\n    const { value: queriesState } = useQueries({\n      queries: [\n        {\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n          initialData: () => undefined as { wow: boolean } | undefined,\n        },\n      ],\n    })\n\n    expectTypeOf(queriesState[0].data).toEqualTypeOf<\n      { wow: boolean } | undefined\n    >()\n  })\n\n  it('TData should have correct type when conditional skipToken is passed', () => {\n    const { value: queriesState } = useQueries({\n      queries: [\n        queryOptions({\n          queryKey: ['key'],\n          queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),\n        }),\n      ],\n    })\n\n    const firstResult = queriesState[0]\n\n    expectTypeOf(firstResult).toEqualTypeOf<\n      QueryObserverResult<number, Error>\n    >()\n    expectTypeOf(firstResult.data).toEqualTypeOf<number | undefined>()\n  })\n\n  describe('custom hook', () => {\n    it('should allow custom hooks using UseQueryOptions', () => {\n      const useCustomQueries = (\n        options?: OmitKeyof<\n          UseQueryOptions<string>,\n          'queryKey' | 'queryFn',\n          'safely'\n        >,\n      ) =>\n        useQueries({\n          queries: [\n            {\n              ...options,\n              queryKey: ['todos-key'],\n              queryFn: () => Promise.resolve('data'),\n            },\n          ],\n        })\n\n      const { value: queriesState } = useCustomQueries()\n\n      expectTypeOf(queriesState[0].data).toEqualTypeOf<string | undefined>()\n    })\n  })\n\n  // Fix #7270\n  it('should have proper type inference with different options provided', () => {\n    const numbers = [1, 2, 3]\n    const queryKey = (n: number) => [n]\n    const queryFn = (n: number) => () => Promise.resolve(n)\n    const select = (data: number) => data.toString()\n\n    const queries = numbers.map((n) => ({\n      queryKey: [n],\n      queryFn: () => Promise.resolve(n),\n      select: (data: number) => data.toString(),\n    }))\n\n    const queriesWithoutSelect = numbers.map((n) => ({\n      queryKey: queryKey(n),\n      queryFn: queryFn(n),\n    }))\n\n    const queriesWithQueryOptions = numbers.map((n) =>\n      queryOptions({\n        queryKey: queryKey(n),\n        queryFn: queryFn(n),\n        select,\n      }),\n    )\n\n    const queriesWithQueryOptionsWithoutSelect = numbers.map((n) =>\n      queryOptions({\n        queryKey: queryKey(n),\n        queryFn: queryFn(n),\n      }),\n    )\n\n    const query1 = useQueries({ queries: queries })\n    expectTypeOf(query1.value).toEqualTypeOf<\n      Array<QueryObserverResult<string, Error>>\n    >()\n\n    const query2 = useQueries({ queries: queriesWithoutSelect })\n    expectTypeOf(query2.value).toEqualTypeOf<\n      Array<QueryObserverResult<number, Error>>\n    >()\n\n    const query3 = useQueries({ queries: queriesWithQueryOptions })\n    expectTypeOf(query3.value).toEqualTypeOf<\n      Array<QueryObserverResult<string, Error>>\n    >()\n\n    const query4 = useQueries({ queries: queriesWithQueryOptionsWithoutSelect })\n    expectTypeOf(query4.value).toEqualTypeOf<\n      Array<QueryObserverResult<number, Error>>\n    >()\n\n    const queryCombine = useQueries({\n      queries: queries,\n      combine: (data) => {\n        return data.reduce((acc, i) => {\n          acc.push(i.data ?? '')\n          return acc\n        }, [] as Array<string>)\n      },\n    })\n    expectTypeOf(queryCombine.value).toEqualTypeOf<Array<string>>()\n\n    const queryCombineWithoutSelect = useQueries({\n      queries: queriesWithoutSelect,\n      combine: (data) => {\n        return data.reduce((acc, i) => {\n          acc.push(i.data ?? 0)\n          return acc\n        }, [] as Array<number>)\n      },\n    })\n\n    expectTypeOf(queryCombineWithoutSelect.value).toEqualTypeOf<Array<number>>()\n  })\n\n  it('should return correct data for dynamic queries with mixed result types', () => {\n    const Queries1 = {\n      get: () =>\n        queryOptions({\n          queryKey: ['key1'],\n          queryFn: () => Promise.resolve(1),\n        }),\n    }\n    const Queries2 = {\n      get: () =>\n        queryOptions({\n          queryKey: ['key2'],\n          queryFn: () => Promise.resolve(true),\n        }),\n    }\n\n    const queries1List = [1, 2, 3].map(() => ({ ...Queries1.get() }))\n    const { value: queriesState } = useQueries({\n      queries: [...queries1List, { ...Queries2.get() }],\n    })\n\n    expectTypeOf(queriesState).toEqualTypeOf<\n      [\n        ...Array<QueryObserverResult<number, Error>>,\n        QueryObserverResult<boolean, Error>,\n      ]\n    >()\n\n    expectTypeOf(queriesState[0].data).toEqualTypeOf<\n      number | boolean | undefined\n    >()\n  })\n})\n"
  },
  {
    "path": "packages/vue-query/src/__tests__/useQueries.test.ts",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { onScopeDispose, ref } from 'vue-demi'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { useQueries } from '../useQueries'\nimport { useQueryClient } from '../useQueryClient'\nimport { QueryClient } from '../queryClient'\nimport type { MockedFunction } from 'vitest'\n\nvi.mock('../useQueryClient')\n\ndescribe('useQueries', () => {\n  beforeEach(() => {\n    vi.clearAllMocks()\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('should return result for each query', () => {\n    const queries = [\n      {\n        queryKey: ['key1'],\n        queryFn: () => sleep(0).then(() => 'Some data'),\n      },\n      {\n        queryKey: ['key2'],\n        queryFn: () => sleep(0).then(() => 'Some data'),\n      },\n    ]\n    const queriesState = useQueries({ queries })\n\n    expect(queriesState.value).toMatchObject([\n      {\n        status: 'pending',\n        isPending: true,\n        isFetching: true,\n        isStale: true,\n      },\n      {\n        status: 'pending',\n        isPending: true,\n        isFetching: true,\n        isStale: true,\n      },\n    ])\n  })\n\n  test('should resolve to success and update reactive state', async () => {\n    const queries = [\n      {\n        queryKey: ['key11'],\n        queryFn: () => sleep(0).then(() => 'Some data'),\n      },\n      {\n        queryKey: ['key12'],\n        queryFn: () => sleep(0).then(() => 'Some data'),\n      },\n    ]\n    const queriesState = useQueries({ queries })\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(queriesState.value).toMatchObject([\n      {\n        status: 'success',\n        isPending: false,\n        isFetching: false,\n        isStale: true,\n      },\n      {\n        status: 'success',\n        isPending: false,\n        isFetching: false,\n        isStale: true,\n      },\n    ])\n  })\n\n  test('should reject one of the queries and update reactive state', async () => {\n    const queries = [\n      {\n        queryKey: ['key21'],\n        queryFn: () =>\n          sleep(0).then(() => Promise.reject(new Error('Some error'))),\n      },\n      {\n        queryKey: ['key22'],\n        queryFn: () => sleep(0).then(() => 'Some data'),\n      },\n    ]\n    const queriesState = useQueries({ queries })\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(queriesState.value).toMatchObject([\n      {\n        status: 'error',\n        isPending: false,\n        isFetching: false,\n        isStale: true,\n      },\n      {\n        status: 'success',\n        isPending: false,\n        isFetching: false,\n        isStale: true,\n      },\n    ])\n  })\n\n  test('should return state for new queries', async () => {\n    const queries = ref([\n      {\n        queryKey: ['key31'],\n        queryFn: () => sleep(0).then(() => 'value31'),\n      },\n      {\n        queryKey: ['key32'],\n        queryFn: () => sleep(0).then(() => 'value32'),\n      },\n      {\n        queryKey: ['key33'],\n        queryFn: () => sleep(0).then(() => 'value33'),\n      },\n    ])\n    const queriesState = useQueries({ queries })\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    queries.value.splice(\n      0,\n      queries.value.length,\n      {\n        queryKey: ['key31'],\n        queryFn: () => sleep(0).then(() => 'value31'),\n      },\n      {\n        queryKey: ['key34'],\n        queryFn: () => sleep(0).then(() => 'value34'),\n      },\n    )\n\n    await vi.advanceTimersByTimeAsync(0)\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(queriesState.value.length).toEqual(2)\n    expect(queriesState.value).toMatchObject([\n      {\n        data: 'value31',\n        status: 'success',\n        isPending: false,\n        isFetching: false,\n        isStale: true,\n      },\n      {\n        data: 'value34',\n        status: 'success',\n        isPending: false,\n        isFetching: false,\n        isStale: true,\n      },\n    ])\n  })\n\n  test('should stop listening to changes on onScopeDispose', async () => {\n    const onScopeDisposeMock = onScopeDispose as MockedFunction<\n      typeof onScopeDispose\n    >\n    onScopeDisposeMock.mockImplementationOnce((fn) => fn())\n\n    const queries = [\n      {\n        queryKey: ['key41'],\n        queryFn: () => sleep(0).then(() => 'Some data'),\n      },\n      {\n        queryKey: ['key42'],\n        queryFn: () => sleep(0).then(() => 'Some data'),\n      },\n    ]\n    const queriesState = useQueries({ queries })\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(queriesState.value).toMatchObject([\n      {\n        status: 'pending',\n        isPending: true,\n        isFetching: true,\n        isStale: true,\n      },\n      {\n        status: 'pending',\n        isPending: true,\n        isFetching: true,\n        isStale: true,\n      },\n    ])\n  })\n\n  test('should use queryClient provided via options', async () => {\n    const queryClient = new QueryClient()\n    const queries = [\n      {\n        queryKey: ['key41'],\n        queryFn: () => sleep(0).then(() => 'Some data'),\n      },\n      {\n        queryKey: ['key42'],\n        queryFn: () => sleep(0).then(() => 'Some data'),\n      },\n    ]\n\n    useQueries({ queries }, queryClient)\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(useQueryClient).toHaveBeenCalledTimes(0)\n  })\n\n  test('should combine queries', async () => {\n    const firstResult = 'first result'\n    const secondResult = 'second result'\n\n    const queryClient = new QueryClient()\n    const queries = [\n      {\n        queryKey: ['key41'],\n        queryFn: () => sleep(0).then(() => firstResult),\n      },\n      {\n        queryKey: ['key42'],\n        queryFn: () => sleep(0).then(() => secondResult),\n      },\n    ]\n\n    const queriesResult = useQueries(\n      {\n        queries,\n        combine: (results) => {\n          return {\n            combined: true,\n            res: results.map((res) => res.data),\n          }\n        },\n      },\n      queryClient,\n    )\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(queriesResult.value).toMatchObject({\n      combined: true,\n      res: [firstResult, secondResult],\n    })\n  })\n\n  test('should be `enabled` to accept getter function', async () => {\n    const fetchFn = vi.fn(() => 'foo')\n    const checked = ref(false)\n\n    useQueries({\n      queries: [\n        {\n          queryKey: ['enabled'],\n          queryFn: fetchFn,\n          enabled: () => checked.value,\n        },\n      ],\n    })\n\n    expect(fetchFn).not.toHaveBeenCalled()\n\n    checked.value = true\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(fetchFn).toHaveBeenCalled()\n  })\n\n  test('should allow getters for query keys', async () => {\n    const fetchFn = vi.fn(() => 'foo')\n    const key1 = ref('key1')\n    const key2 = ref('key2')\n\n    useQueries({\n      queries: [\n        {\n          queryKey: ['key', () => key1.value, () => key2.value],\n          queryFn: fetchFn,\n        },\n      ],\n    })\n\n    expect(fetchFn).toHaveBeenCalledTimes(1)\n\n    key1.value = 'key3'\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(fetchFn).toHaveBeenCalledTimes(2)\n\n    key2.value = 'key4'\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(fetchFn).toHaveBeenCalledTimes(3)\n  })\n\n  test('should allow arbitrarily nested getters for query keys', async () => {\n    const fetchFn = vi.fn(() => 'foo')\n    const key1 = ref('key1')\n    const key2 = ref('key2')\n    const key3 = ref('key3')\n    const key4 = ref('key4')\n    const key5 = ref('key5')\n\n    useQueries({\n      queries: [\n        {\n          queryKey: [\n            'key',\n            key1,\n            () => key2.value,\n            { key: () => key3.value },\n            [{ foo: { bar: () => key4.value } }],\n            () => ({\n              foo: {\n                bar: {\n                  baz: () => key5.value,\n                },\n              },\n            }),\n          ],\n          queryFn: fetchFn,\n        },\n      ],\n    })\n\n    expect(fetchFn).toHaveBeenCalledTimes(1)\n\n    key1.value = 'key1-updated'\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(fetchFn).toHaveBeenCalledTimes(2)\n\n    key2.value = 'key2-updated'\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(fetchFn).toHaveBeenCalledTimes(3)\n\n    key3.value = 'key3-updated'\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(fetchFn).toHaveBeenCalledTimes(4)\n\n    key4.value = 'key4-updated'\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(fetchFn).toHaveBeenCalledTimes(5)\n\n    key5.value = 'key5-updated'\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(fetchFn).toHaveBeenCalledTimes(6)\n  })\n\n  test('should refetch only the specific query without affecting others', async () => {\n    let userCount = 0\n    let postCount = 0\n\n    const queriesState = useQueries({\n      queries: [\n        {\n          queryKey: ['users'],\n          queryFn: () => sleep(10).then(() => `users-${++userCount}`),\n        },\n        {\n          queryKey: ['posts'],\n          queryFn: () => sleep(20).then(() => `posts-${++postCount}`),\n        },\n      ],\n    })\n\n    await vi.advanceTimersByTimeAsync(20)\n\n    expect(queriesState.value[0].data).toBe('users-1')\n    expect(queriesState.value[1].data).toBe('posts-1')\n\n    queriesState.value[0].refetch()\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(queriesState.value[0].data).toBe('users-2')\n    expect(queriesState.value[1].data).toBe('posts-1')\n  })\n\n  test('should warn when used outside of setup function in development mode', () => {\n    vi.stubEnv('NODE_ENV', 'development')\n    const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})\n\n    try {\n      useQueries({\n        queries: [\n          {\n            queryKey: ['outsideScope'],\n            queryFn: () => sleep(0).then(() => 'data'),\n          },\n        ],\n      })\n\n      expect(warnSpy).toHaveBeenCalledWith(\n        'vue-query composable like \"useQuery()\" should only be used inside a \"setup()\" function or a running effect scope. They might otherwise lead to memory leaks.',\n      )\n    } finally {\n      warnSpy.mockRestore()\n      vi.unstubAllEnvs()\n    }\n  })\n\n  test('should work with options getter and be reactive', async () => {\n    const fetchFn = vi.fn(() => 'foo')\n    const key1 = ref('key1')\n    const key2 = ref('key2')\n    const key3 = ref('key3')\n    const key4 = ref('key4')\n    const key5 = ref('key5')\n\n    useQueries({\n      queries: () => [\n        {\n          queryKey: [\n            'key',\n            key1,\n            key2.value,\n            { key: key3.value },\n            [{ foo: { bar: key4.value } }],\n            () => ({\n              foo: {\n                bar: {\n                  baz: key5.value,\n                },\n              },\n            }),\n          ],\n          queryFn: fetchFn,\n        },\n      ],\n    })\n\n    expect(fetchFn).toHaveBeenCalledTimes(1)\n\n    key1.value = 'key1-updated'\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(fetchFn).toHaveBeenCalledTimes(2)\n\n    key2.value = 'key2-updated'\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(fetchFn).toHaveBeenCalledTimes(3)\n\n    key3.value = 'key3-updated'\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(fetchFn).toHaveBeenCalledTimes(4)\n\n    key4.value = 'key4-updated'\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(fetchFn).toHaveBeenCalledTimes(5)\n\n    key5.value = 'key5-updated'\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(fetchFn).toHaveBeenCalledTimes(6)\n  })\n})\n"
  },
  {
    "path": "packages/vue-query/src/__tests__/useQuery.test-d.ts",
    "content": "import { describe, expectTypeOf, it } from 'vitest'\nimport { computed, reactive, ref } from 'vue-demi'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { queryOptions, useQuery } from '..'\nimport type { OmitKeyof, UseQueryOptions } from '..'\n\ndescribe('useQuery', () => {\n  describe('Config object overload', () => {\n    it('TData should always be defined when initialData is provided as an object', () => {\n      const { data } = reactive(\n        useQuery({\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n          initialData: {\n            wow: true,\n          },\n        }),\n      )\n\n      expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n    })\n\n    it('TData should be defined when passed through queryOptions', () => {\n      const options = queryOptions({\n        queryKey: ['key'],\n        queryFn: () => {\n          return {\n            wow: true,\n          }\n        },\n        initialData: {\n          wow: true,\n        },\n      })\n      const { data } = reactive(useQuery(options))\n\n      expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n    })\n\n    it('should be possible to define a different TData than TQueryFnData using select with queryOptions spread into useQuery', () => {\n      const options = queryOptions({\n        queryKey: ['key'],\n        queryFn: () => Promise.resolve(1),\n      })\n\n      const query = reactive(\n        useQuery({\n          ...options,\n          select: (data) => data > 1,\n        }),\n      )\n\n      expectTypeOf(query.data).toEqualTypeOf<boolean | undefined>()\n    })\n\n    it('TData should always be defined when initialData is provided as a function which ALWAYS returns the data', () => {\n      const { data } = reactive(\n        useQuery({\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n          initialData: () => ({\n            wow: true,\n          }),\n        }),\n      )\n\n      expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n    })\n\n    it('TData should have undefined in the union when initialData is NOT provided', () => {\n      const { data } = reactive(\n        useQuery({\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n        }),\n      )\n\n      expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()\n    })\n\n    it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => {\n      const { data } = reactive(\n        useQuery({\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n          initialData: () => undefined as { wow: boolean } | undefined,\n        }),\n      )\n\n      expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()\n    })\n\n    it('TData should be narrowed after an isSuccess check when initialData is provided as a function which can return undefined', () => {\n      const { data, isSuccess } = reactive(\n        useQuery({\n          queryKey: ['key'],\n          queryFn: () => {\n            return {\n              wow: true,\n            }\n          },\n          initialData: () => undefined as { wow: boolean } | undefined,\n        }),\n      )\n\n      if (isSuccess) {\n        expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()\n      }\n    })\n\n    it('data should not have undefined when initialData is provided', () => {\n      const { data } = reactive(\n        useQuery({\n          queryKey: ['query-key'],\n          initialData: 42,\n        }),\n      )\n\n      expectTypeOf(data).toEqualTypeOf<number>()\n    })\n  })\n\n  describe('custom composable', () => {\n    it('should allow custom composable using UseQueryOptions', () => {\n      const useCustomQuery = (\n        options?: OmitKeyof<\n          UseQueryOptions<string>,\n          'queryKey' | 'queryFn',\n          'safely'\n        >,\n      ) => {\n        return useQuery({\n          ...options,\n          queryKey: ['todos-key'],\n          queryFn: () => Promise.resolve('data'),\n        })\n      }\n\n      const { data } = reactive(useCustomQuery())\n\n      expectTypeOf(data).toEqualTypeOf<string | undefined>()\n    })\n  })\n\n  describe('structuralSharing', () => {\n    it('should be able to use structuralSharing with unknown types', () => {\n      // https://github.com/TanStack/query/issues/6525#issuecomment-1938411343\n      useQuery({\n        queryKey: ['key'],\n        queryFn: () => 5,\n        structuralSharing: (oldData, newData) => {\n          expectTypeOf(oldData).toBeUnknown()\n          expectTypeOf(newData).toBeUnknown()\n          return newData\n        },\n      })\n    })\n  })\n\n  describe('Discriminated union return type', () => {\n    it('data should be possibly undefined by default', () => {\n      const query = reactive(\n        useQuery({\n          queryKey: ['key'],\n          queryFn: () => sleep(0).then(() => 'Some data'),\n        }),\n      )\n\n      expectTypeOf(query.data).toEqualTypeOf<string | undefined>()\n    })\n\n    it('data should be defined when query is success', () => {\n      const query = reactive(\n        useQuery({\n          queryKey: ['key'],\n          queryFn: () => sleep(0).then(() => 'Some data'),\n        }),\n      )\n\n      if (query.isSuccess) {\n        expectTypeOf(query.data).toEqualTypeOf<string>()\n      }\n    })\n\n    it('error should be null when query is success', () => {\n      const query = reactive(\n        useQuery({\n          queryKey: ['key'],\n          queryFn: () => sleep(0).then(() => 'Some data'),\n        }),\n      )\n\n      if (query.isSuccess) {\n        expectTypeOf(query.error).toEqualTypeOf<null>()\n      }\n    })\n\n    it('data should be undefined when query is pending', () => {\n      const query = reactive(\n        useQuery({\n          queryKey: ['key'],\n          queryFn: () => sleep(0).then(() => 'Some data'),\n        }),\n      )\n\n      if (query.isPending) {\n        expectTypeOf(query.data).toEqualTypeOf<undefined>()\n      }\n    })\n\n    it('error should be defined when query is error', () => {\n      const query = reactive(\n        useQuery({\n          queryKey: ['key'],\n          queryFn: () => sleep(0).then(() => 'Some data'),\n        }),\n      )\n\n      if (query.isError) {\n        expectTypeOf(query.error).toEqualTypeOf<Error>()\n      }\n    })\n  })\n\n  describe('accept ref options', () => {\n    it('should accept ref options', () => {\n      const options = ref({\n        queryKey: ['key'],\n        queryFn: () => sleep(0).then(() => 'Some data'),\n      })\n\n      const query = reactive(useQuery(options))\n\n      if (query.isSuccess) {\n        expectTypeOf(query.data).toEqualTypeOf<string>()\n      }\n    })\n\n    it('should accept computed options', () => {\n      const options = computed(() => ({\n        queryKey: ['key'],\n        queryFn: () => sleep(0).then(() => 'Some data'),\n      }))\n\n      const query = reactive(useQuery(options))\n\n      if (query.isSuccess) {\n        expectTypeOf(query.data).toEqualTypeOf<string>()\n      }\n    })\n\n    it('should accept computed query options', () => {\n      const options = computed(() =>\n        queryOptions({\n          queryKey: ['key'],\n          queryFn: () => sleep(0).then(() => 'Some data'),\n        }),\n      )\n\n      const query = reactive(useQuery(options))\n\n      if (query.isSuccess) {\n        expectTypeOf(query.data).toEqualTypeOf<string>()\n      }\n    })\n  })\n})\n"
  },
  {
    "path": "packages/vue-query/src/__tests__/useQuery.test.ts",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport {\n  computed,\n  getCurrentInstance,\n  onScopeDispose,\n  reactive,\n  ref,\n} from 'vue-demi'\nimport { QueryObserver } from '@tanstack/query-core'\nimport { sleep } from '@tanstack/query-test-utils'\nimport { useQuery } from '../useQuery'\nimport { useBaseQuery } from '../useBaseQuery'\nimport type { Mock, MockedFunction } from 'vitest'\n\nvi.mock('../useQueryClient')\nvi.mock('../useBaseQuery')\n\ndescribe('useQuery', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('should properly execute query', () => {\n    const queryFn = () => sleep(0).then(() => 'Some data')\n\n    useQuery({\n      queryKey: ['key0'],\n      queryFn,\n      staleTime: 1000,\n    })\n\n    expect(useBaseQuery).toBeCalledWith(\n      QueryObserver,\n      {\n        queryKey: ['key0'],\n        queryFn,\n        staleTime: 1000,\n      },\n      undefined,\n    )\n  })\n\n  test('should work with options getter', async () => {\n    const query = useQuery(() => ({\n      queryKey: ['key01'],\n      queryFn: () => sleep(0).then(() => 'result01'),\n    }))\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(query).toMatchObject({\n      status: { value: 'success' },\n      data: { value: 'result01' },\n      isPending: { value: false },\n      isFetching: { value: false },\n      isFetched: { value: true },\n      isSuccess: { value: true },\n    })\n  })\n\n  test('should work with options getter and be reactive', async () => {\n    const keyRef = ref('key011')\n    const resultRef = ref('result02')\n    const query = useQuery(() => ({\n      queryKey: [keyRef.value],\n      queryFn: () => sleep(0).then(() => resultRef.value),\n    }))\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(query).toMatchObject({\n      status: { value: 'success' },\n      data: { value: 'result02' },\n      isPending: { value: false },\n      isFetching: { value: false },\n      isFetched: { value: true },\n      isSuccess: { value: true },\n    })\n\n    resultRef.value = 'result021'\n    keyRef.value = 'key012'\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(query).toMatchObject({\n      status: { value: 'success' },\n      data: { value: 'result021' },\n      isPending: { value: false },\n      isFetching: { value: false },\n      isFetched: { value: true },\n      isSuccess: { value: true },\n    })\n  })\n\n  test('should return pending status initially', () => {\n    const query = useQuery({\n      queryKey: ['key1'],\n      queryFn: () => sleep(0).then(() => 'Some data'),\n    })\n\n    expect(query).toMatchObject({\n      status: { value: 'pending' },\n      isPending: { value: true },\n      isFetching: { value: true },\n      isStale: { value: true },\n    })\n  })\n\n  test('should resolve to success and update reactive state: useQuery(key, dataFn)', async () => {\n    const query = useQuery({\n      queryKey: ['key2'],\n      queryFn: () => sleep(0).then(() => 'result2'),\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(query).toMatchObject({\n      status: { value: 'success' },\n      data: { value: 'result2' },\n      isPending: { value: false },\n      isFetching: { value: false },\n      isFetched: { value: true },\n      isSuccess: { value: true },\n    })\n  })\n\n  test('should resolve to success and update reactive state: useQuery(optionsObj)', async () => {\n    const query = useQuery({\n      queryKey: ['key31'],\n      queryFn: () => sleep(0).then(() => 'result31'),\n      enabled: true,\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(query).toMatchObject({\n      status: { value: 'success' },\n      data: { value: 'result31' },\n      isPending: { value: false },\n      isFetching: { value: false },\n      isFetched: { value: true },\n      isSuccess: { value: true },\n    })\n  })\n\n  test('should resolve to success and update reactive state: useQuery(key, optionsObj)', async () => {\n    const query = useQuery({\n      queryKey: ['key32'],\n      queryFn: () => sleep(0).then(() => 'result32'),\n      enabled: true,\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(query).toMatchObject({\n      status: { value: 'success' },\n      data: { value: 'result32' },\n      isPending: { value: false },\n      isFetching: { value: false },\n      isFetched: { value: true },\n      isSuccess: { value: true },\n    })\n  })\n\n  test('should reject and update reactive state', async () => {\n    const query = useQuery({\n      queryKey: ['key3'],\n      queryFn: () =>\n        sleep(0).then(() => Promise.reject(new Error('Some error'))),\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(query).toMatchObject({\n      status: { value: 'error' },\n      data: { value: undefined },\n      error: { value: { message: 'Some error' } },\n      isPending: { value: false },\n      isFetching: { value: false },\n      isFetched: { value: true },\n      isError: { value: true },\n      failureCount: { value: 1 },\n      failureReason: { value: { message: 'Some error' } },\n    })\n  })\n\n  test('should update query on reactive (Ref) key change', async () => {\n    const secondKeyRef = ref('key7')\n    const query = useQuery({\n      queryKey: ['key6', secondKeyRef],\n      queryFn: () => sleep(10).then(() => 'Some data'),\n    })\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(query).toMatchObject({\n      status: { value: 'success' },\n    })\n\n    secondKeyRef.value = 'key8'\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(query).toMatchObject({\n      status: { value: 'pending' },\n      data: { value: undefined },\n    })\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(query).toMatchObject({\n      status: { value: 'success' },\n    })\n  })\n\n  test(\"should update query when an option is passed as Ref and it's changed\", async () => {\n    const enabled = ref(false)\n    const query = useQuery({\n      queryKey: ['key9'],\n      queryFn: () => sleep(10).then(() => 'Some data'),\n      enabled,\n    })\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(query).toMatchObject({\n      fetchStatus: { value: 'idle' },\n      data: { value: undefined },\n    })\n\n    enabled.value = true\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(query).toMatchObject({\n      fetchStatus: { value: 'fetching' },\n      data: { value: undefined },\n    })\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(query).toMatchObject({\n      status: { value: 'success' },\n    })\n  })\n\n  test('should properly execute dependent queries', async () => {\n    const { data } = useQuery({\n      queryKey: ['dependent1'],\n      queryFn: () => sleep(0).then(() => 'Some data'),\n    })\n\n    const enabled = computed(() => !!data.value)\n\n    const dependentQueryFn = vi\n      .fn()\n      .mockImplementation(() => sleep(10).then(() => 'Some data'))\n    const { fetchStatus, status } = useQuery(\n      reactive({\n        queryKey: ['dependent2'],\n        queryFn: dependentQueryFn,\n        enabled,\n      }),\n    )\n\n    expect(data.value).toStrictEqual(undefined)\n    expect(fetchStatus.value).toStrictEqual('idle')\n    expect(dependentQueryFn).not.toHaveBeenCalled()\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(data.value).toStrictEqual('Some data')\n    expect(fetchStatus.value).toStrictEqual('fetching')\n\n    await vi.advanceTimersByTimeAsync(10)\n\n    expect(fetchStatus.value).toStrictEqual('idle')\n    expect(status.value).toStrictEqual('success')\n    expect(dependentQueryFn).toHaveBeenCalledTimes(1)\n    expect(dependentQueryFn).toHaveBeenCalledWith(\n      expect.objectContaining({ queryKey: ['dependent2'] }),\n    )\n  })\n\n  test('should stop listening to changes on onScopeDispose', async () => {\n    const onScopeDisposeMock = onScopeDispose as MockedFunction<\n      typeof onScopeDispose\n    >\n    onScopeDisposeMock.mockImplementationOnce((fn) => fn())\n\n    const { status } = useQuery({\n      queryKey: ['onScopeDispose'],\n      queryFn: () => sleep(0).then(() => 'Some data'),\n    })\n\n    expect(status.value).toStrictEqual('pending')\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(status.value).toStrictEqual('pending')\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(status.value).toStrictEqual('pending')\n  })\n\n  test('should use the current value for the queryKey when refetch is called', async () => {\n    const fetchFn = vi.fn(() => 'foo')\n    const keyRef = ref('key11')\n    const query = useQuery({\n      queryKey: ['key10', keyRef],\n      queryFn: fetchFn,\n      enabled: false,\n    })\n\n    expect(fetchFn).not.toHaveBeenCalled()\n    await query.refetch()\n    expect(fetchFn).toHaveBeenCalledTimes(1)\n    expect(fetchFn).toHaveBeenCalledWith(\n      expect.objectContaining({\n        queryKey: ['key10', 'key11'],\n      }),\n    )\n\n    keyRef.value = 'key12'\n    await query.refetch()\n    expect(fetchFn).toHaveBeenCalledTimes(2)\n    expect(fetchFn).toHaveBeenCalledWith(\n      expect.objectContaining({\n        queryKey: ['key10', 'key12'],\n      }),\n    )\n  })\n\n  test('should be `enabled` to accept getter function', async () => {\n    const fetchFn = vi.fn(() => 'foo')\n    const checked = ref(false)\n\n    useQuery({\n      queryKey: ['enabled'],\n      queryFn: fetchFn,\n      enabled: () => checked.value,\n    })\n\n    expect(fetchFn).not.toHaveBeenCalled()\n\n    checked.value = true\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(fetchFn).toHaveBeenCalled()\n  })\n\n  test('should allow getters for query keys', async () => {\n    const fetchFn = vi.fn(() => 'foo')\n    const key1 = ref('key1')\n    const key2 = ref('key2')\n\n    useQuery({\n      queryKey: ['key', () => key1.value, () => key2.value],\n      queryFn: fetchFn,\n    })\n\n    expect(fetchFn).toHaveBeenCalledTimes(1)\n\n    key1.value = 'key3'\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(fetchFn).toHaveBeenCalledTimes(2)\n\n    key2.value = 'key4'\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(fetchFn).toHaveBeenCalledTimes(3)\n  })\n\n  test('should allow arbitrarily nested getters for query keys', async () => {\n    const fetchFn = vi.fn(() => 'foo')\n    const key1 = ref('key1')\n    const key2 = ref('key2')\n    const key3 = ref('key3')\n    const key4 = ref('key4')\n    const key5 = ref('key5')\n\n    useQuery({\n      queryKey: [\n        'key',\n        key1,\n        () => key2.value,\n        { key: () => key3.value },\n        [{ foo: { bar: () => key4.value } }],\n        () => ({\n          foo: {\n            bar: {\n              baz: () => key5.value,\n            },\n          },\n        }),\n      ],\n      queryFn: fetchFn,\n    })\n\n    expect(fetchFn).toHaveBeenCalledTimes(1)\n\n    key1.value = 'key1-updated'\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(fetchFn).toHaveBeenCalledTimes(2)\n\n    key2.value = 'key2-updated'\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(fetchFn).toHaveBeenCalledTimes(3)\n\n    key3.value = 'key3-updated'\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(fetchFn).toHaveBeenCalledTimes(4)\n\n    key4.value = 'key4-updated'\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(fetchFn).toHaveBeenCalledTimes(5)\n\n    key5.value = 'key5-updated'\n\n    await vi.advanceTimersByTimeAsync(0)\n\n    expect(fetchFn).toHaveBeenCalledTimes(6)\n  })\n\n  describe('throwOnError', () => {\n    test('should evaluate throwOnError when query is expected to throw', async () => {\n      const boundaryFn = vi.fn()\n      useQuery({\n        queryKey: ['key'],\n        queryFn: () =>\n          sleep(0).then(() => Promise.reject(new Error('Some error'))),\n        retry: false,\n        throwOnError: boundaryFn,\n      })\n\n      await vi.advanceTimersByTimeAsync(0)\n\n      expect(boundaryFn).toHaveBeenCalledTimes(1)\n      expect(boundaryFn).toHaveBeenCalledWith(\n        Error('Some error'),\n        expect.objectContaining({\n          state: expect.objectContaining({ status: 'error' }),\n        }),\n      )\n    })\n  })\n\n  describe('outside scope warning', () => {\n    test('should warn when used outside of setup function in development mode', () => {\n      vi.stubEnv('NODE_ENV', 'development')\n      const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})\n\n      try {\n        useQuery({\n          queryKey: ['outsideScope'],\n          queryFn: () => sleep(0).then(() => 'data'),\n        })\n\n        expect(warnSpy).toHaveBeenCalledWith(\n          'vue-query composable like \"useQuery()\" should only be used inside a \"setup()\" function or a running effect scope. They might otherwise lead to memory leaks.',\n        )\n      } finally {\n        warnSpy.mockRestore()\n        vi.unstubAllEnvs()\n      }\n    })\n  })\n\n  describe('suspense', () => {\n    test('should return a Promise', () => {\n      const getCurrentInstanceSpy = getCurrentInstance as Mock\n      getCurrentInstanceSpy.mockImplementation(() => ({ suspense: {} }))\n\n      const query = useQuery({\n        queryKey: ['suspense'],\n        queryFn: () => sleep(0).then(() => 'Some data'),\n      })\n      const result = query.suspense()\n\n      expect(result).toBeInstanceOf(Promise)\n    })\n\n    test('should resolve after being enabled', async () => {\n      const getCurrentInstanceSpy = getCurrentInstance as Mock\n      getCurrentInstanceSpy.mockImplementation(() => ({ suspense: {} }))\n\n      let afterTimeout = false\n      const isEnabled = ref(false)\n      const query = useQuery({\n        queryKey: ['suspense2'],\n        queryFn: () => sleep(0).then(() => 'Some data'),\n        enabled: isEnabled,\n      })\n\n      setTimeout(() => {\n        afterTimeout = true\n        isEnabled.value = true\n      }, 200)\n\n      query.suspense()\n\n      await vi.advanceTimersByTimeAsync(200)\n\n      expect(afterTimeout).toBe(true)\n    })\n\n    test('should resolve immediately when stale without refetching', () => {\n      const getCurrentInstanceSpy = getCurrentInstance as Mock\n      getCurrentInstanceSpy.mockImplementation(() => ({ suspense: {} }))\n\n      const fetcherSpy = vi.fn(() => sleep(0).then(() => 'Some data'))\n\n      // let afterTimeout = false;\n      const query = useQuery({\n        queryKey: ['suspense3'],\n        queryFn: () => sleep(0).then(() => 'Some data'),\n        staleTime: 10000,\n        initialData: 'foo',\n      })\n\n      return query.suspense().then(() => {\n        expect(fetcherSpy).toHaveBeenCalledTimes(0)\n      })\n    })\n\n    test('should not throw from suspense by default', async () => {\n      const getCurrentInstanceSpy = getCurrentInstance as Mock\n      getCurrentInstanceSpy.mockImplementation(() => ({ suspense: {} }))\n\n      const query = useQuery({\n        queryKey: ['suspense4'],\n        queryFn: () =>\n          sleep(0).then(() => Promise.reject(new Error('Some error'))),\n        staleTime: 10000,\n      })\n\n      await vi.advanceTimersByTimeAsync(0)\n\n      expect(query).toMatchObject({\n        status: { value: 'error' },\n        isError: { value: true },\n      })\n    })\n\n    test('should throw from suspense when throwOnError is true', async () => {\n      const getCurrentInstanceSpy = getCurrentInstance as Mock\n      getCurrentInstanceSpy.mockImplementation(() => ({ suspense: {} }))\n\n      const boundaryFn = vi.fn()\n      const query = useQuery({\n        queryKey: ['suspense5'],\n        queryFn: () =>\n          sleep(0).then(() => Promise.reject(new Error('Some error'))),\n        staleTime: 10000,\n        throwOnError: boundaryFn,\n      })\n\n      query.suspense()\n\n      await vi.advanceTimersByTimeAsync(10000)\n\n      expect(boundaryFn).toHaveBeenCalledTimes(2)\n      expect(boundaryFn).toHaveBeenNthCalledWith(\n        1,\n        Error('Some error'),\n        expect.objectContaining({\n          state: expect.objectContaining({ status: 'error' }),\n        }),\n      )\n      expect(boundaryFn).toHaveBeenNthCalledWith(\n        2,\n        Error('Some error'),\n        expect.objectContaining({\n          state: expect.objectContaining({ status: 'error' }),\n        }),\n      )\n    })\n  })\n})\n"
  },
  {
    "path": "packages/vue-query/src/__tests__/useQueryClient.test.ts",
    "content": "import { beforeEach, describe, expect, test, vi } from 'vitest'\nimport * as VueDemi from 'vue-demi'\nimport { useQueryClient } from '../useQueryClient'\nimport { VUE_QUERY_CLIENT } from '../utils'\n\nvi.mock('vue-demi', async () => {\n  const actual = await vi.importActual<typeof VueDemi>('vue-demi')\n  return {\n    ...actual,\n    inject: vi.fn(),\n    hasInjectionContext: vi.fn(() => true),\n  }\n})\n\ndescribe('useQueryClient', () => {\n  const injectSpy = vi.mocked(VueDemi.inject)\n  const hasInjectionContextSpy = vi.mocked(VueDemi.hasInjectionContext)\n\n  beforeEach(() => {\n    vi.clearAllMocks()\n  })\n\n  test('should return queryClient when it is provided in the context', () => {\n    const queryClientMock = { name: 'Mocked client' }\n    injectSpy.mockReturnValueOnce(queryClientMock)\n\n    const queryClient = useQueryClient()\n\n    expect(queryClient).toStrictEqual(queryClientMock)\n    expect(injectSpy).toHaveBeenCalledTimes(1)\n    expect(injectSpy).toHaveBeenCalledWith(VUE_QUERY_CLIENT)\n  })\n\n  test('should throw an error when queryClient does not exist in the context', () => {\n    injectSpy.mockReturnValueOnce(undefined)\n\n    expect(useQueryClient).toThrowError()\n    expect(injectSpy).toHaveBeenCalledTimes(1)\n    expect(injectSpy).toHaveBeenCalledWith(VUE_QUERY_CLIENT)\n  })\n\n  test('should throw an error when used outside of setup function', () => {\n    hasInjectionContextSpy.mockReturnValueOnce(false)\n\n    expect(useQueryClient).toThrowError()\n    expect(hasInjectionContextSpy).toHaveBeenCalledTimes(1)\n  })\n\n  test('should call inject with a custom key as a suffix', () => {\n    const queryClientKey = 'foo'\n    const expectedKeyParameter = `${VUE_QUERY_CLIENT}:${queryClientKey}`\n    const queryClientMock = { name: 'Mocked client' }\n    injectSpy.mockReturnValueOnce(queryClientMock)\n\n    useQueryClient(queryClientKey)\n\n    expect(injectSpy).toHaveBeenCalledWith(expectedKeyParameter)\n  })\n})\n"
  },
  {
    "path": "packages/vue-query/src/__tests__/utils.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { reactive, ref } from 'vue-demi'\nimport { cloneDeep, cloneDeepUnref, updateState } from '../utils'\n\ndescribe('utils', () => {\n  describe('updateState', () => {\n    test('should update first object with values from the second one', () => {\n      const origin = { option1: 'a', option2: 'b', option3: 'c' }\n      const update = { option1: 'x', option2: 'y', option3: 'z' }\n      const expected = { option1: 'x', option2: 'y', option3: 'z' }\n\n      updateState(origin, update)\n      expect(origin).toEqual(expected)\n    })\n\n    test('should update only existing keys', () => {\n      const origin = { option1: 'a', option2: 'b' }\n      const update = { option1: 'x', option2: 'y', option3: 'z' }\n      const expected = { option1: 'x', option2: 'y' }\n\n      updateState(origin, update)\n      expect(origin).toEqual(expected)\n    })\n\n    test('should remove non existing keys', () => {\n      const origin = { option1: 'a', option2: 'b', option3: 'c' }\n      const update = { option1: 'x', option2: 'y' }\n      const expected = { option1: 'x', option2: 'y' }\n\n      updateState(origin, update)\n      expect(origin).toEqual(expected)\n    })\n  })\n\n  describe('cloneDeep', () => {\n    test('should copy primitives and functions AS-IS', () => {\n      expect(cloneDeep(3456)).toBe(3456)\n      expect(cloneDeep('theString')).toBe('theString')\n      expect(cloneDeep(null)).toBe(null)\n    })\n\n    test('should copy Maps and Sets AS-IS', () => {\n      const setVal = new Set([3, 4, 5])\n      const setValCopy = cloneDeep(setVal)\n      expect(setValCopy).toBe(setVal)\n      expect(setValCopy).toStrictEqual(new Set([3, 4, 5]))\n\n      const mapVal = new Map([\n        ['a', 'aVal'],\n        ['b', 'bVal'],\n      ])\n      const mapValCopy = cloneDeep(mapVal)\n      expect(mapValCopy).toBe(mapVal)\n      expect(mapValCopy).toStrictEqual(\n        new Map([\n          ['a', 'aVal'],\n          ['b', 'bVal'],\n        ]),\n      )\n    })\n\n    test('should deeply copy arrays', () => {\n      const val = [\n        25,\n        'str',\n        null,\n        new Set([3, 4]),\n        [5, 6, { a: 1 }],\n        undefined,\n      ]\n      const cp = cloneDeep(val)\n      expect(cp).toStrictEqual([\n        25,\n        'str',\n        null,\n        new Set([3, 4]),\n        [5, 6, { a: 1 }],\n        undefined,\n      ])\n      expect(cp).not.toBe(val)\n      expect(cp[3]).toBe(val[3]) // Set([3, 4])\n      expect(cp[4]).not.toBe(val[4]) // [5, 6, { a: 1 }]\n      expect((cp[4] as Array<number>)[2]).not.toBe((val[4] as Array<number>)[2]) // { a : 1 }\n    })\n\n    test('should deeply copy object', () => {\n      const val = reactive({\n        a: 25,\n        b: 'str',\n        c: null,\n        d: undefined,\n        e: new Set([5, 6]),\n        f: [3, 4],\n        g: { fa: 26 },\n      })\n      const cp = cloneDeep(val)\n\n      expect(cp).toStrictEqual({\n        a: 25,\n        b: 'str',\n        c: null,\n        d: undefined,\n        e: new Set([5, 6]),\n        f: [3, 4],\n        g: { fa: 26 },\n      })\n\n      expect(cp.e).toBe(val.e) // Set\n      expect(cp.f).not.toBe(val.f) // []\n      expect(cp.g).not.toBe(val.g) // {}\n    })\n  })\n\n  describe('cloneDeepUnref', () => {\n    test('should unref primitives', () => {\n      expect(cloneDeepUnref(ref(34))).toBe(34)\n      expect(cloneDeepUnref(ref('myStr'))).toBe('myStr')\n    })\n\n    test('should deeply unref arrays', () => {\n      const val = ref([2, 3, ref(4), ref('5'), { a: ref(6) }, [ref(7)]])\n      const cp = cloneDeepUnref(val)\n      expect(cp).toStrictEqual([2, 3, 4, '5', { a: 6 }, [7]])\n    })\n\n    test('should deeply unref objects', () => {\n      const val = ref({\n        a: 1,\n        b: ref(2),\n        c: [ref('c1'), ref(['c2'])],\n        d: {\n          e: ref('e'),\n        },\n      })\n      const cp = cloneDeepUnref(val)\n\n      expect(cp).toEqual({\n        a: 1,\n        b: 2,\n        c: ['c1', ['c2']],\n        d: { e: 'e' },\n      })\n    })\n\n    test('should clone getters returning values in queryKey', () => {\n      const val = ref({ queryKey: [1, 2, () => '3'] })\n      const cp = cloneDeepUnref(val)\n      expect(cp).toStrictEqual({ queryKey: [1, 2, '3'] })\n    })\n\n    test('should unref undefined', () => {\n      expect(cloneDeepUnref(ref(undefined))).toBe(undefined)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/vue-query/src/__tests__/vueQueryPlugin.test.ts",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { isVue2, isVue3, ref } from 'vue-demi'\nimport { QueryClient } from '../queryClient'\nimport { VueQueryPlugin } from '../vueQueryPlugin'\nimport { VUE_QUERY_CLIENT } from '../utils'\nimport { setupDevtools } from '../devtools/devtools'\nimport { useQuery } from '../useQuery'\nimport { useQueries } from '../useQueries'\nimport type { App, ComponentOptions } from 'vue'\nimport type { Mock } from 'vitest'\n\nvi.mock('../devtools/devtools')\nvi.mock('../useQueryClient')\nvi.mock('../useBaseQuery')\n\ntype UnmountCallback = () => void\n\ninterface TestApp extends App {\n  onUnmount: UnmountCallback\n  _unmount: UnmountCallback\n  _mixin: ComponentOptions\n  _provided: Record<string, any>\n  $root: TestApp\n}\n\nconst testIf = (condition: boolean) => (condition ? test : test.skip)\n\nfunction getAppMock(withUnmountHook = false): TestApp {\n  const mock = {\n    provide: vi.fn(),\n    unmount: vi.fn(),\n    onUnmount: withUnmountHook\n      ? vi.fn((u: UnmountCallback) => {\n          mock._unmount = u\n        })\n      : undefined,\n    mixin: (m: ComponentOptions) => {\n      mock._mixin = m\n    },\n  } as unknown as TestApp\n\n  return mock\n}\n\ndescribe('VueQueryPlugin', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  describe('devtools', () => {\n    test('should NOT setup devtools', () => {\n      const setupDevtoolsMock = setupDevtools as Mock\n      const appMock = getAppMock()\n      VueQueryPlugin.install(appMock)\n\n      expect(setupDevtoolsMock).toHaveBeenCalledTimes(0)\n    })\n\n    testIf(isVue2)('should NOT setup devtools by default', () => {\n      const envCopy = process.env.NODE_ENV\n      process.env.NODE_ENV = 'development'\n      const setupDevtoolsMock = setupDevtools as Mock\n      const appMock = getAppMock()\n      VueQueryPlugin.install(appMock)\n\n      appMock.$root = appMock\n      appMock._mixin.beforeCreate?.call(appMock)\n      process.env.NODE_ENV = envCopy\n\n      expect(setupDevtoolsMock).toHaveBeenCalledTimes(0)\n    })\n\n    testIf(isVue2)('should setup devtools', () => {\n      const envCopy = process.env.NODE_ENV\n      process.env.NODE_ENV = 'development'\n      const setupDevtoolsMock = setupDevtools as Mock\n      const appMock = getAppMock()\n      VueQueryPlugin.install(appMock, { enableDevtoolsV6Plugin: true })\n\n      appMock.$root = appMock\n      appMock._mixin.beforeCreate?.call(appMock)\n      process.env.NODE_ENV = envCopy\n\n      expect(setupDevtoolsMock).toHaveBeenCalledTimes(1)\n    })\n\n    testIf(isVue3)('should NOT setup devtools by default', () => {\n      const envCopy = process.env.NODE_ENV\n      process.env.NODE_ENV = 'development'\n      const setupDevtoolsMock = setupDevtools as Mock\n      const appMock = getAppMock()\n      VueQueryPlugin.install(appMock)\n      process.env.NODE_ENV = envCopy\n\n      expect(setupDevtoolsMock).toHaveBeenCalledTimes(0)\n    })\n\n    testIf(isVue3)('should setup devtools', () => {\n      const envCopy = process.env.NODE_ENV\n      process.env.NODE_ENV = 'development'\n      const setupDevtoolsMock = setupDevtools as Mock\n      const appMock = getAppMock()\n      VueQueryPlugin.install(appMock, { enableDevtoolsV6Plugin: true })\n      process.env.NODE_ENV = envCopy\n\n      expect(setupDevtoolsMock).toHaveBeenCalledTimes(1)\n    })\n  })\n\n  describe('when app unmounts', () => {\n    test('should call unmount on each client when onUnmount is missing', () => {\n      const appMock = getAppMock()\n      const customClient = {\n        mount: vi.fn(),\n        unmount: vi.fn(),\n      } as unknown as QueryClient\n      const originalUnmount = appMock.unmount\n      VueQueryPlugin.install(appMock, {\n        queryClient: customClient,\n      })\n\n      appMock.unmount()\n\n      expect(appMock.unmount).not.toEqual(originalUnmount)\n      expect(customClient.unmount).toHaveBeenCalledTimes(1)\n      expect(originalUnmount).toHaveBeenCalledTimes(1)\n    })\n\n    test('should call onUnmount if present', () => {\n      const appMock = getAppMock(true)\n      const customClient = {\n        mount: vi.fn(),\n        unmount: vi.fn(),\n      } as unknown as QueryClient\n      const originalUnmount = appMock.unmount\n      VueQueryPlugin.install(appMock, { queryClient: customClient })\n\n      appMock._unmount()\n\n      expect(appMock.unmount).toEqual(originalUnmount)\n      expect(customClient.unmount).toHaveBeenCalledTimes(1)\n    })\n  })\n\n  describe('when called without additional options', () => {\n    testIf(isVue2)('should provide a client with default clientKey', () => {\n      const appMock = getAppMock()\n      VueQueryPlugin.install(appMock)\n\n      appMock._mixin.beforeCreate?.call(appMock)\n\n      expect(appMock._provided).toMatchObject({\n        VUE_QUERY_CLIENT: expect.any(QueryClient),\n      })\n    })\n\n    testIf(isVue3)('should provide a client with default clientKey', () => {\n      const appMock = getAppMock()\n      VueQueryPlugin.install(appMock)\n\n      expect(appMock.provide).toHaveBeenCalledWith(\n        VUE_QUERY_CLIENT,\n        expect.any(QueryClient),\n      )\n    })\n  })\n\n  describe('when called with custom clientKey', () => {\n    testIf(isVue2)('should provide a client with customized clientKey', () => {\n      const appMock = getAppMock()\n      VueQueryPlugin.install(appMock, { queryClientKey: 'CUSTOM' })\n\n      appMock._mixin.beforeCreate?.call(appMock)\n\n      expect(appMock._provided).toMatchObject({\n        [VUE_QUERY_CLIENT + ':CUSTOM']: expect.any(QueryClient),\n      })\n    })\n\n    testIf(isVue3)('should provide a client with customized clientKey', () => {\n      const appMock = getAppMock()\n      VueQueryPlugin.install(appMock, { queryClientKey: 'CUSTOM' })\n\n      expect(appMock.provide).toHaveBeenCalledWith(\n        VUE_QUERY_CLIENT + ':CUSTOM',\n        expect.any(QueryClient),\n      )\n    })\n  })\n\n  describe('when called with custom client', () => {\n    testIf(isVue2)('should provide that custom client', () => {\n      const appMock = getAppMock()\n      const customClient = { mount: vi.fn() } as unknown as QueryClient\n      VueQueryPlugin.install(appMock, { queryClient: customClient })\n\n      appMock._mixin.beforeCreate?.call(appMock)\n\n      expect(customClient.mount).toHaveBeenCalled()\n      expect(appMock._provided).toMatchObject({\n        VUE_QUERY_CLIENT: customClient,\n      })\n    })\n\n    testIf(isVue3)('should provide that custom client', () => {\n      const appMock = getAppMock()\n      const customClient = { mount: vi.fn() } as unknown as QueryClient\n      VueQueryPlugin.install(appMock, { queryClient: customClient })\n\n      expect(customClient.mount).toHaveBeenCalled()\n      expect(appMock.provide).toHaveBeenCalledWith(\n        VUE_QUERY_CLIENT,\n        customClient,\n      )\n    })\n  })\n\n  describe('when called with custom client config', () => {\n    testIf(isVue2)(\n      'should instantiate a client with the provided config',\n      () => {\n        const appMock = getAppMock()\n        const config = {\n          defaultOptions: { queries: { enabled: true } },\n        }\n        VueQueryPlugin.install(appMock, {\n          queryClientConfig: config,\n        })\n\n        appMock._mixin.beforeCreate?.call(appMock)\n        const client = appMock._provided.VUE_QUERY_CLIENT as QueryClient\n        const defaultOptions = client.getDefaultOptions()\n\n        expect(defaultOptions).toEqual(config.defaultOptions)\n      },\n    )\n\n    testIf(isVue3)(\n      'should instantiate a client with the provided config',\n      () => {\n        const appMock = getAppMock()\n        const config = {\n          defaultOptions: { queries: { enabled: true } },\n        }\n        VueQueryPlugin.install(appMock, {\n          queryClientConfig: config,\n        })\n\n        const client = (appMock.provide as Mock).mock.calls[0]?.[1]\n        const defaultOptions = client.getDefaultOptions()\n\n        expect(defaultOptions).toEqual(config.defaultOptions)\n      },\n    )\n  })\n\n  describe('when persister is provided', () => {\n    test('should properly modify isRestoring flag on queryClient', async () => {\n      const appMock = getAppMock()\n      const customClient = {\n        mount: vi.fn(),\n        isRestoring: ref(false),\n      } as unknown as QueryClient\n\n      VueQueryPlugin.install(appMock, {\n        queryClient: customClient,\n        clientPersister: () => [\n          vi.fn(),\n          new Promise((resolve) => {\n            resolve()\n          }),\n        ],\n      })\n\n      expect(customClient.isRestoring?.value).toBeTruthy()\n\n      await vi.advanceTimersByTimeAsync(0)\n\n      expect(customClient.isRestoring?.value).toBeFalsy()\n    })\n\n    test('should delay useQuery subscription and not call fetcher if data is not stale', async () => {\n      const appMock = getAppMock()\n      const customClient = new QueryClient({\n        defaultOptions: {\n          queries: {\n            staleTime: 1000 * 60 * 60,\n          },\n        },\n      })\n\n      VueQueryPlugin.install(appMock, {\n        queryClient: customClient,\n        clientPersister: (client) => [\n          vi.fn(),\n          new Promise((resolve) => {\n            setTimeout(() => {\n              client.setQueryData(['persist'], () => ({\n                foo: 'bar',\n              }))\n              resolve()\n            }, 0)\n          }),\n        ],\n      })\n\n      const fnSpy = vi.fn()\n\n      const query = useQuery(\n        {\n          queryKey: ['persist'],\n          queryFn: fnSpy,\n        },\n        customClient,\n      )\n\n      expect(customClient.isRestoring?.value).toBeTruthy()\n      expect(query.isFetching.value).toBeFalsy()\n      expect(query.data.value).toStrictEqual(undefined)\n      expect(fnSpy).toHaveBeenCalledTimes(0)\n\n      await vi.advanceTimersByTimeAsync(0)\n\n      expect(customClient.isRestoring?.value).toBeFalsy()\n      expect(query.data.value).toStrictEqual({ foo: 'bar' })\n      expect(fnSpy).toHaveBeenCalledTimes(0)\n    })\n\n    test('should delay useQueries subscription and not call fetcher if data is not stale', async () => {\n      const appMock = getAppMock()\n      const customClient = new QueryClient({\n        defaultOptions: {\n          queries: {\n            staleTime: 1000 * 60 * 60,\n          },\n        },\n      })\n\n      VueQueryPlugin.install(appMock, {\n        queryClient: customClient,\n        clientPersister: (client) => [\n          vi.fn(),\n          new Promise((resolve) => {\n            setTimeout(() => {\n              client.setQueryData(['persist1'], () => ({\n                foo1: 'bar1',\n              }))\n              client.setQueryData(['persist2'], () => ({\n                foo2: 'bar2',\n              }))\n              resolve()\n            }, 0)\n          }),\n        ],\n      })\n\n      const fnSpy = vi.fn()\n\n      const query = useQuery(\n        {\n          queryKey: ['persist1'],\n          queryFn: fnSpy,\n        },\n        customClient,\n      )\n\n      const queries = useQueries(\n        {\n          queries: [\n            {\n              queryKey: ['persist2'],\n              queryFn: fnSpy,\n            },\n          ],\n        },\n        customClient,\n      )\n\n      expect(customClient.isRestoring?.value).toBeTruthy()\n\n      expect(query.isFetching.value).toBeFalsy()\n      expect(query.data.value).toStrictEqual(undefined)\n\n      expect(queries.value[0].isFetching).toBeFalsy()\n      expect(queries.value[0].data).toStrictEqual(undefined)\n      expect(fnSpy).toHaveBeenCalledTimes(0)\n\n      await vi.advanceTimersByTimeAsync(0)\n\n      expect(customClient.isRestoring?.value).toBeFalsy()\n      expect(query.data.value).toStrictEqual({ foo1: 'bar1' })\n      expect(queries.value[0].data).toStrictEqual({ foo2: 'bar2' })\n      expect(fnSpy).toHaveBeenCalledTimes(0)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/vue-query/src/devtools/devtools.ts",
    "content": "import { setupDevtoolsPlugin } from '@vue/devtools-api'\nimport { rankItem } from '@tanstack/match-sorter-utils'\nimport { onlineManager } from '@tanstack/query-core'\nimport {\n  getQueryStateLabel,\n  getQueryStatusBg,\n  getQueryStatusFg,\n  sortFns,\n} from './utils'\nimport type { CustomInspectorNode } from '@vue/devtools-api'\nimport type { Query, QueryCacheNotifyEvent } from '@tanstack/query-core'\nimport type { QueryClient } from '../queryClient'\n\nconst pluginId = 'vue-query'\nconst pluginName = 'Vue Query'\n\nexport function setupDevtools(app: any, queryClient: QueryClient) {\n  setupDevtoolsPlugin(\n    {\n      id: pluginId,\n      label: pluginName,\n      packageName: 'vue-query',\n      homepage: 'https://tanstack.com/query/latest',\n      logo: 'https://raw.githubusercontent.com/TanStack/query/main/packages/vue-query/media/vue-query.svg',\n      app,\n      settings: {\n        baseSort: {\n          type: 'choice',\n          component: 'button-group',\n          label: 'Sort Cache Entries',\n          options: [\n            {\n              label: 'ASC',\n              value: 1,\n            },\n            {\n              label: 'DESC',\n              value: -1,\n            },\n          ],\n          defaultValue: 1,\n        },\n        sortFn: {\n          type: 'choice',\n          label: 'Sort Function',\n          options: Object.keys(sortFns).map((key) => ({\n            label: key,\n            value: key,\n          })),\n          defaultValue: Object.keys(sortFns)[0]!,\n        },\n        onlineMode: {\n          type: 'choice',\n          component: 'button-group',\n          label: 'Online mode',\n          options: [\n            {\n              label: 'Online',\n              value: 1,\n            },\n            {\n              label: 'Offline',\n              value: 0,\n            },\n          ],\n          defaultValue: 1,\n        },\n      },\n    },\n    (api) => {\n      const initialSettings = api.getSettings()\n      onlineManager.setOnline(Boolean(initialSettings.onlineMode.valueOf()))\n\n      const queryCache = queryClient.getQueryCache()\n\n      api.addInspector({\n        id: pluginId,\n        label: pluginName,\n        icon: 'api',\n        nodeActions: [\n          {\n            icon: 'file_download',\n            tooltip: 'Refetch',\n            action: (queryHash: string) => {\n              queryCache.get(queryHash)?.fetch()\n            },\n          },\n          {\n            icon: 'alarm',\n            tooltip: 'Invalidate',\n            action: (queryHash: string) => {\n              const query = queryCache.get(queryHash) as Query\n              queryClient.invalidateQueries(query)\n            },\n          },\n          {\n            icon: 'settings_backup_restore',\n            tooltip: 'Reset',\n            action: (queryHash: string) => {\n              queryCache.get(queryHash)?.reset()\n            },\n          },\n          {\n            icon: 'delete',\n            tooltip: 'Remove',\n            action: (queryHash: string) => {\n              const query = queryCache.get(queryHash) as Query\n              queryCache.remove(query)\n            },\n          },\n          {\n            icon: 'hourglass_empty',\n            tooltip: 'Force loading',\n            action: (queryHash: string) => {\n              const query = queryCache.get(queryHash) as Query\n\n              query.setState({\n                data: undefined,\n                status: 'pending',\n              })\n            },\n          },\n          {\n            icon: 'error_outline',\n            tooltip: 'Force error',\n            action: (queryHash: string) => {\n              const query = queryCache.get(queryHash) as Query\n\n              query.setState({\n                data: undefined,\n                status: 'error',\n                error: new Error('Unknown error from devtools'),\n              })\n            },\n          },\n        ],\n      })\n\n      api.addTimelineLayer({\n        id: pluginId,\n        label: pluginName,\n        color: 0xffd94c,\n      })\n\n      queryCache.subscribe((event) => {\n        api.sendInspectorTree(pluginId)\n        api.sendInspectorState(pluginId)\n\n        const queryEvents: Array<QueryCacheNotifyEvent['type']> = [\n          'added',\n          'removed',\n          'updated',\n        ]\n\n        if (queryEvents.includes(event.type)) {\n          api.addTimelineEvent({\n            layerId: pluginId,\n            event: {\n              title: event.type,\n              subtitle: event.query.queryHash,\n              time: api.now(),\n              data: {\n                queryHash: event.query.queryHash,\n                ...event,\n              },\n            },\n          })\n        }\n      })\n\n      api.on.setPluginSettings((payload) => {\n        if (payload.key === 'onlineMode') {\n          onlineManager.setOnline(Boolean(payload.newValue))\n        }\n      })\n\n      api.on.getInspectorTree((payload) => {\n        if (payload.inspectorId === pluginId) {\n          const queries = queryCache.getAll()\n          const settings = api.getSettings()\n\n          const filtered = payload.filter\n            ? queries.filter(\n                (item) => rankItem(item.queryHash, payload.filter).passed,\n              )\n            : [...queries]\n\n          const sorted = filtered.sort(\n            (a, b) => sortFns[settings.sortFn]!(a, b) * settings.baseSort,\n          )\n\n          const nodes: Array<CustomInspectorNode> = sorted.map((query) => {\n            const stateLabel = getQueryStateLabel(query)\n\n            return {\n              id: query.queryHash,\n              label: query.queryHash,\n              tags: [\n                {\n                  label: `${stateLabel} [${query.getObserversCount()}]`,\n                  textColor: getQueryStatusFg(query),\n                  backgroundColor: getQueryStatusBg(query),\n                },\n              ],\n            }\n          })\n          payload.rootNodes = nodes\n        }\n      })\n\n      api.on.getInspectorState((payload) => {\n        if (payload.inspectorId === pluginId) {\n          const query = queryCache.get(payload.nodeId)\n\n          if (!query) {\n            return\n          }\n\n          payload.state = {\n            ' Query Details': [\n              {\n                key: 'Query key',\n                value: query.queryHash,\n              },\n              {\n                key: 'Query status',\n                value: getQueryStateLabel(query),\n              },\n              {\n                key: 'Observers',\n                value: query.getObserversCount(),\n              },\n              {\n                key: 'Last Updated',\n                value: new Date(query.state.dataUpdatedAt).toLocaleTimeString(),\n              },\n            ],\n            'Data Explorer': [\n              {\n                key: 'Data',\n                value: query.state.data,\n              },\n            ],\n            'Query Explorer': [\n              {\n                key: 'Query',\n                value: query,\n              },\n            ],\n          }\n        }\n      })\n    },\n  )\n}\n"
  },
  {
    "path": "packages/vue-query/src/devtools/utils.ts",
    "content": "import type { Query } from '@tanstack/query-core'\n\ntype SortFn = (a: Query, b: Query) => number\n\nenum QueryState {\n  Fetching = 0,\n  Fresh,\n  Stale,\n  Inactive,\n  Paused,\n}\n\nexport function getQueryState(query: Query): QueryState {\n  if (query.state.fetchStatus === 'fetching') {\n    return QueryState.Fetching\n  }\n  if (query.state.fetchStatus === 'paused') {\n    return QueryState.Paused\n  }\n  if (!query.getObserversCount()) {\n    return QueryState.Inactive\n  }\n  if (query.isStale()) {\n    return QueryState.Stale\n  }\n\n  return QueryState.Fresh\n}\n\nexport function getQueryStateLabel(query: Query): string {\n  const queryState = getQueryState(query)\n\n  if (queryState === QueryState.Fetching) {\n    return 'fetching'\n  }\n  if (queryState === QueryState.Paused) {\n    return 'paused'\n  }\n  if (queryState === QueryState.Stale) {\n    return 'stale'\n  }\n  if (queryState === QueryState.Inactive) {\n    return 'inactive'\n  }\n\n  return 'fresh'\n}\n\nexport function getQueryStatusFg(query: Query): number {\n  const queryState = getQueryState(query)\n\n  if (queryState === QueryState.Stale) {\n    return 0x000000\n  }\n\n  return 0xffffff\n}\n\nexport function getQueryStatusBg(query: Query): number {\n  const queryState = getQueryState(query)\n\n  if (queryState === QueryState.Fetching) {\n    return 0x006bff\n  }\n  if (queryState === QueryState.Paused) {\n    return 0x8c49eb\n  }\n  if (queryState === QueryState.Stale) {\n    return 0xffb200\n  }\n  if (queryState === QueryState.Inactive) {\n    return 0x3f4e60\n  }\n\n  return 0x008327\n}\n\nconst queryHashSort: SortFn = (a, b) => a.queryHash.localeCompare(b.queryHash)\n\nconst dateSort: SortFn = (a, b) =>\n  a.state.dataUpdatedAt < b.state.dataUpdatedAt ? 1 : -1\n\nconst statusAndDateSort: SortFn = (a, b) => {\n  if (getQueryState(a) === getQueryState(b)) {\n    return dateSort(a, b)\n  }\n\n  return getQueryState(a) > getQueryState(b) ? 1 : -1\n}\n\nexport const sortFns: Record<string, SortFn> = {\n  'Status > Last Updated': statusAndDateSort,\n  'Query Hash': queryHashSort,\n  'Last Updated': dateSort,\n}\n"
  },
  {
    "path": "packages/vue-query/src/index.ts",
    "content": "export * from '@tanstack/query-core'\n\nexport { useQueryClient } from './useQueryClient'\nexport { VueQueryPlugin } from './vueQueryPlugin'\n\nexport { QueryClient } from './queryClient'\nexport { QueryCache } from './queryCache'\nexport { queryOptions } from './queryOptions'\nexport { infiniteQueryOptions } from './infiniteQueryOptions'\nexport type {\n  DefinedInitialDataInfiniteOptions,\n  UndefinedInitialDataInfiniteOptions,\n} from './infiniteQueryOptions'\nexport { MutationCache } from './mutationCache'\nexport { useQuery } from './useQuery'\nexport { useQueries } from './useQueries'\nexport { useInfiniteQuery } from './useInfiniteQuery'\nexport { useMutation } from './useMutation'\nexport { useIsFetching } from './useIsFetching'\nexport { useIsMutating, useMutationState } from './useMutationState'\nexport { VUE_QUERY_CLIENT } from './utils'\n\nexport type {\n  UseQueryOptions,\n  UseQueryReturnType,\n  UseQueryDefinedReturnType,\n  UndefinedInitialQueryOptions,\n  DefinedInitialQueryOptions,\n} from './useQuery'\nexport type {\n  UseInfiniteQueryOptions,\n  UseInfiniteQueryReturnType,\n} from './useInfiniteQuery'\nexport type { UseMutationOptions, UseMutationReturnType } from './useMutation'\nexport type { UseQueriesOptions, UseQueriesResults } from './useQueries'\nexport type { MutationFilters, MutationStateOptions } from './useMutationState'\nexport type { QueryFilters } from './useIsFetching'\nexport type { VueQueryPluginOptions } from './vueQueryPlugin'\n"
  },
  {
    "path": "packages/vue-query/src/infiniteQueryOptions.ts",
    "content": "import type {\n  DataTag,\n  DefaultError,\n  InfiniteData,\n  NonUndefinedGuard,\n  QueryKey,\n} from '@tanstack/query-core'\nimport type { UseInfiniteQueryOptions } from './useInfiniteQuery'\n\nexport type UndefinedInitialDataInfiniteOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> = UseInfiniteQueryOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey,\n  TPageParam\n> & {\n  initialData?: undefined\n}\n\nexport type DefinedInitialDataInfiniteOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> = UseInfiniteQueryOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey,\n  TPageParam\n> & {\n  initialData:\n    | NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>\n    | (() => NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>)\n}\n\nexport function infiniteQueryOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: UndefinedInitialDataInfiniteOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n): UndefinedInitialDataInfiniteOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey,\n  TPageParam\n> & {\n  queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>\n}\n\nexport function infiniteQueryOptions<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: DefinedInitialDataInfiniteOptions<\n    TQueryFnData,\n    TError,\n    TData,\n    TQueryKey,\n    TPageParam\n  >,\n): DefinedInitialDataInfiniteOptions<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryKey,\n  TPageParam\n> & {\n  queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>\n}\n\nexport function infiniteQueryOptions(options: unknown) {\n  return options\n}\n"
  },
  {
    "path": "packages/vue-query/src/mutationCache.ts",
    "content": "import { MutationCache as MC } from '@tanstack/query-core'\nimport { cloneDeepUnref } from './utils'\nimport type {\n  DefaultError,\n  Mutation,\n  MutationFilters,\n} from '@tanstack/query-core'\nimport type { MaybeRefDeep } from './types'\n\nexport class MutationCache extends MC {\n  find<\n    TData = unknown,\n    TError = DefaultError,\n    TVariables = any,\n    TOnMutateResult = unknown,\n  >(\n    filters: MaybeRefDeep<MutationFilters>,\n  ): Mutation<TData, TError, TVariables, TOnMutateResult> | undefined {\n    return super.find(cloneDeepUnref(filters))\n  }\n\n  findAll(filters: MaybeRefDeep<MutationFilters> = {}): Array<Mutation> {\n    return super.findAll(cloneDeepUnref(filters))\n  }\n}\n"
  },
  {
    "path": "packages/vue-query/src/queryCache.ts",
    "content": "import { QueryCache as QC } from '@tanstack/query-core'\nimport { cloneDeepUnref } from './utils'\nimport type {\n  DefaultError,\n  Query,\n  QueryFilters,\n  WithRequired,\n} from '@tanstack/query-core'\nimport type { MaybeRefDeep } from './types'\n\nexport class QueryCache extends QC {\n  find<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData>(\n    filters: MaybeRefDeep<WithRequired<QueryFilters, 'queryKey'>>,\n  ): Query<TQueryFnData, TError, TData> | undefined {\n    return super.find(cloneDeepUnref(filters))\n  }\n\n  findAll(filters: MaybeRefDeep<QueryFilters> = {}): Array<Query> {\n    return super.findAll(cloneDeepUnref(filters))\n  }\n}\n"
  },
  {
    "path": "packages/vue-query/src/queryClient.ts",
    "content": "import { nextTick, ref } from 'vue-demi'\nimport { QueryClient as QC } from '@tanstack/query-core'\nimport { cloneDeepUnref } from './utils'\nimport { QueryCache } from './queryCache'\nimport { MutationCache } from './mutationCache'\nimport type { UseQueryOptions } from './useQuery'\nimport type { Ref } from 'vue-demi'\nimport type { MaybeRefDeep, NoUnknown, QueryClientConfig } from './types'\nimport type {\n  CancelOptions,\n  DefaultError,\n  DefaultOptions,\n  EnsureQueryDataOptions,\n  FetchInfiniteQueryOptions,\n  FetchQueryOptions,\n  InferDataFromTag,\n  InferErrorFromTag,\n  InfiniteData,\n  InvalidateOptions,\n  InvalidateQueryFilters,\n  MutationFilters,\n  MutationKey,\n  MutationObserverOptions,\n  NoInfer,\n  OmitKeyof,\n  QueryFilters,\n  QueryKey,\n  QueryObserverOptions,\n  QueryState,\n  RefetchOptions,\n  RefetchQueryFilters,\n  ResetOptions,\n  SetDataOptions,\n  Updater,\n} from '@tanstack/query-core'\n\nexport class QueryClient extends QC {\n  constructor(config: QueryClientConfig = {}) {\n    const vueQueryConfig = {\n      defaultOptions: config.defaultOptions,\n      queryCache: config.queryCache || new QueryCache(),\n      mutationCache: config.mutationCache || new MutationCache(),\n    }\n    super(vueQueryConfig)\n  }\n\n  isRestoring?: Ref<boolean> = ref(false)\n\n  isFetching(filters: MaybeRefDeep<QueryFilters> = {}): number {\n    return super.isFetching(cloneDeepUnref(filters))\n  }\n\n  isMutating(filters: MaybeRefDeep<MutationFilters> = {}): number {\n    return super.isMutating(cloneDeepUnref(filters))\n  }\n\n  getQueryData<TData = unknown, TTaggedQueryKey extends QueryKey = QueryKey>(\n    queryKey: TTaggedQueryKey,\n  ): InferDataFromTag<TData, TTaggedQueryKey> | undefined\n  getQueryData<TData = unknown>(\n    queryKey: MaybeRefDeep<QueryKey>,\n  ): TData | undefined\n  getQueryData<TData = unknown>(\n    queryKey: MaybeRefDeep<QueryKey>,\n  ): TData | undefined {\n    return super.getQueryData(cloneDeepUnref(queryKey))\n  }\n\n  ensureQueryData<\n    TQueryFnData,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryKey extends QueryKey = QueryKey,\n  >(\n    options: EnsureQueryDataOptions<TQueryFnData, TError, TData, TQueryKey>,\n  ): Promise<TData>\n  ensureQueryData<\n    TQueryFnData,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryKey extends QueryKey = QueryKey,\n  >(\n    options: MaybeRefDeep<\n      EnsureQueryDataOptions<TQueryFnData, TError, TData, TQueryKey>\n    >,\n  ): Promise<TData>\n  ensureQueryData<\n    TQueryFnData,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryKey extends QueryKey = QueryKey,\n  >(\n    options: MaybeRefDeep<\n      EnsureQueryDataOptions<TQueryFnData, TError, TData, TQueryKey>\n    >,\n  ): Promise<TData> {\n    return super.ensureQueryData(cloneDeepUnref(options))\n  }\n\n  getQueriesData<TData = unknown>(\n    filters: MaybeRefDeep<QueryFilters>,\n  ): Array<[QueryKey, TData | undefined]> {\n    return super.getQueriesData(cloneDeepUnref(filters))\n  }\n\n  setQueryData<\n    TQueryFnData = unknown,\n    TTaggedQueryKey extends QueryKey = QueryKey,\n    TInferredQueryFnData = InferDataFromTag<TQueryFnData, TTaggedQueryKey>,\n  >(\n    queryKey: TTaggedQueryKey,\n    updater: Updater<\n      NoInfer<TInferredQueryFnData> | undefined,\n      NoInfer<TInferredQueryFnData> | undefined\n    >,\n    options?: MaybeRefDeep<SetDataOptions>,\n  ): NoInfer<TInferredQueryFnData> | undefined\n  setQueryData<TQueryFnData, TData = NoUnknown<TQueryFnData>>(\n    queryKey: MaybeRefDeep<QueryKey>,\n    updater: Updater<NoInfer<TData> | undefined, NoInfer<TData> | undefined>,\n    options?: MaybeRefDeep<SetDataOptions>,\n  ): NoInfer<TData> | undefined\n  setQueryData<TData>(\n    queryKey: MaybeRefDeep<QueryKey>,\n    updater: Updater<TData | undefined, TData | undefined>,\n    options: MaybeRefDeep<SetDataOptions> = {},\n  ): NoInfer<TData> | undefined {\n    return super.setQueryData(\n      cloneDeepUnref(queryKey),\n      updater,\n      cloneDeepUnref(options),\n    )\n  }\n\n  setQueriesData<TData>(\n    filters: MaybeRefDeep<QueryFilters>,\n    updater: Updater<TData | undefined, TData | undefined>,\n    options: MaybeRefDeep<SetDataOptions> = {},\n  ): Array<[QueryKey, TData | undefined]> {\n    return super.setQueriesData(\n      cloneDeepUnref(filters),\n      updater,\n      cloneDeepUnref(options),\n    )\n  }\n\n  getQueryState<TData = unknown, TError = DefaultError>(\n    queryKey: MaybeRefDeep<QueryKey>,\n  ): QueryState<TData, TError> | undefined {\n    return super.getQueryState(cloneDeepUnref(queryKey))\n  }\n\n  removeQueries<\n    TQueryFnData = unknown,\n    TError = DefaultError,\n    TTaggedQueryKey extends QueryKey = QueryKey,\n    TInferredQueryFnData = InferDataFromTag<TQueryFnData, TTaggedQueryKey>,\n    TInferredError = InferErrorFromTag<TError, TTaggedQueryKey>,\n  >(filters?: QueryFilters<TTaggedQueryKey>): void\n  removeQueries(filters: MaybeRefDeep<QueryFilters> = {}): void {\n    return super.removeQueries(cloneDeepUnref(filters))\n  }\n\n  resetQueries<\n    TQueryFnData = unknown,\n    TError = DefaultError,\n    TTaggedQueryKey extends QueryKey = QueryKey,\n    TInferredQueryFnData = InferDataFromTag<TQueryFnData, TTaggedQueryKey>,\n    TInferredError = InferErrorFromTag<TError, TTaggedQueryKey>,\n  >(\n    filters?: QueryFilters<TTaggedQueryKey>,\n    options?: MaybeRefDeep<ResetOptions>,\n  ): Promise<void>\n  resetQueries(\n    filters: MaybeRefDeep<QueryFilters> = {},\n    options: MaybeRefDeep<ResetOptions> = {},\n  ): Promise<void> {\n    return super.resetQueries(cloneDeepUnref(filters), cloneDeepUnref(options))\n  }\n\n  cancelQueries<\n    TQueryFnData = unknown,\n    TError = DefaultError,\n    TTaggedQueryKey extends QueryKey = QueryKey,\n    TInferredQueryFnData = InferDataFromTag<TQueryFnData, TTaggedQueryKey>,\n    TInferredError = InferErrorFromTag<TError, TTaggedQueryKey>,\n  >(\n    filters?: QueryFilters<TTaggedQueryKey>,\n    options?: MaybeRefDeep<CancelOptions>,\n  ): Promise<void>\n  cancelQueries(\n    filters: MaybeRefDeep<QueryFilters> = {},\n    options: MaybeRefDeep<CancelOptions> = {},\n  ): Promise<void> {\n    return super.cancelQueries(cloneDeepUnref(filters), cloneDeepUnref(options))\n  }\n\n  invalidateQueries<\n    TQueryFnData = unknown,\n    TError = DefaultError,\n    TTaggedQueryKey extends QueryKey = QueryKey,\n    TInferredQueryFnData = InferDataFromTag<TQueryFnData, TTaggedQueryKey>,\n    TInferredError = InferErrorFromTag<TError, TTaggedQueryKey>,\n  >(\n    filters?: InvalidateQueryFilters<TTaggedQueryKey>,\n    options?: MaybeRefDeep<InvalidateOptions>,\n  ): Promise<void>\n  invalidateQueries<TTaggedQueryKey extends QueryKey = QueryKey>(\n    filters: MaybeRefDeep<InvalidateQueryFilters<TTaggedQueryKey>> = {},\n    options: MaybeRefDeep<InvalidateOptions> = {},\n  ): Promise<void> {\n    const filtersCloned = cloneDeepUnref(filters)\n    const optionsCloned = cloneDeepUnref(options)\n\n    super.invalidateQueries(\n      { ...filtersCloned, refetchType: 'none' },\n      optionsCloned,\n    )\n\n    if (filtersCloned.refetchType === 'none') {\n      return Promise.resolve()\n    }\n\n    const refetchFilters: RefetchQueryFilters<TTaggedQueryKey> = {\n      ...filtersCloned,\n      type: filtersCloned.refetchType ?? filtersCloned.type ?? 'active',\n    }\n\n    // (dosipiuk): We need to delay `refetchQueries` execution to next macro task for all reactive values to be updated.\n    // This ensures that `context` in `queryFn` while `invalidating` along reactive variable change has correct\n    return nextTick().then(() => {\n      return super.refetchQueries(refetchFilters, optionsCloned)\n    })\n  }\n\n  refetchQueries<\n    TQueryFnData = unknown,\n    TError = DefaultError,\n    TTaggedQueryKey extends QueryKey = QueryKey,\n    TInferredQueryFnData = InferDataFromTag<TQueryFnData, TTaggedQueryKey>,\n    TInferredError = InferErrorFromTag<TError, TTaggedQueryKey>,\n  >(\n    filters?: RefetchQueryFilters<TTaggedQueryKey>,\n    options?: MaybeRefDeep<RefetchOptions>,\n  ): Promise<void>\n  refetchQueries(\n    filters: MaybeRefDeep<RefetchQueryFilters> = {},\n    options: MaybeRefDeep<RefetchOptions> = {},\n  ): Promise<void> {\n    return super.refetchQueries(\n      cloneDeepUnref(filters),\n      cloneDeepUnref(options),\n    )\n  }\n\n  fetchQuery<\n    TQueryFnData,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryKey extends QueryKey = QueryKey,\n    TPageParam = never,\n  >(\n    options: FetchQueryOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey,\n      TPageParam\n    >,\n  ): Promise<TData>\n  fetchQuery<\n    TQueryFnData,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryKey extends QueryKey = QueryKey,\n    TPageParam = never,\n  >(\n    options: MaybeRefDeep<\n      FetchQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>\n    >,\n  ): Promise<TData>\n  fetchQuery<\n    TQueryFnData,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryKey extends QueryKey = QueryKey,\n    TPageParam = never,\n  >(\n    options: MaybeRefDeep<\n      FetchQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>\n    >,\n  ): Promise<TData> {\n    return super.fetchQuery(cloneDeepUnref(options))\n  }\n\n  prefetchQuery<\n    TQueryFnData = unknown,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryKey extends QueryKey = QueryKey,\n  >(\n    options: FetchQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  ): Promise<void>\n  prefetchQuery<\n    TQueryFnData = unknown,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryKey extends QueryKey = QueryKey,\n  >(\n    options: MaybeRefDeep<\n      FetchQueryOptions<TQueryFnData, TError, TData, TQueryKey>\n    >,\n  ): Promise<void>\n  prefetchQuery<\n    TQueryFnData = unknown,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryKey extends QueryKey = QueryKey,\n  >(\n    options: MaybeRefDeep<\n      FetchQueryOptions<TQueryFnData, TError, TData, TQueryKey>\n    >,\n  ): Promise<void> {\n    return super.prefetchQuery(cloneDeepUnref(options))\n  }\n\n  fetchInfiniteQuery<\n    TQueryFnData = unknown,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryKey extends QueryKey = QueryKey,\n    TPageParam = unknown,\n  >(\n    options: FetchInfiniteQueryOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey,\n      TPageParam\n    >,\n  ): Promise<InfiniteData<TData, TPageParam>>\n  fetchInfiniteQuery<\n    TQueryFnData,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryKey extends QueryKey = QueryKey,\n    TPageParam = unknown,\n  >(\n    options: MaybeRefDeep<\n      FetchInfiniteQueryOptions<\n        TQueryFnData,\n        TError,\n        TData,\n        TQueryKey,\n        TPageParam\n      >\n    >,\n  ): Promise<InfiniteData<TData, TPageParam>>\n  fetchInfiniteQuery<\n    TQueryFnData,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryKey extends QueryKey = QueryKey,\n    TPageParam = unknown,\n  >(\n    options: MaybeRefDeep<\n      FetchInfiniteQueryOptions<\n        TQueryFnData,\n        TError,\n        TData,\n        TQueryKey,\n        TPageParam\n      >\n    >,\n  ): Promise<InfiniteData<TData, TPageParam>> {\n    return super.fetchInfiniteQuery(cloneDeepUnref(options))\n  }\n\n  prefetchInfiniteQuery<\n    TQueryFnData,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryKey extends QueryKey = QueryKey,\n    TPageParam = unknown,\n  >(\n    options: FetchInfiniteQueryOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey,\n      TPageParam\n    >,\n  ): Promise<void>\n  prefetchInfiniteQuery<\n    TQueryFnData,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryKey extends QueryKey = QueryKey,\n    TPageParam = unknown,\n  >(\n    options: MaybeRefDeep<\n      FetchInfiniteQueryOptions<\n        TQueryFnData,\n        TError,\n        TData,\n        TQueryKey,\n        TPageParam\n      >\n    >,\n  ): Promise<void>\n  prefetchInfiniteQuery<\n    TQueryFnData,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryKey extends QueryKey = QueryKey,\n    TPageParam = unknown,\n  >(\n    options: MaybeRefDeep<\n      FetchInfiniteQueryOptions<\n        TQueryFnData,\n        TError,\n        TData,\n        TQueryKey,\n        TPageParam\n      >\n    >,\n  ): Promise<void> {\n    return super.prefetchInfiniteQuery(cloneDeepUnref(options))\n  }\n\n  setDefaultOptions(options: MaybeRefDeep<DefaultOptions>): void {\n    super.setDefaultOptions(cloneDeepUnref(options))\n  }\n\n  setQueryDefaults<\n    TQueryFnData = unknown,\n    TError = DefaultError,\n    TData = TQueryFnData,\n    TQueryData = TQueryFnData,\n  >(\n    queryKey: MaybeRefDeep<QueryKey>,\n    options: MaybeRefDeep<\n      Omit<UseQueryOptions<TQueryFnData, TError, TData, TQueryData>, 'queryKey'>\n    >,\n  ): void {\n    super.setQueryDefaults(cloneDeepUnref(queryKey), cloneDeepUnref(options))\n  }\n\n  getQueryDefaults(\n    queryKey: MaybeRefDeep<QueryKey>,\n  ): OmitKeyof<QueryObserverOptions<any, any, any, any, any>, 'queryKey'> {\n    return super.getQueryDefaults(cloneDeepUnref(queryKey))\n  }\n\n  setMutationDefaults<\n    TData = unknown,\n    TError = DefaultError,\n    TVariables = void,\n    TOnMutateResult = unknown,\n  >(\n    mutationKey: MaybeRefDeep<MutationKey>,\n    options: MaybeRefDeep<\n      MutationObserverOptions<TData, TError, TVariables, TOnMutateResult>\n    >,\n  ): void {\n    super.setMutationDefaults(\n      cloneDeepUnref(mutationKey),\n      cloneDeepUnref(options),\n    )\n  }\n\n  getMutationDefaults(\n    mutationKey: MaybeRefDeep<MutationKey>,\n  ): MutationObserverOptions<any, any, any, any> {\n    return super.getMutationDefaults(cloneDeepUnref(mutationKey))\n  }\n}\n"
  },
  {
    "path": "packages/vue-query/src/queryOptions.ts",
    "content": "import type { DataTag, DefaultError, QueryKey } from '@tanstack/query-core'\nimport type {\n  DefinedInitialQueryOptions,\n  UndefinedInitialQueryOptions,\n} from './useQuery'\n\nexport function queryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: DefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n): DefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey> & {\n  queryKey: DataTag<TQueryKey, TQueryFnData, TError>\n}\n\nexport function queryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: UndefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n): UndefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey> & {\n  queryKey: DataTag<TQueryKey, TQueryFnData, TError>\n}\n\nexport function queryOptions(options: unknown) {\n  return options\n}\n"
  },
  {
    "path": "packages/vue-query/src/types.ts",
    "content": "import type {\n  DefaultError,\n  DehydrateOptions,\n  HydrateOptions,\n  MutationCache,\n  MutationObserverOptions,\n  OmitKeyof,\n  QueryCache,\n  QueryObserverOptions,\n} from '@tanstack/query-core'\nimport type { ComputedRef, Ref, UnwrapRef } from 'vue-demi'\n\ntype Primitive = string | number | boolean | bigint | symbol | undefined | null\ntype UnwrapLeaf =\n  | Primitive\n  | Function\n  | Date\n  | Error\n  | RegExp\n  | Map<any, any>\n  | WeakMap<any, any>\n  | Set<any>\n  | WeakSet<any>\n\nexport type MaybeRef<T> = Ref<T> | ComputedRef<T> | T\n\nexport type MaybeRefOrGetter<T> = MaybeRef<T> | (() => T)\n\nexport type MaybeRefDeep<T> = MaybeRef<\n  T extends Function\n    ? T\n    : T extends object\n      ? {\n          [Property in keyof T]: MaybeRefDeep<T[Property]>\n        }\n      : T\n>\n\nexport type NoUnknown<T> = Equal<unknown, T> extends true ? never : T\n\nexport type Equal<TTargetA, TTargetB> =\n  (<T>() => T extends TTargetA ? 1 : 2) extends <T>() => T extends TTargetB\n    ? 1\n    : 2\n    ? true\n    : false\n\nexport type DeepUnwrapRef<T> = T extends UnwrapLeaf\n  ? T\n  : T extends Ref<infer U>\n    ? DeepUnwrapRef<U>\n    : T extends {}\n      ? {\n          [Property in keyof T]: DeepUnwrapRef<T[Property]>\n        }\n      : UnwrapRef<T>\n\nexport type ShallowOption = {\n  /**\n   * Return data in a shallow ref object (it is `false` by default). It can be set to `true` to return data in a shallow ref object, which can improve performance if your data does not need to be deeply reactive.\n   */\n  shallow?: boolean\n}\n\nexport interface DefaultOptions<TError = DefaultError> {\n  queries?: OmitKeyof<QueryObserverOptions<unknown, TError>, 'queryKey'> &\n    ShallowOption\n  mutations?: MutationObserverOptions<unknown, TError, unknown, unknown> &\n    ShallowOption\n  hydrate?: HydrateOptions['defaultOptions']\n  dehydrate?: DehydrateOptions\n}\n\nexport interface QueryClientConfig {\n  queryCache?: QueryCache\n  mutationCache?: MutationCache\n  defaultOptions?: DefaultOptions\n}\n"
  },
  {
    "path": "packages/vue-query/src/useBaseQuery.ts",
    "content": "import {\n  computed,\n  getCurrentScope,\n  onScopeDispose,\n  reactive,\n  readonly,\n  shallowReactive,\n  shallowReadonly,\n  toRefs,\n  watch,\n} from 'vue-demi'\nimport { shouldThrowError } from '@tanstack/query-core'\nimport { useQueryClient } from './useQueryClient'\nimport { cloneDeepUnref, updateState } from './utils'\nimport type { Ref } from 'vue-demi'\nimport type {\n  DefaultedQueryObserverOptions,\n  QueryKey,\n  QueryObserver,\n  QueryObserverResult,\n} from '@tanstack/query-core'\nimport type { QueryClient } from './queryClient'\nimport type { UseQueryOptions } from './useQuery'\nimport type { UseInfiniteQueryOptions } from './useInfiniteQuery'\nimport type { MaybeRefOrGetter } from './types'\n\nexport type UseBaseQueryReturnType<\n  TData,\n  TError,\n  TResult = QueryObserverResult<TData, TError>,\n> = {\n  [K in keyof TResult]: K extends\n    | 'fetchNextPage'\n    | 'fetchPreviousPage'\n    | 'refetch'\n    ? TResult[K]\n    : Ref<Readonly<TResult>[K]>\n} & {\n  suspense: () => Promise<TResult>\n}\n\ntype UseQueryOptionsGeneric<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryData,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> =\n  | UseQueryOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>\n  | UseInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>\n\nexport function useBaseQuery<\n  TQueryFnData,\n  TError,\n  TData,\n  TQueryData,\n  TQueryKey extends QueryKey,\n  TPageParam,\n>(\n  Observer: typeof QueryObserver,\n  options: MaybeRefOrGetter<\n    UseQueryOptionsGeneric<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryData,\n      TQueryKey,\n      TPageParam\n    >\n  >,\n  queryClient?: QueryClient,\n): UseBaseQueryReturnType<TData, TError> {\n  if (process.env.NODE_ENV === 'development') {\n    if (!getCurrentScope()) {\n      console.warn(\n        'vue-query composable like \"useQuery()\" should only be used inside a \"setup()\" function or a running effect scope. They might otherwise lead to memory leaks.',\n      )\n    }\n  }\n\n  const client = queryClient || useQueryClient()\n\n  const defaultedOptions = computed(() => {\n    let resolvedOptions = options\n    if (typeof resolvedOptions === 'function') {\n      resolvedOptions = resolvedOptions()\n    }\n    const clonedOptions = cloneDeepUnref(resolvedOptions as any)\n\n    if (typeof clonedOptions.enabled === 'function') {\n      clonedOptions.enabled = clonedOptions.enabled()\n    }\n\n    const defaulted: DefaultedQueryObserverOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryData,\n      TQueryKey\n    > = client.defaultQueryOptions(clonedOptions)\n\n    defaulted._optimisticResults = client.isRestoring?.value\n      ? 'isRestoring'\n      : 'optimistic'\n\n    return defaulted\n  })\n\n  const observer = new Observer(client, defaultedOptions.value)\n  // @ts-expect-error\n  const state = defaultedOptions.value.shallow\n    ? shallowReactive(observer.getCurrentResult())\n    : reactive(observer.getCurrentResult())\n\n  let unsubscribe = () => {\n    // noop\n  }\n\n  if (client.isRestoring) {\n    watch(\n      client.isRestoring,\n      (isRestoring) => {\n        if (!isRestoring) {\n          unsubscribe()\n          unsubscribe = observer.subscribe((result) => {\n            updateState(state, result)\n          })\n        }\n      },\n      { immediate: true },\n    )\n  }\n\n  const updater = () => {\n    observer.setOptions(defaultedOptions.value)\n    updateState(state, observer.getCurrentResult())\n  }\n\n  watch(defaultedOptions, updater)\n\n  onScopeDispose(() => {\n    unsubscribe()\n  })\n\n  // fix #5910\n  const refetch = (...args: Parameters<(typeof state)['refetch']>) => {\n    updater()\n    return state.refetch(...args)\n  }\n\n  const suspense = () => {\n    return new Promise<QueryObserverResult<TData, TError>>(\n      (resolve, reject) => {\n        let stopWatch = () => {\n          // noop\n        }\n        const run = () => {\n          if (defaultedOptions.value.enabled !== false) {\n            // fix #6133\n            observer.setOptions(defaultedOptions.value)\n            const optimisticResult = observer.getOptimisticResult(\n              defaultedOptions.value,\n            )\n            if (optimisticResult.isStale) {\n              stopWatch()\n              observer\n                .fetchOptimistic(defaultedOptions.value)\n                .then(resolve, (error: TError) => {\n                  if (\n                    shouldThrowError(defaultedOptions.value.throwOnError, [\n                      error,\n                      observer.getCurrentQuery(),\n                    ])\n                  ) {\n                    reject(error)\n                  } else {\n                    resolve(observer.getCurrentResult())\n                  }\n                })\n            } else {\n              stopWatch()\n              resolve(optimisticResult)\n            }\n          }\n        }\n\n        run()\n\n        stopWatch = watch(defaultedOptions, run)\n      },\n    )\n  }\n\n  // Handle error boundary\n  watch(\n    () => state.error,\n    (error) => {\n      if (\n        state.isError &&\n        !state.isFetching &&\n        shouldThrowError(defaultedOptions.value.throwOnError, [\n          error as TError,\n          observer.getCurrentQuery(),\n        ])\n      ) {\n        throw error\n      }\n    },\n  )\n\n  // @ts-expect-error\n  const readonlyState = defaultedOptions.value.shallow\n    ? shallowReadonly(state)\n    : readonly(state)\n\n  const object: any = toRefs(readonlyState)\n  for (const key in state) {\n    if (typeof state[key as keyof typeof state] === 'function') {\n      object[key] = state[key as keyof typeof state]\n    }\n  }\n\n  object.suspense = suspense\n  object.refetch = refetch\n\n  return object as UseBaseQueryReturnType<TData, TError>\n}\n"
  },
  {
    "path": "packages/vue-query/src/useInfiniteQuery.ts",
    "content": "import { InfiniteQueryObserver } from '@tanstack/query-core'\nimport { useBaseQuery } from './useBaseQuery'\nimport type {\n  DefinedInitialDataInfiniteOptions,\n  UndefinedInitialDataInfiniteOptions,\n} from './infiniteQueryOptions'\nimport type {\n  DefaultError,\n  InfiniteData,\n  InfiniteQueryObserverOptions,\n  InfiniteQueryObserverResult,\n  QueryKey,\n  QueryObserver,\n} from '@tanstack/query-core'\n\nimport type { UseBaseQueryReturnType } from './useBaseQuery'\n\nimport type {\n  DeepUnwrapRef,\n  MaybeRef,\n  MaybeRefDeep,\n  MaybeRefOrGetter,\n  ShallowOption,\n} from './types'\nimport type { QueryClient } from './queryClient'\n\nexport type UseInfiniteQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n> = MaybeRef<\n  {\n    [Property in keyof InfiniteQueryObserverOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey,\n      TPageParam\n    >]: Property extends 'enabled'\n      ? MaybeRefOrGetter<\n          InfiniteQueryObserverOptions<\n            TQueryFnData,\n            TError,\n            TData,\n            DeepUnwrapRef<TQueryKey>,\n            TPageParam\n          >[Property]\n        >\n      : MaybeRefDeep<\n          InfiniteQueryObserverOptions<\n            TQueryFnData,\n            TError,\n            TData,\n            DeepUnwrapRef<TQueryKey>,\n            TPageParam\n          >[Property]\n        >\n  } & ShallowOption\n>\n\nexport type UseInfiniteQueryReturnType<TData, TError> = UseBaseQueryReturnType<\n  TData,\n  TError,\n  InfiniteQueryObserverResult<TData, TError>\n>\n\nexport function useInfiniteQuery<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: MaybeRefOrGetter<\n    DefinedInitialDataInfiniteOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey,\n      TPageParam\n    >\n  >,\n  queryClient?: QueryClient,\n): UseInfiniteQueryReturnType<TData, TError>\n\nexport function useInfiniteQuery<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: MaybeRefOrGetter<\n    UndefinedInitialDataInfiniteOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryKey,\n      TPageParam\n    >\n  >,\n  queryClient?: QueryClient,\n): UseInfiniteQueryReturnType<TData, TError>\n\nexport function useInfiniteQuery<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = InfiniteData<TQueryFnData>,\n  TQueryKey extends QueryKey = QueryKey,\n  TPageParam = unknown,\n>(\n  options: MaybeRefOrGetter<\n    UseInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>\n  >,\n  queryClient?: QueryClient,\n): UseInfiniteQueryReturnType<TData, TError>\n\nexport function useInfiniteQuery(\n  options: MaybeRefOrGetter<UseInfiniteQueryOptions>,\n  queryClient?: QueryClient,\n) {\n  return useBaseQuery(\n    InfiniteQueryObserver as typeof QueryObserver,\n    options,\n    queryClient,\n  )\n}\n"
  },
  {
    "path": "packages/vue-query/src/useIsFetching.ts",
    "content": "import { getCurrentScope, onScopeDispose, ref, watchEffect } from 'vue-demi'\nimport { useQueryClient } from './useQueryClient'\nimport { cloneDeepUnref } from './utils'\nimport type { Ref } from 'vue-demi'\nimport type { QueryFilters as QF } from '@tanstack/query-core'\nimport type { MaybeRefDeep } from './types'\nimport type { QueryClient } from './queryClient'\n\nexport type QueryFilters = MaybeRefDeep<QF> | (() => MaybeRefDeep<QF>)\n\nexport function useIsFetching(\n  fetchingFilters: QueryFilters = {},\n  queryClient?: QueryClient,\n): Ref<number> {\n  if (process.env.NODE_ENV === 'development') {\n    if (!getCurrentScope()) {\n      console.warn(\n        'vue-query composable like \"useQuery()\" should only be used inside a \"setup()\" function or a running effect scope. They might otherwise lead to memory leaks.',\n      )\n    }\n  }\n\n  const client = queryClient || useQueryClient()\n\n  const isFetching = ref()\n\n  const listener = () => {\n    const resolvedFilters =\n      typeof fetchingFilters === 'function'\n        ? fetchingFilters()\n        : fetchingFilters\n    isFetching.value = client.isFetching(cloneDeepUnref(resolvedFilters))\n  }\n\n  const unsubscribe = client.getQueryCache().subscribe(listener)\n\n  watchEffect(listener)\n\n  onScopeDispose(() => {\n    unsubscribe()\n  })\n\n  return isFetching\n}\n"
  },
  {
    "path": "packages/vue-query/src/useMutation.ts",
    "content": "import {\n  computed,\n  getCurrentScope,\n  onScopeDispose,\n  reactive,\n  readonly,\n  shallowReactive,\n  shallowReadonly,\n  toRefs,\n  watch,\n} from 'vue-demi'\nimport { MutationObserver, shouldThrowError } from '@tanstack/query-core'\nimport { cloneDeepUnref, updateState } from './utils'\nimport { useQueryClient } from './useQueryClient'\nimport type { ToRefs } from 'vue-demi'\nimport type {\n  DefaultError,\n  DistributiveOmit,\n  MutateFunction,\n  MutateOptions,\n  MutationObserverOptions,\n  MutationObserverResult,\n  OmitKeyof,\n} from '@tanstack/query-core'\nimport type { MaybeRefDeep, ShallowOption } from './types'\nimport type { QueryClient } from './queryClient'\n\ntype MutationResult<TData, TError, TVariables, TOnMutateResult> =\n  DistributiveOmit<\n    MutationObserverResult<TData, TError, TVariables, TOnMutateResult>,\n    'mutate' | 'reset'\n  >\n\ntype UseMutationOptionsBase<TData, TError, TVariables, TOnMutateResult> =\n  OmitKeyof<\n    MutationObserverOptions<TData, TError, TVariables, TOnMutateResult>,\n    '_defaulted'\n  > &\n    ShallowOption\n\nexport type UseMutationOptions<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> =\n  | MaybeRefDeep<\n      UseMutationOptionsBase<TData, TError, TVariables, TOnMutateResult>\n    >\n  | (() => MaybeRefDeep<\n      UseMutationOptionsBase<TData, TError, TVariables, TOnMutateResult>\n    >)\n\ntype MutateSyncFunction<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> = (\n  ...options: Parameters<\n    MutateFunction<TData, TError, TVariables, TOnMutateResult>\n  >\n) => void\n\nexport type UseMutationReturnType<\n  TData,\n  TError,\n  TVariables,\n  TOnMutateResult,\n  TResult = MutationResult<TData, TError, TVariables, TOnMutateResult>,\n> = ToRefs<Readonly<TResult>> & {\n  mutate: MutateSyncFunction<TData, TError, TVariables, TOnMutateResult>\n  mutateAsync: MutateFunction<TData, TError, TVariables, TOnMutateResult>\n  reset: MutationObserverResult<\n    TData,\n    TError,\n    TVariables,\n    TOnMutateResult\n  >['reset']\n}\n\nexport function useMutation<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n>(\n  mutationOptions: UseMutationOptions<\n    TData,\n    TError,\n    TVariables,\n    TOnMutateResult\n  >,\n  queryClient?: QueryClient,\n): UseMutationReturnType<TData, TError, TVariables, TOnMutateResult> {\n  if (process.env.NODE_ENV === 'development') {\n    if (!getCurrentScope()) {\n      console.warn(\n        'vue-query composable like \"useQuery()\" should only be used inside a \"setup()\" function or a running effect scope. They might otherwise lead to memory leaks.',\n      )\n    }\n  }\n\n  const client = queryClient || useQueryClient()\n  const options = computed(() => {\n    const resolvedOptions =\n      typeof mutationOptions === 'function'\n        ? mutationOptions()\n        : mutationOptions\n    return client.defaultMutationOptions(cloneDeepUnref(resolvedOptions))\n  })\n  const observer = new MutationObserver(client, options.value)\n  const state = options.value.shallow\n    ? shallowReactive(observer.getCurrentResult())\n    : reactive(observer.getCurrentResult())\n\n  const unsubscribe = observer.subscribe((result) => {\n    updateState(state, result)\n  })\n\n  const mutate = (\n    variables: TVariables,\n    mutateOptions?: MutateOptions<TData, TError, TVariables, TOnMutateResult>,\n  ) => {\n    observer.mutate(variables, mutateOptions).catch(() => {\n      // This is intentional\n    })\n  }\n\n  watch(options, () => {\n    observer.setOptions(options.value)\n  })\n\n  onScopeDispose(() => {\n    unsubscribe()\n  })\n\n  const readonlyState = options.value.shallow\n    ? shallowReadonly(state)\n    : readonly(state)\n\n  const resultRefs = toRefs(readonlyState) as ToRefs<\n    Readonly<MutationResult<TData, TError, TVariables, TOnMutateResult>>\n  >\n\n  watch(\n    () => state.error,\n    (error) => {\n      if (\n        error &&\n        shouldThrowError(options.value.throwOnError, [error as TError])\n      ) {\n        throw error\n      }\n    },\n  )\n\n  return {\n    ...resultRefs,\n    mutate,\n    mutateAsync: state.mutate,\n    reset: state.reset,\n  }\n}\n"
  },
  {
    "path": "packages/vue-query/src/useMutationState.ts",
    "content": "import {\n  computed,\n  getCurrentScope,\n  onScopeDispose,\n  shallowReadonly,\n  shallowRef,\n  watch,\n} from 'vue-demi'\nimport { useQueryClient } from './useQueryClient'\nimport { cloneDeepUnref } from './utils'\nimport type { Ref } from 'vue-demi'\nimport type {\n  MutationFilters as MF,\n  Mutation,\n  MutationState,\n} from '@tanstack/query-core'\nimport type { QueryClient } from './queryClient'\nimport type { MaybeRefDeep } from './types'\nimport type { MutationCache } from './mutationCache'\n\nexport type MutationFilters = MaybeRefDeep<MF>\n\nexport function useIsMutating(\n  filters: MutationFilters | (() => MutationFilters) = {},\n  queryClient?: QueryClient,\n): Ref<number> {\n  if (process.env.NODE_ENV === 'development') {\n    if (!getCurrentScope()) {\n      console.warn(\n        'vue-query composable like \"useQuery()\" should only be used inside a \"setup()\" function or a running effect scope. They might otherwise lead to memory leaks.',\n      )\n    }\n  }\n\n  const client = queryClient || useQueryClient()\n\n  const mutationState = useMutationState(\n    {\n      filters: computed(() => ({\n        ...cloneDeepUnref(typeof filters === 'function' ? filters() : filters),\n        status: 'pending' as const,\n      })),\n    },\n    client,\n  )\n  const length = computed(() => mutationState.value.length)\n\n  return length\n}\n\nexport type MutationStateOptions<TResult = MutationState> = {\n  filters?: MutationFilters\n  select?: (mutation: Mutation) => TResult\n}\n\nfunction getResult<TResult = MutationState>(\n  mutationCache: MutationCache,\n  options: MutationStateOptions<TResult>,\n): Array<TResult> {\n  return mutationCache\n    .findAll(options.filters)\n    .map(\n      (mutation): TResult =>\n        (options.select ? options.select(mutation) : mutation.state) as TResult,\n    )\n}\n\nexport function useMutationState<TResult = MutationState>(\n  options:\n    | MutationStateOptions<TResult>\n    | (() => MutationStateOptions<TResult>) = {},\n  queryClient?: QueryClient,\n): Readonly<Ref<Array<TResult>>> {\n  const resolvedOptions = computed(() => {\n    const newOptions = typeof options === 'function' ? options() : options\n    return {\n      filters: cloneDeepUnref(newOptions.filters),\n      select: newOptions.select,\n    }\n  })\n  const mutationCache = (queryClient || useQueryClient()).getMutationCache()\n  const state = shallowRef(getResult(mutationCache, resolvedOptions.value))\n  const unsubscribe = mutationCache.subscribe(() => {\n    state.value = getResult(mutationCache, resolvedOptions.value)\n  })\n\n  watch(resolvedOptions, () => {\n    state.value = getResult(mutationCache, resolvedOptions.value)\n  })\n\n  onScopeDispose(() => {\n    unsubscribe()\n  })\n\n  return shallowReadonly(state)\n}\n"
  },
  {
    "path": "packages/vue-query/src/useQueries.ts",
    "content": "import { QueriesObserver } from '@tanstack/query-core'\nimport {\n  computed,\n  getCurrentScope,\n  onScopeDispose,\n  readonly,\n  shallowReadonly,\n  shallowRef,\n  unref,\n  watch,\n} from 'vue-demi'\n\nimport { useQueryClient } from './useQueryClient'\nimport { cloneDeepUnref } from './utils'\nimport type { Ref } from 'vue-demi'\nimport type {\n  DefaultError,\n  DefinedQueryObserverResult,\n  QueriesObserverOptions,\n  QueryFunction,\n  QueryKey,\n  QueryObserverResult,\n  ThrowOnError,\n} from '@tanstack/query-core'\nimport type { UseQueryOptions } from './useQuery'\nimport type { QueryClient } from './queryClient'\nimport type { DeepUnwrapRef, MaybeRefDeep, ShallowOption } from './types'\n\n// This defines the `UseQueryOptions` that are accepted in `QueriesOptions` & `GetOptions`.\n// `placeholderData` function does not have a parameter\ntype UseQueryOptionsForUseQueries<\n  TQueryFnData = unknown,\n  TError = unknown,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = UseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>\n\n// Avoid TS depth-limit error in case of large array literal\ntype MAXIMUM_DEPTH = 20\n\n// Widen the type of the symbol to enable type inference even if skipToken is not immutable.\ntype SkipTokenForUseQueries = symbol\n\ntype GetUseQueryOptionsForUseQueries<T> =\n  // Part 1: if UseQueryOptions are already being sent through, then just return T\n  T extends UseQueryOptions\n    ? DeepUnwrapRef<T>\n    : // Part 2: responsible for applying explicit type parameter to function arguments, if object { queryFnData: TQueryFnData, error: TError, data: TData }\n      T extends {\n          queryFnData: infer TQueryFnData\n          error?: infer TError\n          data: infer TData\n        }\n      ? UseQueryOptionsForUseQueries<TQueryFnData, TError, TData>\n      : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n        ? UseQueryOptionsForUseQueries<TQueryFnData, TError>\n        : T extends { data: infer TData; error?: infer TError }\n          ? UseQueryOptionsForUseQueries<unknown, TError, TData>\n          : // Part 3: responsible for applying explicit type parameter to function arguments, if tuple [TQueryFnData, TError, TData]\n            T extends [infer TQueryFnData, infer TError, infer TData]\n            ? UseQueryOptionsForUseQueries<TQueryFnData, TError, TData>\n            : T extends [infer TQueryFnData, infer TError]\n              ? UseQueryOptionsForUseQueries<TQueryFnData, TError>\n              : T extends [infer TQueryFnData]\n                ? UseQueryOptionsForUseQueries<TQueryFnData>\n                : // Part 4: responsible for inferring and enforcing type if no explicit parameter was provided\n                  T extends {\n                      queryFn?:\n                        | QueryFunction<infer TQueryFnData, infer TQueryKey>\n                        | SkipTokenForUseQueries\n                      select?: (data: any) => infer TData\n                      throwOnError?: ThrowOnError<any, infer TError, any, any>\n                    }\n                  ? UseQueryOptionsForUseQueries<\n                      TQueryFnData,\n                      unknown extends TError ? DefaultError : TError,\n                      unknown extends TData ? TQueryFnData : TData,\n                      TQueryKey\n                    >\n                  : T extends {\n                        queryFn?:\n                          | QueryFunction<infer TQueryFnData, infer TQueryKey>\n                          | SkipTokenForUseQueries\n                        throwOnError?: ThrowOnError<any, infer TError, any, any>\n                      }\n                    ? UseQueryOptionsForUseQueries<\n                        TQueryFnData,\n                        TError,\n                        TQueryFnData,\n                        TQueryKey\n                      >\n                    : // Fallback\n                      UseQueryOptionsForUseQueries\n\n// A defined initialData setting should return a DefinedQueryObserverResult rather than QueryObserverResult\ntype GetDefinedOrUndefinedQueryResult<T, TData, TError = unknown> = T extends {\n  initialData?: infer TInitialData\n}\n  ? unknown extends TInitialData\n    ? QueryObserverResult<TData, TError>\n    : TInitialData extends TData\n      ? DefinedQueryObserverResult<TData, TError>\n      : TInitialData extends () => infer TInitialDataResult\n        ? unknown extends TInitialDataResult\n          ? QueryObserverResult<TData, TError>\n          : TInitialDataResult extends TData\n            ? DefinedQueryObserverResult<TData, TError>\n            : QueryObserverResult<TData, TError>\n        : QueryObserverResult<TData, TError>\n  : QueryObserverResult<TData, TError>\n\ntype GetUseQueryResult<T> =\n  // Part 1: if using UseQueryOptions then the types are already set\n  T extends UseQueryOptions<\n    infer TQueryFnData,\n    infer TError,\n    infer TData,\n    any,\n    any\n  >\n    ? GetDefinedOrUndefinedQueryResult<\n        T,\n        undefined extends TData ? TQueryFnData : TData,\n        unknown extends TError ? DefaultError : TError\n      >\n    : // Part 2: responsible for mapping explicit type parameter to function result, if object\n      T extends { queryFnData: any; error?: infer TError; data: infer TData }\n      ? GetDefinedOrUndefinedQueryResult<T, TData, TError>\n      : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n        ? GetDefinedOrUndefinedQueryResult<T, TQueryFnData, TError>\n        : T extends { data: infer TData; error?: infer TError }\n          ? GetDefinedOrUndefinedQueryResult<T, TData, TError>\n          : // Part 3: responsible for mapping explicit type parameter to function result, if tuple\n            T extends [any, infer TError, infer TData]\n            ? GetDefinedOrUndefinedQueryResult<T, TData, TError>\n            : T extends [infer TQueryFnData, infer TError]\n              ? GetDefinedOrUndefinedQueryResult<T, TQueryFnData, TError>\n              : T extends [infer TQueryFnData]\n                ? GetDefinedOrUndefinedQueryResult<T, TQueryFnData>\n                : // Part 4: responsible for mapping inferred type to results, if no explicit parameter was provided\n                  T extends {\n                      queryFn?:\n                        | QueryFunction<infer TQueryFnData, any>\n                        | SkipTokenForUseQueries\n                      select?: (data: any) => infer TData\n                      throwOnError?: ThrowOnError<any, infer TError, any, any>\n                    }\n                  ? GetDefinedOrUndefinedQueryResult<\n                      T,\n                      unknown extends TData ? TQueryFnData : TData,\n                      unknown extends TError ? DefaultError : TError\n                    >\n                  : T extends {\n                        queryFn?:\n                          | QueryFunction<infer TQueryFnData, any>\n                          | SkipTokenForUseQueries\n                        throwOnError?: ThrowOnError<any, infer TError, any, any>\n                      }\n                    ? GetDefinedOrUndefinedQueryResult<\n                        T,\n                        TQueryFnData,\n                        unknown extends TError ? DefaultError : TError\n                      >\n                    : // Fallback\n                      QueryObserverResult\n\n/**\n * UseQueriesOptions reducer recursively unwraps function arguments to infer/enforce type param\n */\nexport type UseQueriesOptions<\n  T extends Array<any>,\n  TResults extends Array<any> = [],\n  TDepth extends ReadonlyArray<number> = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n  ? Array<UseQueryOptionsForUseQueries>\n  : T extends []\n    ? []\n    : T extends [infer Head]\n      ? [...TResults, GetUseQueryOptionsForUseQueries<Head>]\n      : T extends [infer Head, ...infer Tails]\n        ? UseQueriesOptions<\n            [...Tails],\n            [...TResults, GetUseQueryOptionsForUseQueries<Head>],\n            [...TDepth, 1]\n          >\n        : ReadonlyArray<unknown> extends T\n          ? T\n          : // If T is *some* array but we couldn't assign unknown[] to it, then it must hold some known/homogenous type!\n            // use this to infer the param types in the case of Array.map() argument\n            T extends Array<\n                UseQueryOptionsForUseQueries<\n                  infer TQueryFnData,\n                  infer TError,\n                  infer TData,\n                  infer TQueryKey\n                >\n              >\n            ? Array<\n                UseQueryOptionsForUseQueries<\n                  TQueryFnData,\n                  TError,\n                  TData,\n                  TQueryKey\n                >\n              >\n            : // Fallback\n              Array<UseQueryOptionsForUseQueries>\n\n/**\n * UseQueriesResults reducer recursively maps type param to results\n */\nexport type UseQueriesResults<\n  T extends Array<any>,\n  TResults extends Array<any> = [],\n  TDepth extends ReadonlyArray<number> = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n  ? Array<QueryObserverResult>\n  : T extends []\n    ? []\n    : T extends [infer Head]\n      ? [...TResults, GetUseQueryResult<Head>]\n      : T extends [infer Head, ...infer Tails]\n        ? UseQueriesResults<\n            [...Tails],\n            [...TResults, GetUseQueryResult<Head>],\n            [...TDepth, 1]\n          >\n        : { [K in keyof T]: GetUseQueryResult<T[K]> }\n\ntype UseQueriesOptionsArg<T extends Array<any>> = readonly [\n  ...UseQueriesOptions<T>,\n]\n\nexport function useQueries<\n  T extends Array<any>,\n  TCombinedResult = UseQueriesResults<T>,\n>(\n  {\n    queries,\n    ...options\n  }: ShallowOption & {\n    queries:\n      | (() => MaybeRefDeep<UseQueriesOptionsArg<T>>)\n      | MaybeRefDeep<UseQueriesOptionsArg<T>>\n      | MaybeRefDeep<\n          readonly [\n            ...{ [K in keyof T]: GetUseQueryOptionsForUseQueries<T[K]> },\n          ]\n        >\n    combine?: (result: UseQueriesResults<T>) => TCombinedResult\n  },\n  queryClient?: QueryClient,\n): Readonly<Ref<TCombinedResult>> {\n  if (process.env.NODE_ENV === 'development') {\n    if (!getCurrentScope()) {\n      console.warn(\n        'vue-query composable like \"useQuery()\" should only be used inside a \"setup()\" function or a running effect scope. They might otherwise lead to memory leaks.',\n      )\n    }\n  }\n\n  const client = queryClient || useQueryClient()\n\n  const defaultedQueries = computed(() => {\n    const resolvedQueries =\n      typeof queries === 'function'\n        ? (queries as () => MaybeRefDeep<UseQueriesOptionsArg<T>>)()\n        : queries\n    // Only unref the top level array.\n    const queriesRaw = unref(resolvedQueries) as ReadonlyArray<any>\n\n    // Unref the rest for each element in the top level array.\n    return queriesRaw.map((queryOptions) => {\n      const clonedOptions = cloneDeepUnref(queryOptions)\n\n      if (typeof clonedOptions.enabled === 'function') {\n        clonedOptions.enabled = queryOptions.enabled()\n      }\n\n      const defaulted = client.defaultQueryOptions(clonedOptions)\n      defaulted._optimisticResults = client.isRestoring?.value\n        ? 'isRestoring'\n        : 'optimistic'\n\n      return defaulted\n    })\n  })\n\n  const observer = new QueriesObserver<TCombinedResult>(\n    client,\n    defaultedQueries.value,\n    options as QueriesObserverOptions<TCombinedResult>,\n  )\n\n  const getOptimisticResult = () => {\n    const [results, getCombinedResult] = observer.getOptimisticResult(\n      defaultedQueries.value,\n      (options as QueriesObserverOptions<TCombinedResult>).combine,\n    )\n\n    return getCombinedResult(\n      results.map((result, index) => {\n        return {\n          ...result,\n          refetch: async (...args: Array<any>) => {\n            const [{ [index]: query }] = observer.getOptimisticResult(\n              defaultedQueries.value,\n              (options as QueriesObserverOptions<TCombinedResult>).combine,\n            )\n\n            return query!.refetch(...args)\n          },\n        }\n      }),\n    )\n  }\n\n  const state = shallowRef(getOptimisticResult())\n\n  let unsubscribe = () => {\n    // noop\n  }\n\n  if (client.isRestoring) {\n    watch(\n      client.isRestoring,\n      (isRestoring) => {\n        if (!isRestoring) {\n          unsubscribe()\n          unsubscribe = observer.subscribe(() => {\n            state.value = getOptimisticResult()\n          })\n\n          state.value = getOptimisticResult()\n        }\n      },\n      { immediate: true },\n    )\n  }\n\n  watch(defaultedQueries, (queriesValue) => {\n    observer.setQueries(\n      queriesValue,\n      options as QueriesObserverOptions<TCombinedResult>,\n    )\n    state.value = getOptimisticResult()\n  })\n\n  onScopeDispose(() => {\n    unsubscribe()\n  })\n\n  return options.shallow\n    ? shallowReadonly(state)\n    : (readonly(state) as Readonly<Ref<TCombinedResult>>)\n}\n"
  },
  {
    "path": "packages/vue-query/src/useQuery.ts",
    "content": "import { QueryObserver } from '@tanstack/query-core'\nimport { useBaseQuery } from './useBaseQuery'\nimport type {\n  DefaultError,\n  DefinedQueryObserverResult,\n  Enabled,\n  InitialDataFunction,\n  NonUndefinedGuard,\n  QueryKey,\n  QueryObserverOptions,\n} from '@tanstack/query-core'\nimport type { UseBaseQueryReturnType } from './useBaseQuery'\nimport type {\n  DeepUnwrapRef,\n  MaybeRef,\n  MaybeRefDeep,\n  MaybeRefOrGetter,\n  ShallowOption,\n} from './types'\nimport type { QueryClient } from './queryClient'\n\nexport type UseQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = MaybeRef<\n  {\n    [Property in keyof QueryObserverOptions<\n      TQueryFnData,\n      TError,\n      TData,\n      TQueryData,\n      TQueryKey\n    >]: Property extends 'enabled'\n      ?\n          | MaybeRefOrGetter<boolean | undefined>\n          | (() => Enabled<\n              TQueryFnData,\n              TError,\n              TQueryData,\n              DeepUnwrapRef<TQueryKey>\n            >)\n      : MaybeRefDeep<\n          QueryObserverOptions<\n            TQueryFnData,\n            TError,\n            TData,\n            TQueryData,\n            DeepUnwrapRef<TQueryKey>\n          >[Property]\n        >\n  } & ShallowOption\n>\n\nexport type UndefinedInitialQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = UseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey> & {\n  initialData?:\n    | undefined\n    | InitialDataFunction<NonUndefinedGuard<TQueryFnData>>\n    | NonUndefinedGuard<TQueryFnData>\n}\n\nexport type DefinedInitialQueryOptions<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n> = UseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey> & {\n  initialData:\n    | NonUndefinedGuard<TQueryFnData>\n    | (() => NonUndefinedGuard<TQueryFnData>)\n}\n\nexport type UseQueryReturnType<TData, TError> = UseBaseQueryReturnType<\n  TData,\n  TError\n>\n\nexport type UseQueryDefinedReturnType<TData, TError> = UseBaseQueryReturnType<\n  TData,\n  TError,\n  DefinedQueryObserverResult<TData, TError>\n>\n\nexport function useQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: DefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  queryClient?: QueryClient,\n): UseQueryDefinedReturnType<TData, TError>\n\nexport function useQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: UndefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  queryClient?: QueryClient,\n): UseQueryReturnType<TData, TError>\n\nexport function useQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: MaybeRefOrGetter<\n    UseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>\n  >,\n  queryClient?: QueryClient,\n): UseQueryReturnType<TData, TError>\n\nexport function useQuery<\n  TQueryFnData,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: MaybeRefOrGetter<\n    UseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>\n  >,\n  queryClient?: QueryClient,\n):\n  | UseQueryReturnType<TData, TError>\n  | UseQueryDefinedReturnType<TData, TError> {\n  return useBaseQuery(QueryObserver, options, queryClient)\n}\n"
  },
  {
    "path": "packages/vue-query/src/useQueryClient.ts",
    "content": "import { hasInjectionContext, inject } from 'vue-demi'\n\nimport { getClientKey } from './utils'\nimport type { QueryClient } from './queryClient'\n\nexport function useQueryClient(id = ''): QueryClient {\n  // ensures that `inject()` can be used\n  if (!hasInjectionContext()) {\n    throw new Error(\n      'vue-query hooks can only be used inside setup() function or functions that support injection context.',\n    )\n  }\n\n  const key = getClientKey(id)\n  const queryClient = inject<QueryClient>(key)\n\n  if (!queryClient) {\n    throw new Error(\n      \"No 'queryClient' found in Vue context, use 'VueQueryPlugin' to properly initialize the library.\",\n    )\n  }\n\n  return queryClient\n}\n"
  },
  {
    "path": "packages/vue-query/src/utils.ts",
    "content": "import { isRef, unref } from 'vue-demi'\nimport type { MaybeRefDeep } from './types'\n\nexport const VUE_QUERY_CLIENT = 'VUE_QUERY_CLIENT'\n\nexport function getClientKey(key?: string) {\n  const suffix = key ? `:${key}` : ''\n  return `${VUE_QUERY_CLIENT}${suffix}`\n}\n\nexport function updateState(\n  state: Record<string, any>,\n  update: Record<string, any>,\n): void {\n  Object.keys(state).forEach((key) => {\n    state[key] = update[key]\n  })\n}\n\n// Helper function for cloning deep objects where\n// the level and key is provided to the callback function.\nfunction _cloneDeep<T>(\n  value: MaybeRefDeep<T>,\n  customize?: (\n    val: MaybeRefDeep<T>,\n    key: string,\n    level: number,\n  ) => T | undefined,\n  currentKey: string = '',\n  currentLevel: number = 0,\n): T {\n  if (customize) {\n    const result = customize(value, currentKey, currentLevel)\n    if (result === undefined && isRef(value)) {\n      return result as T\n    }\n    if (result !== undefined) {\n      return result\n    }\n  }\n\n  if (Array.isArray(value)) {\n    return value.map((val, index) =>\n      _cloneDeep(val, customize, String(index), currentLevel + 1),\n    ) as unknown as T\n  }\n\n  if (typeof value === 'object' && isPlainObject(value)) {\n    const entries = Object.entries(value).map(([key, val]) => [\n      key,\n      _cloneDeep(val, customize, key, currentLevel + 1),\n    ])\n    return Object.fromEntries(entries)\n  }\n\n  return value as T\n}\n\nexport function cloneDeep<T>(\n  value: MaybeRefDeep<T>,\n  customize?: (\n    val: MaybeRefDeep<T>,\n    key: string,\n    level: number,\n  ) => T | undefined,\n): T {\n  return _cloneDeep(value, customize)\n}\n\nexport function cloneDeepUnref<T>(\n  obj: MaybeRefDeep<T>,\n  unrefGetters = false,\n): T {\n  return cloneDeep(obj, (val, key, level) => {\n    // Check if we're at the top level and the key is 'queryKey'\n    //\n    // If so, take the recursive descent where we resolve\n    // getters to values as well as refs.\n    if (level === 1 && key === 'queryKey') {\n      return cloneDeepUnref(val, true)\n    }\n\n    // Resolve getters to values if specified.\n    if (unrefGetters && isFunction(val)) {\n      // Cast due to older TS versions not allowing calling\n      // on certain intersection types.\n      return cloneDeepUnref((val as Function)(), unrefGetters)\n    }\n\n    // Unref refs and continue to recurse into the value.\n    if (isRef(val)) {\n      return cloneDeepUnref(unref(val), unrefGetters)\n    }\n\n    return undefined\n  })\n}\n\n// eslint-disable-next-line @typescript-eslint/no-wrapper-object-types\nfunction isPlainObject(value: unknown): value is Object {\n  if (Object.prototype.toString.call(value) !== '[object Object]') {\n    return false\n  }\n\n  const prototype = Object.getPrototypeOf(value)\n  return prototype === null || prototype === Object.prototype\n}\n\nfunction isFunction(value: unknown): value is Function {\n  return typeof value === 'function'\n}\n"
  },
  {
    "path": "packages/vue-query/src/vueQueryPlugin.ts",
    "content": "import { isVue2 } from 'vue-demi'\nimport { isServer } from '@tanstack/query-core'\n\nimport { QueryClient } from './queryClient'\nimport { getClientKey } from './utils'\nimport { setupDevtools } from './devtools/devtools'\nimport type { QueryClientConfig } from './types'\n\ntype ClientPersister = (client: QueryClient) => [() => void, Promise<void>]\n\ninterface CommonOptions {\n  enableDevtoolsV6Plugin?: boolean\n  queryClientKey?: string\n  clientPersister?: ClientPersister\n  clientPersisterOnSuccess?: (client: QueryClient) => void\n}\n\ninterface ConfigOptions extends CommonOptions {\n  queryClientConfig?: QueryClientConfig\n}\n\ninterface ClientOptions extends CommonOptions {\n  queryClient?: QueryClient\n}\n\nexport type VueQueryPluginOptions = ConfigOptions | ClientOptions\n\nexport const VueQueryPlugin = {\n  install: (app: any, options: VueQueryPluginOptions = {}) => {\n    const clientKey = getClientKey(options.queryClientKey)\n    let client: QueryClient\n\n    if ('queryClient' in options && options.queryClient) {\n      client = options.queryClient\n    } else {\n      const clientConfig =\n        'queryClientConfig' in options ? options.queryClientConfig : undefined\n      client = new QueryClient(clientConfig)\n    }\n\n    if (!isServer) {\n      client.mount()\n    }\n\n    let persisterUnmount = () => {\n      // noop\n    }\n\n    if (options.clientPersister) {\n      if (client.isRestoring) {\n        client.isRestoring.value = true\n      }\n      const [unmount, promise] = options.clientPersister(client)\n      persisterUnmount = unmount\n      promise.then(() => {\n        if (client.isRestoring) {\n          client.isRestoring.value = false\n        }\n        options.clientPersisterOnSuccess?.(client)\n      })\n    }\n\n    const cleanup = () => {\n      client.unmount()\n      persisterUnmount()\n    }\n\n    if (app.onUnmount) {\n      app.onUnmount(cleanup)\n    } else {\n      const originalUnmount = app.unmount\n      app.unmount = function vueQueryUnmount() {\n        cleanup()\n        originalUnmount()\n      }\n    }\n\n    if (isVue2) {\n      app.mixin({\n        beforeCreate() {\n          // HACK: taken from provide(): https://github.com/vuejs/composition-api/blob/master/src/apis/inject.ts#L30\n          if (!this._provided) {\n            const provideCache = {}\n            Object.defineProperty(this, '_provided', {\n              get: () => provideCache,\n              set: (v) => Object.assign(provideCache, v),\n            })\n          }\n\n          this._provided[clientKey] = client\n\n          if (process.env.NODE_ENV === 'development') {\n            if (this === this.$root && options.enableDevtoolsV6Plugin) {\n              setupDevtools(this, client)\n            }\n          }\n        },\n      })\n    } else {\n      app.provide(clientKey, client)\n\n      if (process.env.NODE_ENV === 'development') {\n        if (options.enableDevtoolsV6Plugin) {\n          setupDevtools(app, client)\n        }\n      }\n    }\n  },\n}\n"
  },
  {
    "path": "packages/vue-query/test-setup.ts",
    "content": "import { vi } from 'vitest'\n\nvi.mock('vue-demi', async () => {\n  const vue = await vi.importActual('vue-demi')\n  return {\n    ...(vue as any),\n    inject: vi.fn(),\n    provide: vi.fn(),\n    onScopeDispose: vi.fn(),\n    getCurrentInstance: vi.fn(() => ({ proxy: {} })),\n    hasInjectionContext: vi.fn(() => true),\n  }\n})\n"
  },
  {
    "path": "packages/vue-query/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\"\n  },\n  \"include\": [\"src\", \"test-setup.ts\", \"*.config.*\", \"package.json\"],\n  \"references\": [{ \"path\": \"../query-core\" }]\n}\n"
  },
  {
    "path": "packages/vue-query/tsconfig.legacy.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts/legacy\"\n  },\n  \"include\": [\"src\"],\n  \"exclude\": [\"src/__mocks__\", \"src/__tests__\"],\n  \"references\": [{ \"path\": \"../query-core\" }]\n}\n"
  },
  {
    "path": "packages/vue-query/tsconfig.prod.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"incremental\": false,\n    \"composite\": false,\n    \"rootDir\": \"../../\"\n  }\n}\n"
  },
  {
    "path": "packages/vue-query/tsup.config.ts",
    "content": "import { defineConfig } from 'tsup'\nimport { legacyConfig, modernConfig } from './root.tsup.config.js'\n\nexport default defineConfig([\n  modernConfig({ entry: ['src/*.ts', 'src/devtools/*.ts'] }),\n  legacyConfig({ entry: ['src/*.ts', 'src/devtools/*.ts'] }),\n])\n"
  },
  {
    "path": "packages/vue-query/vite.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\nimport vue from '@vitejs/plugin-vue'\n\nimport packageJson from './package.json'\n\nexport default defineConfig({\n  plugins: [vue()],\n  // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660\n  resolve: {\n    conditions: ['@tanstack/custom-condition'],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        conditions: ['@tanstack/custom-condition'],\n      },\n    },\n  },\n  test: {\n    name: packageJson.name,\n    dir: './src',\n    watch: false,\n    environment: 'jsdom',\n    setupFiles: ['test-setup.ts'],\n    coverage: {\n      enabled: true,\n      provider: 'istanbul',\n      include: ['src/**/*'],\n      exclude: ['src/__tests__/**'],\n    },\n    typecheck: { enabled: true },\n    onConsoleLog: function (log) {\n      if (log.includes('Download the Vue Devtools extension')) {\n        return false\n      }\n      return undefined\n    },\n  },\n})\n"
  },
  {
    "path": "packages/vue-query-devtools/.attw.json",
    "content": "{\n  \"ignoreRules\": [\n    \"cjs-resolves-to-esm\",\n    \"internal-resolution-error\",\n    \"no-resolution\"\n  ]\n}\n"
  },
  {
    "path": "packages/vue-query-devtools/CHANGELOG.md",
    "content": "# @tanstack/vue-query-devtools\n\n## 6.1.5\n\n### Patch Changes\n\n- fix: style prop type ([#10087](https://github.com/TanStack/query/pull/10087))\n\n## 6.1.4\n\n### Patch Changes\n\n- Updated dependencies [[`83366c4`](https://github.com/TanStack/query/commit/83366c46a6825b5c591399c705d8128743c527dd)]:\n  - @tanstack/query-devtools@5.93.0\n\n## 6.1.3\n\n### Patch Changes\n\n- Updated dependencies [[`f9fc56a`](https://github.com/TanStack/query/commit/f9fc56a9b8724bcfae46f8f6cb229123478eb4db), [`0b29b6f`](https://github.com/TanStack/query/commit/0b29b6f877d4b3a6d05b1c85fb9cb1e6ea736291)]:\n  - @tanstack/query-devtools@5.92.0\n  - @tanstack/vue-query@5.92.3\n\n## 6.1.2\n\n### Patch Changes\n\n- Updated dependencies [[`758414f`](https://github.com/TanStack/query/commit/758414fcecb9b56142014edf3ff455c283fb556e)]:\n  - @tanstack/vue-query@5.92.0\n\n## 6.1.1\n\n### Patch Changes\n\n- Updated dependencies [[`b261b6f`](https://github.com/TanStack/query/commit/b261b6f29eee2a9bdbe1bc20035fe9b83b15376b)]:\n  - @tanstack/query-devtools@5.91.1\n\n## 6.1.0\n\n### Minor Changes\n\n- feat(devtools): allow passing a theme via prop ([#9887](https://github.com/TanStack/query/pull/9887))\n\n### Patch Changes\n\n- Updated dependencies [[`0e9d5b5`](https://github.com/TanStack/query/commit/0e9d5b565276f0de2a1a14ffbb079b5988581c27)]:\n  - @tanstack/query-devtools@5.91.0\n\n## 6.0.0\n\n### Patch Changes\n\n- Updated dependencies [[`b2bd79d`](https://github.com/TanStack/query/commit/b2bd79d0a6b2707461897c426b0d2275a3318e4b)]:\n  - @tanstack/vue-query@5.91.0\n\n## 5.91.0\n\n### Minor Changes\n\n- feat(vue-query-devtools): Add embedded panel mode ([#9790](https://github.com/TanStack/query/pull/9790))\n"
  },
  {
    "path": "packages/vue-query-devtools/eslint.config.js",
    "content": "// @ts-check\n\nimport pluginVue from 'eslint-plugin-vue'\nimport rootConfig from './root.eslint.config.js'\n\nexport default [...rootConfig, ...pluginVue.configs['flat/base']]\n"
  },
  {
    "path": "packages/vue-query-devtools/package.json",
    "content": "{\n  \"name\": \"@tanstack/vue-query-devtools\",\n  \"version\": \"6.1.5\",\n  \"description\": \"Developer tools to interact with and visualize the TanStack/vue-query cache\",\n  \"author\": \"tannerlinsley\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TanStack/query.git\",\n    \"directory\": \"packages/vue-query-devtools\"\n  },\n  \"homepage\": \"https://tanstack.com/query\",\n  \"funding\": {\n    \"type\": \"github\",\n    \"url\": \"https://github.com/sponsors/tannerlinsley\"\n  },\n  \"scripts\": {\n    \"clean\": \"premove ./build ./coverage ./dist-ts\",\n    \"compile\": \"vue-tsc --build\",\n    \"test:eslint\": \"eslint --concurrency=auto ./src\",\n    \"test:types\": \"vue-tsc --build\",\n    \"test:build\": \"publint --strict && attw --pack\",\n    \"build\": \"pnpm run compile && vite build\"\n  },\n  \"type\": \"module\",\n  \"types\": \"dist/esm/index.d.ts\",\n  \"module\": \"dist/esm/index.js\",\n  \"main\": \"dist/esm/index.js\",\n  \"exports\": {\n    \".\": {\n      \"@tanstack/custom-condition\": \"./src/index.ts\",\n      \"types\": \"./dist/esm/index.d.ts\",\n      \"default\": \"./dist/esm/index.js\"\n    },\n    \"./production\": {\n      \"@tanstack/custom-condition\": \"./src/production.ts\",\n      \"types\": \"./dist/esm/production.d.ts\",\n      \"default\": \"./dist/esm/production.js\"\n    },\n    \"./dist/production.js\": {\n      \"types\": \"./dist/esm/production.d.ts\",\n      \"default\": \"./dist/esm/production.js\"\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"sideEffects\": false,\n  \"files\": [\n    \"dist\",\n    \"src\",\n    \"!src/__tests__\"\n  ],\n  \"dependencies\": {\n    \"@tanstack/query-devtools\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"@tanstack/vue-query\": \"workspace:*\",\n    \"@vitejs/plugin-vue\": \"^5.2.4\",\n    \"eslint-plugin-vue\": \"^10.5.0\",\n    \"typescript\": \"5.8.3\",\n    \"vite\": \"^6.4.1\",\n    \"vue\": \"^3.4.27\",\n    \"vue-tsc\": \"^2.2.8\"\n  },\n  \"peerDependencies\": {\n    \"@tanstack/vue-query\": \"workspace:^\",\n    \"vue\": \"^3.3.0\"\n  }\n}\n"
  },
  {
    "path": "packages/vue-query-devtools/src/devtools.vue",
    "content": "<script setup lang=\"ts\">\nimport { onMounted, onScopeDispose, ref, watchEffect } from 'vue'\nimport { onlineManager, useQueryClient } from '@tanstack/vue-query'\nimport { TanstackQueryDevtools } from '@tanstack/query-devtools'\nimport type { DevtoolsOptions } from './types'\n\nconst props = defineProps<DevtoolsOptions>()\n\nconst div = ref<HTMLElement>()\nconst client = props.client || useQueryClient()\nconst devtools = new TanstackQueryDevtools({\n  client,\n  queryFlavor: 'Vue Query',\n  version: '5',\n  onlineManager,\n  buttonPosition: props.buttonPosition,\n  position: props.position,\n  initialIsOpen: props.initialIsOpen,\n  errorTypes: props.errorTypes,\n  styleNonce: props.styleNonce,\n  shadowDOMTarget: props.shadowDOMTarget,\n  hideDisabledQueries: props.hideDisabledQueries,\n  theme: props.theme,\n})\n\nwatchEffect(() => {\n  devtools.setButtonPosition(props.buttonPosition || 'bottom-right')\n  devtools.setPosition(props.position || 'bottom')\n  devtools.setInitialIsOpen(props.initialIsOpen)\n  devtools.setErrorTypes(props.errorTypes || [])\n  devtools.setTheme(props.theme || 'system')\n})\n\nonMounted(() => {\n  devtools.mount(div.value as HTMLElement)\n})\n\nonScopeDispose(() => {\n  devtools.unmount()\n})\n</script>\n\n<template>\n  <div className=\"tsqd-parent-container\" ref=\"div\"></div>\n</template>\n"
  },
  {
    "path": "packages/vue-query-devtools/src/devtoolsPanel.vue",
    "content": "<script setup lang=\"ts\">\nimport { computed, onMounted, onScopeDispose, ref, watchEffect } from 'vue'\nimport { onlineManager, useQueryClient } from '@tanstack/vue-query'\nimport { TanstackQueryDevtoolsPanel } from '@tanstack/query-devtools'\nimport type { DevtoolsPanelOptions } from './types'\n\nconst props = defineProps<DevtoolsPanelOptions>()\nconst style = computed<any>(() => {\n  return {\n    height: '500px',\n    ...props.style,\n  }\n})\n\nconst div = ref<HTMLElement>()\nconst client = props.client || useQueryClient()\nconst devtools = new TanstackQueryDevtoolsPanel({\n  client,\n  queryFlavor: 'Vue Query',\n  version: '5',\n  onlineManager,\n  buttonPosition: 'bottom-left',\n  position: 'bottom',\n  initialIsOpen: true,\n  errorTypes: props.errorTypes,\n  styleNonce: props.styleNonce,\n  shadowDOMTarget: props.shadowDOMTarget,\n  hideDisabledQueries: props.hideDisabledQueries,\n  onClose: props.onClose,\n  theme: props.theme,\n})\n\nwatchEffect(() => {\n  devtools.setOnClose(props.onClose ?? (() => {}))\n  devtools.setErrorTypes(props.errorTypes || [])\n  devtools.setTheme(props.theme)\n})\n\nonMounted(() => {\n  devtools.mount(div.value as HTMLElement)\n})\n\nonScopeDispose(() => {\n  devtools.unmount()\n})\n</script>\n\n<template>\n  <div :style=\"style\" className=\"tsqd-parent-container\" ref=\"div\"></div>\n</template>\n"
  },
  {
    "path": "packages/vue-query-devtools/src/index.ts",
    "content": "import devtools from './devtools.vue'\nimport devtoolsPanel from './devtoolsPanel.vue'\nimport type { DefineComponent } from 'vue'\nimport type { DevtoolsOptions, DevtoolsPanelOptions } from './types'\n\nexport const VueQueryDevtools = (\n  process.env.NODE_ENV !== 'development'\n    ? function () {\n        return null\n      }\n    : devtools\n) as DefineComponent<DevtoolsOptions, {}, unknown>\n\nexport const VueQueryDevtoolsPanel = (\n  process.env.NODE_ENV !== 'development'\n    ? function () {\n        return null\n      }\n    : devtoolsPanel\n) as DefineComponent<DevtoolsPanelOptions, {}, unknown>\n"
  },
  {
    "path": "packages/vue-query-devtools/src/production.ts",
    "content": "import devtools from './devtools.vue'\n\nexport default devtools\n"
  },
  {
    "path": "packages/vue-query-devtools/src/types.ts",
    "content": "import type {\n  DevtoolsButtonPosition,\n  DevtoolsErrorType,\n  DevtoolsPosition,\n  Theme,\n} from '@tanstack/query-devtools'\nimport type { QueryClient } from '@tanstack/vue-query'\n\nexport interface DevtoolsOptions {\n  /**\n   * Set this true if you want the dev tools to default to being open\n   */\n  initialIsOpen?: boolean\n  /**\n   * The position of the React Query logo to open and close the devtools panel.\n   * 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'\n   * Defaults to 'bottom-right'.\n   */\n  buttonPosition?: DevtoolsButtonPosition\n  /**\n   * The position of the React Query devtools panel.\n   * 'top' | 'bottom' | 'left' | 'right'\n   * Defaults to 'bottom'.\n   */\n  position?: DevtoolsPosition\n  /**\n   * Custom instance of QueryClient\n   */\n  client?: QueryClient\n  /**\n   * Use this so you can define custom errors that can be shown in the devtools.\n   */\n  errorTypes?: Array<DevtoolsErrorType>\n  /**\n   * 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.\n   */\n  styleNonce?: string\n  /**\n   * Use this so you can attach the devtool's styles to specific element in the DOM.\n   */\n  shadowDOMTarget?: ShadowRoot\n  /**\n   * Set this to true to hide disabled queries from the devtools panel.\n   */\n  hideDisabledQueries?: boolean\n  /**\n   * Set this to 'light', 'dark', or 'system' to change the theme of the devtools panel.\n   * Defaults to 'system'.\n   */\n  theme?: Theme\n}\n\nexport interface DevtoolsPanelOptions {\n  /**\n   * Custom instance of QueryClient\n   */\n  client?: QueryClient\n  /**\n   * Use this so you can define custom errors that can be shown in the devtools.\n   */\n  errorTypes?: Array<DevtoolsErrorType>\n  /**\n   * 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.\n   */\n  styleNonce?: string\n  /**\n   * Use this so you can attach the devtool's styles to specific element in the DOM.\n   */\n  shadowDOMTarget?: ShadowRoot\n\n  /**\n   * Custom styles for the devtools panel\n   * @default { height: '500px' }\n   * @example { height: '100%' }\n   * @example { height: '100%', width: '100%' }\n   */\n  style?: Partial<CSSStyleDeclaration>\n\n  /**\n   * Callback function that is called when the devtools panel is closed\n   */\n  onClose?: () => unknown\n  /**\n   * Set this to true to hide disabled queries from the devtools panel.\n   */\n  hideDisabledQueries?: boolean\n  /**\n   * Set this to 'light', 'dark', or 'system' to change the theme of the devtools panel.\n   * Defaults to 'system'.\n   */\n  theme?: Theme\n}\n"
  },
  {
    "path": "packages/vue-query-devtools/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist-ts\",\n    \"rootDir\": \".\"\n  },\n  \"include\": [\"src\", \"*.config.*\", \"package.json\"],\n  \"references\": [{ \"path\": \"../vue-query\" }, { \"path\": \"../query-devtools\" }]\n}\n"
  },
  {
    "path": "packages/vue-query-devtools/vite.config.ts",
    "content": "import { defineConfig, mergeConfig } from 'vite'\nimport vue from '@vitejs/plugin-vue'\nimport { tanstackViteConfig } from '@tanstack/vite-config'\n\nconst config = defineConfig({\n  plugins: [vue()],\n  // fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660\n  resolve: {\n    conditions: ['@tanstack/custom-condition'],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        conditions: ['@tanstack/custom-condition'],\n      },\n    },\n  },\n})\n\nexport default mergeConfig(\n  config,\n  tanstackViteConfig({\n    entry: ['src/index.ts', 'src/production.ts'],\n    srcDir: 'src',\n  }),\n)\n"
  },
  {
    "path": "pnpm-workspace.yaml",
    "content": "cleanupUnusedCatalogs: true\nlinkWorkspacePackages: true\npreferWorkspacePackages: true\n\npackages:\n  - 'packages/*'\n  - 'integrations/*'\n  - 'examples/angular/*'\n  - 'examples/react/*'\n  - 'examples/preact/*'\n  - 'examples/solid/*'\n  - 'examples/svelte/*'\n  - 'examples/vue/*'\n  - '!examples/vue/2*'\n  - '!examples/vue/nuxt*'\n"
  },
  {
    "path": "prettier.config.js",
    "content": "// @ts-check\n\n/** @type {import('prettier').Config} */\nconst config = {\n  semi: false,\n  singleQuote: true,\n  trailingComma: 'all',\n  plugins: ['prettier-plugin-svelte'],\n  overrides: [{ files: '*.svelte', options: { parser: 'svelte' } }],\n}\n\nexport default config\n"
  },
  {
    "path": "scripts/create-github-release.mjs",
    "content": "// @ts-nocheck\nimport fs from 'fs'\nimport path from 'node:path'\nimport { globSync } from 'node:fs'\nimport { execSync, execFileSync } from 'node:child_process'\nimport { tmpdir } from 'node:os'\n\nconst rootDir = path.join(import.meta.dirname, '..')\nconst ghToken = process.env.GH_TOKEN || process.env.GITHUB_TOKEN\n\n// Resolve GitHub usernames from commit author emails\nconst usernameCache = {}\nasync function resolveUsername(email) {\n  if (!ghToken || !email) return null\n  if (usernameCache[email] !== undefined) return usernameCache[email]\n\n  try {\n    const res = await fetch(`https://api.github.com/search/users?q=${email}`, {\n      headers: { Authorization: `token ${ghToken}` },\n    })\n    const data = await res.json()\n    const login = data?.items?.[0]?.login || null\n    usernameCache[email] = login\n    return login\n  } catch {\n    usernameCache[email] = null\n    return null\n  }\n}\n\n// Resolve author from a PR number via GitHub API\nconst prAuthorCache = {}\nasync function resolveAuthorForPR(prNumber) {\n  if (prAuthorCache[prNumber] !== undefined) return prAuthorCache[prNumber]\n\n  if (!ghToken) {\n    prAuthorCache[prNumber] = null\n    return null\n  }\n\n  try {\n    const res = await fetch(\n      `https://api.github.com/repos/TanStack/query/pulls/${prNumber}`,\n      { headers: { Authorization: `token ${ghToken}` } },\n    )\n    const data = await res.json()\n    const login = data?.user?.login || null\n    prAuthorCache[prNumber] = login\n    return login\n  } catch {\n    prAuthorCache[prNumber] = null\n    return null\n  }\n}\n\n// Get the previous release commit to diff against.\n// This script runs right after the \"ci: changeset release\" commit is pushed,\n// so HEAD is the release commit.\nconst releaseLogs = execSync(\n  'git log --oneline --grep=\"ci: changeset release\" --format=%H',\n)\n  .toString()\n  .trim()\n  .split('\\n')\n  .filter(Boolean)\n\nconst currentRelease = releaseLogs[0] || 'HEAD'\nconst previousRelease = releaseLogs[1]\n\n// Find packages that were actually bumped by comparing versions\nconst packagesDir = path.join(rootDir, 'packages')\nconst allPkgJsonPaths = globSync('*/package.json', { cwd: packagesDir })\n\nconst bumpedPackages = []\nfor (const relPath of allPkgJsonPaths) {\n  const fullPath = path.join(packagesDir, relPath)\n  const currentPkg = JSON.parse(fs.readFileSync(fullPath, 'utf-8'))\n  if (currentPkg.private) continue\n\n  // Get the version from the previous release commit\n  if (previousRelease) {\n    try {\n      const prevContent = execFileSync(\n        'git',\n        ['show', `${previousRelease}:packages/${relPath}`],\n        { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] },\n      )\n      const prevPkg = JSON.parse(prevContent)\n      if (prevPkg.version !== currentPkg.version) {\n        bumpedPackages.push({\n          name: currentPkg.name,\n          version: currentPkg.version,\n          prevVersion: prevPkg.version,\n          dir: path.dirname(relPath),\n        })\n      }\n    } catch {\n      // Package didn't exist in previous release — it's new\n      bumpedPackages.push({\n        name: currentPkg.name,\n        version: currentPkg.version,\n        prevVersion: null,\n        dir: path.dirname(relPath),\n      })\n    }\n  } else {\n    // No previous release — include all non-private packages\n    bumpedPackages.push({\n      name: currentPkg.name,\n      version: currentPkg.version,\n      prevVersion: null,\n      dir: path.dirname(relPath),\n    })\n  }\n}\n\nbumpedPackages.sort((a, b) => a.name.localeCompare(b.name))\n\n// Build changelog from git log between releases (conventional commits)\nconst rangeFrom = previousRelease || `${currentRelease}~1`\nconst rawLog = execSync(\n  `git log ${rangeFrom}..${currentRelease} --pretty=format:\"%h %ae %s\" --no-merges`,\n  { encoding: 'utf-8' },\n).trim()\n\nconst typeOrder = [\n  'breaking',\n  'feat',\n  'fix',\n  'perf',\n  'refactor',\n  'docs',\n  'chore',\n  'test',\n  'ci',\n]\nconst typeLabels = {\n  breaking: '⚠️ Breaking Changes',\n  feat: 'Features',\n  fix: 'Fix',\n  perf: 'Performance',\n  refactor: 'Refactor',\n  docs: 'Documentation',\n  chore: 'Chore',\n  test: 'Tests',\n  ci: 'CI',\n}\nconst typeIndex = (t) => {\n  const i = typeOrder.indexOf(t)\n  return i === -1 ? 99 : i\n}\n\nconst groups = {}\nconst commits = rawLog ? rawLog.split('\\n') : []\n\nfor (const line of commits) {\n  const match = line.match(/^(\\w+)\\s+(\\S+)\\s+(.*)$/)\n  if (!match) continue\n  const [, hash, email, subject] = match\n\n  // Skip release commits\n  if (subject.startsWith('ci: changeset release')) continue\n\n  // Parse conventional commit: type(scope)!: message\n  const conventionalMatch = subject.match(/^(\\w+)(?:\\(([^)]*)\\))?(!)?:\\s*(.*)$/)\n  const type = conventionalMatch ? conventionalMatch[1] : 'other'\n  const isBreaking = conventionalMatch ? !!conventionalMatch[3] : false\n  const scope = conventionalMatch ? conventionalMatch[2] || '' : ''\n  const message = conventionalMatch ? conventionalMatch[4] : subject\n\n  // Only include user-facing change types\n  if (!['feat', 'fix', 'perf', 'refactor', 'build', 'chore'].includes(type))\n    continue\n\n  // Extract PR number if present\n  const prMatch = message.match(/\\(#(\\d+)\\)/)\n  const prNumber = prMatch ? prMatch[1] : null\n\n  const bucket = isBreaking ? 'breaking' : type\n  if (!groups[bucket]) groups[bucket] = []\n  groups[bucket].push({ hash, email, scope, message, prNumber })\n}\n\n// Build markdown grouped by conventional commit type\nconst sortedTypes = Object.keys(groups).sort(\n  (a, b) => typeIndex(a) - typeIndex(b),\n)\n\nlet changelogMd = ''\nfor (const type of sortedTypes) {\n  const label = typeLabels[type] || type.charAt(0).toUpperCase() + type.slice(1)\n  changelogMd += `### ${label}\\n\\n`\n\n  for (const commit of groups[type]) {\n    const scopePrefix = commit.scope ? `${commit.scope}: ` : ''\n    const cleanMessage = commit.message.replace(/\\s*\\(#\\d+\\)/, '')\n    const prRef = commit.prNumber ? ` (#${commit.prNumber})` : ''\n    const username = commit.prNumber\n      ? await resolveAuthorForPR(commit.prNumber)\n      : await resolveUsername(commit.email)\n    const authorSuffix = username ? ` by @${username}` : ''\n\n    changelogMd += `- ${scopePrefix}${cleanMessage}${prRef} (${commit.hash})${authorSuffix}\\n`\n  }\n  changelogMd += '\\n'\n}\n\nif (!changelogMd.trim()) {\n  changelogMd = '- No changelog entries\\n\\n'\n}\n\nconst now = new Date()\nconst date = now.toISOString().slice(0, 10)\nconst time = now.toISOString().slice(11, 16).replace(':', '')\nconst tagName = `release-${date}-${time}`\nconst titleDate = `${date} ${now.toISOString().slice(11, 16)}`\n\nconst isPrerelease = process.argv.includes('--prerelease')\nconst isLatest = process.argv.includes('--latest')\n\nconst body = `Release ${titleDate}\n\n## Changes\n\n${changelogMd}\n## Packages\n\n${bumpedPackages.map((p) => `- ${p.name}@${p.version}`).join('\\n')}\n`\n\n// Create the release\n// Check if tag already exists — if so, try to create the release for it\n// (handles retries where the tag was pushed but release creation failed)\nlet tagExists = false\ntry {\n  execSync(`git rev-parse ${tagName}`, { stdio: 'ignore' })\n  tagExists = true\n} catch {\n  // Tag doesn't exist yet\n}\n\nif (!tagExists) {\n  execSync(`git tag -a -m \"${tagName}\" ${tagName}`)\n  execSync('git push --tags')\n}\n\nconst prereleaseFlag = isPrerelease ? '--prerelease' : ''\nconst latestFlag = isLatest ? ' --latest' : ''\nconst tmpFile = path.join(tmpdir(), `release-notes-${tagName}.md`)\nfs.writeFileSync(tmpFile, body)\n\ntry {\n  execSync(\n    `gh release create ${tagName} ${prereleaseFlag} --title \"Release ${titleDate}\" --notes-file ${tmpFile}${latestFlag}`,\n    { stdio: 'inherit' },\n  )\n  console.info(`GitHub release ${tagName} created.`)\n} catch (err) {\n  // Clean up the tag if we created it but release failed\n  if (!tagExists) {\n    console.info(`Release creation failed, cleaning up tag ${tagName}...`)\n    try {\n      execSync(`git push --delete origin ${tagName}`, { stdio: 'ignore' })\n      execSync(`git tag -d ${tagName}`, { stdio: 'ignore' })\n    } catch {\n      // Best effort cleanup\n    }\n  }\n  throw err\n} finally {\n  fs.unlinkSync(tmpFile)\n}\n"
  },
  {
    "path": "scripts/generate-docs.ts",
    "content": "import { resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { generateReferenceDocs } from '@tanstack/typedoc-config'\n\nconst __dirname = fileURLToPath(new URL('.', import.meta.url))\n\nawait generateReferenceDocs({\n  packages: [\n    {\n      name: 'angular-query-experimental',\n      entryPoints: [\n        resolve(\n          __dirname,\n          '../packages/angular-query-experimental/src/index.ts',\n        ),\n      ],\n      tsconfig: resolve(\n        __dirname,\n        '../packages/angular-query-experimental/tsconfig.json',\n      ),\n      outputDir: resolve(__dirname, '../docs/framework/angular/reference'),\n      exclude: ['./packages/query-core/**/*'],\n    },\n    {\n      name: 'svelte-query',\n      entryPoints: [\n        resolve(__dirname, '../packages/svelte-query/src/index.ts'),\n      ],\n      tsconfig: resolve(__dirname, '../packages/svelte-query/tsconfig.json'),\n      outputDir: resolve(__dirname, '../docs/framework/svelte/reference'),\n      exclude: ['./packages/query-core/**/*'],\n    },\n    {\n      name: 'preact-query',\n      entryPoints: [\n        resolve(__dirname, '../packages/preact-query/src/index.ts'),\n      ],\n      tsconfig: resolve(__dirname, '../packages/preact-query/tsconfig.json'),\n      outputDir: resolve(__dirname, '../docs/framework/preact/reference'),\n      exclude: ['./packages/query-core/**/*'],\n    },\n  ],\n})\n\nconsole.log('\\n✅ All markdown files have been processed!')\n\nprocess.exit(0)\n"
  },
  {
    "path": "scripts/generate-labeler-config.ts",
    "content": "import * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport * as prettier from 'prettier'\n\n/** Pairs of package labels and their corresponding paths */\ntype LabelerPair = [string, string]\n\nfunction readPairsFromFs(): Array<LabelerPair> {\n  const ignored = new Set(['.DS_Store'])\n\n  const pairs: Array<LabelerPair> = []\n\n  // Add subfolders in the packages folder, i.e. packages/**\n  fs.readdirSync(path.resolve('packages'))\n    .filter((folder) => !ignored.has(folder))\n    .forEach((folder) => {\n      // Check if package.json exists for the folder before adding it\n      if (\n        fs.existsSync(\n          path.resolve(path.join('packages', folder, 'package.json')),\n        )\n      ) {\n        pairs.push([`package: ${folder}`, `packages/${folder}/**/*`])\n      } else {\n        console.info(\n          `Skipping \\`${folder}\\` as it does not have a \\`package.json\\` file.`,\n        )\n      }\n    })\n\n  // Sort by package name in alphabetical order\n  pairs.sort((a, b) => a[0].localeCompare(b[0]))\n\n  return pairs\n}\n\nasync function generateLabelerYaml(pairs: Array<LabelerPair>): Promise<string> {\n  function s(n = 1) {\n    return ' '.repeat(n)\n  }\n\n  // Convert the pairs into valid yaml\n  const formattedPairs = pairs\n    .map(([packageLabel, packagePath]) => {\n      const result = [\n        `'${packageLabel}':`,\n        `${s(2)}-${s(1)}changed-files:`,\n        `${s(4)}-${s(1)}any-glob-to-any-file:${s(1)}'${packagePath}'`,\n      ].join('\\n')\n\n      return result\n    })\n    .join('\\n')\n\n  // Get the location of the Prettier config file\n  const prettierConfigPath = await prettier.resolveConfigFile()\n  if (!prettierConfigPath) {\n    throw new Error(\n      'No Prettier config file found. Please ensure you have a Prettier config file in your project.',\n    )\n  }\n  console.info('using prettier config file at:', prettierConfigPath)\n\n  // Resolve the Prettier config\n  const prettierConfig = await prettier.resolveConfig(prettierConfigPath)\n  console.info('using resolved prettier config:', prettierConfig)\n\n  // Format the YAML string using Prettier\n  const formattedStr = await prettier.format(formattedPairs, {\n    parser: 'yaml',\n    ...prettierConfig,\n  })\n\n  return formattedStr\n}\n\nasync function run() {\n  console.info('Generating labeler config...')\n\n  // Generate the pairs of package labels and their corresponding paths\n  const pairs = readPairsFromFs()\n\n  // Always add the docs folder\n  pairs.push(['documentation', 'docs/**/*'])\n\n  // Convert the pairs into valid yaml\n  const yamlStr = await generateLabelerYaml(pairs)\n\n  // Write to 'labeler-config.yml'\n  const configPath = path.resolve('labeler-config.yml')\n  fs.writeFileSync(configPath, yamlStr, {\n    encoding: 'utf-8',\n  })\n\n  console.info(`Generated labeler config at \\`${configPath}\\`!`)\n  return\n}\n\ntry {\n  run().then(() => {\n    process.exit(0)\n  })\n} catch (error) {\n  console.error('Error generating labeler config:', error)\n  process.exit(1)\n}\n"
  },
  {
    "path": "scripts/getTsupConfig.js",
    "content": "// @ts-check\n\nimport { esbuildPluginFilePathExtensions } from 'esbuild-plugin-file-path-extensions'\n\n/**\n * @param {Object} opts - Options for building configurations.\n * @param {string[]} opts.entry - The entry array.\n * @returns {import('tsup').Options}\n */\nexport function modernConfig(opts) {\n  return {\n    entry: opts.entry,\n    format: ['cjs', 'esm'],\n    target: ['chrome91', 'firefox90', 'edge91', 'safari15', 'ios15', 'opera77'],\n    outDir: 'build/modern',\n    experimentalDts: true,\n    sourcemap: true,\n    clean: true,\n    esbuildPlugins: [esbuildPluginFilePathExtensions({ esmExtension: 'js' })],\n  }\n}\n\n/**\n * @param {Object} opts - Options for building configurations.\n * @param {string[]} opts.entry - The entry array.\n * @returns {import('tsup').Options}\n */\nexport function legacyConfig(opts) {\n  return {\n    entry: opts.entry,\n    format: ['cjs', 'esm'],\n    target: ['es2020', 'node16'],\n    outDir: 'build/legacy',\n    experimentalDts: true,\n    sourcemap: true,\n    clean: true,\n    esbuildPlugins: [esbuildPluginFilePathExtensions({ esmExtension: 'js' })],\n  }\n}\n"
  },
  {
    "path": "scripts/getViteAliases.js",
    "content": "// @ts-check\n\nimport path from 'node:path'\nimport ts from 'typescript'\n\nconst tsconfig = ts.readConfigFile(\n  path.resolve(__dirname, '..', 'tsconfig.json'),\n  ts.sys.readFile,\n).config\n\nexport const dynamicAliases = Object.entries(\n  tsconfig.compilerOptions.paths || {},\n).reduce((aliases, [key, [value]]) => {\n  const aliasKey = key.replace('/*', '')\n  aliases[aliasKey] = path.resolve(value.replace('/*', ''))\n  return aliases\n}, /** @type {Record<string, string>} */ ({}))\n"
  },
  {
    "path": "scripts/tsconfig.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"include\": [\"**/*\"]\n}\n"
  },
  {
    "path": "scripts/verify-links.ts",
    "content": "import { existsSync, readFileSync, statSync } from 'node:fs'\nimport { extname, resolve } from 'node:path'\nimport { glob } from 'tinyglobby'\n// @ts-ignore Could not find a declaration file for module 'markdown-link-extractor'.\nimport markdownLinkExtractor from 'markdown-link-extractor'\n\nconst errors: Array<{\n  file: string\n  link: string\n  resolvedPath: string\n  reason: string\n}> = []\n\nfunction isRelativeLink(link: string) {\n  return (\n    !link.startsWith('/') &&\n    !link.startsWith('http://') &&\n    !link.startsWith('https://') &&\n    !link.startsWith('//') &&\n    !link.startsWith('#') &&\n    !link.startsWith('mailto:')\n  )\n}\n\n/** Remove any trailing .md */\nfunction stripExtension(p: string): string {\n  return p.replace(`${extname(p)}`, '')\n}\n\nfunction relativeLinkExists(link: string, file: string): boolean {\n  // Remove hash if present\n  const linkWithoutHash = link.split('#')[0]\n  // If the link is empty after removing hash, it's not a file\n  if (!linkWithoutHash) return false\n\n  // Strip the file/link extensions\n  const filePath = stripExtension(file)\n  const linkPath = stripExtension(linkWithoutHash)\n\n  // Resolve the path relative to the markdown file's directory\n  // Nav up a level to simulate how links are resolved on the web\n  let absPath = resolve(filePath, '..', linkPath)\n\n  // Ensure the resolved path is within /docs\n  const docsRoot = resolve('docs')\n  if (!absPath.startsWith(docsRoot)) {\n    errors.push({\n      link,\n      file,\n      resolvedPath: absPath,\n      reason: 'Path outside /docs',\n    })\n    return false\n  }\n\n  // Check if this is an example path\n  const isExample = absPath.includes('/examples/')\n\n  let exists = false\n\n  if (isExample) {\n    // Transform /docs/framework/{framework}/examples/ to /examples/{framework}/\n    absPath = absPath.replace(\n      /\\/docs\\/framework\\/([^/]+)\\/examples\\//,\n      '/examples/$1/',\n    )\n    // For examples, we want to check if the directory exists\n    exists = existsSync(absPath) && statSync(absPath).isDirectory()\n  } else {\n    // For non-examples, we want to check if the .md file exists\n    if (!absPath.endsWith('.md')) {\n      absPath = `${absPath}.md`\n    }\n    exists = existsSync(absPath)\n  }\n\n  if (!exists) {\n    errors.push({\n      link,\n      file,\n      resolvedPath: absPath,\n      reason: 'Not found',\n    })\n  }\n  return exists\n}\n\nasync function verifyMarkdownLinks() {\n  // Find all markdown files in docs directory\n  const markdownFiles = await glob('docs/**/*.md', {\n    ignore: ['**/node_modules/**'],\n  })\n\n  console.log(`Found ${markdownFiles.length} markdown files\\n`)\n\n  // Process each file\n  for (const file of markdownFiles) {\n    const content = readFileSync(file, 'utf-8')\n    const links: Array<string> = markdownLinkExtractor(content)\n\n    const relativeLinks = links.filter((link: string) => {\n      return isRelativeLink(link)\n    })\n\n    if (relativeLinks.length > 0) {\n      relativeLinks.forEach((link) => {\n        relativeLinkExists(link, file)\n      })\n    }\n  }\n\n  if (errors.length > 0) {\n    console.log(`\\n❌ Found ${errors.length} broken links:`)\n    errors.forEach((err) => {\n      console.log(\n        `${err.file}\\n  link:      ${err.link}\\n  resolved:  ${err.resolvedPath}\\n  why:       ${err.reason}\\n`,\n      )\n    })\n    process.exit(1)\n  } else {\n    console.log('\\n✅ No broken links found!')\n  }\n}\n\nverifyMarkdownLinks().catch(console.error)\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"$schema\": \"https://json.schemastore.org/tsconfig\",\n  \"compilerOptions\": {\n    \"allowJs\": true,\n    \"allowSyntheticDefaultImports\": true,\n    \"allowUnreachableCode\": false,\n    \"allowUnusedLabels\": false,\n    \"checkJs\": true,\n    \"composite\": true,\n    \"customConditions\": [\"@tanstack/custom-condition\"],\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"emitDeclarationOnly\": true,\n    \"esModuleInterop\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"incremental\": true,\n    \"isolatedModules\": true,\n    \"lib\": [\"DOM\", \"DOM.Iterable\", \"ES2022\"],\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"noEmit\": false,\n    \"noImplicitReturns\": true,\n    \"noUncheckedIndexedAccess\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"resolveJsonModule\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"target\": \"ES2020\",\n    \"types\": [\"node\"]\n  },\n  \"include\": [\"*.config.*\"]\n}\n"
  }
]