snapshot of https://github.com/TanStack/query.git (main, 2026-09-16; blobs > 131072B omitted)
Some checks failed
autofix.ci / autofix (push) Failing after 4s
Release / Release (push) Has been skipped
GitHub Actions Security Analysis / Run zizmor (push) Failing after 2s

This commit is contained in:
upstream-mirror
2026-09-16 01:13:08 +05:00
commit 3a013ccdfe
3570 changed files with 490194 additions and 0 deletions

View File

@@ -0,0 +1,4 @@
{
"name": "Node.js",
"image": "mcr.microsoft.com/devcontainers/javascript-node:22"
}

View File

@@ -0,0 +1,6 @@
// @ts-check
/** @type {import('eslint').Linter.Config} */
const config = {}
module.exports = config

View File

@@ -0,0 +1,6 @@
# TanStack Query Angular basic example
To run this example:
- `pnpm install`
- `pnpm start`

View File

@@ -0,0 +1,130 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"cli": {
"packageManager": "pnpm",
"analytics": false,
"cache": {
"enabled": false
}
},
"newProjectRoot": "projects",
"projects": {
"basic": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"inlineTemplate": true,
"inlineStyle": true,
"skipTests": true
},
"@schematics/angular:class": {
"skipTests": true
},
"@schematics/angular:directive": {
"skipTests": true
},
"@schematics/angular:guard": {
"skipTests": true
},
"@schematics/angular:interceptor": {
"skipTests": true
},
"@schematics/angular:pipe": {
"skipTests": true
},
"@schematics/angular:resolver": {
"skipTests": true
},
"@schematics/angular:service": {
"skipTests": true
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular/build:application",
"options": {
"outputPath": "dist/basic",
"index": "src/index.html",
"browser": "src/main.ts",
"polyfills": ["zone.js"],
"tsConfig": "tsconfig.app.json",
"assets": ["src/favicon.ico", "src/assets"],
"styles": [],
"scripts": []
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular/build:dev-server",
"configurations": {
"production": {
"buildTarget": "basic:build:production"
},
"development": {
"buildTarget": "basic:build:development"
}
},
"defaultConfiguration": "development"
},
"extract-i18n": {
"builder": "@angular/build:extract-i18n",
"options": {
"buildTarget": "basic:build"
}
}
}
}
},
"schematics": {
"@schematics/angular:component": {
"type": "component"
},
"@schematics/angular:directive": {
"type": "directive"
},
"@schematics/angular:service": {
"type": "service"
},
"@schematics/angular:guard": {
"typeSeparator": "."
},
"@schematics/angular:interceptor": {
"typeSeparator": "."
},
"@schematics/angular:module": {
"typeSeparator": "."
},
"@schematics/angular:pipe": {
"typeSeparator": "."
},
"@schematics/angular:resolver": {
"typeSeparator": "."
}
}
}

View File

@@ -0,0 +1,27 @@
{
"name": "@tanstack/query-example-angular-basic",
"type": "module",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development"
},
"private": true,
"dependencies": {
"@angular/common": "^20.0.0",
"@angular/compiler": "^20.0.0",
"@angular/core": "^20.0.0",
"@angular/platform-browser": "^20.0.0",
"@tanstack/angular-query-experimental": "^5.102.8",
"rxjs": "^7.8.2",
"tslib": "^2.8.1",
"zone.js": "0.15.0"
},
"devDependencies": {
"@angular/build": "^20.0.0",
"@angular/cli": "^20.0.0",
"@angular/compiler-cli": "^20.0.0",
"typescript": "5.8.3"
}
}

View File

@@ -0,0 +1,15 @@
<p>
As you visit the posts below, you will notice them in a loading state the
first time you load them. However, after you return to this list and click on
any posts you have already visited again, you will see them load instantly and
background refresh right before your eyes!
<strong>
(You may need to throttle your network speed to simulate longer loading
sequences)
</strong>
</p>
@if (postId() > -1) {
<post [postId]="postId()" (setPostId)="postId.set($event)"></post>
} @else {
<posts (setPostId)="postId.set($event)" />
}

View File

@@ -0,0 +1,13 @@
import { ChangeDetectionStrategy, Component, signal } from '@angular/core'
import { PostComponent } from './components/post.component'
import { PostsComponent } from './components/posts.component'
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'basic-example',
templateUrl: './app.component.html',
imports: [PostComponent, PostsComponent],
})
export class BasicExampleComponent {
readonly postId = signal(-1)
}

View File

@@ -0,0 +1,23 @@
import { provideHttpClient, withFetch } from '@angular/common/http'
import {
QueryClient,
provideTanStackQuery,
} from '@tanstack/angular-query-experimental'
import { withDevtools } from '@tanstack/angular-query-experimental/devtools'
import type { ApplicationConfig } from '@angular/core'
export const appConfig: ApplicationConfig = {
providers: [
provideHttpClient(withFetch()),
provideTanStackQuery(
new QueryClient({
defaultOptions: {
queries: {
gcTime: 1000 * 60 * 60 * 24, // 24 hours
},
},
}),
withDevtools(),
),
],
}

