feat: add ESLint rule for schema key naming convention in cache and preference schemas

- Introduced a new ESLint rule to enforce a specific naming convention for schema keys: `namespace.sub.key_name`.
- Updated cache and preference schema files to include documentation on the naming convention and examples of valid/invalid keys.
- Modified existing keys in cache schemas to comply with the new convention.
This commit is contained in:
fullex 2025-11-26 12:50:38 +08:00
parent 9583c7c3d2
commit 0f8136705e
3 changed files with 99 additions and 4 deletions

View File

@ -157,4 +157,60 @@ export default defineConfig([
// ] // ]
} }
}, },
// Schema key naming convention (cache & preferences)
{
files: ['packages/shared/data/cache/cacheSchemas.ts', 'packages/shared/data/preference/preferenceSchemas.ts'],
plugins: {
'data-schema-key': {
rules: {
'valid-key': {
meta: {
type: 'problem',
docs: {
description: 'Enforce schema key naming convention: namespace.sub.key_name',
recommended: true
},
messages: {
invalidKey:
'Schema key "{{key}}" must follow format: namespace.sub.key_name (e.g., app.user.avatar).'
}
},
create(context) {
const VALID_KEY_PATTERN = /^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$/
return {
TSPropertySignature(node) {
if (node.key.type === 'Literal' && typeof node.key.value === 'string') {
const key = node.key.value
if (!VALID_KEY_PATTERN.test(key)) {
context.report({
node: node.key,
messageId: 'invalidKey',
data: { key }
})
}
}
},
Property(node) {
if (node.key.type === 'Literal' && typeof node.key.value === 'string') {
const key = node.key.value
if (!VALID_KEY_PATTERN.test(key)) {
context.report({
node: node.key,
messageId: 'invalidKey',
data: { key }
})
}
}
}
}
}
}
}
}
},
rules: {
'data-schema-key/valid-key': 'error'
}
}
]) ])

View File

@ -1,5 +1,27 @@
import type * as CacheValueTypes from './cacheValueTypes' import type * as CacheValueTypes from './cacheValueTypes'
/**
* Cache Schema Definitions
*
* ## Key Naming Convention
*
* All cache keys MUST follow the format: `namespace.sub.key_name`
*
* Rules:
* - At least 2 segments separated by dots (.)
* - Each segment uses lowercase letters, numbers, and underscores only
* - Pattern: /^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$/
*
* Examples:
* - 'app.user.avatar' (valid)
* - 'chat.multi_select_mode' (valid)
* - 'minapp.opened_keep_alive' (valid)
* - 'userAvatar' (invalid - missing dot separator)
* - 'App.user' (invalid - uppercase not allowed)
*
* This convention is enforced by ESLint rule: data-schema-key/valid-key
*/
/** /**
* Use cache schema for renderer hook * Use cache schema for renderer hook
*/ */
@ -63,11 +85,11 @@ export const DefaultUseCache: UseCacheSchema = {
* Use shared cache schema for renderer hook * Use shared cache schema for renderer hook
*/ */
export type UseSharedCacheSchema = { export type UseSharedCacheSchema = {
'example-key': string 'example_scope.example_key': string
} }
export const DefaultUseSharedCache: UseSharedCacheSchema = { export const DefaultUseSharedCache: UseSharedCacheSchema = {
'example-key': 'example default value' 'example_scope.example_key': 'example default value'
} }
/** /**
@ -75,11 +97,11 @@ export const DefaultUseSharedCache: UseSharedCacheSchema = {
* This ensures type safety and prevents key conflicts * This ensures type safety and prevents key conflicts
*/ */
export type RendererPersistCacheSchema = { export type RendererPersistCacheSchema = {
'example-key': string 'example_scope.example_key': string
} }
export const DefaultRendererPersistCache: RendererPersistCacheSchema = { export const DefaultRendererPersistCache: RendererPersistCacheSchema = {
'example-key': 'example default value' 'example_scope.example_key': 'example default value'
} }
/** /**

View File

@ -6,6 +6,23 @@
* To update this file, modify classification.json and run: * To update this file, modify classification.json and run:
* node .claude/data-classify/scripts/generate-preferences.js * node .claude/data-classify/scripts/generate-preferences.js
* *
* ## Key Naming Convention
*
* All preference keys MUST follow the format: `namespace.sub.key_name`
*
* Rules:
* - At least 2 segments separated by dots (.)
* - Each segment uses lowercase letters, numbers, and underscores only
* - Pattern: /^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$/
*
* Examples:
* - 'app.user.avatar' (valid)
* - 'chat.multi_select_mode' (valid)
* - 'userAvatar' (invalid - missing dot separator)
* - 'App.user' (invalid - uppercase not allowed)
*
* This convention is enforced by ESLint rule: data-schema-key/valid-key
*
* === AUTO-GENERATED CONTENT START === * === AUTO-GENERATED CONTENT START ===
*/ */