@pythoughts/vue-skills-mcp 0.1.0

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 (208) hide show
  1. package/README.md +63 -0
  2. package/index.mjs +139 -0
  3. package/package.json +34 -0
  4. package/skills/create-adaptable-composable/SKILL.md +76 -0
  5. package/skills/vue-best-practices/SKILL.md +154 -0
  6. package/skills/vue-best-practices/references/animation-class-based-technique.md +254 -0
  7. package/skills/vue-best-practices/references/animation-state-driven-technique.md +291 -0
  8. package/skills/vue-best-practices/references/component-async.md +97 -0
  9. package/skills/vue-best-practices/references/component-data-flow.md +350 -0
  10. package/skills/vue-best-practices/references/component-fallthrough-attrs.md +174 -0
  11. package/skills/vue-best-practices/references/component-keep-alive.md +137 -0
  12. package/skills/vue-best-practices/references/component-slots.md +216 -0
  13. package/skills/vue-best-practices/references/component-suspense.md +228 -0
  14. package/skills/vue-best-practices/references/component-teleport.md +108 -0
  15. package/skills/vue-best-practices/references/component-transition-group.md +128 -0
  16. package/skills/vue-best-practices/references/component-transition.md +125 -0
  17. package/skills/vue-best-practices/references/composables.md +290 -0
  18. package/skills/vue-best-practices/references/directives.md +162 -0
  19. package/skills/vue-best-practices/references/perf-avoid-component-abstraction-in-lists.md +159 -0
  20. package/skills/vue-best-practices/references/perf-v-once-v-memo-directives.md +182 -0
  21. package/skills/vue-best-practices/references/perf-virtualize-large-lists.md +187 -0
  22. package/skills/vue-best-practices/references/plugins.md +166 -0
  23. package/skills/vue-best-practices/references/reactivity.md +346 -0
  24. package/skills/vue-best-practices/references/render-functions.md +201 -0
  25. package/skills/vue-best-practices/references/sfc.md +310 -0
  26. package/skills/vue-best-practices/references/state-management.md +135 -0
  27. package/skills/vue-best-practices/references/updated-hook-performance.md +187 -0
  28. package/skills/vue-debug-guides/SKILL.md +205 -0
  29. package/skills/vue-debug-guides/reference/animation-key-for-rerender.md +160 -0
  30. package/skills/vue-debug-guides/reference/animation-transitiongroup-performance.md +241 -0
  31. package/skills/vue-debug-guides/reference/async-component-error-handling.md +115 -0
  32. package/skills/vue-debug-guides/reference/async-component-keepalive-ref-issue.md +112 -0
  33. package/skills/vue-debug-guides/reference/async-component-suspense-control.md +84 -0
  34. package/skills/vue-debug-guides/reference/async-component-vue-router.md +109 -0
  35. package/skills/vue-debug-guides/reference/attrs-event-listener-merging.md +205 -0
  36. package/skills/vue-debug-guides/reference/checkbox-true-false-value-form-submission.md +118 -0
  37. package/skills/vue-debug-guides/reference/cleanup-side-effects.md +172 -0
  38. package/skills/vue-debug-guides/reference/click-events-on-components.md +180 -0
  39. package/skills/vue-debug-guides/reference/component-naming-conflicts.md +159 -0
  40. package/skills/vue-debug-guides/reference/component-ref-requires-defineexpose.md +176 -0
  41. package/skills/vue-debug-guides/reference/composable-avoid-hidden-side-effects.md +208 -0
  42. package/skills/vue-debug-guides/reference/composable-call-location-restrictions.md +141 -0
  43. package/skills/vue-debug-guides/reference/composable-naming-return-pattern.md +139 -0
  44. package/skills/vue-debug-guides/reference/composable-tovalue-inside-watcheffect.md +182 -0
  45. package/skills/vue-debug-guides/reference/composition-api-not-functional-programming.md +120 -0
  46. package/skills/vue-debug-guides/reference/composition-api-script-setup-async-context.md +203 -0
  47. package/skills/vue-debug-guides/reference/composition-api-vs-react-hooks-differences.md +156 -0
  48. package/skills/vue-debug-guides/reference/computed-array-mutation.md +148 -0
  49. package/skills/vue-debug-guides/reference/computed-conditional-dependencies.md +147 -0
  50. package/skills/vue-debug-guides/reference/computed-no-parameters.md +159 -0
  51. package/skills/vue-debug-guides/reference/computed-no-side-effects.md +107 -0
  52. package/skills/vue-debug-guides/reference/computed-return-value-readonly.md +160 -0
  53. package/skills/vue-debug-guides/reference/configure-app-before-mount.md +89 -0
  54. package/skills/vue-debug-guides/reference/declare-emits-for-documentation.md +212 -0
  55. package/skills/vue-debug-guides/reference/define-expose-before-await.md +192 -0
  56. package/skills/vue-debug-guides/reference/define-model-default-value-sync.md +139 -0
  57. package/skills/vue-debug-guides/reference/defineEmits-must-be-top-level.md +164 -0
  58. package/skills/vue-debug-guides/reference/defineEmits-no-runtime-and-type-mixed.md +170 -0
  59. package/skills/vue-debug-guides/reference/definemodel-object-mutation-no-emit.md +148 -0
  60. package/skills/vue-debug-guides/reference/dom-update-timing-nexttick.md +90 -0
  61. package/skills/vue-debug-guides/reference/dynamic-argument-constraints.md +146 -0
  62. package/skills/vue-debug-guides/reference/dynamic-component-registration-vite.md +147 -0
  63. package/skills/vue-debug-guides/reference/event-modifier-order-matters.md +101 -0
  64. package/skills/vue-debug-guides/reference/exact-modifier-for-precise-shortcuts.md +155 -0
  65. package/skills/vue-debug-guides/reference/fallthrough-attrs-overwrite-vue3.md +159 -0
  66. package/skills/vue-debug-guides/reference/in-dom-template-parsing-caveats.md +149 -0
  67. package/skills/vue-debug-guides/reference/inheritattrs-false-for-wrapper-components.md +230 -0
  68. package/skills/vue-debug-guides/reference/keepalive-router-nested-double-mount.md +222 -0
  69. package/skills/vue-debug-guides/reference/keepalive-transition-memory-leak.md +144 -0
  70. package/skills/vue-debug-guides/reference/keyup-modifier-timing.md +137 -0
  71. package/skills/vue-debug-guides/reference/lifecycle-dom-access-timing.md +216 -0
  72. package/skills/vue-debug-guides/reference/lifecycle-hooks-synchronous-registration.md +156 -0
  73. package/skills/vue-debug-guides/reference/lifecycle-ssr-awareness.md +184 -0
  74. package/skills/vue-debug-guides/reference/local-components-not-in-descendants.md +151 -0
  75. package/skills/vue-debug-guides/reference/mount-return-value.md +88 -0
  76. package/skills/vue-debug-guides/reference/multi-root-component-class-attrs.md +93 -0
  77. package/skills/vue-debug-guides/reference/native-event-collision-with-emits.md +162 -0
  78. package/skills/vue-debug-guides/reference/no-passive-with-prevent.md +141 -0
  79. package/skills/vue-debug-guides/reference/no-v-if-with-v-for.md +136 -0
  80. package/skills/vue-debug-guides/reference/perf-computed-object-stability.md +157 -0
  81. package/skills/vue-debug-guides/reference/perf-props-stability-update-optimization.md +140 -0
  82. package/skills/vue-debug-guides/reference/plugin-global-properties-sparingly.md +109 -0
  83. package/skills/vue-debug-guides/reference/plugin-install-before-mount.md +124 -0
  84. package/skills/vue-debug-guides/reference/plugin-prefer-provide-inject-over-global-properties.md +120 -0
  85. package/skills/vue-debug-guides/reference/plugin-typescript-type-augmentation.md +157 -0
  86. package/skills/vue-debug-guides/reference/prop-defineprops-scope-limitation.md +161 -0
  87. package/skills/vue-debug-guides/reference/provide-inject-debugging-challenges.md +203 -0
  88. package/skills/vue-debug-guides/reference/provide-inject-default-value-factory.md +244 -0
  89. package/skills/vue-debug-guides/reference/provide-inject-reactivity-not-automatic.md +226 -0
  90. package/skills/vue-debug-guides/reference/provide-inject-synchronous-setup.md +235 -0
  91. package/skills/vue-debug-guides/reference/reactive-destructuring.md +89 -0
  92. package/skills/vue-debug-guides/reference/reactivity-debugging-hooks.md +132 -0
  93. package/skills/vue-debug-guides/reference/reactivity-markraw-for-non-reactive.md +149 -0
  94. package/skills/vue-debug-guides/reference/reactivity-proxy-identity-hazard.md +96 -0
  95. package/skills/vue-debug-guides/reference/reactivity-same-tick-batching.md +166 -0
  96. package/skills/vue-debug-guides/reference/ref-value-access.md +61 -0
  97. package/skills/vue-debug-guides/reference/refs-in-collections-need-value.md +81 -0
  98. package/skills/vue-debug-guides/reference/render-function-avoid-internal-vnode-properties.md +151 -0
  99. package/skills/vue-debug-guides/reference/render-function-vnodes-must-be-unique.md +133 -0
  100. package/skills/vue-debug-guides/reference/rendering-render-function-h-import-vue3.md +148 -0
  101. package/skills/vue-debug-guides/reference/rendering-render-function-return-from-setup.md +148 -0
  102. package/skills/vue-debug-guides/reference/rendering-render-function-slots-as-functions.md +168 -0
  103. package/skills/vue-debug-guides/reference/rendering-resolve-component-for-string-names.md +231 -0
  104. package/skills/vue-debug-guides/reference/select-initial-value-ios-bug.md +91 -0
  105. package/skills/vue-debug-guides/reference/self-referencing-component-name.md +157 -0
  106. package/skills/vue-debug-guides/reference/sfc-named-exports-forbidden.md +184 -0
  107. package/skills/vue-debug-guides/reference/sfc-scoped-css-child-component-styling.md +156 -0
  108. package/skills/vue-debug-guides/reference/sfc-scoped-css-dynamic-content.md +193 -0
  109. package/skills/vue-debug-guides/reference/sfc-scoped-css-slot-content.md +242 -0
  110. package/skills/vue-debug-guides/reference/sfc-script-setup-reactivity.md +195 -0
  111. package/skills/vue-debug-guides/reference/slot-forwarding-to-child-components.md +143 -0
  112. package/skills/vue-debug-guides/reference/slot-implicit-default-content.md +155 -0
  113. package/skills/vue-debug-guides/reference/slot-name-reserved-prop.md +109 -0
  114. package/skills/vue-debug-guides/reference/slot-named-scoped-explicit-default.md +95 -0
  115. package/skills/vue-debug-guides/reference/slot-render-scope-parent-only.md +135 -0
  116. package/skills/vue-debug-guides/reference/slot-v-slot-on-components-or-templates-only.md +122 -0
  117. package/skills/vue-debug-guides/reference/ssr-hydration-mismatch-causes.md +280 -0
  118. package/skills/vue-debug-guides/reference/ssr-platform-specific-apis.md +256 -0
  119. package/skills/vue-debug-guides/reference/state-ssr-cross-request-pollution.md +276 -0
  120. package/skills/vue-debug-guides/reference/suspense-no-builtin-error-handling.md +127 -0
  121. package/skills/vue-debug-guides/reference/suspense-ssr-hydration-issues.md +159 -0
  122. package/skills/vue-debug-guides/reference/tailwind-dynamic-class-generation.md +144 -0
  123. package/skills/vue-debug-guides/reference/teleport-scoped-styles-limitation.md +191 -0
  124. package/skills/vue-debug-guides/reference/teleport-ssr-hydration.md +152 -0
  125. package/skills/vue-debug-guides/reference/teleport-target-must-exist.md +113 -0
  126. package/skills/vue-debug-guides/reference/template-expressions-restrictions.md +114 -0
  127. package/skills/vue-debug-guides/reference/template-functions-no-side-effects.md +187 -0
  128. package/skills/vue-debug-guides/reference/template-ref-null-with-v-if.md +123 -0
  129. package/skills/vue-debug-guides/reference/template-ref-unwrapping-top-level.md +104 -0
  130. package/skills/vue-debug-guides/reference/template-ref-v-for-order.md +172 -0
  131. package/skills/vue-debug-guides/reference/textarea-no-interpolation.md +72 -0
  132. package/skills/vue-debug-guides/reference/transition-group-flip-inline-elements.md +152 -0
  133. package/skills/vue-debug-guides/reference/transition-group-move-animation-position-absolute.md +130 -0
  134. package/skills/vue-debug-guides/reference/transition-group-no-default-wrapper-vue3.md +152 -0
  135. package/skills/vue-debug-guides/reference/transition-js-hooks-done-callback.md +251 -0
  136. package/skills/vue-debug-guides/reference/transition-nested-duration.md +182 -0
  137. package/skills/vue-debug-guides/reference/transition-reusable-scoped-style.md +245 -0
  138. package/skills/vue-debug-guides/reference/transition-router-view-appear.md +193 -0
  139. package/skills/vue-debug-guides/reference/transition-type-when-mixed.md +172 -0
  140. package/skills/vue-debug-guides/reference/transition-unmount-hook-timing.md +149 -0
  141. package/skills/vue-debug-guides/reference/ts-defineprops-boolean-default-false.md +225 -0
  142. package/skills/vue-debug-guides/reference/ts-defineprops-imported-types-limitations.md +281 -0
  143. package/skills/vue-debug-guides/reference/ts-event-handler-explicit-typing.md +213 -0
  144. package/skills/vue-debug-guides/reference/ts-reactive-no-generic-argument.md +196 -0
  145. package/skills/vue-debug-guides/reference/ts-shallowref-for-dynamic-components.md +218 -0
  146. package/skills/vue-debug-guides/reference/ts-template-ref-null-handling.md +249 -0
  147. package/skills/vue-debug-guides/reference/ts-template-type-casting.md +214 -0
  148. package/skills/vue-debug-guides/reference/ts-withdefaults-mutable-factory-function.md +171 -0
  149. package/skills/vue-debug-guides/reference/undeclared-emits-double-firing.md +195 -0
  150. package/skills/vue-debug-guides/reference/use-template-ref-vue35.md +158 -0
  151. package/skills/vue-debug-guides/reference/v-else-must-follow-v-if.md +136 -0
  152. package/skills/vue-debug-guides/reference/v-for-component-props.md +95 -0
  153. package/skills/vue-debug-guides/reference/v-for-computed-reverse-sort.md +86 -0
  154. package/skills/vue-debug-guides/reference/v-for-key-attribute.md +90 -0
  155. package/skills/vue-debug-guides/reference/v-for-range-starts-at-one.md +66 -0
  156. package/skills/vue-debug-guides/reference/v-if-null-check-order.md +171 -0
  157. package/skills/vue-debug-guides/reference/v-model-ignores-html-attributes.md +83 -0
  158. package/skills/vue-debug-guides/reference/v-model-ime-composition.md +83 -0
  159. package/skills/vue-debug-guides/reference/v-model-number-modifier-behavior.md +124 -0
  160. package/skills/vue-debug-guides/reference/v-show-template-limitation.md +124 -0
  161. package/skills/vue-debug-guides/reference/watch-async-cleanup.md +180 -0
  162. package/skills/vue-debug-guides/reference/watch-async-creation-memory-leak.md +176 -0
  163. package/skills/vue-debug-guides/reference/watch-deep-same-object-reference.md +165 -0
  164. package/skills/vue-debug-guides/reference/watch-flush-timing.md +189 -0
  165. package/skills/vue-debug-guides/reference/watch-reactive-property-getter.md +108 -0
  166. package/skills/vue-debug-guides/reference/watcheffect-async-dependency-tracking.md +173 -0
  167. package/skills/vue-debug-guides/reference/watcheffect-flush-post-for-refs.md +176 -0
  168. package/skills/vue-jsx-best-practices/SKILL.md +12 -0
  169. package/skills/vue-jsx-best-practices/reference/render-function-jsx-vue-vs-react.md +141 -0
  170. package/skills/vue-options-api-best-practices/SKILL.md +23 -0
  171. package/skills/vue-options-api-best-practices/reference/no-arrow-functions-in-lifecycle-hooks.md +95 -0
  172. package/skills/vue-options-api-best-practices/reference/no-arrow-functions-in-methods.md +68 -0
  173. package/skills/vue-options-api-best-practices/reference/stateful-methods-lifecycle.md +61 -0
  174. package/skills/vue-options-api-best-practices/reference/ts-options-api-arrow-functions-validators.md +141 -0
  175. package/skills/vue-options-api-best-practices/reference/ts-options-api-computed-return-types.md +192 -0
  176. package/skills/vue-options-api-best-practices/reference/ts-options-api-proptype-complex-types.md +212 -0
  177. package/skills/vue-options-api-best-practices/reference/ts-options-api-provide-inject-limitations.md +135 -0
  178. package/skills/vue-options-api-best-practices/reference/ts-options-api-type-event-handlers.md +202 -0
  179. package/skills/vue-options-api-best-practices/reference/ts-options-api-use-definecomponent.md +172 -0
  180. package/skills/vue-options-api-best-practices/reference/ts-strict-mode-options-api.md +197 -0
  181. package/skills/vue-pinia-best-practices/SKILL.md +21 -0
  182. package/skills/vue-pinia-best-practices/reference/pinia-no-active-pinia-error.md +248 -0
  183. package/skills/vue-pinia-best-practices/reference/pinia-setup-store-return-all-state.md +227 -0
  184. package/skills/vue-pinia-best-practices/reference/pinia-store-destructuring-breaks-reactivity.md +193 -0
  185. package/skills/vue-pinia-best-practices/reference/state-url-for-ephemeral-filters.md +238 -0
  186. package/skills/vue-pinia-best-practices/reference/state-use-pinia-for-large-apps.md +262 -0
  187. package/skills/vue-pinia-best-practices/reference/store-method-binding-parentheses.md +191 -0
  188. package/skills/vue-router-best-practices/SKILL.md +23 -0
  189. package/skills/vue-router-best-practices/reference/router-beforeenter-no-param-trigger.md +167 -0
  190. package/skills/vue-router-best-practices/reference/router-beforerouteenter-no-this.md +176 -0
  191. package/skills/vue-router-best-practices/reference/router-guard-async-await-pattern.md +227 -0
  192. package/skills/vue-router-best-practices/reference/router-navigation-guard-infinite-loop.md +187 -0
  193. package/skills/vue-router-best-practices/reference/router-navigation-guard-next-deprecated.md +150 -0
  194. package/skills/vue-router-best-practices/reference/router-param-change-no-lifecycle.md +181 -0
  195. package/skills/vue-router-best-practices/reference/router-simple-routing-cleanup.md +209 -0
  196. package/skills/vue-router-best-practices/reference/router-use-vue-router-for-production.md +183 -0
  197. package/skills/vue-testing-best-practices/SKILL.md +29 -0
  198. package/skills/vue-testing-best-practices/reference/async-component-testing.md +163 -0
  199. package/skills/vue-testing-best-practices/reference/teleport-testing-complexity.md +158 -0
  200. package/skills/vue-testing-best-practices/reference/testing-async-await-flushpromises.md +175 -0
  201. package/skills/vue-testing-best-practices/reference/testing-browser-vs-node-runners.md +208 -0
  202. package/skills/vue-testing-best-practices/reference/testing-component-blackbox-approach.md +144 -0
  203. package/skills/vue-testing-best-practices/reference/testing-composables-helper-wrapper.md +238 -0
  204. package/skills/vue-testing-best-practices/reference/testing-e2e-playwright-recommended.md +242 -0
  205. package/skills/vue-testing-best-practices/reference/testing-no-snapshot-only.md +197 -0
  206. package/skills/vue-testing-best-practices/reference/testing-pinia-store-setup.md +228 -0
  207. package/skills/vue-testing-best-practices/reference/testing-suspense-async-components.md +229 -0
  208. package/skills/vue-testing-best-practices/reference/testing-vitest-recommended-for-vue.md +204 -0
