import type { QueryKey } from '@tanstack/query-core'; import { QueryApi } from '../query.api'; import type { ComposableStore } from './decorator'; /** A target for declarative refresh: either a QueryApi instance or a raw QueryKey. */ export type RefreshTarget = QueryApi | QueryKey; /** * Marker class for declarative refresh-on-mount behavior. * The `@queryStore` decorator auto-discovers instances, binds the store reference, * and calls `execute()` during initialize(). * * @example * ```typescript * @queryStore * class JobsStore extends Store { * jobs = query(() => ({ ... })); * * // Ensure fresh data from external store caches when this store mounts * refresh = refreshOnMount(['business-units', 'list'], ['techs', 'list']); * } * ``` */ export class RefreshOnMountDef { /** @internal Bound by `@queryStore` decorator during initialize(). */ composableStore?: ComposableStore; /** @internal Prevents duplicate execution in deep inheritance chains. */ private executed = false; constructor(private targets: RefreshTarget[]) {} /** @internal Called by the decorator during initialize(). Runs only once per instance. */ execute(): void { if (this.executed) { return; } this.executed = true; this.doInvalidate(); } /** Manually re-trigger the refresh. */ refresh(): void { this.doInvalidate(); } private doInvalidate(): void { const clientStore = this.composableStore?.queryClientStore; if (!clientStore) { // eslint-disable-next-line no-console console.error( 'RefreshOnMountDef: queryClientStore not found. Is the store decorated with @queryStore?' ); return; } for (const target of this.targets) { if (target instanceof QueryApi) { const key = target.queryKey; if (key) { clientStore.invalidate(key, { dedupe: true }); } } else { clientStore.invalidate(target as QueryKey, { dedupe: true }); } } } } /** * Declarative refresh-on-mount: creates a {@link RefreshOnMountDef} marker that the * `@queryStore` decorator picks up and executes during initialize(). * * Accepts any number of QueryApi instances and QueryKey arrays, comma-separated. * * @example QueryKey targets * ```typescript * refresh = refreshOnMount(['business-units', 'list'], ['techs', 'list']); * ``` */ export function refreshOnMount(...targets: RefreshTarget[]): RefreshOnMountDef { return new RefreshOnMountDef(targets); }