feat: biblioteca inteligente libs/ + 5 novas skills (20 skills total)

NOVAS SKILLS:
- next-best-practices      v0.1.0  (CLEAN) — Next.js App Router, RSC, caching, data
- nextjs-patterns          v1.0.0  (CLEAN) — Next.js 15: Server Actions, route handlers
- vite                     v1.0.0  (CLEAN) — env vars, aliases, proxy, CJS compat
- uncle-bob                v1.0.0  (CLEAN) — Clean Code, SOLID, Clean Architecture
- clean-code-review        v1.0.0  (CLEAN) — naming, guard clauses, anti-patterns, refactoring
- vue                      v1.0.0  (CLEAN) — Vue framework
- vue-composition-api-best-practices v1.0.0 (CLEAN) — composables, Pinia, reactivity

BIBLIOTECA INTELIGENTE libs/ (10 dominios, 11 arquivos):
- typescript/ — TS safe + generics gotchas
- react/ — Next.js App Router + Vite config
- vue/ — Composition API + Pinia
- linux/ — System diagnostic cheatsheet
- database/ — PostgreSQL + MySQL patterns
- browser/ — Chromium CLI + E2E testing
- security/ — SAST audit (OWASP Top 10)
- best-practices/ — Clean Code + SOLID + Clean Architecture
- deploy/ — Docker multi-stack + OpenClaw ops
- + INDEX.md como guia de navegacao

.learnings/ — LRN-20260519-003 criado (biblioteca compartilhada)
This commit is contained in:
Pulse
2026-05-19 21:03:25 -03:00
parent 22d9f5b21d
commit ae39e45460
83 changed files with 13349 additions and 1 deletions
@@ -0,0 +1,164 @@
# Store Without 模式
## 问题
Pinia 的 `useStore()` 默认依赖 Vue 组件上下文(inject/provide)。在组件外(hooks、utils、plugins、路由守卫、axios 拦截器)直接调用会抛出错误:
```
Error: "getActivePinia()" was called but there was no active Pinia.
```
## 解决方案:Store Without 模式
每个 store 模块额外导出一个 `useXxxStoreWithOut` 函数,接收全局 pinia 实例作为参数,使 store 可在任意上下文中安全访问。
### 模式定义
```typescript
// store/modules/app.ts
import { defineStore } from 'pinia'
import { store } from '@/store'
export const useAppStore = defineStore('app', {
// ... store 定义
})
// 在组件外使用时,传入全局 pinia 实例
export const useAppStoreWithOut = () => {
return useAppStore(store)
}
```
### 全局 Pinia 实例
```typescript
// store/index.ts
import { createPinia } from 'pinia'
const pinia = createPinia()
export default pinia
// 导出 store 供 Without 函数使用
export const store = pinia
```
## 使用规则
### 何时使用哪个
| 函数 | 使用场景 | 原因 |
|------|---------|------|
| `useAppStore()` | Vue 组件 `<script setup>` 内 | 自动从组件上下文获取 pinia |
| `useAppStoreWithOut()` | hooks、utils、plugins、路由守卫等 | 组件上下文不可用,需显式传入 pinia |
### 在 Vue 组件中(始终使用标准方式)
```typescript
// ✅ GOOD:组件内使用标准方式
<script setup lang="ts">
import { useAppStore } from '@/store/modules/app'
const appStore = useAppStore()
</script>
```
```typescript
// ❌ BAD:组件内使用 WithOut 是多余的
<script setup lang="ts">
import { useAppStoreWithOut } from '@/store/modules/app'
const appStore = useAppStoreWithOut() // 可以工作但不必要
</script>
```
### 在 Hooks / Utils / Plugins 中(必须使用 WithOut
```typescript
// ✅ GOODhooks 中使用 WithOut
// hooks/web/useSideCategory.ts
import { useBusinessStoreWithOut } from '@/store/modules/business'
export function useSideCategory() {
const businessStore = useBusinessStoreWithOut()
const categories = computed(() => businessStore.getSideCategory)
return { categories }
}
```
```typescript
// ✅ GOODutils 中使用 WithOut
// utils/migration.ts
import { useBusinessStoreWithOut } from '@/store/modules/business'
export async function migrateOnlineIcons() {
const businessStore = useBusinessStoreWithOut()
// ...
}
```
```typescript
// ❌ BAD:组件外直接使用标准方式会报错
// utils/migration.ts
import { useBusinessStore } from '@/store/modules/business'
export async function migrateOnlineIcons() {
const businessStore = useBusinessStore() // Error: no active Pinia
}
```
## 命名规范
所有模块遵循统一命名规范:
| Store 模块 | 标准函数 | WithOut 函数 |
|-----------|---------|-------------|
| `app.ts` | `useAppStore` | `useAppStoreWithOut` |
| `business.ts` | `useBusinessStore` | `useBusinessStoreWithOut` |
| `dict.ts` | `useDictStore` | `useDictStoreWithOut` |
| `locale.ts` | `useLocaleStore` | `useLocaleStoreWithOut` |
**规则**`use{ModuleName}StoreWithOut` — 模块名首字母大写 + Store + WithOut(注意大小写)。
## 实现清单
每个 store 模块必须:
- [ ] 导出标准 `useXxxStore` 函数(`defineStore` 的返回值)
- [ ] 导出 `useXxxStoreWithOut` 函数,内部调用 `useXxxStore(store)`
- [ ]`@/store` 导入全局 `store` 实例
- [ ] WithOut 函数放在文件底部,紧跟标准函数之后
## 为什么不直接使用 `useXxxStore(pinia)`
理论上可以直接调用 `useAppStore(pinia)`,但 `WithOut` 函数提供了:
1. **语义明确** — 函数名直接表达"在组件外使用"的意图
2. **统一入口** — 不需要每个调用方都 import `store`,减少依赖
3. **集中管理** — 如果 pinia 实例获取方式变更,只需改 WithOut 函数
4. **可搜索** — 搜索 `WithOut` 即可找到所有组件外使用 store 的地方
## 替代方案:`storeToRefs` 注意事项
注意 `useXxxStoreWithOut()` 返回的是 store 实例,如需解构响应式属性,仍需使用 `storeToRefs`
```typescript
import { storeToRefs } from 'pinia'
import { useAppStoreWithOut } from '@/store/modules/app'
export function useAppInfo() {
const appStore = useAppStoreWithOut()
const { pure, theme } = storeToRefs(appStore) // 保持响应式
return { pure, theme }
}
```
## 总结
| 优势 | 说明 |
|------|------|
| 解决组件外访问 | 核心价值,让 store 可在任意上下文使用 |
| 命名约定清晰 | `WithOut` 后缀一目了然 |
| 减少样板代码 | 调用方无需 import store |
| 易于维护 | pinia 实例变更只需改一处 |
| 可追溯 | 搜索 `WithOut` 可定位所有组件外使用 |