@@ -0,0 +1,124 @@
1
+ # Install Plugins Before Mounting the App
2
+
3
+ ## Rule
4
+
5
+ All plugins must be installed using `app.use()` BEFORE calling `app.mount()`. Installing plugins after the app is mounted can lead to reactivity issues, missing dependencies, and unexpected behavior.
6
+
7
+ ## Why This Matters
8
+
9
+ 1. **Hidden dependencies**: Components may render before plugins they depend on are available, causing runtime errors.
10
+
11
+ 2. **Reactivity issues**: Late plugin installation can cause subtle reactivity problems where provided values aren't properly reactive.
12
+
13
+ 3. **Initialization order**: Many plugins (like vue-router, pinia) need to set up state before any component renders.
14
+
15
+ 4. **Ecosystem complexity**: Adding plugins after mount can cause issues with Vue's internal ecosystem and hydration in SSR scenarios.
16
+
17
+ ## Bad Practice
18
+
19
+ ```typescript
20
+ import { createApp } from 'vue'
21
+ import App from './App.vue'
22
+ import router from './router'
23
+ import i18nPlugin from './plugins/i18n'
24
+
25
+ const app = createApp(App)
26
+
27
+ // Mounting first - plugins not yet available!
28
+ app.mount('#app')
29
+
30
+ // Installing after mount - TOO LATE!
31
+ app.use(router)
32
+ app.use(i18nPlugin, { locale: 'en' })
33
+ ```
34
+
35
+ ## Good Practice
36
+
37
+ ```typescript
38
+ import { createApp } from 'vue'
39
+ import App from './App.vue'
40
+ import router from './router'
41
+ import { createPinia } from 'pinia'
42
+ import i18nPlugin from './plugins/i18n'
43
+
44
+ const app = createApp(App)
45
+
46
+ // Install all plugins BEFORE mounting
47
+ app.use(createPinia())
48
+ app.use(router)
49
+ app.use(i18nPlugin, { locale: 'en' })
50
+
51
+ // Mount LAST
52
+ app.mount('#app')
53
+ ```
54
+
55
+ ## Plugin Installation Order
56
+
57
+ The order of `app.use()` calls can matter when plugins depend on each other:
58
+
59
+ ```typescript
60
+ const app = createApp(App)
61
+
62
+ // 1. State management first (other plugins might need it)
63
+ app.use(createPinia())
64
+
65
+ // 2. Router (may depend on state)
66
+ app.use(router)
67
+
68
+ // 3. Other plugins (may depend on router or state)
69
+ app.use(authPlugin)
70
+ app.use(i18nPlugin, { locale: 'en' })
71
+
72
+ // 4. Mount last
73
+ app.mount('#app')
74
+ ```
75
+
76
+ ## Async Plugin Installation
77
+
78
+ If you need to perform async operations before mounting:
79
+
80
+ ```typescript
81
+ import { createApp } from 'vue'
82
+ import App from './App.vue'
83
+ import { loadPlugins } from './plugins'
84
+
85
+ async function bootstrap() {
86
+ const app = createApp(App)
87
+
88
+ // Await async plugin setup
89
+ const i18nPlugin = await loadI18nMessages()
90
+
91
+ // Install all plugins
92
+ app.use(i18nPlugin)
93
+
94
+ // Mount after everything is ready
95
+ app.mount('#app')
96
+ }
97
+
98
+ bootstrap()
99
+ ```
100
+
101
+ ## Duplicate Installation Protection
102
+
103
+ Vue's `app.use()` automatically prevents duplicate plugin installation:
104
+
105
+ ```typescript
106
+ app.use(myPlugin)
107
+ app.use(myPlugin) // This second call is ignored - no double installation
108
+
109
+ // This is handled internally by Vue, providing a safety net
110
+ ```
111
+
112
+ ## Common Symptoms of Late Plugin Installation
113
+
114
+ - `inject()` returns `undefined` unexpectedly
115
+ - Router navigation guards not firing
116
+ - Store state not reactive
117
+ - Template errors about undefined global properties
118
+ - Hydration mismatches in SSR
119
+
120
+ ## References
121
+
122
+ - [Vue.js Plugins Documentation](https://vuejs.org/guide/reusability/plugins.html)
123
+ - [Vue.js Application API](https://vuejs.org/api/application.html)
124
+ - [Vue 3 Migration Guide - Global API](https://v3-migration.vuejs.org/breaking-changes/global-api.html)
@@ -0,0 +1,120 @@
1
+ # Prefer provide/inject Over Global Properties in Plugins
2
+
3
+ ## Rule
4
+
5
+ When creating Vue plugins, prefer using `app.provide()` to make plugin functionality available to components instead of attaching properties to `app.config.globalProperties`.
6
+
7
+ ## Why This Matters
8
+
9
+ 1. **globalProperties don't work in setup()**: Properties attached to `globalProperties` are only accessible via `this` in Options API. They are NOT available in the Composition API's `setup()` function.
10
+
11
+ 2. **Type safety**: `provide/inject` integrates better with TypeScript and requires less type augmentation boilerplate.
12
+
13
+ 3. **Testability**: Injected dependencies are easier to mock in tests compared to global properties.
14
+
15
+ 4. **Code clarity**: Explicit `inject()` calls make dependencies visible, while global properties can appear "magic".
16
+
17
+ 5. **Scoping**: `provide/inject` follows Vue's component hierarchy, making it easier to provide different values to different parts of your app.
18
+
19
+ ## Bad Practice
20
+
21
+ ```typescript
22
+ // plugins/i18n.ts
23
+ export default {
24
+ install(app, options) {
25
+ // Attaching to globalProperties - only works with Options API
26
+ app.config.globalProperties.$translate = (key: string) => {
27
+ return key.split('.').reduce((o, i) => o?.[i], options)
28
+ }
29
+ }
30
+ }
31
+
32
+ // In component - requires type augmentation for TypeScript
33
+ // Also DOES NOT work in <script setup>
34
+ export default {
35
+ mounted() {
36
+ console.log(this.$translate('greeting.hello'))
37
+ }
38
+ }
39
+ ```
40
+
41
+ ## Good Practice
42
+
43
+ ```typescript
44
+ // plugins/i18n.ts
45
+ import type { InjectionKey, App } from 'vue'
46
+
47
+ export interface I18nOptions {
48
+ [key: string]: string | I18nOptions
49
+ }
50
+
51
+ export interface I18n {
52
+ translate: (key: string) => string
53
+ options: I18nOptions
54
+ }
55
+
56
+ export const i18nKey: InjectionKey<I18n> = Symbol('i18n')
57
+
58
+ export default {
59
+ install(app: App, options: I18nOptions) {
60
+ const translate = (key: string): string => {
61
+ return key.split('.').reduce((o, i) => o?.[i], options) as string ?? key
62
+ }
63
+
64
+ // Use provide for Composition API compatibility
65
+ app.provide(i18nKey, { translate, options })
66
+ }
67
+ }
68
+
69
+ // In component - works in setup() and has full type safety
70
+ <script setup lang="ts">
71
+ import { inject } from 'vue'
72
+ import { i18nKey } from '@/plugins/i18n'
73
+
74
+ const i18n = inject(i18nKey)
75
+ console.log(i18n?.translate('greeting.hello'))
76
+ </script>
77
+ ```
78
+
79
+ ## Hybrid Approach
80
+
81
+ If you must support both APIs (e.g., for backwards compatibility), provide both:
82
+
83
+ ```typescript
84
+ export default {
85
+ install(app: App, options: I18nOptions) {
86
+ const i18n = {
87
+ translate: (key: string) => /* ... */
88
+ }
89
+
90
+ // For Composition API
91
+ app.provide(i18nKey, i18n)
92
+
93
+ // For Options API (use sparingly)
94
+ app.config.globalProperties.$i18n = i18n
95
+ }
96
+ }
97
+ ```
98
+
99
+ ## TypeScript Type Augmentation (if using globalProperties)
100
+
101
+ If you must use globalProperties, you need proper type augmentation:
102
+
103
+ ```typescript
104
+ // types/vue.d.ts
105
+ export {}
106
+
107
+ declare module 'vue' {
108
+ interface ComponentCustomProperties {
109
+ $translate: (key: string) => string
110
+ }
111
+ }
112
+ ```
113
+
114
+ **Important**: The file MUST contain `export {}` or another top-level export/import. Without it, the augmentation will OVERWRITE types instead of augmenting them.
115
+
116
+ ## References
117
+
118
+ - [Vue.js Plugins Documentation](https://vuejs.org/guide/reusability/plugins.html)
119
+ - [Vue.js Provide/Inject](https://vuejs.org/guide/components/provide-inject.html)
120
+ - [TypeScript with Options API](https://vuejs.org/guide/typescript/options-api.html)
@@ -0,0 +1,157 @@
1
+ # Proper TypeScript Type Augmentation for Plugins
2
+
3
+ ## Rule
4
+
5
+ When creating Vue plugins that add global properties, you MUST properly augment TypeScript types. The augmentation file MUST contain at least one top-level `import` or `export` statement to be treated as a module.
6
+
7
+ ## Why This Matters
8
+
9
+ 1. **Without module syntax, types are overwritten**: If your augmentation file isn't a module, it will OVERWRITE Vue's types instead of augmenting them, breaking type checking for the entire application.
10
+
11
+ 2. **Type safety**: Proper augmentation enables autocomplete and type checking for plugin-provided properties.
12
+
13
+ 3. **IDE support**: Developers get proper IntelliSense for global properties like `this.$translate`.
14
+
15
+ 4. **Error prevention**: Catch typos and incorrect usage at compile time rather than runtime.
16
+
17
+ ## Critical Rule: Module Syntax Required
18
+
19
+ ```typescript
20
+ // BAD - This OVERWRITES Vue types instead of augmenting!
21
+ // types/vue.d.ts
22
+ declare module 'vue' {
23
+ interface ComponentCustomProperties {
24
+ $translate: (key: string) => string
25
+ }
26
+ }
27
+
28
+ // GOOD - The export {} makes this a module, so it AUGMENTS types
29
+ // types/vue.d.ts
30
+ export {} // This line is CRITICAL!
31
+
32
+ declare module 'vue' {
33
+ interface ComponentCustomProperties {
34
+ $translate: (key: string) => string
35
+ }
36
+ }
37
+ ```
38
+
39
+ ## Complete Plugin Type Augmentation Example
40
+
41
+ ```typescript
42
+ // plugins/i18n.ts
43
+ import type { App, InjectionKey } from 'vue'
44
+
45
+ export interface I18nOptions {
46
+ locale: string
47
+ messages: Record<string, Record<string, string>>
48
+ }
49
+
50
+ export interface I18nInstance {
51
+ translate: (key: string) => string
52
+ locale: string
53
+ }
54
+
55
+ export const i18nInjectionKey: InjectionKey<I18nInstance> = Symbol('i18n')
56
+
57
+ export function createI18n(options: I18nOptions) {
58
+ const i18n: I18nInstance = {
59
+ translate(key: string) {
60
+ return options.messages[options.locale]?.[key] ?? key
61
+ },
62
+ locale: options.locale
63
+ }
64
+
65
+ return {
66
+ install(app: App) {
67
+ // For Composition API
68
+ app.provide(i18nInjectionKey, i18n)
69
+
70
+ // For Options API / templates
71
+ app.config.globalProperties.$t = i18n.translate
72
+ app.config.globalProperties.$i18n = i18n
73
+ }
74
+ }
75
+ }
76
+
77
+ // types/i18n.d.ts (or in the same file after export)
78
+ export {}
79
+
80
+ declare module 'vue' {
81
+ interface ComponentCustomProperties {
82
+ $t: (key: string) => string
83
+ $i18n: I18nInstance
84
+ }
85
+ }
86
+ ```
87
+
88
+ ## Alternative: Augment @vue/runtime-core
89
+
90
+ Some plugins augment `@vue/runtime-core` instead of `vue`:
91
+
92
+ ```typescript
93
+ // types/global.d.ts
94
+ export {}
95
+
96
+ declare module '@vue/runtime-core' {
97
+ interface ComponentCustomProperties {
98
+ $myPlugin: MyPluginInstance
99
+ }
100
+ }
101
+ ```
102
+
103
+ Both approaches work, but `'vue'` is more common in application code.
104
+
105
+ ## Ensure tsconfig.json Includes the Declaration File
106
+
107
+ ```json
108
+ {
109
+ "compilerOptions": {
110
+ // ...
111
+ },
112
+ "include": [
113
+ "src/**/*.ts",
114
+ "src/**/*.vue",
115
+ "types/**/*.d.ts" // Include your declaration files
116
+ ]
117
+ }
118
+ ```
119
+
120
+ ## For Library Authors: package.json Types Field
121
+
122
+ If publishing a plugin as a package:
123
+
124
+ ```json
125
+ {
126
+ "name": "my-vue-plugin",
127
+ "types": "./dist/types/index.d.ts",
128
+ "exports": {
129
+ ".": {
130
+ "types": "./dist/types/index.d.ts",
131
+ "import": "./dist/index.mjs"
132
+ }
133
+ }
134
+ }
135
+ ```
136
+
137
+ ## Common Errors and Solutions
138
+
139
+ ### Error: Property '$xyz' does not exist on type
140
+
141
+ 1. Check that your `.d.ts` file has `export {}` or an import statement
142
+ 2. Verify the file is included in `tsconfig.json`
143
+ 3. Restart your TypeScript language server (VS Code: Cmd+Shift+P > "Restart TS Server")
144
+
145
+ ### Error: Types work in some components but not others
146
+
147
+ This often happens when using Vetur instead of Volar. If you're on Vue 3, switch to Volar (Vue - Official extension).
148
+
149
+ ### Error in Options API but not Composition API
150
+
151
+ Global properties on `this` require proper augmentation of `ComponentCustomProperties`. The Composition API uses `inject()` which is typed separately.
152
+
153
+ ## References
154
+
155
+ - [Vue.js TypeScript with Options API](https://vuejs.org/guide/typescript/options-api.html)
156
+ - [TypeScript Module Augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation)
157
+ - [Vue.js Plugins Documentation](https://vuejs.org/guide/reusability/plugins.html)
@@ -0,0 +1,161 @@
1
+ ---
2
+ title: defineProps Cannot Access Variables from script setup
3
+ impact: MEDIUM
4
+ impactDescription: Variables declared in script setup are not accessible inside defineProps arguments
5
+ type: gotcha
6
+ tags: [vue3, props, script-setup, defineProps, compiler]
7
+ ---
8
+
9
+ # defineProps Cannot Access Variables from script setup
10
+
11
+ **Impact: MEDIUM** - Code inside the `defineProps()` argument cannot access other variables declared in `<script setup>`. The entire expression is moved to an outer function scope when compiled, making local variables inaccessible.
12
+
13
+ This commonly surprises developers trying to use imported constants or computed validation logic.
14
+
15
+ ## Task Checklist
16
+
17
+ - [ ] Define validation constants outside `<script setup>` or in a separate file
18
+ - [ ] Import constants before using them in defineProps
19
+ - [ ] Use external type definitions for TypeScript props
20
+ - [ ] For dynamic validation, use watchers instead of prop validators
21
+
22
+ **Incorrect:**
23
+ ```vue
24
+ <script setup>
25
+ import { ref } from 'vue'
26
+
27
+ // These are in <script setup> scope
28
+ const VALID_SIZES = ['sm', 'md', 'lg']
29
+ const maxLength = ref(100)
30
+
31
+ defineProps({
32
+ size: {
33
+ type: String,
34
+ // WRONG: VALID_SIZES is not accessible here
35
+ validator: (v) => VALID_SIZES.includes(v) // ReferenceError!
36
+ },
37
+ name: {
38
+ type: String,
39
+ // WRONG: Cannot access refs
40
+ validator: (v) => v.length <= maxLength.value // ReferenceError!
41
+ }
42
+ })
43
+ </script>
44
+ ```
45
+
46
+ **Correct:**
47
+ ```vue
48
+ <script>
49
+ // Define constants in regular <script> block (module scope)
50
+ export const VALID_SIZES = ['sm', 'md', 'lg']
51
+ export const MAX_LENGTH = 100
52
+ </script>
53
+
54
+ <script setup>
55
+ // Now accessible in defineProps
56
+ defineProps({
57
+ size: {
58
+ type: String,
59
+ validator: (v) => VALID_SIZES.includes(v) // Works!
60
+ },
61
+ name: {
62
+ type: String,
63
+ validator: (v) => v.length <= MAX_LENGTH // Works!
64
+ }
65
+ })
66
+ </script>
67
+ ```
68
+
69
+ ## Pattern: Import from External File
70
+
71
+ ```javascript
72
+ // validation.js
73
+ export const VALID_SIZES = ['sm', 'md', 'lg']
74
+ export const VALID_COLORS = ['red', 'blue', 'green']
75
+ export const sizeValidator = (v) => VALID_SIZES.includes(v)
76
+ ```
77
+
78
+ ```vue
79
+ <script setup>
80
+ import { VALID_SIZES, VALID_COLORS, sizeValidator } from './validation'
81
+
82
+ // Imported values ARE accessible
83
+ defineProps({
84
+ size: {
85
+ type: String,
86
+ validator: sizeValidator
87
+ },
88
+ color: {
89
+ type: String,
90
+ validator: (v) => VALID_COLORS.includes(v)
91
+ }
92
+ })
93
+ </script>
94
+ ```
95
+
96
+ ## Pattern: Dual Script Blocks
97
+
98
+ ```vue
99
+ <script>
100
+ // Regular script for module-level declarations
101
+ const options = {
102
+ themes: ['light', 'dark', 'system'],
103
+ defaults: {
104
+ theme: 'light',
105
+ size: 'md'
106
+ }
107
+ }
108
+ </script>
109
+
110
+ <script setup>
111
+ // options is accessible here
112
+ const props = defineProps({
113
+ theme: {
114
+ type: String,
115
+ default: options.defaults.theme,
116
+ validator: (v) => options.themes.includes(v)
117
+ }
118
+ })
119
+ </script>
120
+ ```
121
+
122
+ ## TypeScript: External Type Definitions
123
+
124
+ ```typescript
125
+ // types.ts
126
+ export interface UserProps {
127
+ name: string
128
+ email: string
129
+ age?: number
130
+ }
131
+ ```
132
+
133
+ ```vue
134
+ <script setup lang="ts">
135
+ import type { UserProps } from './types'
136
+
137
+ // Type imports work fine
138
+ const props = defineProps<UserProps>()
139
+ </script>
140
+ ```
141
+
142
+ ## Why This Happens
143
+
144
+ Vue's compiler transforms `<script setup>` code. The `defineProps()` call is extracted and moved to component options at compile time, before the setup function runs:
145
+
146
+ ```javascript
147
+ // Your code:
148
+ const MY_CONST = 'value'
149
+ defineProps({ prop: { default: MY_CONST } })
150
+
151
+ // Compiled (simplified):
152
+ export default {
153
+ props: { prop: { default: MY_CONST } }, // MY_CONST doesn't exist here!
154
+ setup() {
155
+ const MY_CONST = 'value' // Defined too late
156
+ }
157
+ }
158
+ ```
159
+
160
+ ## Reference
161
+ - [Vue.js Script Setup - defineProps](https://vuejs.org/api/sfc-script-setup.html#defineprops-defineemits)