vue-nuxt-permission
Version:
A unified permission system for Vue 3 and Nuxt 3 / Nuxt 4 with directives, guards, and async support.
336 lines (335 loc) • 10.8 kB
JavaScript
import { ref as j, isRef as y, watch as k } from "vue";
/*! vue-nuxt-permission v2.2.1 | (c) 2026 Kerolos Zakaria | MIT License */
const C = "__v_permission__", x = () => typeof window < "u" && typeof localStorage < "u", F = (e) => {
try {
const r = JSON.stringify(e);
if (typeof TextEncoder < "u") {
const s = new TextEncoder().encode(r), a = Array.from(
s,
(t) => String.fromCharCode(t)
).join("");
return btoa(a);
}
return btoa(unescape(encodeURIComponent(r)));
} catch {
return "";
}
}, T = (e) => {
try {
const r = atob(e);
if (typeof TextDecoder < "u") {
const a = new Uint8Array(r.length);
for (let n = 0; n < r.length; n++)
a[n] = r.charCodeAt(n);
const t = new TextDecoder().decode(a);
return JSON.parse(t);
}
const s = decodeURIComponent(escape(r));
return JSON.parse(s);
} catch {
return null;
}
}, g = (e) => {
if (x())
try {
localStorage.setItem(C, F(e));
} catch (r) {
console.warn("[v-permission] Failed to save permissions to storage:", r);
}
}, D = () => {
if (!x()) return null;
try {
const e = localStorage.getItem(C);
return e ? T(e) : null;
} catch (e) {
return console.warn("[v-permission] Failed to read permissions from storage:", e), null;
}
}, $ = () => {
if (x())
try {
localStorage.removeItem(C);
} catch (e) {
console.warn("[v-permission] Failed to clear permissions from storage:", e);
}
}, u = {
permissions: null,
developmentMode: !1,
decrypt: void 0
}, v = j([]), Q = () => u.decrypt, ee = (e) => {
u.decrypt = e;
}, J = (e, r) => {
const s = (r == null ? void 0 : r.decrypt) ?? (r == null ? void 0 : r.transform) ?? u.decrypt;
if ((r != null && r.decrypt || r != null && r.transform) && (u.decrypt = r.decrypt ?? r.transform), u.developmentMode = (r == null ? void 0 : r.developmentMode) ?? !1, y(e)) {
const t = e;
if (u.permissions = t, s && t.value && !Array.isArray(t.value)) {
const o = s(t.value);
if (o instanceof Promise) {
o.then((c) => {
const i = Array.isArray(c) ? c : [];
t.value = i, v.value = i, (r == null ? void 0 : r.persist) !== !1 && g(i);
});
return;
} else {
const c = Array.isArray(o) ? o : [];
t.value = c;
}
}
const n = Array.isArray(t.value) ? t.value : [];
v.value = n, (r == null ? void 0 : r.persist) !== !1 && g(n);
return;
}
if (s && e !== null && e !== void 0 && !Array.isArray(e)) {
const t = s(e);
if (t instanceof Promise) {
t.then((n) => {
const o = Array.isArray(n) ? n : [];
u.permissions = o, v.value = o, (r == null ? void 0 : r.persist) !== !1 && g(o);
});
return;
} else {
const n = Array.isArray(t) ? t : [];
u.permissions = n, v.value = n, (r == null ? void 0 : r.persist) !== !1 && g(n);
return;
}
}
const a = Array.isArray(e) ? e : [];
u.permissions = a, v.value = a, (r == null ? void 0 : r.persist) !== !1 && g(a);
}, R = () => v, U = () => {
const { permissions: e } = u;
if (!e) return [];
if (y(e)) {
const r = e.value;
return Array.isArray(r) ? r : [];
}
return Array.isArray(e) ? e : [];
}, b = () => u.developmentMode, l = /* @__PURE__ */ new Map(), H = 1e3, W = 5 * 60 * 1e3, z = (e) => {
const r = l.get(e);
return r ? Date.now() - r.timestamp > W ? (l.delete(e), null) : r.value : null;
}, K = (e, r) => {
if (l.size >= H) {
const s = l.keys().next().value;
s && l.delete(s);
}
l.set(e, {
value: r,
timestamp: Date.now()
});
}, q = () => l.clear(), re = () => {
const e = Date.now();
for (const [r, s] of l.entries())
e - s.timestamp > W && l.delete(r);
}, p = (e) => {
if (!e) return [];
const r = y(e) ? e.value : e;
return Array.isArray(r) ? r.filter(Boolean) : [];
}, se = (e) => Array.from(new Set(e)).sort(), B = (e) => {
const r = /* @__PURE__ */ new WeakSet();
return JSON.stringify(e, (s, a) => a && typeof a == "object" ? r.has(a) ? void 0 : (r.add(a), Array.isArray(a) ? a : Object.keys(a).sort().reduce((t, n) => (t[n] = a[n], t), {})) : a);
}, E = (e) => !!e && typeof e == "object" && !Array.isArray(e) && "permissions" in e && "mode" in e, S = /* @__PURE__ */ new Set([
"and",
"or",
"not",
"startWith",
"endWith",
"regex"
]), M = (e) => {
try {
return new RegExp(e).test(""), !0;
} catch {
return !1;
}
}, L = (e, r) => {
var a;
const s = U();
if (e === "*") return !0;
if (typeof e == "string")
return s.includes(e);
if (Array.isArray(e))
return e.includes("*") ? !0 : e.some((t) => s.includes(t));
if (E(e)) {
const { permissions: t, mode: n } = e;
if (!S.has(n) || !Array.isArray(t) || t.length === 0)
return !1;
if (t.includes("*")) return !0;
const o = {
and: () => t.every((c) => s.includes(c)),
or: () => t.some((c) => s.includes(c)),
not: () => !t.some((c) => s.includes(c)),
startWith: () => t.some((c) => s.some((i) => i.startsWith(c))),
endWith: () => t.some((c) => s.some((i) => i.endsWith(c))),
regex: () => t.some((c) => {
if (!M(c))
return !1;
try {
const i = new RegExp(c);
return s.some((h) => i.test(h));
} catch {
return !1;
}
})
};
return ((a = o[n]) == null ? void 0 : a.call(o)) ?? !1;
}
return !1;
}, G = async (e, r) => {
const s = r ?? U(), a = B({ permissionValue: e, current: s }), t = z(a);
if (t !== null) return t;
const n = (...i) => {
b() && console.log("[v-permission:core]", ...i);
}, c = await (async (i) => {
var h;
if (i === "*") return !0;
if (typeof i == "string") return s.includes(i);
if (Array.isArray(i))
return i.includes("*") ? !0 : i.some((d) => s.includes(d));
if (E(i)) {
const { permissions: d, mode: P } = i;
if (!S.has(P))
return n(
`Invalid permission mode: "${P}". Valid modes:`,
Array.from(S)
), !1;
if (!Array.isArray(d) || d.length === 0)
return n("Permission array is empty or invalid"), !1;
if (d.includes("*")) return !0;
const A = {
and: () => d.every((m) => s.includes(m)),
or: () => d.some((m) => s.includes(m)),
not: () => !d.some((m) => s.includes(m)),
startWith: () => d.some((m) => s.some((f) => f.startsWith(m))),
endWith: () => d.some((m) => s.some((f) => f.endsWith(m))),
regex: () => d.some((m) => {
if (!M(m))
return n("Invalid or dangerous regex pattern:", m), !1;
try {
const f = new RegExp(m);
return s.some((I) => f.test(I));
} catch (f) {
return n("Regex evaluation error:", m, f), !1;
}
})
};
return ((h = A[P]) == null ? void 0 : h.call(A)) ?? !1;
}
return n("Invalid permission value:", i), !1;
})(e);
return K(a, c), c;
}, N = (...e) => {
b() && (console.groupCollapsed("[v-permission:debug]"), console.log(...e), console.groupEnd());
};
function _(e, r) {
const s = e._vPermissionValueRef;
return s && y(s) ? s.value : y(r) ? r.value : r;
}
function O(e) {
try {
const r = window.getComputedStyle(e);
e._vPermissionOriginalDisplay = r.display || e.style.display || "";
} catch {
e._vPermissionOriginalDisplay = e.style.display || "";
}
}
function V(e) {
if (e.parentNode && !e._vPermissionComment) {
const r = document.createComment("v-permission");
e._vPermissionParent = e.parentNode, e._vPermissionNextSibling = e.nextSibling, e._vPermissionComment = r, e.replaceWith(r), N("Removed element from DOM");
}
}
function X(e) {
if (e._vPermissionComment) {
const r = e._vPermissionComment;
e.parentNode ? r.remove() : r.replaceWith(e), e._vPermissionComment = void 0;
}
}
function w(e, r) {
const s = e._vPermissionUseShow === !0;
L(r) ? (X(e), s && (e.style.display = e._vPermissionOriginalDisplay || "")) : s ? e.style.display = "none" : V(e), G(r).catch((t) => {
console.error("[v-permission] Async evaluation failed:", t);
});
}
const Y = {
mounted(e, r) {
const { modifiers: s, arg: a } = r;
e._vPermissionUseShow = a === "show" || s.show === !0, e._vPermissionValueRef = y(r.value) ? r.value : null, O(e), s.once && (e._vPermissionSkipUpdates = !0);
const t = _(e, r.value);
if (w(e, t), N("Mounted v-permission =>", t), !s.once) {
const n = k(
R(),
() => {
if (e._vPermissionSkipUpdates) return;
const o = _(e, r.value);
w(e, o);
},
{ deep: !0 }
);
e._vPermissionUnwatch = n;
}
},
updated(e, r) {
if (e._vPermissionSkipUpdates) return;
const s = _(e, r.value);
let a = r.oldValue;
y(a) && (a = a.value);
const t = JSON.stringify(s) !== JSON.stringify(a);
r.modifiers.lazy && !t || (t && e.parentNode && O(e), w(e, s));
},
unmounted(e) {
e._vPermissionUnwatch && (e._vPermissionUnwatch(), e._vPermissionUnwatch = void 0), e._vPermissionComment && e._vPermissionComment.remove(), delete e._vPermissionOriginalDisplay, delete e._vPermissionSkipUpdates, delete e._vPermissionParent, delete e._vPermissionNextSibling, delete e._vPermissionComment, delete e._vPermissionValueRef, delete e._vPermissionUseShow;
}
}, te = {
async install(e, r) {
let s = [];
const a = (r == null ? void 0 : r.decrypt) ?? (r == null ? void 0 : r.transform);
if (r != null && r.fetchPermissions)
try {
const n = await r.fetchPermissions();
if (a && n && !Array.isArray(n)) {
const o = await a(n);
s = Array.isArray(o) ? o : [];
} else
s = p(n);
} catch (n) {
console.error("[v-permission] Failed to fetch permissions:", n), s = D() ?? [];
}
else if ((r == null ? void 0 : r.permissions) !== void 0)
if (a && r.permissions && !Array.isArray(r.permissions)) {
const n = await a(r.permissions);
s = Array.isArray(n) ? n : [];
} else
s = p(r.permissions);
else
s = D() ?? [];
q(), J(s, {
developmentMode: r == null ? void 0 : r.developmentMode,
persist: r == null ? void 0 : r.persist,
decrypt: r == null ? void 0 : r.decrypt,
transform: r == null ? void 0 : r.transform
});
const t = R();
e.provide("__v_permission_reactive__", t), e.directive("permission", Y);
}
};
export {
te as P,
Q as a,
R as b,
J as c,
D as d,
q as e,
ee as f,
U as g,
G as h,
b as i,
z as j,
K as k,
re as l,
se as m,
p as n,
B as o,
E as p,
$ as q,
N as r,
g as s,
Y as v
};
//# sourceMappingURL=plugin-BUIUV0Ey.js.map