{"id":10838,"library":"eslint-plugin-vue-composable","title":"ESLint Plugin for Vue Composables","description":"This ESLint plugin provides a set of rules specifically designed to enforce best practices and prevent common pitfalls when working with Vue 3 composables and lifecycle hooks. It ensures that composable functions (prefixed with `use`) and lifecycle hook calls (like `onMounted`, `onBeforeUnmount`, etc.) are correctly placed within `setup()` functions, other composables, or Vue's `<script setup>` block. The plugin, currently at version 1.0.0, aims to help developers maintain proper reactivity contexts and avoid issues like calling hooks or composables after `await` expressions in incorrect scopes. It supports both modern ESLint flat configurations (`eslint.config.js`) and legacy `.eslintrc` formats, providing flexibility for different project setups. Its release cadence is likely tied to the evolving best practices for Vue composables, offering focused linting compared to general Vue ESLint plugins.","status":"active","version":"1.0.0","language":"javascript","source_language":"en","source_url":null,"tags":["javascript","eslint","eslint-plugin","vue","composable"],"install":[{"cmd":"npm install eslint-plugin-vue-composable","lang":"bash","label":"npm"},{"cmd":"yarn add eslint-plugin-vue-composable","lang":"bash","label":"yarn"},{"cmd":"pnpm add eslint-plugin-vue-composable","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Peer dependency for ESLint core functionality.","package":"eslint","optional":false},{"reason":"Required for general Vue-related linting context and integration.","package":"eslint-plugin-vue","optional":false}],"imports":[{"note":"Primarily used for ESLint flat configurations (eslint.config.js). The CommonJS `require` form may lead to issues or incorrect configuration loading in modern setups expecting ESM.","wrong":"const vueComposable = require('eslint-plugin-vue-composable')","symbol":"vueComposable","correct":"import vueComposable from 'eslint-plugin-vue-composable'"},{"note":"This is the recommended way to integrate with ESLint flat configurations, providing a baseline of rules for composables.","symbol":"flat/recommended config","correct":"import vueComposable from 'eslint-plugin-vue-composable'; export default [...vueComposable.configs['flat/recommended']]"},{"note":"For projects using the legacy `.eslintrc` configuration format, the plugin is enabled via the 'extends' property with a string identifier, not a direct import.","symbol":"Legacy .eslintrc config","correct":"{ \"extends\": [\"plugin:vue-composable/recommended\"] }"}],"quickstart":{"code":"import vueComposable from 'eslint-plugin-vue-composable'\n\nexport default [\n  // Ensure ESLint is configured for Vue and TypeScript if applicable\n  // For example: \n  // ...require('@eslint/js').configs.recommended, \n  // ...pluginVue.configs['flat/recommended'],\n  // ...parserTs.configs.recommended,\n  \n  // Add the vue-composable recommended rules\n  ...vueComposable.configs['flat/recommended'],\n\n  // You can override specific rules or add custom configurations\n  {\n    rules: {\n      'vue-composable/lifecycle-placement': 'warn', // Change severity of a specific rule\n      'vue-composable/composable-placement': 'error' // Enforce composable placement strictly\n    }\n  },\n  // Define files to lint\n  {\n    files: ['**/*.vue', '**/*.ts', '**/*.js'],\n    languageOptions: {\n      parserOptions: {\n        ecmaVersion: 'latest',\n        sourceType: 'module'\n      }\n    }\n  }\n]","lang":"javascript","description":"Demonstrates how to configure `eslint-plugin-vue-composable` using the modern ESLint flat configuration (`eslint.config.js`), including how to apply recommended rules and override specific rule severities."},"warnings":[{"fix":"Ensure composables and lifecycle hooks are called directly within `setup()`, another composable, or within `<script setup>` before any `await` expressions, unless specifically supported by `<script setup>` behavior.","message":"Incorrect placement of composable functions or lifecycle hooks can lead to reactivity issues or unintended behavior. Rules like `composable-placement` and `lifecycle-placement` explicitly warn against calling them after `await` expressions outside of `<script setup>`.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Choose either the legacy `.eslintrc` or the modern `eslint.config.js` format and follow the corresponding installation instructions. Do not attempt to use both simultaneously or combine their configuration syntaxes.","message":"Mixing ESLint's legacy (`.eslintrc`) and flat (`eslint.config.js`) configuration formats can cause rules to not be applied correctly or lead to parsing errors. This plugin provides distinct setup instructions for each.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Refactor your code to ensure that composables and lifecycle hooks are only invoked from `setup()`, within other composable functions, or directly in `<script setup>`.","message":"Calling composable functions or lifecycle hooks within regular, non-composable JavaScript functions (i.e., functions not starting with `use` or not directly `setup()`) will trigger linting errors for rules like `composable-placement` and `lifecycle-placement`.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Move the composable call before the `await` expression, or refactor the code to use `<script setup>` if suitable for async operations, or ensure the call is within a valid composable context.","cause":"A Vue composable function (e.g., `useSomething()`) was called after an `await` statement in a context other than Vue's `<script setup>`.","error":"ESLint: Composable call must be placed in `setup()` or another composable, not after an `await` expression. (vue-composable/composable-placement)"},{"fix":"Ensure all lifecycle hook calls are made before any `await` expressions within `setup()` or other composables, or leverage `<script setup>`'s async capabilities where appropriate.","cause":"A Vue lifecycle hook (e.g., `onMounted()`) was invoked after an `await` statement in a context other than Vue's `<script setup>`.","error":"ESLint: Lifecycle hook call must be placed in `setup()` or another composable, not after an `await` expression. (vue-composable/lifecycle-placement)"},{"fix":"Refactor the calling function to be a composable (start its name with `use`) or move the composable call into `setup()` or an existing composable.","cause":"A function recognized as a composable (due to its `use` prefix) was called from a regular JavaScript function that is not itself a composable or `setup()` function.","error":"ESLint: Composable 'useBar' called in non-composable function 'foo'. (vue-composable/composable-placement)"}],"ecosystem":"npm"}