{"_id":"@ali7040/ng-signal-query","_rev":"2-3e07ce5ffb8932456b7478913121489b","name":"@ali7040/ng-signal-query","dist-tags":{"latest":"0.1.0"},"versions":{"0.0.2":{"name":"@ali7040/ng-signal-query","version":"0.0.2","_id":"@ali7040/ng-signal-query@0.0.2","maintainers":[{"name":"ng-signal-query","email":"ha4219466@gmail.com"}],"homepage":"https://github.com/ali7040/ng-signal-query#readme","bugs":{"url":"https://github.com/ali7040/ng-signal-query/issues"},"dist":{"shasum":"22041b7e3b99f680e055d82634833b71683ca258","tarball":"https://registry.npmjs.org/@ali7040/ng-signal-query/-/ng-signal-query-0.0.2.tgz","fileCount":6,"integrity":"sha512-CyezQDK5CvTclm6Is/fpz63rDVPZhJantuXynjPESDvdVNDXkR/i5qqHCeG+mXRuFqWaOVgpOTEI0RD4ejtsaw==","signatures":[{"sig":"MEUCIQDGXAlnmD/Vv/Io8xYad8VBXATcV8g05X9cIVswAe6VQwIgbnW6NSPqKlU1LdxRCaDNxEckttuohe1phhJyKesPlsM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":107542},"module":"fesm2022/ali7040-ng-signal-query.mjs","exports":{".":{"types":"./types/ali7040-ng-signal-query.d.ts","default":"./fesm2022/ali7040-ng-signal-query.mjs"},"./package.json":{"default":"./package.json"}},"gitHead":"b3b722f5e5f04286ff5fda7287247fa61e5047b5","typings":"types/ali7040-ng-signal-query.d.ts","_npmUser":{"name":"ng-signal-query","email":"ha4219466@gmail.com"},"repository":{"url":"git+https://github.com/ali7040/ng-signal-query.git","type":"git"},"_npmVersion":"11.6.1","description":"[![npm version](https://img.shields.io/npm/v/@ali7040/ng-signal-query?style=flat-square)](https://www.npmjs.com/package/@ali7040/ng-signal-query)\r [![Sponsor](https://img.shields.io/badge/Sponsor-%E2%9D%A4-lightpink?style=flat-square)](https://github.com/","directories":{},"sideEffects":false,"_nodeVersion":"24.10.0","dependencies":{"tslib":"^2.3.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"@angular/core":"^21.1.0","@angular/common":"^21.1.0"},"_npmOperationalInternal":{"tmp":"tmp/ng-signal-query_0.0.2_1774712787464_0.5201839393001946","host":"s3://npm-registry-packages-npm-production"}},"0.1.0":{"name":"@ali7040/ng-signal-query","version":"0.1.0","description":"Signal-native server state management for Angular — queries, mutations, infinite scroll, caching, and SSR hydration built on Angular signals.","keywords":["angular","signals","query","server-state","data-fetching","cache","caching","mutation","infinite-query","pagination","ssr","hydration","optimistic-updates","async","state-management","angular-signals","tanstack-query"],"author":{"name":"Ali Haider","url":"https://github.com/ali7040"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Ali7040/ng-signal-query.git"},"bugs":{"url":"https://github.com/Ali7040/ng-signal-query/issues"},"homepage":"https://github.com/Ali7040/ng-signal-query#readme","funding":{"type":"github","url":"https://github.com/sponsors/ali7040"},"publishConfig":{"access":"public"},"peerDependencies":{"@angular/common":"^21.1.0","@angular/core":"^21.1.0"},"dependencies":{"tslib":"^2.3.0"},"sideEffects":false,"module":"fesm2022/ali7040-ng-signal-query.mjs","typings":"types/ali7040-ng-signal-query.d.ts","exports":{"./package.json":{"default":"./package.json"},".":{"types":"./types/ali7040-ng-signal-query.d.ts","default":"./fesm2022/ali7040-ng-signal-query.mjs"}},"gitHead":"6bdb119e9d79a5c8b8e482570ac8f27819d2399e","_id":"@ali7040/ng-signal-query@0.1.0","_nodeVersion":"22.23.1","_npmVersion":"12.0.2","dist":{"integrity":"sha512-iimTv5HoaQbhOsWMSQsytLRKgVLs/0Er19YfQ2xVMuFPQP34IMYk5qT8K4nwQCF9Kl0cYm+rrteM/OGNGmN71g==","shasum":"df1051fc82b5b99c78fe28836d82bec233c3263c","tarball":"https://registry.npmjs.org/@ali7040/ng-signal-query/-/ng-signal-query-0.1.0.tgz","fileCount":6,"unpackedSize":135060,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ali7040%2fng-signal-query@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQC9GKlKXI9WZd/J0EMIBd+SGOoQNdZLhaX9lEi05LAHYAIgRz18I//7KMSOeXxb2t3kWEXnm/EHd2h//vsf0FK3o60="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:572849da-14d0-47d2-85ae-99e95e80c0de"}},"directories":{},"maintainers":[{"name":"ng-signal-query","email":"ha4219466@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ng-signal-query_0.1.0_1785583792695_0.4126343597082405"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-28T15:46:27.326Z","modified":"2026-08-01T11:29:53.181Z","0.0.2":"2026-03-28T15:46:27.601Z","0.1.0":"2026-08-01T11:29:52.848Z"},"bugs":{"url":"https://github.com/Ali7040/ng-signal-query/issues"},"homepage":"https://github.com/Ali7040/ng-signal-query#readme","repository":{"type":"git","url":"git+https://github.com/Ali7040/ng-signal-query.git"},"description":"Signal-native server state management for Angular — queries, mutations, infinite scroll, caching, and SSR hydration built on Angular signals.","maintainers":[{"name":"ng-signal-query","email":"ha4219466@gmail.com"}],"readme":"# 🎯 ng-signal-query\n\n[![npm version](https://img.shields.io/npm/v/@ali7040/ng-signal-query?style=flat-square)](https://www.npmjs.com/package/@ali7040/ng-signal-query)\n[![Sponsor](https://img.shields.io/badge/Sponsor-%E2%9D%A4-lightpink?style=flat-square)](https://github.com/sponsors/ali7040)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](./LICENSE)\n[![Angular](https://img.shields.io/badge/Angular-21.1.0-red.svg?style=flat-square)](https://angular.io/)\n[![TypeScript](https://img.shields.io/badge/TypeScript-5.9-blue.svg?style=flat-square)](https://www.typescriptlang.org/)\n\nA powerful, type-safe querying library for Angular applications built with signals. Manage server state, infinite queries, mutations, and caching with elegance and performance.\n\n## ✨ Features\n\n- 🚀 **Signal-Driven Architecture** - Leverage Angular signals for reactive state management\n- 🔄 **Server State Management** - Queries, mutations, and automatic caching\n- ∞ **Infinite Queries** - Seamless pagination with automatic data accumulation\n- 🎯 **Type-Safe** - Full TypeScript support with strict typing\n- 🛠️ **DevTools Integration** - Built-in debugging component for development\n- 📦 **Lightweight** - Minimal bundle size with zero external dependencies (except Angular & RxJS)\n- 🔌 **Adapter Pattern** - Custom adapters for different HTTP clients\n- 💾 **Smart Caching** - Automatic query result caching with configurable strategies\n- 🌐 **SSR Ready** - Server-side rendering support with hydration\n\n## 📦 Installation\n\n```bash\nnpm install @ali7040/ng-signal-query\n```\n\nOr with yarn:\n\n```bash\nyarn add @ali7040/ng-signal-query\n```\n\nOr with pnpm:\n\n```bash\npnpm add @ali7040/ng-signal-query\n```\n\n## 🐙 GitHub Packages\n\nYou can also publish/install this package from GitHub Packages.\n\n### Publish to GitHub Packages\n\n1. Create a GitHub Personal Access Token (classic) with:\n- `write:packages`\n- `read:packages`\n- `repo` (only if repository is private)\n\n2. Login to GitHub npm registry:\n\n```bash\nnpm login --scope=@ali7040 --auth-type=legacy --registry=https://npm.pkg.github.com\n```\n\n3. Publish:\n\n```bash\nnpm run release:github\n```\n\n### Install from GitHub Packages\n\n```bash\nnpm install @ali7040/ng-signal-query --registry=https://npm.pkg.github.com\n```\n\n### Requirements\n\n- Angular >= 21.1.0\n- TypeScript >= 5.9\n- RxJS >= 7.8\n\n## 🚀 Quick Start\n\n### 1. Import the Module\n\n```typescript\nimport { QueryClient } from '@ali7040/ng-signal-query';\n\n@Component({\n  selector: 'app-root',\n  template: `\n    <div *ngIf=\"users(); else loading\">\n      <div *ngFor=\"let user of users()\">{{ user.name }}</div>\n    </div>\n    <ng-template #loading>Loading...</ng-template>\n  `,\n  standalone: true,\n})\nexport class AppComponent {\n  private queryClient = inject(QueryClient);\n\n  users = this.queryClient.createQuery({\n    queryKey: ['users'],\n    queryFn: () => fetch('/api/users').then(r => r.json()),\n  });\n}\n```\n\n### 2. Create Queries\n\n```typescript\n// Simple query\nconst users = this.queryClient.createQuery({\n  queryKey: ['users'],\n  queryFn: () => this.http.get('/api/users'),\n  staleTime: 5 * 60 * 1000, // 5 minutes\n});\n\n// Parametized query\nconst user = signal('1');\nconst userDetails = this.queryClient.createSignalQuery({\n  queryKey: computed(() => ['user', user()]),\n  queryFn: async () => this.http.get(`/api/users/${user()}`),\n});\n```\n\n### 3. Create Mutations\n\n```typescript\nconst createUser = createMutation({\n  mutationFn: (data: User) => this.http.post('/api/users', data),\n  invalidateQueries: [['users']],\n  onSuccess: (data) => console.log('Created:', data),\n});\n\n// Use in template\n<button (click)=\"createUser.mutate({ name: 'John' })\">\n  {{ createUser.isLoading() ? 'Creating...' : 'Create User' }}\n</button>\n```\n\n### 3b. Mutation Concurrency Strategy\n\nControl how overlapping `mutate()` calls are handled — inspired by RxJS flattening operators:\n\n```typescript\nimport { createMutation } from '@ali7040/ng-signal-query';\n\n// Prevent duplicate form submissions\nconst submitForm = createMutation({\n  mutationFn: (form: FormData) => api.submit(form),\n  concurrencyStrategy: 'exhaust', // ignore clicks while submitting\n});\n\n// Auto-save: only keep the latest\nconst autoSave = createMutation({\n  mutationFn: (draft: Draft) => api.saveDraft(draft),\n  concurrencyStrategy: 'switch', // discard stale saves\n});\n\n// Ordered steps: execute one at a time\nconst processStep = createMutation({\n  mutationFn: (step: Step) => api.process(step),\n  concurrencyStrategy: 'concat', // queue in order\n});\n```\n\n| Strategy | RxJS equivalent | Behavior |\n|----------|-----------------|----------|\n| `merge` | `mergeMap` | Run all in parallel (default) |\n| `concat` | `concatMap` | Queue and run sequentially |\n| `switch` | `switchMap` | Discard previous, keep latest |\n| `exhaust` | `exhaustMap` | Ignore new while running |\n\n### 3c. Retry & Cancellation (opt-in)\n\nFetchers receive an `AbortSignal` so superseded requests are cancelled automatically:\n\n```typescript\nconst users = createQuery({\n  key: ['users'],\n  fetcher: ({ signal }) => fetch('/api/users', { signal }).then(r => r.json()),\n});\n```\n\nRetries are **opt-in** — by default a failed request reports its error immediately:\n\n```typescript\nconst users = createQuery({\n  key: ['users'],\n  fetcher: ({ signal }) => fetch('/api/users', { signal }).then(r => r.json()),\n  retry: 3,                          // default: 0 (no retries)\n  retryDelay: (attempt) => attempt * 1000, // default: 1s → 2s → 4s, max 30s\n});\n```\n\n`retry` also accepts a predicate for conditional retries:\n\n```typescript\nretry: (failureCount, error) => failureCount < 3 && !isAuthError(error),\n```\n\nQueries using the same key **share a single in-flight request**, so mounting several\ncomponents that read `['users']` performs one fetch.\n\n### 4. Infinite Queries\n\n```typescript\nconst infiniteUsers = this.queryClient.createInfiniteQuery({\n  queryKey: ['users', 'infinite'],\n  queryFn: ({ pageParam = 0 }) =>\n    this.http.get(`/api/users?page=${pageParam}`),\n  getNextPageParam: (lastPage) => lastPage.nextCursor,\n});\n\n// Load more\n<button (click)=\"infiniteUsers.fetchNextPage()\">\n  Load More\n</button>\n```\n\n## 📚 API Documentation\n\n### QueryClient\n\nMain service for managing all queries and mutations.\n\n```typescript\n// Create a query\ncreateQuery(options: CreateQueryOptions)\n\n// Create a signal-based query\ncreateSignalQuery(options: CreateSignalQuery)\n\n// Create an infinite query\ncreateInfiniteQuery(options: CreateInfiniteQueryOptions)\n\n// Create a mutation\ncreateMutation(options: CreateMutationOptions)\n\n// Invalidate queries\ninvalidateQueries(queryKey: QueryKey)\n\n// Refetch queries\nrefetchQueries(queryKey: QueryKey)\n\n// Clear all caches\nclearCache()\n```\n\n### Query State\n\n```typescript\ninterface QueryState {\n  data: TData | null;\n  error: Error | null;\n  status: 'pending' | 'error' | 'success';\n  isLoading: boolean;\n  isError: boolean;\n  isSuccess: boolean;\n}\n```\n\n### Mutation State\n\n```typescript\ntype MutationConcurrencyStrategy = 'merge' | 'concat' | 'switch' | 'exhaust';\n\ninterface MutationState<TData> {\n  data: TData | null;\n  error: unknown;\n  status: 'idle' | 'loading' | 'success' | 'error';\n}\n\ninterface MutationResult<TInput, TOutput> {\n  data: Signal<TOutput | null>;\n  error: Signal<unknown>;\n  status: Signal<MutationStatus>;\n  isLoading: Signal<boolean>;\n  mutate: (input: TInput) => Promise<void>;\n}\n```\n\n## 🔧 Development\n\n### Building\n\n```bash\nnpm run build\n```\n\n### Running Tests\n\n```bash\nnpm run test\n```\n\n### Running Examples\n\n```bash\nnpm run start\n```\n\nBrowse to `http://localhost:4200`\n\n## 🛠️ Examples\n\nCheck the [examples directory](./examples) for complete working examples:\n\n- [Simple Query Example](./examples/signal-query-example.component.ts)\n- [Infinite Query Example](./examples/infinite-query-example.component.ts)\n- [Create User Mutation](./examples/create-user.component.ts)\n- [DevTools Integration](./examples/devtools-example.component.ts)\n\n## 📖 DevTools\n\nMonitor your queries and mutations in real-time:\n\n```typescript\nimport { SignalQueryDevtoolsComponent } from '@ali7040/ng-signal-query';\n\n@Component({\n  selector: 'app-root',\n  template: `\n    <app-main></app-main>\n    <signal-query-devtools *ngIf=\"isDev\"></signal-query-devtools>\n  `,\n  imports: [SignalQueryDevtoolsComponent],\n})\nexport class AppComponent {\n  isDev = !environment.production;\n}\n```\n\n## 🚀 Live Testing\n\nTry the library in action:\n\n- **StackBlitz Demo**: [Coming Soon]\n- **CodeSandbox**: [Coming Soon]\n- **Documentation**: [https://github.com/ali7040/ng-signal-query](https://github.com/ali7040/ng-signal-query)\n\n## 🤝 Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](./CONTRIBUTING.md) for detailed instructions.\n\n## 📄 License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## 🙏 Acknowledgments\n\n- Built with [Angular 21.1](https://angular.io/)\n- Inspired by [TanStack Query](https://tanstack.com/query)\n- Type-safe with [TypeScript 5.9](https://www.typescriptlang.org/)\n\n## �️ Roadmap & Future Features\n\nWe're committed to evolving ng-signal-query to meet production-grade requirements. Here are planned features:\n\n### High Priority ⭐\n- ~~**MutationConcurrencyStrategy**~~ ✅ **Shipped!** Control mutation execution with `concurrencyStrategy: 'merge' | 'concat' | 'switch' | 'exhaust'`. See [DOCS.md](./DOCS.md) for details.\n  \n- **Better Error Handling** - Enhanced error boundaries and recovery patterns\n- **Advanced Cache Invalidation Strategies** - More granular control over cache lifecycle\n- **Offline Support** - Queue mutations while offline, sync when reconnected\n\n### Medium Priority 📋\n- **Request Deduplication** - Automatic duplicate request elimination within a time window\n- **Pause/Resume Queries** - Ability to pause and resume query execution\n- **Query Dependencies** - Automatic refetch when dependent query data changes\n- **Custom Retry Strategies** - Plugin system for complex retry logic\n\n### Community Feedback Welcome\nHave ideas? [Open an issue](https://github.com/ali7040/ng-signal-query/issues) or [submit a PR](./CONTRIBUTING.md)!\n\n## �📮 Support\n\n- 🐛 [Report Bugs](https://github.com/ali7040/ng-signal-query/issues)\n- 💡 [Request Features](https://github.com/ali7040/ng-signal-query/issues)\n- 📧 [Email Support](mailto:support@example.com)\n\n## ❤️ Sponsor\n\nIf you want to support this project, you can sponsor ongoing development:\n\n- [GitHub Sponsors](https://github.com/sponsors/ali7040)\n\n## 🔗 Useful Links\n\n- [NPM Package](https://www.npmjs.com/package/@ali7040/ng-signal-query)\n- [GitHub Repository](https://github.com/ali7040/ng-signal-query)\n- [Project Roadmap](./ROADMAP.md)\n- [Angular Documentation](https://angular.io/docs)\n- [RxJS Documentation](https://rxjs.dev/)\n\n---\n\n**Made with ❤️ by Ali**\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","readmeFilename":"README.md","keywords":["angular","signals","query","server-state","data-fetching","cache","caching","mutation","infinite-query","pagination","ssr","hydration","optimistic-updates","async","state-management","angular-signals","tanstack-query"],"author":{"name":"Ali Haider","url":"https://github.com/ali7040"},"license":"MIT"}