@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,69 @@
|
|
|
1
|
+
# vue-skills
|
|
2
|
+
|
|
3
|
+
Agent skills for Vue 3 development.
|
|
4
|
+
|
|
5
|
+
> 🚧 **Early Experiment**
|
|
6
|
+
>
|
|
7
|
+
> This repository is an early experiment in creating specialized skills for AI agents to enhance their capabilities in Vue 3 development. The skills are derived from real-world issues and best practices, but might be incomplete or inaccurate due to hallucinations.
|
|
8
|
+
>
|
|
9
|
+
> Please give feedback when encountering any issues.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx add-skill hyf0/vue-skills
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Available Skills
|
|
18
|
+
|
|
19
|
+
### vue-best-practices (17 rules)
|
|
20
|
+
|
|
21
|
+
Vue 3 development best practices covering TypeScript configuration, tooling troubleshooting, and testing patterns.
|
|
22
|
+
|
|
23
|
+
| Type | Count | Examples |
|
|
24
|
+
|------|-------|----------|
|
|
25
|
+
| Capability | 15 | vue-tsc strictTemplates, Volar 3.0 breaking changes, Vue 3.5 deep watch, @vue-ignore directives |
|
|
26
|
+
| Efficiency | 2 | HMR in SSR, Pinia store mocking |
|
|
27
|
+
|
|
28
|
+
**Key rules that models don't know without the skill:**
|
|
29
|
+
- `vue-tsc-strict-templates` - vueCompilerOptions.strictTemplates config
|
|
30
|
+
- `deep-watch-numeric` - Vue 3.5 `deep: 1` for efficient partial-depth watching
|
|
31
|
+
- `vue-directive-comments` - @vue-ignore, @vue-expect-error, @vue-skip directives
|
|
32
|
+
- `pinia-store-mocking` - createSpy requirement in @pinia/testing 1.0+
|
|
33
|
+
|
|
34
|
+
## Rule Types
|
|
35
|
+
|
|
36
|
+
Rules are classified into two categories:
|
|
37
|
+
|
|
38
|
+
- **Capability**: AI *cannot* solve the problem without the skill. These address version-specific issues, undocumented behaviors, recent features, or edge cases outside AI's training data.
|
|
39
|
+
|
|
40
|
+
- **Efficiency**: AI *can* solve the problem but not well. These provide optimal patterns, best practices, and consistent approaches that improve solution quality.
|
|
41
|
+
|
|
42
|
+
## Methodology
|
|
43
|
+
|
|
44
|
+
Every skill in this repository is created through a rigorous, evidence-based process:
|
|
45
|
+
|
|
46
|
+
**1. Real-World Issue Collection**
|
|
47
|
+
|
|
48
|
+
Skills are sourced from actual developer pain points encountered in production.
|
|
49
|
+
|
|
50
|
+
**2. Multi-Model Verification**
|
|
51
|
+
|
|
52
|
+
Each skill undergoes systematic testing:
|
|
53
|
+
- **Baseline test**: Verify the model fails to solve the problem *without* the skill
|
|
54
|
+
- **Skill test**: Confirm the model correctly solves the problem *with* the skill
|
|
55
|
+
- **Deletion criteria**: If both Sonnet AND Haiku pass without the skill, the rule will be deleted
|
|
56
|
+
|
|
57
|
+
**3. Model Tier Validation**
|
|
58
|
+
|
|
59
|
+
| Model | Without Skill | With Skill | Action |
|
|
60
|
+
|-------|--------------|------------|--------|
|
|
61
|
+
| Haiku | Fail | Pass | Keep |
|
|
62
|
+
| Sonnet | Fail | Pass | Keep |
|
|
63
|
+
| Both | Pass | - | Delete |
|
|
64
|
+
|
|
65
|
+
**Acceptance criteria**: A skill is only kept if it enables Haiku or Sonnet to solve a problem they couldn't solve without it.
|
|
66
|
+
|
|
67
|
+
## License
|
|
68
|
+
|
|
69
|
+
MIT
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vue-best-practices
|
|
3
|
+
description: Vue 3 TypeScript, vue-tsc, Volar, Vite, component props, testing, composition API.
|
|
4
|
+
license: MIT
|
|
5
|
+
metadata:
|
|
6
|
+
author: hyf0
|
|
7
|
+
version: "7.0.0"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Vue Best Practices
|
|
11
|
+
|
|
12
|
+
## Capability Rules
|
|
13
|
+
|
|
14
|
+
| Rule | Keywords | Description |
|
|
15
|
+
|------|----------|-------------|
|
|
16
|
+
| [vue-tsc-strict-templates](rules/vue-tsc-strict-templates.md) | undefined component, template error, strictTemplates | Catch undefined components in templates |
|
|
17
|
+
| [fallthrough-attributes](rules/fallthrough-attributes.md) | fallthrough, $attrs, wrapper component | Type-check fallthrough attributes |
|
|
18
|
+
| [strict-css-modules](rules/strict-css-modules.md) | css modules, $style, typo | Catch CSS module class typos |
|
|
19
|
+
| [data-attributes-config](rules/data-attributes-config.md) | data-*, strictTemplates, attribute | Allow data-* attributes |
|
|
20
|
+
| [volar-3-breaking-changes](rules/volar-3-breaking-changes.md) | volar, vue-language-server, editor | Fix Volar 3.0 upgrade issues |
|
|
21
|
+
| [module-resolution-bundler](rules/module-resolution-bundler.md) | cannot find module, @vue/tsconfig, moduleResolution | Fix module resolution errors |
|
|
22
|
+
| [unplugin-auto-import-conflicts](rules/unplugin-auto-import-conflicts.md) | unplugin, auto-import, types any | Fix unplugin type conflicts |
|
|
23
|
+
| [codeactions-save-performance](rules/codeactions-save-performance.md) | slow save, vscode, performance | Fix slow save in large projects |
|
|
24
|
+
| [duplicate-plugin-detection](rules/duplicate-plugin-detection.md) | duplicate plugin, vite, vue plugin | Detect duplicate plugins |
|
|
25
|
+
| [define-model-update-event](rules/define-model-update-event.md) | defineModel, update event, undefined | Fix model update errors |
|
|
26
|
+
| [with-defaults-union-types](rules/with-defaults-union-types.md) | withDefaults, union type, default | Fix union type defaults |
|
|
27
|
+
| [deep-watch-numeric](rules/deep-watch-numeric.md) | watch, deep, array, Vue 3.5 | Efficient array watching |
|
|
28
|
+
| [vue-directive-comments](rules/vue-directive-comments.md) | @vue-ignore, @vue-skip, template | Control template type checking |
|
|
29
|
+
| [script-setup-jsdoc](rules/script-setup-jsdoc.md) | jsdoc, script setup, documentation | Add JSDoc to script setup |
|
|
30
|
+
| [vue-router-typed-params](rules/vue-router-typed-params.md) | route params, typed router, unplugin | Fix route params typing |
|
|
31
|
+
|
|
32
|
+
## Efficiency Rules
|
|
33
|
+
|
|
34
|
+
| Rule | Keywords | Description |
|
|
35
|
+
|------|----------|-------------|
|
|
36
|
+
| [hmr-vue-ssr](rules/hmr-vue-ssr.md) | hmr, ssr, hot reload | Fix HMR in SSR apps |
|
|
37
|
+
| [pinia-store-mocking](rules/pinia-store-mocking.md) | pinia, mock, vitest, store | Mock Pinia stores |
|
|
38
|
+
|
|
39
|
+
## Reference
|
|
40
|
+
|
|
41
|
+
- [Vue Language Tools](https://github.com/vuejs/language-tools)
|
|
42
|
+
- [Vue 3 Documentation](https://vuejs.org/)
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Fix Slow Save Times with Code Actions Setting
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: fixes 30-60 second save delays in large Vue projects
|
|
5
|
+
type: capability
|
|
6
|
+
tags: performance, save-time, vscode, code-actions, volar
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Fix Slow Save Times with Code Actions Setting
|
|
10
|
+
|
|
11
|
+
**Impact: HIGH** - fixes 30-60 second save delays in large Vue projects
|
|
12
|
+
|
|
13
|
+
In large Vue projects, saving files can take 30-60+ seconds due to VSCode's code actions triggering expensive TypeScript state synchronization.
|
|
14
|
+
|
|
15
|
+
## Problem
|
|
16
|
+
|
|
17
|
+
Symptoms:
|
|
18
|
+
- Save operation takes 30+ seconds
|
|
19
|
+
- Editor becomes unresponsive during save
|
|
20
|
+
- CPU spikes when saving Vue files
|
|
21
|
+
- Happens more in larger projects
|
|
22
|
+
|
|
23
|
+
## Root Cause
|
|
24
|
+
|
|
25
|
+
VSCode emits document change events multiple times during save cycles. Each event triggers Volar to synchronize with TypeScript, causing expensive re-computation.
|
|
26
|
+
|
|
27
|
+
## Solution
|
|
28
|
+
|
|
29
|
+
Disable code actions or limit their timeout:
|
|
30
|
+
|
|
31
|
+
**Option 1: Disable code actions (fastest)**
|
|
32
|
+
```json
|
|
33
|
+
// .vscode/settings.json
|
|
34
|
+
{
|
|
35
|
+
"vue.codeActions.enabled": false
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Option 2: Limit code action time**
|
|
40
|
+
```json
|
|
41
|
+
// .vscode/settings.json
|
|
42
|
+
{
|
|
43
|
+
"vue.codeActions.savingTimeLimit": 1000
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Option 3: Disable specific code actions**
|
|
48
|
+
```json
|
|
49
|
+
// .vscode/settings.json
|
|
50
|
+
{
|
|
51
|
+
"vue.codeActions.enabled": true,
|
|
52
|
+
"editor.codeActionsOnSave": {
|
|
53
|
+
"source.organizeImports": "never"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## VSCode Version Requirement
|
|
59
|
+
|
|
60
|
+
VSCode 1.81.0+ includes fixes that reduce save time issues. Upgrade if using an older version.
|
|
61
|
+
|
|
62
|
+
## Additional Optimizations
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
// .vscode/settings.json
|
|
66
|
+
{
|
|
67
|
+
"vue.codeActions.enabled": false,
|
|
68
|
+
"editor.formatOnSave": true,
|
|
69
|
+
"editor.codeActionsOnSave": {},
|
|
70
|
+
"[vue]": {
|
|
71
|
+
"editor.formatOnSave": true,
|
|
72
|
+
"editor.defaultFormatter": "Vue.volar"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Reference
|
|
78
|
+
|
|
79
|
+
- [Vue Language Tools Discussion #2740](https://github.com/vuejs/language-tools/discussions/2740)
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Allow Data Attributes with Strict Templates
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: fixes data-testid and data-* attribute errors in strict mode
|
|
5
|
+
type: capability
|
|
6
|
+
tags: dataAttributes, vueCompilerOptions, strictTemplates, data-testid, testing
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Allow Data Attributes with Strict Templates
|
|
10
|
+
|
|
11
|
+
**Impact: MEDIUM** - fixes data-testid and data-* attribute errors in strict mode
|
|
12
|
+
|
|
13
|
+
With `strictTemplates` enabled, `data-*` attributes on components cause type errors. Use the `dataAttributes` option to allow specific patterns.
|
|
14
|
+
|
|
15
|
+
## Problem
|
|
16
|
+
|
|
17
|
+
```vue
|
|
18
|
+
<template>
|
|
19
|
+
<!-- Error: Property 'data-testid' does not exist on type... -->
|
|
20
|
+
<MyComponent data-testid="submit-button" />
|
|
21
|
+
|
|
22
|
+
<!-- Error: Property 'data-cy' does not exist on type... -->
|
|
23
|
+
<MyComponent data-cy="login-form" />
|
|
24
|
+
</template>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Solution
|
|
28
|
+
|
|
29
|
+
Configure `dataAttributes` to allow specific patterns:
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
// tsconfig.json or tsconfig.app.json
|
|
33
|
+
{
|
|
34
|
+
"vueCompilerOptions": {
|
|
35
|
+
"strictTemplates": true,
|
|
36
|
+
"dataAttributes": ["data-*"]
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Now all `data-*` attributes are allowed on any component.
|
|
42
|
+
|
|
43
|
+
## Specific Patterns
|
|
44
|
+
|
|
45
|
+
You can be more selective:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"vueCompilerOptions": {
|
|
50
|
+
"dataAttributes": [
|
|
51
|
+
"data-testid",
|
|
52
|
+
"data-cy",
|
|
53
|
+
"data-test-*"
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
This only allows the specified patterns, not all data attributes.
|
|
60
|
+
|
|
61
|
+
## Common Testing Attributes
|
|
62
|
+
|
|
63
|
+
For testing libraries, allow their specific attributes:
|
|
64
|
+
|
|
65
|
+
| Library | Attribute | Pattern |
|
|
66
|
+
|---------|-----------|---------|
|
|
67
|
+
| Testing Library | `data-testid` | `"data-testid"` |
|
|
68
|
+
| Cypress | `data-cy` | `"data-cy"` |
|
|
69
|
+
| Playwright | `data-testid` | `"data-testid"` |
|
|
70
|
+
| Generic | All data attributes | `"data-*"` |
|
|
71
|
+
|
|
72
|
+
## Reference
|
|
73
|
+
|
|
74
|
+
- [Vue Language Tools Wiki - Vue Compiler Options](https://github.com/vuejs/language-tools/wiki/Vue-Compiler-Options)
|
package/knowledge/skills/external/vue-skills/skills/vue-best-practices/rules/deep-watch-numeric.md
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Vue 3.5+ Deep Watch Numeric Depth
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: enables efficient array mutation watching with numeric deep option
|
|
5
|
+
type: capability
|
|
6
|
+
tags: watch, deep, vue-3.5, array, mutation, performance
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Vue 3.5+ Deep Watch Numeric Depth
|
|
10
|
+
|
|
11
|
+
**Impact: MEDIUM** - enables efficient array mutation watching with numeric deep option
|
|
12
|
+
|
|
13
|
+
Vue 3.5 introduced `deep: number` for watch depth control. This allows watching array mutations without the performance cost of deep traversal.
|
|
14
|
+
|
|
15
|
+
## Symptoms
|
|
16
|
+
|
|
17
|
+
- Array mutations not triggering watch callback
|
|
18
|
+
- Deep watch causing performance issues on large nested objects
|
|
19
|
+
- Unaware of new Vue 3.5 feature
|
|
20
|
+
|
|
21
|
+
> **Note:** TypeScript error "Type 'number' is not assignable to type 'boolean'" no longer occurs with Vue 3.5+ and current TypeScript versions. The types now correctly support numeric `deep` values.
|
|
22
|
+
|
|
23
|
+
## The Feature
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
// Vue 3.5+ only
|
|
27
|
+
watch(items, (newVal) => {
|
|
28
|
+
// Triggered on array mutations (push, pop, splice, etc.)
|
|
29
|
+
}, { deep: 1 })
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
| deep value | Behavior |
|
|
33
|
+
|------------|----------|
|
|
34
|
+
| `true` | Full recursive traversal (original behavior) |
|
|
35
|
+
| `false` | Only reference changes |
|
|
36
|
+
| `1` | One level deep - array mutations, not nested objects |
|
|
37
|
+
| `2` | Two levels deep |
|
|
38
|
+
| `n` | N levels deep |
|
|
39
|
+
|
|
40
|
+
## Fix
|
|
41
|
+
|
|
42
|
+
**Step 1: Ensure Vue 3.5+**
|
|
43
|
+
```bash
|
|
44
|
+
npm install vue@^3.5.0
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Step 2: Update @vue/runtime-core types**
|
|
48
|
+
```bash
|
|
49
|
+
npm install -D @vue/runtime-core@latest
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Step 3: Use numeric depth**
|
|
53
|
+
```typescript
|
|
54
|
+
import { watch, ref } from 'vue'
|
|
55
|
+
|
|
56
|
+
const items = ref([{ id: 1, data: { nested: 'value' } }])
|
|
57
|
+
|
|
58
|
+
// Watch array mutations only (push, pop, etc.)
|
|
59
|
+
watch(items, (newItems) => {
|
|
60
|
+
console.log('Array mutated')
|
|
61
|
+
}, { deep: 1 })
|
|
62
|
+
|
|
63
|
+
// Won't trigger on: items.value[0].data.nested = 'new'
|
|
64
|
+
// Will trigger on: items.value.push(newItem)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Performance Comparison
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
const largeNestedData = ref({ /* deeply nested structure */ })
|
|
71
|
+
|
|
72
|
+
// SLOW - traverses entire structure
|
|
73
|
+
watch(largeNestedData, handler, { deep: true })
|
|
74
|
+
|
|
75
|
+
// FAST - only watches top-level changes
|
|
76
|
+
watch(largeNestedData, handler, { deep: 1 })
|
|
77
|
+
|
|
78
|
+
// FASTEST - only reference changes
|
|
79
|
+
watch(largeNestedData, handler, { deep: false })
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Alternative: watchEffect for Selective Tracking
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
// Only tracks properties actually accessed
|
|
86
|
+
watchEffect(() => {
|
|
87
|
+
// Only re-runs when items.value.length or first item changes
|
|
88
|
+
console.log(items.value.length, items.value[0]?.id)
|
|
89
|
+
})
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## TypeScript Note
|
|
93
|
+
|
|
94
|
+
If TypeScript complains about numeric deep, ensure:
|
|
95
|
+
1. Vue version is 3.5+
|
|
96
|
+
2. `@vue/runtime-core` types are updated
|
|
97
|
+
3. tsconfig targets correct node_modules types
|
|
98
|
+
|
|
99
|
+
## Reference
|
|
100
|
+
|
|
101
|
+
- [Vue Watchers Docs](https://vuejs.org/guide/essentials/watchers.html)
|
|
102
|
+
- [Vue 3.5 Release Notes](https://blog.vuejs.org/posts/vue-3-5)
|
|
@@ -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)
|