npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

vue-permission-directive

v3.0.6

Published

A flexible Vue 3 directive for managing user permissions with support for AND, OR, regex, and pattern-based checks.

Downloads

42

Readme

🔐 v-permission

Vue directive for controlling element visibility based on user permissions.

Supports dynamic permission checks, customizable strategies, Nuxt, and Pinia.


📦 Installation

npm install vue-permission-directive
# or
yarn add vue-permission-directive

🚀 Usage

Register globally (main.ts)

import { createApp } from "vue";
import App from "./App.vue";
import vPermission, {
  configurePermissionDirective,
} from "vue-permission-directive";

const app = createApp(App);

configurePermissionDirective({
  getUserPermissions: () => ["view_dashboard", "edit_profile"],
});

app.directive("permission", vPermission);
app.mount("#app");

👁️ Basic Usage

<!-- Will be shown only if user has 'view_dashboard' permission -->
<button v-permission="'view_dashboard'">Dashboard</button>

<!-- Will be shown if user has ANY of the listed permissions -->
<button v-permission="['edit_user', 'delete_user']">Manage User</button>

🔄 Dynamic Updates

If user permissions change during runtime, call:

import { clearPermissionCache } from "vue-permission-directive";
clearPermissionCache();

🔧 Advanced Configuration

configurePermissionDirective({
  getUserPermissions: async () => {
    const user = await fetchUser();
    return user.permissions;
  },
  strategy: "some", // or 'every' for AND logic
  fallback: "hide", // or 'disable'
});

🧪 Development Mode

Enable logging to debug permission checks:

import { setDevelopmentMode } from "vue-permission-directive";
setDevelopmentMode(true);

🧠 Custom Strategies

configurePermissionDirective({
  strategyFn: (required, userPermissions) => {
    return (
      userPermissions.includes("super_admin") ||
      required.some((p) => userPermissions.includes(p))
    );
  },
});

🎯 Permission Format Types

The directive supports multiple permission formats for flexible permission checking:

1. String Format

<!-- Single permission -->
<button v-permission="'user.read'">View Users</button>

<!-- Wildcard permission (allows everything) -->
<button v-permission="'*'">Super Admin Action</button>

2. Array Format (OR Logic)

<!-- User needs ANY of these permissions -->
<button v-permission="['user.edit', 'user.delete', 'admin.manage']">
  Manage Users
</button>

3. Permission Object Format

For advanced permission logic, use objects with different modes:

<!-- AND Logic: User needs ALL permissions -->
<button
  v-permission="{ permissions: ['user.read', 'user.write'], mode: 'and' }"
>
  Full User Access
</button>

<!-- OR Logic: User needs ANY permission -->
<button
  v-permission="{ permissions: ['admin.dashboard', 'user.manage'], mode: 'or' }"
>
  Admin Panel
</button>

<!-- StartWith Logic: Check if user has permissions starting with pattern -->
<button
  v-permission="{ permissions: ['admin', 'moderator'], mode: 'startWith' }"
>
  Staff Only
</button>

<!-- EndWith Logic: Check if user has permissions ending with pattern -->
<button v-permission="{ permissions: ['.write', '.delete'], mode: 'endWith' }">
  Edit Actions
</button>

<!-- Exact Match: Same as 'or' but more explicit -->
<button v-permission="{ permissions: ['posts.publish'], mode: 'exact' }">
  Publish Post
</button>

<!-- Regex Logic: Use regex patterns to match permissions -->
<button
  v-permission="{ permissions: ['user\\.(read|write|edit)'], mode: 'regex' }"
>
  User Operations
</button>

4. Mixed Array Format

<!-- Combine strings and objects for complex logic -->
<button
  v-permission="[
    'super_admin',
    { permissions: ['user.read', 'posts.read'], mode: 'and' },
  ]"
>
  Advanced Access
</button>

Permission Modes Reference

| Mode | Description | Example | | ----------- | ------------------------------------------- | ----------------------------------------------------------- | | and | ALL permissions must be satisfied | User needs both user.read AND user.write | | or | ANY permission must be satisfied | User needs admin.dashboard OR user.manage | | startWith | Any user permission starts with the pattern | User permission admin.users.read matches pattern admin | | endWith | Any user permission ends with the pattern | User permission posts.create matches pattern .create | | exact | Exact match (same as basic string check) | User permission must be exactly posts.publish | | regex | Regular expression matching | User permission matches regex pattern user\.(read\|write) |


🌐 Nuxt Support

Inside plugins/v-permission.client.ts:

import { defineNuxtPlugin } from "#app";
import vPermission, {
  configurePermissionDirective,
} from "vue-permission-directive";

export default defineNuxtPlugin((nuxtApp) => {
  configurePermissionDirective({
    getUserPermissions: () => useAuthStore().permissions,
  });

  nuxtApp.vueApp.directive("permission", vPermission);
});

