@blueking/bkui-knowledge 0.0.1-beta.1 → 0.0.1-beta.11
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.
- package/README.md +166 -58
- package/bin/bkui-knowledge.js +229 -86
- package/knowledge/manifest.json +38 -1
- package/knowledge/skills/.template/README.md +1 -1
- package/knowledge/skills/bk-security-redlines/SKILL.md +47 -0
- package/knowledge/skills/bk-security-redlines/references/auth-check.md +73 -0
- package/knowledge/skills/bk-security-redlines/references/data-encryption.md +78 -0
- package/knowledge/skills/bk-security-redlines/references/input-validation.md +96 -0
- package/knowledge/skills/bk-skill-creator/SKILL.md +37 -0
- package/knowledge/skills/bk-skill-creator/references/common-mistakes.md +43 -0
- package/knowledge/skills/bk-skill-creator/references/quick-start.md +42 -0
- package/knowledge/skills/bk-skill-creator/references/skill-checklist.md +93 -0
- package/knowledge/skills/bk-skill-creator/references/structure-guide.md +88 -0
- package/knowledge/skills/bk-skill-creator/references/writing-tips.md +153 -0
- package/knowledge/skills/bkui-quick-start/SKILL.md +52 -0
- package/knowledge/skills/bkui-quick-start/references/components-list.md +17 -0
- package/knowledge/skills/bkui-quick-start/references/skills-index.md +26 -0
- package/knowledge/skills/external/vue-skills/LICENSE +21 -0
- package/knowledge/skills/external/vue-skills/README.md +69 -0
- package/knowledge/skills/external/vue-skills/skills/vue-best-practices/SKILL.md +42 -0
- package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/codeactions-save-performance.md +79 -0
- package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/data-attributes-config.md +74 -0
- package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/deep-watch-numeric.md +102 -0
- package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/define-model-update-event.md +79 -0
- package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/duplicate-plugin-detection.md +102 -0
- package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/fallthrough-attributes.md +63 -0
- package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/hmr-vue-ssr.md +124 -0
- package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/module-resolution-bundler.md +81 -0
- package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/pinia-store-mocking.md +159 -0
- package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/script-setup-jsdoc.md +85 -0
- package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/strict-css-modules.md +68 -0
- package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/unplugin-auto-import-conflicts.md +97 -0
- package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/volar-3-breaking-changes.md +66 -0
- package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/vue-directive-comments.md +73 -0
- package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/vue-router-typed-params.md +81 -0
- package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/vue-tsc-strict-templates.md +69 -0
- package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/with-defaults-union-types.md +102 -0
- package/knowledge/skills/web-security-guide/SKILL.md +48 -0
- package/knowledge/skills/web-security-guide/references/access-control.md +123 -0
- package/knowledge/skills/web-security-guide/references/auth-session.md +99 -0
- package/knowledge/skills/web-security-guide/references/csrf.md +59 -0
- package/knowledge/skills/web-security-guide/references/data-exposure.md +108 -0
- package/knowledge/skills/web-security-guide/references/deserialization.md +59 -0
- package/knowledge/skills/web-security-guide/references/injection.md +357 -0
- package/knowledge/skills/web-security-guide/references/logging-monitoring.md +47 -0
- package/knowledge/skills/web-security-guide/references/security-config.md +73 -0
- package/knowledge/skills/web-security-guide/references/ssrf.md +55 -0
- package/knowledge/skills/web-security-guide/references/xss.md +134 -0
- package/package.json +3 -3
- package/server/mcp-core.js +48 -33
|
@@ -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)
|
package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/pinia-store-mocking.md
ADDED
|
@@ -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)
|
package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/script-setup-jsdoc.md
ADDED
|
@@ -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)
|
package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/strict-css-modules.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Enable Strict CSS Modules Type Checking
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: catches typos in CSS module class names at compile time
|
|
5
|
+
type: capability
|
|
6
|
+
tags: strictCssModules, vueCompilerOptions, css-modules, style-module
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Enable Strict CSS Modules Type Checking
|
|
10
|
+
|
|
11
|
+
**Impact: MEDIUM** - catches typos in CSS module class names at compile time
|
|
12
|
+
|
|
13
|
+
When using CSS modules with `<style module>`, Vue doesn't validate class names by default. Enable `strictCssModules` to catch typos and undefined classes.
|
|
14
|
+
|
|
15
|
+
## Problem
|
|
16
|
+
|
|
17
|
+
CSS module class name errors go undetected:
|
|
18
|
+
|
|
19
|
+
```vue
|
|
20
|
+
<script setup lang="ts">
|
|
21
|
+
// No error for typo in class name
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<template>
|
|
25
|
+
<div :class="$style.buttn">Click me</div>
|
|
26
|
+
</template>
|
|
27
|
+
|
|
28
|
+
<style module>
|
|
29
|
+
.button {
|
|
30
|
+
background: blue;
|
|
31
|
+
}
|
|
32
|
+
</style>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The typo `buttn` instead of `button` silently fails at runtime.
|
|
36
|
+
|
|
37
|
+
## Solution
|
|
38
|
+
|
|
39
|
+
Enable `strictCssModules` in your tsconfig:
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
// tsconfig.json or tsconfig.app.json
|
|
43
|
+
{
|
|
44
|
+
"vueCompilerOptions": {
|
|
45
|
+
"strictCssModules": true
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Now `$style.buttn` will show a type error because `buttn` doesn't exist in the CSS module.
|
|
51
|
+
|
|
52
|
+
## What Gets Checked
|
|
53
|
+
|
|
54
|
+
| Access | With strictCssModules |
|
|
55
|
+
|--------|----------------------|
|
|
56
|
+
| `$style.validClass` | OK |
|
|
57
|
+
| `$style.typo` | Error: Property 'typo' does not exist |
|
|
58
|
+
| `$style['dynamic']` | OK (dynamic access not checked) |
|
|
59
|
+
|
|
60
|
+
## Limitations
|
|
61
|
+
|
|
62
|
+
- Only checks static property access (`$style.className`)
|
|
63
|
+
- Dynamic access (`$style[variable]`) is not validated
|
|
64
|
+
- Only works with `<style module>`, not external CSS files
|
|
65
|
+
|
|
66
|
+
## Reference
|
|
67
|
+
|
|
68
|
+
- [Vue Language Tools Wiki - Vue Compiler Options](https://github.com/vuejs/language-tools/wiki/Vue-Compiler-Options)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: unplugin-vue-components and unplugin-auto-import Type Conflicts
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: fixes component types resolving as any when using both plugins
|
|
5
|
+
type: capability
|
|
6
|
+
tags: unplugin-vue-components, unplugin-auto-import, types, any, dts
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# unplugin-vue-components and unplugin-auto-import Type Conflicts
|
|
10
|
+
|
|
11
|
+
**Impact: HIGH** - fixes component types resolving as any when using both plugins
|
|
12
|
+
|
|
13
|
+
Installing both `unplugin-vue-components` and `unplugin-auto-import` can cause component types to resolve as `any`. The generated `.d.ts` files conflict with each other.
|
|
14
|
+
|
|
15
|
+
## Symptoms
|
|
16
|
+
|
|
17
|
+
- Components typed as `any` instead of proper component types
|
|
18
|
+
- No autocomplete for component props
|
|
19
|
+
- No type errors for invalid props
|
|
20
|
+
- Types work when using only one plugin but break with both
|
|
21
|
+
|
|
22
|
+
## Root Cause
|
|
23
|
+
|
|
24
|
+
Both plugins generate declaration files (`components.d.ts` and `auto-imports.d.ts`) that can have conflicting declarations. TypeScript declaration merging fails silently.
|
|
25
|
+
|
|
26
|
+
## Fix
|
|
27
|
+
|
|
28
|
+
**Step 1: Ensure both .d.ts files are in tsconfig include**
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"include": [
|
|
32
|
+
"src/**/*.ts",
|
|
33
|
+
"src/**/*.vue",
|
|
34
|
+
"components.d.ts",
|
|
35
|
+
"auto-imports.d.ts"
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**Step 2: Set explicit, different dts paths**
|
|
41
|
+
```typescript
|
|
42
|
+
// vite.config.ts
|
|
43
|
+
import Components from 'unplugin-vue-components/vite'
|
|
44
|
+
import AutoImport from 'unplugin-auto-import/vite'
|
|
45
|
+
|
|
46
|
+
export default defineConfig({
|
|
47
|
+
plugins: [
|
|
48
|
+
Components({
|
|
49
|
+
dts: 'src/types/components.d.ts' // Explicit unique path
|
|
50
|
+
}),
|
|
51
|
+
AutoImport({
|
|
52
|
+
dts: 'src/types/auto-imports.d.ts' // Explicit unique path
|
|
53
|
+
})
|
|
54
|
+
]
|
|
55
|
+
})
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Step 3: Regenerate type files**
|
|
59
|
+
```bash
|
|
60
|
+
# Delete existing .d.ts files
|
|
61
|
+
rm components.d.ts auto-imports.d.ts
|
|
62
|
+
|
|
63
|
+
# Restart dev server to regenerate
|
|
64
|
+
npm run dev
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Step 4: Verify no duplicate declarations**
|
|
68
|
+
|
|
69
|
+
Check that the same component isn't declared in both files.
|
|
70
|
+
|
|
71
|
+
## Plugin Order Matters
|
|
72
|
+
|
|
73
|
+
Configure Components plugin AFTER AutoImport:
|
|
74
|
+
```typescript
|
|
75
|
+
plugins: [
|
|
76
|
+
AutoImport({ /* ... */ }),
|
|
77
|
+
Components({ /* ... */ }) // Must come after AutoImport
|
|
78
|
+
]
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Common Mistake: Duplicate Imports
|
|
82
|
+
|
|
83
|
+
Don't configure the same import in both plugins:
|
|
84
|
+
```typescript
|
|
85
|
+
// Wrong - Vue imported in both
|
|
86
|
+
AutoImport({
|
|
87
|
+
imports: ['vue']
|
|
88
|
+
})
|
|
89
|
+
Components({
|
|
90
|
+
resolvers: [/* includes Vue components */]
|
|
91
|
+
})
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Reference
|
|
95
|
+
|
|
96
|
+
- [unplugin-vue-components#640](https://github.com/unplugin/unplugin-vue-components/issues/640)
|
|
97
|
+
- [unplugin-auto-import docs](https://github.com/unplugin/unplugin-auto-import)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Volar 3.0 Breaking Changes
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: fixes editor integration after Volar/vue-language-server upgrade
|
|
5
|
+
type: capability
|
|
6
|
+
tags: volar, vue-language-server, neovim, vscode, ide, ts_ls, vtsls
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Volar 3.0 Breaking Changes
|
|
10
|
+
|
|
11
|
+
**Impact: HIGH** - fixes editor integration after Volar/vue-language-server upgrade
|
|
12
|
+
|
|
13
|
+
Volar 3.0 (vue-language-server 3.x) introduced breaking changes to the language server protocol. Editors configured for Volar 2.x will break with errors like "vue_ls doesn't work with ts_ls.. it expects vtsls".
|
|
14
|
+
|
|
15
|
+
## Symptoms
|
|
16
|
+
|
|
17
|
+
- `vue_ls doesn't work with ts_ls`
|
|
18
|
+
- TypeScript features stop working in Vue files
|
|
19
|
+
- No autocomplete, type hints, or error highlighting
|
|
20
|
+
- Editor shows "Language server initialization failed"
|
|
21
|
+
|
|
22
|
+
## Fix by Editor
|
|
23
|
+
|
|
24
|
+
### VSCode
|
|
25
|
+
|
|
26
|
+
Update the "Vue - Official" extension to latest version. It manages the language server automatically.
|
|
27
|
+
|
|
28
|
+
### NeoVim (nvim-lspconfig)
|
|
29
|
+
|
|
30
|
+
**Option 1: Use vtsls instead of ts_ls**
|
|
31
|
+
```lua
|
|
32
|
+
-- Replace ts_ls/tsserver with vtsls
|
|
33
|
+
require('lspconfig').vtsls.setup({})
|
|
34
|
+
require('lspconfig').volar.setup({})
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Option 2: Downgrade vue-language-server**
|
|
38
|
+
```bash
|
|
39
|
+
npm install -g @vue/language-server@2.1.10
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### JetBrains IDEs
|
|
43
|
+
|
|
44
|
+
Update to latest Vue plugin. If issues persist, disable and re-enable the Vue plugin.
|
|
45
|
+
|
|
46
|
+
## What Changed in 3.0
|
|
47
|
+
|
|
48
|
+
| Feature | Volar 2.x | Volar 3.0 |
|
|
49
|
+
|---------|-----------|-----------|
|
|
50
|
+
| Package name | volar | vue_ls |
|
|
51
|
+
| TypeScript integration | ts_ls/tsserver | vtsls required |
|
|
52
|
+
| Hybrid mode | Optional | Default |
|
|
53
|
+
|
|
54
|
+
## Workaround: Stay on 2.x
|
|
55
|
+
|
|
56
|
+
If upgrading is not possible:
|
|
57
|
+
```bash
|
|
58
|
+
npm install -g @vue/language-server@^2.0.0
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Pin in your project's package.json to prevent accidental upgrades.
|
|
62
|
+
|
|
63
|
+
## Reference
|
|
64
|
+
|
|
65
|
+
- [vuejs/language-tools#5598](https://github.com/vuejs/language-tools/issues/5598)
|
|
66
|
+
- [NeoVim Vue Setup Guide](https://dev.to/danwalsh/solved-vue-3-typescript-inlay-hint-support-in-neovim-53ej)
|