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
JavaScript
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 };