From 10e567ebc66cc82343ad168df26d119c80d909df Mon Sep 17 00:00:00 2001 From: Stephen Zhou <38493346+hyoban@users.noreply.github.com> Date: Fri, 8 May 2026 17:08:55 +0800 Subject: [PATCH] tweaks --- .../skills/how-to-write-component/SKILL.md | 43 +++++-------------- 1 file changed, 10 insertions(+), 33 deletions(-) diff --git a/.agents/skills/how-to-write-component/SKILL.md b/.agents/skills/how-to-write-component/SKILL.md index 628dd31bd5..72a759e5e2 100644 --- a/.agents/skills/how-to-write-component/SKILL.md +++ b/.agents/skills/how-to-write-component/SKILL.md @@ -31,39 +31,16 @@ Follow existing project patterns first. Use these rules to resolve unclear compo ## Query And Mutation Contracts -- Keep `web/contract/*` as the single source of truth for API shape. -- Define contracts with `base.route({...}).output(type<...>())`. -- Add `.input(type<...>())` only when the request has `params`, `query`, or `body`. -- Keep contract input shaped as `{ params, query?, body? }`. -- For no-input `GET` routes, omit `.input(...)`; do not use `.input(type())`. -- Use `{paramName}` in route paths and match the same name in `params`. -- Register contracts in `web/contract/router.ts` by API prefix. -- Import contract modules directly from their domain files; do not add barrel files. -- Consume contract queries directly with `useQuery(consoleQuery.xxx.queryOptions(...))` or `useQuery(marketplaceQuery.xxx.queryOptions(...))`. -- Avoid wrapping `useQuery` and contract `queryOptions()` in pass-through hooks, such as `useAccessEnvironmentScope`. -- If three or more call sites share the same extra query options, extract a small `queryOptions` helper instead of a `use-*` hook. -- Keep feature hooks only when they orchestrate multiple operations, own workflow state, expose shared domain behavior, or normalize a feature-specific API. -- Treat `web/service/use-*` query and mutation wrappers as legacy migration targets. -- Do not create new thin `web/service/use-*` wrappers for oRPC contract calls. -- Inline existing wrappers when they only rename a single `queryOptions()` or `mutationOptions()` call. -- Avoid wrapper signatures such as `options?: Partial` because they degrade inference. -- Do not split `queryKey` and `queryFn` when oRPC `queryOptions()` already fits the use case. -- For missing required query input, pass `input: skipToken`. -- Use `enabled` only for extra business gating after the query input is already valid. -- Consume mutations with `useMutation(consoleQuery.xxx.mutationOptions(...))` or `useMutation(marketplaceQuery.xxx.mutationOptions(...))`. -- For heavily custom mutation flows, use oRPC clients as `mutationFn` instead of handwritten non-oRPC request logic. -- Put shared stale time, cache writes, and invalidation in `createTanstackQueryUtils(...experimental_defaults...)` when behavior belongs to a contract operation. -- Keep operation defaults in `web/service/client.ts` when they need sibling oRPC key builders. -- Keep multi-operation workflow orchestration in feature vertical hooks. -- Components may add UI feedback callbacks, but should not own shared cache invalidation decisions. -- Use `.key()` for namespace invalidation, refetch, and cancel patterns. -- Use `.queryKey(...)` for exact cache reads and writes. -- Use `.mutationKey(...)` for mutation defaults, mutation-status filtering, and devtools grouping. -- Invalidate with `queryClient.invalidateQueries(...)` in mutation `onSuccess`. -- Do not use deprecated `useInvalid` from `use-base.ts`. -- Prefer `mutate(...)` by default. -- Use `mutateAsync(...)` only when Promise semantics are required, such as sequential or parallel mutation flows. -- Wrap every `await mutateAsync(...)` in `try/catch`. +- Keep `web/contract/*` as the single source of truth for API shape; follow existing domain/router patterns and the `{ params, query?, body? }` input shape. +- Consume queries directly with `useQuery(consoleQuery.xxx.queryOptions(...))` or `useQuery(marketplaceQuery.xxx.queryOptions(...))`. +- Avoid pass-through hooks that only wrap `useQuery` and contract `queryOptions()`, such as `useAccessEnvironmentScope`. +- Do not create new thin `web/service/use-*` wrappers for oRPC contract calls; inline legacy wrappers when they only rename one `queryOptions()` or `mutationOptions()` call. +- Extract a small `queryOptions` helper only when repeated call-site options justify it; keep feature hooks for real orchestration, workflow state, or shared domain behavior. +- For missing required query input, use `input: skipToken`; use `enabled` only for extra business gating after the input is valid. +- Consume mutations directly with `useMutation(consoleQuery.xxx.mutationOptions(...))` or `useMutation(marketplaceQuery.xxx.mutationOptions(...))`; use oRPC clients as `mutationFn` only for custom flows. +- Put shared cache behavior in `createTanstackQueryUtils(...experimental_defaults...)`; components may add UI feedback callbacks, but should not own shared invalidation rules. +- Do not use deprecated `useInvalid` or `useReset`. +- Prefer `mutate(...)`; use `mutateAsync(...)` only when Promise semantics are required, and wrap awaited calls in `try/catch`. ## Component Boundaries