@blueking/bkui-knowledge 0.0.1-beta.1 → 0.0.1-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +166 -58
  2. package/bin/bkui-knowledge.js +147 -82
  3. package/knowledge/manifest.json +38 -1
  4. package/knowledge/skills/.template/README.md +1 -1
  5. package/knowledge/skills/bk-security-redlines/SKILL.md +47 -0
  6. package/knowledge/skills/bk-security-redlines/references/auth-check.md +73 -0
  7. package/knowledge/skills/bk-security-redlines/references/data-encryption.md +78 -0
  8. package/knowledge/skills/bk-security-redlines/references/input-validation.md +96 -0
  9. package/knowledge/skills/bk-skill-creator/SKILL.md +37 -0
  10. package/knowledge/skills/bk-skill-creator/references/common-mistakes.md +43 -0
  11. package/knowledge/skills/bk-skill-creator/references/quick-start.md +42 -0
  12. package/knowledge/skills/bk-skill-creator/references/skill-checklist.md +93 -0
  13. package/knowledge/skills/bk-skill-creator/references/structure-guide.md +88 -0
  14. package/knowledge/skills/bk-skill-creator/references/writing-tips.md +153 -0
  15. package/knowledge/skills/bkui-quick-start/SKILL.md +52 -0
  16. package/knowledge/skills/bkui-quick-start/references/components-list.md +17 -0
  17. package/knowledge/skills/bkui-quick-start/references/skills-index.md +26 -0
  18. package/knowledge/skills/external/vue-skills/LICENSE +21 -0
  19. package/knowledge/skills/external/vue-skills/README.md +69 -0
  20. package/knowledge/skills/external/vue-skills/skills/vue-best-practices/SKILL.md +42 -0
  21. package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/codeactions-save-performance.md +79 -0
  22. package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/data-attributes-config.md +74 -0
  23. package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/deep-watch-numeric.md +102 -0
  24. package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/define-model-update-event.md +79 -0
  25. package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/duplicate-plugin-detection.md +102 -0
  26. package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/fallthrough-attributes.md +63 -0
  27. package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/hmr-vue-ssr.md +124 -0
  28. package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/module-resolution-bundler.md +81 -0
  29. package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/pinia-store-mocking.md +159 -0
  30. package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/script-setup-jsdoc.md +85 -0
  31. package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/strict-css-modules.md +68 -0
  32. package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/unplugin-auto-import-conflicts.md +97 -0
  33. package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/volar-3-breaking-changes.md +66 -0
  34. package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/vue-directive-comments.md +73 -0
  35. package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/vue-router-typed-params.md +81 -0
  36. package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/vue-tsc-strict-templates.md +69 -0
  37. package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/with-defaults-union-types.md +102 -0
  38. package/knowledge/skills/web-security-guide/SKILL.md +48 -0
  39. package/knowledge/skills/web-security-guide/references/access-control.md +123 -0
  40. package/knowledge/skills/web-security-guide/references/auth-session.md +99 -0
  41. package/knowledge/skills/web-security-guide/references/csrf.md +59 -0
  42. package/knowledge/skills/web-security-guide/references/data-exposure.md +108 -0
  43. package/knowledge/skills/web-security-guide/references/deserialization.md +59 -0
  44. package/knowledge/skills/web-security-guide/references/injection.md +357 -0
  45. package/knowledge/skills/web-security-guide/references/logging-monitoring.md +47 -0
  46. package/knowledge/skills/web-security-guide/references/security-config.md +73 -0
  47. package/knowledge/skills/web-security-guide/references/ssrf.md +55 -0
  48. package/knowledge/skills/web-security-guide/references/xss.md +134 -0
  49. package/package.json +3 -3
  50. package/server/mcp-core.js +48 -33
