vue-accessguard 1.0.0 → 1.0.2

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 CHANGED
@@ -1,8 +1,8 @@
1
1
  <div align="center">
2
- <img src="./public/logo.png" alt="AccessGuard Logo" width="100%" />
2
+ <img src="https://unpkg.com/vue-accessguard/dist/logo.png" alt="AccessGuard Logo" width="100%" />
3
3
  </div>
4
4
 
5
- # @sawalabs/vue-accessguard
5
+ # vue-accessguard
6
6
 
7
7
  The **vue-accessguard** library is a robust, lightweight **Role-Based Access Control (RBAC)** solution for **Vue 3** applications. It provides granular control over UI rendering and module protection using Directives, Components, and Composables for protecting views depending on user *roles* or *permissions*. It supports dynamic **Wildcard Matching** (e.g. `*` for Super Admin or `resource:*` for namespaces).
8
8
 
@@ -169,7 +169,12 @@ Vue-accessguard scales linearly with enterprise needs with built in string-based
169
169
 
170
170
  ## Storybook
171
171
 
172
- You can visually test permission mocking by launching Storybook locally:
172
+ Interactive visual documentation is available online:
173
+ 👉 **[View Live Storybook Documentation](https://sawalabs.github.io/Vue-AccessGuard/)**
174
+
175
+ ### Running Locally
176
+
177
+ You can also visually test permission mocking by launching Storybook locally:
173
178
 
174
179
  ```bash
175
180
  pnpm run storybook
@@ -1,5 +1,5 @@
1
- import { defineComponent as l, toRef as y, provide as A, effectScope as v, watchEffect as h, inject as G, computed as w } from "vue";
2
- const u = /* @__PURE__ */ Symbol("AccessGuard"), b = l({
1
+ import { defineComponent as f, toRef as v, provide as h, effectScope as G, watchEffect as w, inject as S, computed as R } from "vue";
2
+ const i = Symbol("AccessGuard"), x = f({
3
3
  name: "AccessGuardProvider",
4
4
  props: {
5
5
  user: {
@@ -8,65 +8,73 @@ const u = /* @__PURE__ */ Symbol("AccessGuard"), b = l({
8
8
  }
9
9
  },
10
10
  setup(r, { slots: n }) {
11
- const s = y(r, "user");
12
- return A(u, {
13
- user: s
14
- }), () => n.default?.();
11
+ const c = v(r, "user");
12
+ return h(i, {
13
+ user: c
14
+ }), () => {
15
+ var t;
16
+ return (t = n.default) == null ? void 0 : t.call(n);
17
+ };
15
18
  }
16
19
  });
17
- function d(r, n, s = "any") {
18
- if (!r?.length) return !1;
19
- const t = Array.isArray(n) ? n : [n], e = (o) => {
20
- if (r.includes("*") || r.includes(o)) return !0;
21
- const [c] = o.split(":"), i = `${c}:*`;
22
- return r.includes(i);
20
+ function m(r, n, c = "any") {
21
+ if (!(r != null && r.length)) return !1;
22
+ const t = Array.isArray(n) ? n : [n], e = (s) => {
23
+ if (r.includes("*") || r.includes(s)) return !0;
24
+ const [o] = s.split(":"), a = `${o}:*`;
25
+ return r.includes(a);
23
26
  };
24
- return s === "all" ? t.every(e) : t.some(e);
27
+ return c === "all" ? t.every(e) : t.some(e);
25
28
  }
26
- const S = {
29
+ const b = {
27
30
  mounted(r, n) {
28
- const s = n.instance;
29
- if (!s) return;
30
- let t = s.$.parent, e;
31
+ var o;
32
+ const c = n.instance;
33
+ if (!c) return;
34
+ let t = c.$.parent, e;
31
35
  for (; t && !e; )
32
- e = t.provides?.[u], t = t.parent;
36
+ e = (o = t.provides) == null ? void 0 : o[i], t = t.parent;
33
37
  if (!e)
34
38
  throw new Error("[AccessGuard] v-can used outside AccessGuardProvider");
35
- const o = v();
36
- o.run(() => {
37
- h(() => {
38
- const c = n.value;
39
- let i, a = "any";
40
- typeof c == "string" || Array.isArray(c) ? i = c : (i = c.permission, a = c.mode ?? "any");
41
- const m = e.user.value?.permissions ?? [], p = d(m, i, a);
42
- r.style.display = p ? "" : "none";
39
+ const s = G();
40
+ s.run(() => {
41
+ w(() => {
42
+ var l;
43
+ const a = n.value;
44
+ let u, d = "any";
45
+ typeof a == "string" || Array.isArray(a) ? u = a : (u = a.permission, d = a.mode ?? "any");
46
+ const y = ((l = e.user.value) == null ? void 0 : l.permissions) ?? [], A = m(y, u, d);
47
+ r.style.display = A ? "" : "none";
43
48
  });
44
- }), r._scope = o;
49
+ }), r._scope = s;
45
50
  },
46
51
  unmounted(r) {
47
- r._scope?.stop();
52
+ var n;
53
+ (n = r._scope) == null || n.stop();
48
54
  }
49
55
  };
50
- function f() {
51
- const r = G(
52
- u
56
+ function p() {
57
+ const r = S(
58
+ i
53
59
  );
54
60
  if (!r)
55
61
  throw new Error("useAccessGuard must be used within AccessGuardProvider");
56
62
  const n = (t, e = "any") => {
57
- const o = r.user.value?.permissions || [];
58
- return d(o, t, e);
63
+ var o;
64
+ const s = ((o = r.user.value) == null ? void 0 : o.permissions) || [];
65
+ return m(s, t, e);
59
66
  };
60
67
  return {
61
68
  can: n,
62
69
  cannot: (t, e) => !n(t, e),
63
70
  hasRole: (t, e = "any") => {
64
- const o = r.user.value?.roles || [], c = Array.isArray(t) ? t : [t];
65
- return e === "all" ? c.every((i) => o.includes(i)) : c.some((i) => o.includes(i));
71
+ var a;
72
+ const s = ((a = r.user.value) == null ? void 0 : a.roles) || [], o = Array.isArray(t) ? t : [t];
73
+ return e === "all" ? o.every((u) => s.includes(u)) : o.some((u) => s.includes(u));
66
74
  }
67
75
  };
68
76
  }
69
- const g = l({
77
+ const E = f({
70
78
  name: "Guard",
71
79
  props: {
72
80
  permission: {
@@ -83,30 +91,33 @@ const g = l({
83
91
  }
84
92
  },
85
93
  setup(r, { slots: n }) {
86
- const s = f(), t = w(() => {
94
+ const c = p(), t = R(() => {
87
95
  if (!r.permission && !r.role) return !0;
88
96
  let e = !0;
89
- return r.permission && (e = e && s.can(r.permission, r.mode)), r.role && e && (e = e && s.hasRole(r.role, r.mode)), e;
97
+ return r.permission && (e = e && c.can(r.permission, r.mode)), r.role && e && (e = e && c.hasRole(r.role, r.mode)), e;
90
98
  });
91
- return () => t.value ? n.default?.() : null;
99
+ return () => {
100
+ var e;
101
+ return t.value ? (e = n.default) == null ? void 0 : e.call(n) : null;
102
+ };
92
103
  }
93
104
  });
94
- function x(r) {
95
- const { can: n, hasRole: s } = f();
105
+ function j(r) {
106
+ const { can: n, hasRole: c } = p();
96
107
  return r.beforeEach((t) => {
97
108
  const e = t.meta;
98
- if (e.permission && !n(e.permission, e.mode) || e.role && !s(e.role, e.mode))
109
+ if (e.permission && !n(e.permission, e.mode) || e.role && !c(e.role, e.mode))
99
110
  return e.redirect || "/";
100
111
  });
101
112
  }
102
- function E(r) {
103
- r.directive("can", S);
113
+ function q(r) {
114
+ r.directive("can", b);
104
115
  }
105
116
  export {
106
- b as AccessGuardProvider,
107
- u as AccessGuardSymbol,
108
- g as Guard,
109
- x as applyAccessGuard,
110
- E as install,
111
- f as useAccessGuard
117
+ x as AccessGuardProvider,
118
+ i as AccessGuardSymbol,
119
+ E as Guard,
120
+ j as applyAccessGuard,
121
+ q as install,
122
+ p as useAccessGuard
112
123
  };
@@ -1 +1 @@
1
- (function(t,c){typeof exports=="object"&&typeof module<"u"?c(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],c):(t=typeof globalThis<"u"?globalThis:t||self,c(t.VueAccessGuard={},t.Vue))})(this,(function(t,c){"use strict";const d=Symbol("AccessGuard"),y=c.defineComponent({name:"AccessGuardProvider",props:{user:{type:Object,required:!0}},setup(r,{slots:s}){const o=c.toRef(r,"user");return c.provide(d,{user:o}),()=>s.default?.()}});function f(r,s,o="any"){if(!r?.length)return!1;const n=Array.isArray(s)?s:[s],e=i=>{if(r.includes("*")||r.includes(i))return!0;const[u]=i.split(":"),a=`${u}:*`;return r.includes(a)};return o==="all"?n.every(e):n.some(e)}const p={mounted(r,s){const o=s.instance;if(!o)return;let n=o.$.parent,e;for(;n&&!e;)e=n.provides?.[d],n=n.parent;if(!e)throw new Error("[AccessGuard] v-can used outside AccessGuardProvider");const i=c.effectScope();i.run(()=>{c.watchEffect(()=>{const u=s.value;let a,m="any";typeof u=="string"||Array.isArray(u)?a=u:(a=u.permission,m=u.mode??"any");const v=e.user.value?.permissions??[],w=f(v,a,m);r.style.display=w?"":"none"})}),r._scope=i},unmounted(r){r._scope?.stop()}};function l(){const r=c.inject(d);if(!r)throw new Error("useAccessGuard must be used within AccessGuardProvider");const s=(n,e="any")=>{const i=r.user.value?.permissions||[];return f(i,n,e)};return{can:s,cannot:(n,e)=>!s(n,e),hasRole:(n,e="any")=>{const i=r.user.value?.roles||[],u=Array.isArray(n)?n:[n];return e==="all"?u.every(a=>i.includes(a)):u.some(a=>i.includes(a))}}}const A=c.defineComponent({name:"Guard",props:{permission:{type:[String,Array],required:!1},role:{type:[String,Array],required:!1},mode:{type:String,default:"any"}},setup(r,{slots:s}){const o=l(),n=c.computed(()=>{if(!r.permission&&!r.role)return!0;let e=!0;return r.permission&&(e=e&&o.can(r.permission,r.mode)),r.role&&e&&(e=e&&o.hasRole(r.role,r.mode)),e});return()=>n.value?s.default?.():null}});function G(r){const{can:s,hasRole:o}=l();return r.beforeEach(n=>{const e=n.meta;if(e.permission&&!s(e.permission,e.mode)||e.role&&!o(e.role,e.mode))return e.redirect||"/"})}function h(r){r.directive("can",p)}t.AccessGuardProvider=y,t.AccessGuardSymbol=d,t.Guard=A,t.applyAccessGuard=G,t.install=h,t.useAccessGuard=l,Object.defineProperty(t,Symbol.toStringTag,{value:"Module"})}));
1
+ (function(c,s){typeof exports=="object"&&typeof module<"u"?s(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],s):(c=typeof globalThis<"u"?globalThis:c||self,s(c.VueAccessGuard={},c.Vue))})(this,(function(c,s){"use strict";const l=Symbol("AccessGuard"),A=s.defineComponent({name:"AccessGuardProvider",props:{user:{type:Object,required:!0}},setup(r,{slots:n}){const o=s.toRef(r,"user");return s.provide(l,{user:o}),()=>{var t;return(t=n.default)==null?void 0:t.call(n)}}});function m(r,n,o="any"){if(!(r!=null&&r.length))return!1;const t=Array.isArray(n)?n:[n],e=u=>{if(r.includes("*")||r.includes(u))return!0;const[i]=u.split(":"),a=`${i}:*`;return r.includes(a)};return o==="all"?t.every(e):t.some(e)}const G={mounted(r,n){var i;const o=n.instance;if(!o)return;let t=o.$.parent,e;for(;t&&!e;)e=(i=t.provides)==null?void 0:i[l],t=t.parent;if(!e)throw new Error("[AccessGuard] v-can used outside AccessGuardProvider");const u=s.effectScope();u.run(()=>{s.watchEffect(()=>{var p;const a=n.value;let d,y="any";typeof a=="string"||Array.isArray(a)?d=a:(d=a.permission,y=a.mode??"any");const S=((p=e.user.value)==null?void 0:p.permissions)??[],b=m(S,d,y);r.style.display=b?"":"none"})}),r._scope=u},unmounted(r){var n;(n=r._scope)==null||n.stop()}};function f(){const r=s.inject(l);if(!r)throw new Error("useAccessGuard must be used within AccessGuardProvider");const n=(t,e="any")=>{var i;const u=((i=r.user.value)==null?void 0:i.permissions)||[];return m(u,t,e)};return{can:n,cannot:(t,e)=>!n(t,e),hasRole:(t,e="any")=>{var a;const u=((a=r.user.value)==null?void 0:a.roles)||[],i=Array.isArray(t)?t:[t];return e==="all"?i.every(d=>u.includes(d)):i.some(d=>u.includes(d))}}}const h=s.defineComponent({name:"Guard",props:{permission:{type:[String,Array],required:!1},role:{type:[String,Array],required:!1},mode:{type:String,default:"any"}},setup(r,{slots:n}){const o=f(),t=s.computed(()=>{if(!r.permission&&!r.role)return!0;let e=!0;return r.permission&&(e=e&&o.can(r.permission,r.mode)),r.role&&e&&(e=e&&o.hasRole(r.role,r.mode)),e});return()=>{var e;return t.value?(e=n.default)==null?void 0:e.call(n):null}}});function v(r){const{can:n,hasRole:o}=f();return r.beforeEach(t=>{const e=t.meta;if(e.permission&&!n(e.permission,e.mode)||e.role&&!o(e.role,e.mode))return e.redirect||"/"})}function w(r){r.directive("can",G)}c.AccessGuardProvider=A,c.AccessGuardSymbol=l,c.Guard=h,c.applyAccessGuard=v,c.install=w,c.useAccessGuard=f,Object.defineProperty(c,Symbol.toStringTag,{value:"Module"})}));
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "vue-accessguard",
3
+ "license": "MIT",
3
4
  "publishConfig": {
4
5
  "access": "public"
5
6
  },
6
- "version": "1.0.0",
7
+ "version": "1.0.2",
7
8
  "type": "module",
8
9
  "main": "dist/vue-access-guard.umd.js",
9
10
  "module": "dist/vue-access-guard.es.js",
@@ -35,12 +36,13 @@
35
36
  "@vitest/coverage-v8": "4.0.18",
36
37
  "@vue/test-utils": "^2.4.6",
37
38
  "@vue/tsconfig": "^0.8.1",
39
+ "gh-pages": "^6.3.0",
38
40
  "jsdom": "^28.1.0",
39
41
  "playwright": "^1.58.2",
40
42
  "storybook": "^8.6.17",
41
43
  "storybook-vue3-router": "^4.0.1",
42
44
  "typescript": "~5.9.3",
43
- "vite": "^7.3.1",
45
+ "vite": "^6.0.0",
44
46
  "vitest": "^4.0.18",
45
47
  "vue-router": "^4.6.4",
46
48
  "vue-tsc": "^3.1.5"
@@ -53,6 +55,7 @@
53
55
  "dev": "vite",
54
56
  "build": "vue-tsc -b && vite build",
55
57
  "storybook": "storybook dev -p 6006",
56
- "build-storybook": "storybook build"
58
+ "build-storybook": "storybook build",
59
+ "deploy-storybook": "storybook build && gh-pages -d storybook-static"
57
60
  }
58
61
  }