packages/shared was never a real pnpm workspace package (no package.json); it was referenced only through the @shared TypeScript path alias. Relocate it under src/ via git mv (143 files, detected as pure renames).
Repoint the @shared alias and include globs to src/shared across electron.vite.config.ts, tsconfig.{json,node,web}.json and vitest.config.ts; update scripts/check-custom-exts.ts, scripts/update-languages.ts, the eslint.config.mjs generated-file globs, the data-classify generator output targets, .github/CODEOWNERS path rules, and CLAUDE.md/docs/source-comment references.
The @shared alias name is unchanged, so all 1403 @shared/* import sites resolve without modification. Verified with typecheck:node, typecheck:web and the full test suite (700 files, 9739 tests passing).
5.0 KiB
Cache Schema Guide
How to add fixed and template keys. Aligned with Preference Schema Guide and Boot Config Schema Guide.
Schemas
| Schema | Tier | File | Default map |
|---|---|---|---|
UseCacheSchema |
Memory | src/shared/data/cache/cacheSchemas.ts |
DefaultUseCache |
SharedCacheSchema |
Shared | src/shared/data/cache/cacheSchemas.ts |
DefaultSharedCache |
RendererPersistCacheSchema |
Persist | src/shared/data/cache/cacheSchemas.ts |
DefaultRendererPersistCache |
Complex value types go in src/shared/data/cache/cacheValueTypes.ts and are imported via CacheValueTypes.*.
Naming Convention
Enforced by ESLint rule data-schema-key/valid-key. Pattern: /^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$/.
| Valid | Invalid | Why |
|---|---|---|
app.user.avatar |
userAvatar |
No dot separator |
chat.multi_select_mode |
chat.multiSelectMode |
No camelCase |
scroll.position.${topicId} |
scroll.position:${id} |
Colon not allowed |
entity.cache.${type}_${id} |
App.user |
No uppercase |
Template placeholders ${xxx} are treated as literal segments for the naming check. At runtime, the placeholder name is ignored — ${providerId} and ${foo} produce identical regex; each placeholder expands to [\w\-]+ (no dots, no colons, no non-ASCII).
Choosing Fixed / Template / Casual
| Fixed key | Template key | Casual (Memory only) | |
|---|---|---|---|
| Type inference | Automatic | Automatic | Manual generic |
| Compile-time validation | Yes | Yes | No |
| Dynamic segments | No | Yes | Yes |
| Shared tier | Yes | Yes | Not supported |
| Persist tier | Yes | Not supported | Not supported |
| Default value | Per key | Shared across instances | None |
Prefer Fixed > Template > Casual. Cross-window dynamic keys must be Template — there is no getSharedCasual.
Adding a Fixed Key
1. Add the entry
// src/shared/data/cache/cacheSchemas.ts
export type UseCacheSchema = {
// ...existing entries
'feature.my_feature.data': MyDataType
}
export const DefaultUseCache: UseCacheSchema = {
// ...existing defaults
'feature.my_feature.data': { items: [], lastUpdated: 0 }
}
2. Define complex value type (if needed)
// src/shared/data/cache/cacheValueTypes.ts
export interface MyDataType {
items: string[]
lastUpdated: number
}
3. Use it
const [data, setData] = useCache('feature.my_feature.data')
// data is MyDataType
Adding a Template Key
// cacheSchemas.ts
export type UseCacheSchema = {
'scroll.position.${topicId}': number
}
export const DefaultUseCache: UseCacheSchema = {
'scroll.position.${topicId}': 0 // shared by every concrete instance
}
Use with any string in the dynamic segment:
const [pos, setPos] = useCache(`scroll.position.${topicId}`)
// pos is number; default 0 for every topicId that hasn't been written yet
The placeholder name is documentation-only. ${topicId} and ${id} compile to the same runtime matcher. Pick a name that matches the concept (not convention).
Shared and Persist Variants
- Shared: add to
SharedCacheSchema/DefaultSharedCache. Fixed and template both supported. - Persist: add to
RendererPersistCacheSchema/DefaultRendererPersistCache. Fixed keys only. Persist values survive restart via localStorage — keep them small and typed.
Validation
| Check | Command / location |
|---|---|
| ESLint naming rule | pnpm lint (rule: data-schema-key/valid-key) |
| Template matching unit tests | src/shared/data/cache/__tests__/templateKey.test.ts |
| Schema exhaustiveness | TypeScript compiler — default map must satisfy the schema type |
See Also
- Cache Overview — design invariants, tier semantics
- Cache Usage — hooks, direct API, patterns