@@ -0,0 +1,79 @@
1
+ ---
2
+ title: defineModel Fires Update Event with Undefined
3
+ impact: MEDIUM
4
+ impactDescription: fixes runtime errors from unexpected undefined in model updates
5
+ type: capability
6
+ tags: defineModel, v-model, update-event, undefined, vue-3.5
7
+ ---
8
+
9
+ # defineModel Fires Update Event with Undefined
10
+
11
+ **Impact: MEDIUM** - fixes runtime errors from unexpected undefined in model updates
12
+
13
+ > **Version Note (2025):** This issue may be resolved in Vue 3.5+. Testing with Vue 3.5.26 could not reproduce the double emission with `undefined`. If you're on Vue 3.5+, verify the issue exists in your specific scenario before applying workarounds.
14
+
15
+ Components using `defineModel` may fire the `@update:model-value` event with `undefined` in certain edge cases. TypeScript types don't always reflect this behavior, potentially causing runtime errors when the parent expects a non-nullable value.
16
+
17
+ ## Symptoms
18
+
19
+ - Parent component receives `undefined` unexpectedly
20
+ - Runtime error: "Cannot read property of undefined"
21
+ - Type mismatch between expected `T` and received `T | undefined`
22
+ - Issue appears when clearing/resetting the model value
23
+
24
+ ## Root Cause
25
+
26
+ `defineModel` returns `Ref<T | undefined>` by default, even when `T` is non-nullable. The update event can fire with `undefined` when:
27
+ - Component unmounts
28
+ - Model is explicitly cleared
29
+ - Internal state resets
30
+
31
+ ## Fix
32
+
33
+ **Option 1: Use required option (Vue 3.5+)**
34
+ ```typescript
35
+ // Returns Ref<Item> instead of Ref<Item | undefined>
36
+ const model = defineModel<Item>({ required: true })
37
+ ```
38
+
39
+ **Option 2: Type parent handler to accept undefined**
40
+ ```vue
41
+ <template>
42
+ <MyComponent
43
+ v-model="item"
44
+ @update:model-value="handleUpdate"
45
+ />
46
+ </template>
47
+
48
+ <script setup lang="ts">
49
+ // Handle both value and undefined
50
+ const handleUpdate = (value: Item | undefined) => {
51
+ if (value !== undefined) {
52
+ item.value = value
53
+ }
54
+ }
55
+ </script>
56
+ ```
57
+
58
+ **Option 3: Use default value in defineModel**
59
+ ```typescript
60
+ const model = defineModel<string>({ default: '' })
61
+ ```
62
+
63
+ ## Type Declaration Pattern
64
+
65
+ ```typescript
66
+ // In child component
67
+ interface Props {
68
+ modelValue: Item
69
+ }
70
+ const model = defineModel<Item>({ required: true })
71
+
72
+ // Emits will be typed as (value: Item) not (value: Item | undefined)
73
+ ```
74
+
75
+ ## Reference
76
+
77
+ - [vuejs/core#12817](https://github.com/vuejs/core/issues/12817)
78
+ - [vuejs/core#10103](https://github.com/vuejs/core/issues/10103)
79
+ - [defineModel docs](https://vuejs.org/api/sfc-script-setup.html#definemodel)
@@ -0,0 +1,102 @@
1
+ ---
2
+ title: Duplicate Vue Plugin Detection
3
+ impact: MEDIUM
4
+ impactDescription: fixes cryptic build errors from Vue plugin registered twice
5
+ type: capability
6
+ tags: vite, plugin, vue, duplicate, config, inline
7
+ ---
8
+
9
+ # Duplicate Vue Plugin Detection
10
+
11
+ **Impact: MEDIUM** - fixes cryptic build errors from Vue plugin registered twice
12
+
13
+ When using Vite's JavaScript API, if the Vue plugin is loaded in `vite.config.js` and specified again in `inlineConfig`, it gets registered twice, causing cryptic build errors.
14
+
15
+ ## Symptoms
16
+
17
+ - Build produces unexpected output or fails silently
18
+ - "Cannot read property of undefined" during build
19
+ - Different build behavior between CLI and JavaScript API
20
+ - Vue components render incorrectly after build
21
+
22
+ ## Root Cause
23
+
24
+ Vite doesn't deduplicate plugins by name when merging configs. The Vue plugin's internal state gets corrupted when registered twice.
25
+
26
+ ## Fix
27
+
28
+ **Option 1: Use configFile: false with inline plugins**
29
+ ```typescript
30
+ import { build } from 'vite'
31
+ import vue from '@vitejs/plugin-vue'
32
+
33
+ await build({
34
+ configFile: false, // Don't load vite.config.js
35
+ plugins: [vue()],
36
+ // ... rest of config
37
+ })
38
+ ```
39
+
40
+ **Option 2: Don't specify plugins in inlineConfig**
41
+ ```typescript
42
+ // vite.config.js already has vue plugin
43
+ import { build } from 'vite'
44
+
45
+ await build({
46
+ // Don't add vue plugin here - it's in vite.config.js
47
+ root: './src',
48
+ build: { outDir: '../dist' }
49
+ })
50
+ ```
51
+
52
+ **Option 3: Filter out Vue plugin before merging**
53
+ ```typescript
54
+ import { build, loadConfigFromFile } from 'vite'
55
+ import vue from '@vitejs/plugin-vue'
56
+
57
+ const { config } = await loadConfigFromFile({ command: 'build', mode: 'production' })
58
+
59
+ // Remove existing Vue plugin
60
+ const filteredPlugins = config.plugins?.filter(
61
+ p => !p || (Array.isArray(p) ? false : p.name !== 'vite:vue')
62
+ ) || []
63
+
64
+ await build({
65
+ ...config,
66
+ plugins: [...filteredPlugins, vue({ /* your options */ })]
67
+ })
68
+ ```
69
+
70
+ ## Detection Script
71
+
72
+ Add this to debug plugin registration:
73
+ ```typescript
74
+ // vite.config.ts
75
+ export default defineConfig({
76
+ plugins: [
77
+ vue(),
78
+ {
79
+ name: 'debug-plugins',
80
+ configResolved(config) {
81
+ const vuePlugins = config.plugins.filter(p => p.name?.includes('vue'))
82
+ if (vuePlugins.length > 1) {
83
+ console.warn('WARNING: Multiple Vue plugins detected:', vuePlugins.map(p => p.name))
84
+ }
85
+ }
86
+ }
87
+ ]
88
+ })
89
+ ```
90
+
91
+ ## Common Scenarios
92
+
93
+ | Scenario | Solution |
94
+ |----------|----------|
95
+ | Using `vite.createServer()` | Use `configFile: false` |
96
+ | Build script with custom config | Don't duplicate plugins |
97
+ | Monorepo with shared config | Check for plugin inheritance |
98
+
99
+ ## Reference
100
+
101
+ - [Vite Issue #5335](https://github.com/vitejs/vite/issues/5335)
102
+ - [Vite JavaScript API](https://vite.dev/guide/api-javascript.html)
@@ -0,0 +1,63 @@
1
+ ---
2
+ title: Enable Fallthrough Attributes Type Checking
3
+ impact: HIGH
4
+ impactDescription: enables type-safe fallthrough attributes in component libraries
5
+ type: capability
6
+ tags: fallthroughAttributes, vueCompilerOptions, component-library, wrapper-components
7
+ ---
8
+
9
+ # Enable Fallthrough Attributes Type Checking
10
+
11
+ **Impact: MEDIUM** - enables type-aware attribute forwarding in component libraries
12
+
13
+ When building component libraries with wrapper components, enable `fallthroughAttributes` to get IDE autocomplete for attributes that will be forwarded to child elements.
14
+
15
+ ## What It Does
16
+
17
+ Wrapper components that pass attributes to child elements can benefit from type-aware completion:
18
+
19
+ ```vue
20
+ <!-- MyButton.vue - wrapper around native button -->
21
+ <template>
22
+ <button v-bind="$attrs"><slot /></button>
23
+ </template>
24
+ ```
25
+
26
+ ## Solution
27
+
28
+ Enable `fallthroughAttributes` in your tsconfig:
29
+
30
+ ```json
31
+ // tsconfig.json or tsconfig.app.json
32
+ {
33
+ "vueCompilerOptions": {
34
+ "fallthroughAttributes": true
35
+ }
36
+ }
37
+ ```
38
+
39
+ ## How It Works
40
+
41
+ When `fallthroughAttributes: true`:
42
+ - Vue Language Server analyzes which element receives `$attrs`
43
+ - IDE autocomplete suggests valid attributes for the target element
44
+ - Helps developers discover available attributes
45
+
46
+ > **Note:** This primarily enables IDE autocomplete for valid fallthrough attributes. It does NOT reject invalid attributes as type errors - arbitrary attributes are still allowed.
47
+
48
+ ## Related Options
49
+
50
+ Combine with `strictTemplates` for comprehensive checking:
51
+
52
+ ```json
53
+ {
54
+ "vueCompilerOptions": {
55
+ "strictTemplates": true,
56
+ "fallthroughAttributes": true
57
+ }
58
+ }
59
+ ```
60
+
61
+ ## Reference
62
+
63
+ - [Vue Language Tools Wiki - Vue Compiler Options](https://github.com/vuejs/language-tools/wiki/Vue-Compiler-Options)
@@ -0,0 +1,124 @@
1
+ ---
2
+ title: HMR Debugging for Vue SSR
3
+ impact: MEDIUM
4
+ impactDescription: fixes Hot Module Replacement breaking in Vue SSR applications
5
+ type: efficiency
6
+ tags: vite, hmr, ssr, vue, hot-reload, server-side-rendering
7
+ ---
8
+
9
+ # HMR Debugging for Vue SSR
10
+
11
+ **Impact: MEDIUM** - fixes Hot Module Replacement breaking in Vue SSR applications
12
+
13
+ Hot Module Replacement breaks when modifying Vue component `<script setup>` sections in SSR applications. Changes cause errors instead of smooth updates, requiring full page reloads.
14
+
15
+ ## Symptoms
16
+
17
+ - HMR works for `<template>` changes but breaks for `<script setup>`
18
+ - "Cannot read property of undefined" after saving
19
+ - Full page reload required after script changes
20
+ - HMR works in dev:client but not dev:ssr
21
+
22
+ ## Root Cause
23
+
24
+ SSR mode has a different transformation pipeline. The Vue plugin's HMR boundary detection doesn't handle SSR modules the same way as client modules.
25
+
26
+ ## Fix
27
+
28
+ **Step 1: Ensure correct SSR plugin configuration**
29
+ ```typescript
30
+ // vite.config.ts
31
+ import { defineConfig } from 'vite'
32
+ import vue from '@vitejs/plugin-vue'
33
+
34
+ export default defineConfig({
35
+ plugins: [vue()],
36
+ ssr: {
37
+ // Don't externalize these for HMR to work
38
+ noExternal: ['vue', '@vue/runtime-core', '@vue/runtime-dom']
39
+ }
40
+ })
41
+ ```
42
+
43
+ **Step 2: Configure dev server for SSR HMR**
44
+ ```typescript
45
+ // server.ts
46
+ import { createServer } from 'vite'
47
+
48
+ const vite = await createServer({
49
+ server: { middlewareMode: true },
50
+ appType: 'custom'
51
+ })
52
+
53
+ // Use vite.ssrLoadModule for server-side imports
54
+ const { render } = await vite.ssrLoadModule('/src/entry-server.ts')
55
+
56
+ // Handle HMR
57
+ vite.watcher.on('change', async (file) => {
58
+ if (file.endsWith('.vue')) {
59
+ // Invalidate the module
60
+ const mod = vite.moduleGraph.getModuleById(file)
61
+ if (mod) {
62
+ vite.moduleGraph.invalidateModule(mod)
63
+ }
64
+ }
65
+ })
66
+ ```
67
+
68
+ **Step 3: Add HMR acceptance in entry-server**
69
+ ```typescript
70
+ // entry-server.ts
71
+ import { createApp } from './main'
72
+
73
+ export async function render(url: string) {
74
+ const app = createApp()
75
+ // ... render logic
76
+ }
77
+
78
+ // Accept HMR updates
79
+ if (import.meta.hot) {
80
+ import.meta.hot.accept()
81
+ }
82
+ ```
83
+
84
+ ## Framework-Specific Solutions
85
+
86
+ ### Nuxt 3
87
+ HMR should work out of the box. If not:
88
+ ```bash
89
+ rm -rf .nuxt node_modules/.vite
90
+ npm install
91
+ npm run dev
92
+ ```
93
+
94
+ ### Vite SSR Template
95
+ Ensure you're using the latest `@vitejs/plugin-vue`:
96
+ ```bash
97
+ npm install @vitejs/plugin-vue@latest
98
+ ```
99
+
100
+ ## Debugging
101
+
102
+ Enable verbose HMR logging:
103
+ ```typescript
104
+ // vite.config.ts
105
+ export default defineConfig({
106
+ server: {
107
+ hmr: {
108
+ overlay: true
109
+ }
110
+ },
111
+ logLevel: 'info' // Shows HMR updates
112
+ })
113
+ ```
114
+
115
+ ## Known Limitations
116
+
117
+ - HMR for `<script>` (not `<script setup>`) may require full reload
118
+ - SSR components with external dependencies may not hot-reload
119
+ - State is not preserved for SSR components (expected behavior)
120
+
121
+ ## Reference
122
+
123
+ - [vite-plugin-vue#525](https://github.com/vitejs/vite-plugin-vue/issues/525)
124
+ - [Vite SSR Guide](https://vite.dev/guide/ssr.html)
@@ -0,0 +1,81 @@
1
+ ---
2
+ title: moduleResolution Bundler Migration Issues
3
+ impact: HIGH
4
+ impactDescription: fixes "Cannot find module" errors after @vue/tsconfig upgrade
5
+ type: capability
6
+ tags: moduleResolution, bundler, tsconfig, vue-tsconfig, node, esm
7
+ ---
8
+
9
+ # moduleResolution Bundler Migration Issues
10
+
11
+ **Impact: HIGH** - fixes "Cannot find module" errors after @vue/tsconfig upgrade
12
+
13
+ Recent versions of `@vue/tsconfig` changed `moduleResolution` from `"node"` to `"bundler"`. This can break existing projects with errors like "Cannot find module 'vue'" or issues with `resolveJsonModule`.
14
+
15
+ ## Symptoms
16
+
17
+ - `Cannot find module 'vue'` or other packages
18
+ - `Option '--resolveJsonModule' cannot be specified without 'node' module resolution`
19
+ - Errors appear after updating `@vue/tsconfig`
20
+ - Some third-party packages no longer resolve
21
+
22
+ ## Root Cause
23
+
24
+ `moduleResolution: "bundler"` requires:
25
+ 1. TypeScript 5.0+
26
+ 2. Packages to have proper `exports` field in package.json
27
+ 3. Different resolution rules than Node.js classic resolution
28
+
29
+ ## Fix
30
+
31
+ **Option 1: Ensure TypeScript 5.0+ everywhere**
32
+ ```bash
33
+ npm install -D typescript@^5.0.0
34
+ ```
35
+
36
+ In monorepos, ALL packages must use TypeScript 5.0+.
37
+
38
+ **Option 2: Add compatibility workaround**
39
+ ```json
40
+ {
41
+ "compilerOptions": {
42
+ "module": "ESNext",
43
+ "moduleResolution": "bundler",
44
+ "resolvePackageJsonExports": false
45
+ }
46
+ }
47
+ ```
48
+
49
+ Setting `resolvePackageJsonExports: false` restores compatibility with packages that don't have proper exports.
50
+
51
+ **Option 3: Revert to Node resolution**
52
+ ```json
53
+ {
54
+ "compilerOptions": {
55
+ "moduleResolution": "node"
56
+ }
57
+ }
58
+ ```
59
+
60
+ ## Which Packages Break?
61
+
62
+ Packages break if they:
63
+ - Lack `exports` field in package.json
64
+ - Have incorrect `exports` configuration
65
+ - Rely on Node.js-specific resolution behavior
66
+
67
+ ## Diagnosis
68
+
69
+ ```bash
70
+ # Check which resolution is being used
71
+ cat tsconfig.json | grep moduleResolution
72
+
73
+ # Test if a specific module resolves
74
+ npx tsc --traceResolution 2>&1 | grep "module-name"
75
+ ```
76
+
77
+ ## Reference
78
+
79
+ - [vuejs/tsconfig#8](https://github.com/vuejs/tsconfig/issues/8)
80
+ - [TypeScript moduleResolution docs](https://www.typescriptlang.org/tsconfig#moduleResolution)
81
+ - [Vite discussion#14001](https://github.com/vitejs/vite/discussions/14001)
@@ -0,0 +1,159 @@
1
+ ---
2
+ title: Mocking Pinia Stores with Vitest
3
+ impact: HIGH
4
+ impactDescription: properly mocks Pinia stores in component tests
5
+ type: efficiency
6
+ tags: pinia, vitest, testing, mock, createTestingPinia, store
7
+ ---
8
+
9
+ # Mocking Pinia Stores with Vitest
10
+
11
+ **Impact: HIGH** - properly mocks Pinia stores in component tests
12
+
13
+ Developers struggle to properly mock Pinia stores: `createTestingPinia` requires explicit `createSpy` configuration, and "injection Symbol(pinia) not found" errors occur without proper setup.
14
+
15
+ > **Important (@pinia/testing 1.0+):** The `createSpy` option is **REQUIRED**, not optional. Omitting it throws an error: "You must configure the `createSpy` option."
16
+
17
+ ## Symptoms
18
+
19
+ - "injection Symbol(pinia) not found" error
20
+ - "You must configure the `createSpy` option" error
21
+ - Actions not properly mocked
22
+ - Store state not reset between tests
23
+
24
+ ## Fix
25
+
26
+ **Pattern 1: Basic setup with createTestingPinia**
27
+ ```typescript
28
+ import { mount } from '@vue/test-utils'
29
+ import { createTestingPinia } from '@pinia/testing'
30
+ import { vi } from 'vitest'
31
+ import MyComponent from './MyComponent.vue'
32
+ import { useCounterStore } from '@/stores/counter'
33
+
34
+ test('component uses store', async () => {
35
+ const wrapper = mount(MyComponent, {
36
+ global: {
37
+ plugins: [
38
+ createTestingPinia({
39
+ createSpy: vi.fn, // REQUIRED in @pinia/testing 1.0+
40
+ initialState: {
41
+ counter: { count: 10 } // Set initial state
42
+ }
43
+ })
44
+ ]
45
+ }
46
+ })
47
+
48
+ // Get the store instance AFTER mounting
49
+ const store = useCounterStore()
50
+
51
+ // Actions are automatically stubbed
52
+ await wrapper.find('button').trigger('click')
53
+ expect(store.increment).toHaveBeenCalled()
54
+ })
55
+ ```
56
+
57
+ **Pattern 2: Customize action behavior**
58
+ ```typescript
59
+ test('component handles async action', async () => {
60
+ const wrapper = mount(MyComponent, {
61
+ global: {
62
+ plugins: [
63
+ createTestingPinia({
64
+ createSpy: vi.fn,
65
+ stubActions: false // Don't stub, use real actions
66
+ })
67
+ ]
68
+ }
69
+ })
70
+
71
+ const store = useCounterStore()
72
+
73
+ // Override specific action
74
+ store.fetchData = vi.fn().mockResolvedValue({ items: [] })
75
+
76
+ await wrapper.find('.load-button').trigger('click')
77
+ expect(store.fetchData).toHaveBeenCalled()
78
+ })
79
+ ```
80
+
81
+ **Pattern 3: Testing store directly**
82
+ ```typescript
83
+ import { setActivePinia, createPinia } from 'pinia'
84
+ import { useCounterStore } from '@/stores/counter'
85
+
86
+ describe('Counter Store', () => {
87
+ beforeEach(() => {
88
+ setActivePinia(createPinia())
89
+ })
90
+
91
+ test('increments count', () => {
92
+ const store = useCounterStore()
93
+ expect(store.count).toBe(0)
94
+
95
+ store.increment()
96
+ expect(store.count).toBe(1)
97
+ })
98
+ })
99
+ ```
100
+
101
+ ## Setup Store with Vitest
102
+
103
+ ```typescript
104
+ // stores/counter.ts - Setup store syntax
105
+ export const useCounterStore = defineStore('counter', () => {
106
+ const count = ref(0)
107
+ const doubleCount = computed(() => count.value * 2)
108
+
109
+ function increment() {
110
+ count.value++
111
+ }
112
+
113
+ return { count, doubleCount, increment }
114
+ })
115
+
116
+ // Test file
117
+ test('setup store works', async () => {
118
+ const pinia = createTestingPinia({
119
+ createSpy: vi.fn,
120
+ initialState: {
121
+ counter: { count: 5 }
122
+ }
123
+ })
124
+
125
+ const wrapper = mount(MyComponent, {
126
+ global: { plugins: [pinia] }
127
+ })
128
+
129
+ const store = useCounterStore()
130
+ expect(store.count).toBe(5)
131
+ expect(store.doubleCount).toBe(10)
132
+ })
133
+ ```
134
+
135
+ ## Reset Between Tests
136
+
137
+ ```typescript
138
+ describe('Store Tests', () => {
139
+ let pinia: Pinia
140
+
141
+ beforeEach(() => {
142
+ pinia = createTestingPinia({
143
+ createSpy: vi.fn
144
+ })
145
+ })
146
+
147
+ afterEach(() => {
148
+ vi.clearAllMocks()
149
+ })
150
+
151
+ test('test 1', () => { /* ... */ })
152
+ test('test 2', () => { /* ... */ })
153
+ })
154
+ ```
155
+
156
+ ## Reference
157
+
158
+ - [Pinia Testing Guide](https://pinia.vuejs.org/cookbook/testing.html)
159
+ - [Pinia Discussion #2092](https://github.com/vuejs/pinia/discussions/2092)
@@ -0,0 +1,85 @@
1
+ ---
2
+ title: JSDoc Documentation for Script Setup Components
3
+ impact: MEDIUM
4
+ impactDescription: enables proper documentation for composition API components
5
+ type: capability
6
+ tags: jsdoc, script-setup, documentation, composition-api, component
7
+ ---
8
+
9
+ # JSDoc Documentation for Script Setup Components
10
+
11
+ **Impact: MEDIUM** - enables proper documentation for composition API components
12
+
13
+ `<script setup>` doesn't have an obvious place to attach JSDoc comments for the component itself. Use a dual-script pattern.
14
+
15
+ ## Problem
16
+
17
+ **Incorrect:**
18
+ ```vue
19
+ <script setup lang="ts">
20
+ /**
21
+ * This comment doesn't appear in IDE hover or docs
22
+ * @component
23
+ */
24
+ import { ref } from 'vue'
25
+
26
+ const count = ref(0)
27
+ </script>
28
+ ```
29
+
30
+ JSDoc comments inside `<script setup>` don't attach to the component export because there's no explicit export statement.
31
+
32
+ ## Solution
33
+
34
+ Use both `<script>` and `<script setup>` blocks:
35
+
36
+ **Correct:**
37
+ ```vue
38
+ <script lang="ts">
39
+ /**
40
+ * A counter component that displays and increments a value.
41
+ *
42
+ * @example
43
+ * ```vue
44
+ * <Counter :initial="5" @update="handleUpdate" />
45
+ * ```
46
+ *
47
+ * @component
48
+ */
49
+ export default {}
50
+ </script>
51
+
52
+ <script setup lang="ts">
53
+ import { ref } from 'vue'
54
+
55
+ const props = defineProps<{
56
+ /** Starting value for the counter */
57
+ initial?: number
58
+ }>()
59
+
60
+ const emit = defineEmits<{
61
+ /** Emitted when counter value changes */
62
+ update: [value: number]
63
+ }>()
64
+
65
+ const count = ref(props.initial ?? 0)
66
+ </script>
67
+ ```
68
+
69
+ ## How It Works
70
+
71
+ - The regular `<script>` block's default export is merged with `<script setup>`
72
+ - JSDoc on `export default {}` attaches to the component
73
+ - Props and emits JSDoc in `<script setup>` still work normally
74
+
75
+ ## What Gets Documented
76
+
77
+ | Location | Shows In |
78
+ |----------|----------|
79
+ | `export default {}` JSDoc | Component import hover |
80
+ | `defineProps` JSDoc | Prop hover in templates |
81
+ | `defineEmits` JSDoc | Event handler hover |
82
+
83
+ ## Reference
84
+
85
+ - [Vue Language Tools Discussion #5932](https://github.com/vuejs/language-tools/discussions/5932)