View File

@@ -0,0 +1,19 @@
<div>
<div>
<a (click)="setPostId.emit(-1)" href="#"> Back </a>
</div>
@if (postQuery.isPending()) {
Loading...
} @else if (postQuery.isError()) {
Error: {{ postQuery.error().message }}
}
@if (postQuery.data(); as post) {
<h1>{{ post.title }}</h1>
<div>
<p>{{ post.body }}</p>
</div>
@if (postQuery.isFetching()) {
Background Updating...
}
}
</div>

View File

@@ -0,0 +1,34 @@
import {
ChangeDetectionStrategy,
Component,
inject,
input,
output,
} from '@angular/core'
import { injectQuery } from '@tanstack/angular-query-experimental'
import { fromEvent, lastValueFrom, takeUntil } from 'rxjs'
import { PostsService } from '../services/posts-service'
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'post',
templateUrl: './post.component.html',
})
export class PostComponent {
readonly #postsService = inject(PostsService)
readonly setPostId = output<number>()
readonly postId = input(0)
readonly postQuery = injectQuery(() => ({
enabled: this.postId() > 0,
queryKey: ['post', this.postId()],
queryFn: (context) => {
// Cancels the request when component is destroyed before the request finishes
const abort$ = fromEvent(context.signal, 'abort')
return lastValueFrom(
this.#postsService.postById$(this.postId()).pipe(takeUntil(abort$)),
)
},
}))
}

View File

@@ -0,0 +1,35 @@
<div>
<h1>Posts</h1>
@if (postsQuery.isPending()) {
Loading...
} @else if (postsQuery.isError()) {
Error: {{ postsQuery.error().message }}
} @else if (postsQuery.isSuccess()) {
<div class="todo-container">
@for (post of postsQuery.data(); track post.id) {
<p>
<!-- We can access the query data here to show bold links for-->
<!-- ones that are cached-->
<a
href="#"
(click)="setPostId.emit(post.id)"
[style]="
queryClient.getQueryData(['post', post.id])
? {
fontWeight: 'bold',
color: 'green',
}
: {}
"
>{{ post.title }}</a
>
</p>
}
</div>
}
<div>
@if (postsQuery.isFetching()) {
Background Updating...
}
</div>
</div>

View File

@@ -0,0 +1,25 @@
import {
ChangeDetectionStrategy,
Component,
inject,
output,
} from '@angular/core'
import { QueryClient, injectQuery } from '@tanstack/angular-query-experimental'
import { lastValueFrom } from 'rxjs'
import { PostsService } from '../services/posts-service'
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'posts',
templateUrl: './posts.component.html',
})
export class PostsComponent {
readonly queryClient = inject(QueryClient)
readonly #postsService = inject(PostsService)
readonly setPostId = output<number>()
readonly postsQuery = injectQuery(() => ({
queryKey: ['posts'],
queryFn: () => lastValueFrom(this.#postsService.allPosts$()),
}))
}

View File

@@ -0,0 +1,21 @@
import { HttpClient } from '@angular/common/http'
import { Injectable, inject } from '@angular/core'
@Injectable({
providedIn: 'root',
})
export class PostsService {
readonly #http = inject(HttpClient)
postById$ = (postId: number) =>
this.#http.get<Post>(`https://jsonplaceholder.typicode.com/posts/${postId}`)
allPosts$ = () =>
this.#http.get<Array<Post>>('https://jsonplaceholder.typicode.com/posts')
}
export interface Post {
id: number
title: string
body: string
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>TanStack Query Angular basic example</title>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
</head>
<body>
<basic-example></basic-example>
</body>
</html>

View File

@@ -0,0 +1,7 @@
import { bootstrapApplication } from '@angular/platform-browser'
import { appConfig } from './app/app.config'
import { BasicExampleComponent } from './app/app.component'
bootstrapApplication(BasicExampleComponent, appConfig).catch((err) =>
console.error(err),
)

View File

@@ -0,0 +1,9 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app",
"types": []
},
"files": ["src/main.ts"],
"include": ["src/**/*.d.ts"]
}

View File

@@ -0,0 +1,31 @@
{
"compileOnSave": false,
"compilerOptions": {
"outDir": "./dist/out-tsc",
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"skipLibCheck": true,
"isolatedModules": true,
"esModuleInterop": true,
"sourceMap": true,
"declaration": false,
"experimentalDecorators": true,
"moduleResolution": "Bundler",
"importHelpers": true,
"target": "ES2022",
"module": "ES2022",
"useDefineForClassFields": false,
"lib": ["ES2022", "dom"]
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": true,
"strictInputAccessModifiers": true,
"strictStandalone": true,
"strictTemplates": true
}
}