fd98616
/**
* Cache-key conventions for the local-first store (`@/shared/storage`).
*
* One key per (scope, payload): the key is the contract between a `useAsync`
* consumer, a hover `prefetch` and any mutation that invalidates — building
* them here keeps the three from drifting apart. Pure string arithmetic, no
* business logic, which is why this lives in shared.
*
* Scopes nest by prefix so `invalidateCache('space:foo:')` drops everything
* belonging to one space. Always invalidate with the trailing separator.
*
* The member list intentionally has three keys: three fetchers post-process
* the same endpoint into three different payload shapes (admin rows with
* limit 200, chat's flattened picker rows, the issue board's page object),
* and a shared key would serve one consumer another's shape.
*/
/* ---------------------------------------------------------- global identity */
export const meKey = () => 'me'
export const spacesKey = () => 'spaces'
export const dmsKey = () => 'dms'
/* ------------------------------------------------------- space-scoped lists */
export const spaceRoomsKey = (space: string) => `space:${space}:rooms`
export const spaceDirKey = (space: string) => `space:${space}:dir`
export const spaceReposKey = (space: string) => `space:${space}:repos`
/**
* The full name-sorted repo list behind the repo pickers (link a PR, …).
*
* Deliberately separate from `spaceReposKey`: the sidebar fetches 50 rows in
* default order, this one up to 100 in name order, and `useAsync` caches by key
* alone — one key for both would let whichever loaded first decide the other's
* ordering and truncation.
*/
export const spaceReposPickKey = (space: string) => `space:${space}:repos:pick`
export const spaceBoardsKey = (space: string) => `space:${space}:boards`
export const spaceAgentCollectionsKey = (space: string) => `space:${space}:agent-collections`
export const spaceEmojisKey = (space: string) => `space:${space}:emojis`
/** features/space-management rows (limit 200). */
export const spaceAdminMembersKey = (space: string) => `space:${space}:admin:members`
/** entities/chat flattened picker rows (limit 100). */
export const spaceMembersFlatKey = (space: string) => `space:${space}:members:flat`
/** entities/issue page object (limit 100). */
export const spaceMembersPageKey = (space: string) => `space:${space}:members:page`
/**
* Space settings/admin sections: `invites`, `groups`, `bans`, `join-rules`,
* `membership`, `images`, `settings`, `overwrites:{nodeId}`, …
*/
export const spaceAdminKey = (space: string, part: string) => `space:${space}:admin:${part}`
/**
* One uploaded space image (`banner`, `icon`, …) as a single `SpaceImage` row.
*
* Distinct from `spaceAdminKey(space, 'images')`, which caches the *record of
* all kinds* the settings section renders: sharing a key would serve one
* consumer the other's shape. The sidebar reads this key so a community banner
* is on screen from the first frame instead of arriving after a refetch.
*/
export const spaceImageKey = (space: string, kind: string) => `space:${space}:image:${kind}`
/** Whole-space invalidation prefix (note the trailing separator). */
export const spacePrefix = (space: string) => `space:${space}:`
/* --------------------------------------------------------------------- chat */
/** Room side data: `room`, `members`, `pins`, `threads`. */
export const roomKey = (roomId: string, part: string) => `room:${roomId}:${part}`
/** Transcript seed page of one scope (`threadId === null` is the main stream). */
export const chatSeedKey = (roomId: string, threadId: string | null) =>
`chat:${roomId}:${threadId ?? 'main'}:seed`
/* ------------------------------------------------------------------- issues */
/** Board payloads: `board`, `labels`, `milestones`, `issues:{queryKey}`. */
export const boardKey = (space: string, board: string, part: string) =>
`board:${space}/${board}:${part}`
/** Issue payloads: `detail`, `labels`, `comments`, `events`. */
export const issueKey = (space: string, board: string, issueId: string, part: string) =>
`issue:${space}/${board}/${issueId}:${part}`
/* -------------------------------------------------------------------- repos */
/**
* Repo payloads: `detail`, `tags`, `branches:{limit}`, `tree:{rev}:{path}`,
* `readme:{rev}:{path}`, `commits:…`, `diff:…`, `remotes`, `topics`,
* `insights:…`, `lfs-locks:…`.
*/
export const repoKey = (space: string, repo: string, part: string) =>
`repo:${space}/${repo}:${part}`
/* ------------------------------------------------------------ notifications */
/** `list:{filter}`, `unread`. */
export const notifyKey = (part: string) => `notify:${part}`
/* ----------------------------------------------------------- user settings */
/** `preferences`, `emails`, `sessions`, `totp`, `access-keys`, `ssh-keys`, `suspensions`. */
export const settingsKey = (part: string) => `settings:${part}`