🧩 Pinia Example

import { useAuthStore } from "@/stores/auth";

configurePermissionDirective({
  getUserPermissions: () => useAuthStore().permissions,
});

📝 Directive Modifiers

Show/Hide Behavior

<!-- Default: Remove element from DOM when permission denied -->
<button v-permission="'admin.access'">Admin Panel</button>

<!-- Show modifier: Hide element but keep in DOM -->
<button v-permission:show="'user.profile'">Edit Profile</button>

Performance Modifiers

<!-- Once modifier: Check permission only once (no reactive updates) -->
<button v-permission.once="'static.permission'">Static Action</button>

<!-- Lazy modifier: Don't watch for permission changes -->
<button v-permission.lazy="'user.read'">User List</button>

🔄 Programmatic Permission Checking

You can also check permissions programmatically in your components:

import { hasPermission } from "vue-permission-directive";

export default {
  async mounted() {
    // Check single permission
    const canEdit = await hasPermission("user.edit");

    // Check multiple permissions (OR logic)
    const canManage = await hasPermission(["user.edit", "user.delete"]);

    // Check with advanced logic
    const hasAdvancedAccess = await hasPermission({
      permissions: ["admin.read", "admin.write"],
      mode: "and",
    });

    if (canEdit) {
      this.showEditButton = true;
    }
  },
};

✅ API Reference

v-permission="string | string[] | PermissionObject | (string | PermissionObject)[]"

Required permission(s) to display the element.

configurePermissionDirective(permissions, options?)

| Parameter | Type | Description | | ------------------------- | --------------------------- | ----------------------------------------------- | | permissions | string[] \| Ref<string[]> | Array of user permissions or reactive reference | | options.developmentMode | boolean | Enable debug logging (default: false) |

Core Functions

  • hasPermission(permission) - Check if user has specific permission(s)
  • setDevelopmentMode(enabled) - Enable/disable debug logging
  • clearPermissionCache() - Clear cached permissions for dynamic updates
  • initPermissionDirectiveIfNeeded() - Initialize permissions from localStorage

Permission Types

export type PermissionMode =
  | "and"
  | "or"
  | "startWith"
  | "endWith"
  | "exact"
  | "regex";

export interface PermissionObject {
  permissions: string[];
  mode: PermissionMode;
}

export type PermissionValue =
  | string
  | string[]
  | PermissionObject
  | (string | PermissionObject)[];

🛠️ Best Practices

1. Permission Naming Convention

// ✅ Good: Use hierarchical naming
"user.read";
"user.write";
"user.delete";
"admin.dashboard.view";
"posts.create";
"posts.edit.own";

// ❌ Avoid: Flat or unclear naming
"read";
"edit";
"access";

2. Use Appropriate Permission Modes

<!-- ✅ Use 'and' when user needs multiple permissions -->
<button
  v-permission="{ permissions: ['user.read', 'user.write'], mode: 'and' }"
>
  Full Access
</button>

<!-- ✅ Use 'startWith' for hierarchical permissions -->
<div v-permission="{ permissions: ['admin'], mode: 'startWith' }">
  Admin Section
</div>

<!-- ✅ Use regex for complex patterns -->
<button
  v-permission="{
    permissions: ['posts\\.(create|edit|delete)'],
    mode: 'regex',
  }"
>
  Manage Posts
</button>

3. Combine with Route Guards

// router/index.ts
router.beforeEach(async (to, from, next) => {
  const requiredPermission = to.meta.permission;
  if (requiredPermission && !(await hasPermission(requiredPermission))) {
    next("/403");
  } else {
    next();
  }
});

4. Handle Permission Updates

// When user permissions change (login, role update, etc.)
const updateUserPermissions = async () => {
  // Update permissions in your store
  authStore.permissions = await fetchUserPermissions();

  // Clear cache to trigger re-evaluation
  clearPermissionCache();
};

🔍 Debugging

Enable development mode to see detailed permission check logs:

import { setDevelopmentMode } from "vue-permission-directive";

setDevelopmentMode(true);

// Now you'll see logs like:
// [v-permission] Checking permission: user.read
// [v-permission] User permissions: ['user.read', 'user.write']
// [v-permission] Permission granted: true

🧪 Testing

Test different permission scenarios:

import { testPermissions } from "vue-permission-directive";

// Run comprehensive tests
await testPermissions();

📊 Performance Notes

  • Permissions are cached to avoid repeated evaluations
  • Use .once modifier for static permissions that don't change
  • Use .lazy modifier to disable reactive updates
  • Clear cache only when permissions actually change

🤝 Contributing

We welcome contributions! Please read our contributing guidelines before submitting PRs.


📄 License

MIT © Kerolos