UNPKG

permix

Version:

Permix is a lightweight, framework-agnostic, type-safe permissions management library for JavaScript applications on the client and server sides.

107 lines (106 loc) 2.9 kB
import { createCheck } from "../core/index.mjs"; import { computed, defineComponent, inject, onUnmounted, provide, ref, watch } from "vue"; //#region src/vue/context.ts const PERMIX_CONTEXT_KEY = Symbol("vue-permix"); function providePermixContext(permix) { if (!permix) throw new Error("[Permix]: Looks like you forgot to provide the permix instance to PermixProvider"); const context = ref({ permix, rules: permix.getRules(), isReady: permix.isReady() }); provide(PERMIX_CONTEXT_KEY, context); const setup = permix.hook("setup", () => { context.value.rules = permix.getRules(); }); const ready = permix.hook("ready", () => { context.value.isReady = permix.isReady(); }); return () => { setup(); ready(); }; } function usePermixContext() { const context = inject(PERMIX_CONTEXT_KEY); if (!context) throw new Error("[Permix]: Looks like you forgot to wrap your app with <PermixProvider>"); return context; } //#endregion //#region src/vue/composables.ts /** * Access Permix check and readiness state inside a Vue component. * * @link https://permix.letstri.dev/docs/integrations/vue */ function usePermix(permix) { const context = usePermixContext(); const check = (...args) => createCheck(() => context.value.rules ?? permix.getRules())(...args); return { check, isReady: computed(() => context.value.isReady) }; } //#endregion //#region src/vue/components.ts /** * Provides Permix context to the Vue component tree. * * @link https://permix.letstri.dev/docs/integrations/vue */ const PermixProvider = defineComponent({ name: "PermixProvider", props: { permix: { type: Object, required: true } }, setup(props, { slots }) { onUnmounted(providePermixContext(props.permix)); return () => slots.default?.(); } }); /** * Restores dehydrated server permissions on the client. * * @link https://permix.letstri.dev/docs/integrations/vue */ const PermixHydrate = defineComponent({ name: "PermixHydrate", props: { state: { type: Object, required: true } }, setup(props, { slots }) { const context = usePermixContext(); const hydrate = () => context.value.permix.hydrate(props.state); hydrate(); watch(() => props.state, hydrate); return () => slots.default?.(); } }); function createComponents(permix) { function Check(props, context) { const { check } = usePermix(permix); const hasPermission = check(...[props.path, props.data]); return props.reverse ? hasPermission ? context.slots.otherwise?.() : context.slots.default?.() : hasPermission ? context.slots.default?.() : context.slots.otherwise?.(); } Check.inheritAttrs = false; Check.props = { path: { type: String, required: true }, data: { type: Object, required: false }, reverse: { type: Boolean, required: false, default: false } }; return { Check }; } //#endregion export { PermixHydrate, PermixProvider, createComponents, usePermix };