Standalone trackQuery / syncQuery operators, deprecate router.trackQuery method
- Dominant language
- TypeScript
- Stars
- 8
- Forks
- 2
- Avg merge
- 13h 44m
- Merged PRs (30d)
- 1
Description
### Problem
`trackQuery` is a method on `Router`/`RouterControls`, which is invisible to `effector/babel-plugin` / SWC plugin factories (`factories: ['@effector/router']`) — units created inside get no stable SIDs for SSR/devtools. Additionally, there is no primitive for two-way store↔query binding: atomic-router's `querySync` use case ("keep N stores in sync with N query keys, with cleanup") is not covered by the zod-based `trackQuery`, making migration painful.
### Proposed solution
Two top-level operators, single config field `router` accepting either a `Router` or `RouterControls`:
```ts
import { trackQuery, syncQuery } from '@effector/router';
const tracker = trackQuery({
router, // Router | RouterControls
parameters: z.object({ modal: z.literal('settings') }),
forRoutes: [settingsPage], // any routes, incl. virtual/group
check, // Event, optional
});
syncQuery({
router,
source: { page: $page, sort: $sort }, // query key -> Store
forRoutes: [listPage], // optional
clock, // Unit, optional; when to write to URL, default: source change
cleanup: { empty: true, irrelevant: false, preserve: [] }, // documented default
});
```
Key design change: `forRoutes` is implemented via `or(...forRoutes.map((r) => r.$isOpened))` (patronum) instead of `$activeRoutes`. This removes the Router/Controls asymmetry (no overloads needed), lets `forRoutes` accept pathless/virtual/group/chained routes and routes from nested routers, and is semantically more correct — a tracker should not "enter" while `beforeOpen` guards are pending or a chain was cancelled. `router.trackQuery`/`controls.trackQuery` methods stay as deprecated delegates in the same minor and are removed in the next major (user base is still tiny). Behavioral note for the changelog: with `forRoutes` the filter shifts from "path matched" to "route actually opened".
Related: #40 (read/write mapping fits `syncQuery` design), #35.
### Alternatives considered
Adding `$activeRoutes` to `RouterControls` for symmetry — rejected: controls are deliberately route-agnostic and shared between routers; aggregating routes there couples them to whoever happens to attach.
### Package
`@effector/router` (core)
Contributor guide
Research direction
Start by reading the existing Router and RouterControls trackQuery methods in the @effector/router core package, then review related issues #40 and #35 for the mapping and migration context. Done means the standalone trackQuery and syncQuery operators, Router/RouterControls delegates, route-opening behavior, cleanup defaults, and deprecation path are covered consistently.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- web-dev
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100