feat: Complete fleet — 94 skills across 10+ domains
Pulled ALL skills from 15 source repositories: - anthropics/skills: 16 (docs, design, MCP, testing) - obra/superpowers: 14 (TDD, debugging, agents, planning) - coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth) - better-auth/skills: 5 (auth patterns) - vercel-labs/agent-skills: 5 (React, design, Vercel) - antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo) - Plus 13 individual skills from various repos Mosaic Stack is not limited to coding — the Orchestrator and subagents serve coding, business, design, marketing, writing, logistics, analysis, and more. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
203
skills/pinia/references/features-plugins.md
Normal file
203
skills/pinia/references/features-plugins.md
Normal file
@@ -0,0 +1,203 @@
|
||||
---
|
||||
name: plugins
|
||||
description: Extend stores with custom properties, methods, and behavior
|
||||
---
|
||||
|
||||
# Plugins
|
||||
|
||||
Plugins extend all stores with custom properties, methods, or behavior.
|
||||
|
||||
## Basic Plugin
|
||||
|
||||
```ts
|
||||
import { createPinia } from 'pinia'
|
||||
|
||||
function SecretPiniaPlugin() {
|
||||
return { secret: 'the cake is a lie' }
|
||||
}
|
||||
|
||||
const pinia = createPinia()
|
||||
pinia.use(SecretPiniaPlugin)
|
||||
|
||||
// In any store
|
||||
const store = useStore()
|
||||
store.secret // 'the cake is a lie'
|
||||
```
|
||||
|
||||
## Plugin Context
|
||||
|
||||
Plugins receive a context object:
|
||||
|
||||
```ts
|
||||
import { PiniaPluginContext } from 'pinia'
|
||||
|
||||
export function myPiniaPlugin(context: PiniaPluginContext) {
|
||||
context.pinia // pinia instance
|
||||
context.app // Vue app instance
|
||||
context.store // store being augmented
|
||||
context.options // store definition options
|
||||
}
|
||||
```
|
||||
|
||||
## Adding Properties
|
||||
|
||||
Return an object to add properties (tracked in devtools):
|
||||
|
||||
```ts
|
||||
pinia.use(() => ({ hello: 'world' }))
|
||||
```
|
||||
|
||||
Or set directly on store:
|
||||
|
||||
```ts
|
||||
pinia.use(({ store }) => {
|
||||
store.hello = 'world'
|
||||
// For devtools visibility in dev mode
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
store._customProperties.add('hello')
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Adding State
|
||||
|
||||
Add to both `store` and `store.$state` for SSR/devtools:
|
||||
|
||||
```ts
|
||||
import { toRef, ref } from 'vue'
|
||||
|
||||
pinia.use(({ store }) => {
|
||||
if (!store.$state.hasOwnProperty('hasError')) {
|
||||
const hasError = ref(false)
|
||||
store.$state.hasError = hasError
|
||||
}
|
||||
store.hasError = toRef(store.$state, 'hasError')
|
||||
})
|
||||
```
|
||||
|
||||
## Adding External Properties
|
||||
|
||||
Wrap non-reactive objects with `markRaw()`:
|
||||
|
||||
```ts
|
||||
import { markRaw } from 'vue'
|
||||
import { router } from './router'
|
||||
|
||||
pinia.use(({ store }) => {
|
||||
store.router = markRaw(router)
|
||||
})
|
||||
```
|
||||
|
||||
## Custom Store Options
|
||||
|
||||
Define custom options consumed by plugins:
|
||||
|
||||
```ts
|
||||
// Store definition
|
||||
defineStore('search', {
|
||||
actions: {
|
||||
searchContacts() { /* ... */ },
|
||||
},
|
||||
debounce: {
|
||||
searchContacts: 300,
|
||||
},
|
||||
})
|
||||
|
||||
// Plugin reads custom option
|
||||
import debounce from 'lodash/debounce'
|
||||
|
||||
pinia.use(({ options, store }) => {
|
||||
if (options.debounce) {
|
||||
return Object.keys(options.debounce).reduce((acc, action) => {
|
||||
acc[action] = debounce(store[action], options.debounce[action])
|
||||
return acc
|
||||
}, {})
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
For Setup Stores, pass options as third argument:
|
||||
|
||||
```ts
|
||||
defineStore(
|
||||
'search',
|
||||
() => { /* ... */ },
|
||||
{
|
||||
debounce: { searchContacts: 300 },
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
## TypeScript Augmentation
|
||||
|
||||
### Custom Properties
|
||||
|
||||
```ts
|
||||
import 'pinia'
|
||||
import type { Router } from 'vue-router'
|
||||
|
||||
declare module 'pinia' {
|
||||
export interface PiniaCustomProperties {
|
||||
router: Router
|
||||
hello: string
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Custom State
|
||||
|
||||
```ts
|
||||
declare module 'pinia' {
|
||||
export interface PiniaCustomStateProperties<S> {
|
||||
hasError: boolean
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Custom Options
|
||||
|
||||
```ts
|
||||
declare module 'pinia' {
|
||||
export interface DefineStoreOptionsBase<S, Store> {
|
||||
debounce?: Partial<Record<keyof StoreActions<Store>, number>>
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Subscribe in Plugins
|
||||
|
||||
```ts
|
||||
pinia.use(({ store }) => {
|
||||
store.$subscribe(() => {
|
||||
// React to state changes
|
||||
})
|
||||
store.$onAction(() => {
|
||||
// React to actions
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Nuxt Plugin
|
||||
|
||||
Create a Nuxt plugin to add Pinia plugins:
|
||||
|
||||
```ts
|
||||
// plugins/myPiniaPlugin.ts
|
||||
import { PiniaPluginContext } from 'pinia'
|
||||
|
||||
function MyPiniaPlugin({ store }: PiniaPluginContext) {
|
||||
store.$subscribe((mutation) => {
|
||||
console.log(`[🍍 ${mutation.storeId}]: ${mutation.type}`)
|
||||
})
|
||||
return { creationTime: new Date() }
|
||||
}
|
||||
|
||||
export default defineNuxtPlugin(({ $pinia }) => {
|
||||
$pinia.use(MyPiniaPlugin)
|
||||
})
|
||||
```
|
||||
|
||||
<!--
|
||||
Source references:
|
||||
- https://pinia.vuejs.org/core-concepts/plugins.html
|
||||
-->
|
||||
Reference in New Issue
Block a user