locator-ars-lib 1.0.3 → 1.0.5

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.
@@ -38,18 +38,18 @@ const $ = {
38
38
  e.provide(f, n);
39
39
  }
40
40
  };
41
- function d() {
41
+ function p() {
42
42
  const e = v(f);
43
43
  if (!e)
44
44
  throw new Error("Permissions plugin not installed!");
45
45
  return e;
46
46
  }
47
47
  function D(e, s = {}) {
48
- const n = d(), a = l(null), i = l(!1), t = l(null), p = m(() => typeof e == "string" ? e : e.value), c = async () => {
49
- if (p.value) {
48
+ const n = p(), a = l(null), i = l(!1), t = l(null), d = m(() => typeof e == "string" ? e : e.value), c = async () => {
49
+ if (d.value) {
50
50
  i.value = !0, t.value = null;
51
51
  try {
52
- a.value = await n.can(p.value);
52
+ a.value = await n.can(d.value);
53
53
  } catch (r) {
54
54
  t.value = r instanceof Error ? r : new Error(String(r)), a.value = !1;
55
55
  } finally {
@@ -101,32 +101,33 @@ const E = k({
101
101
  function b(e, s, n, a, i, t) {
102
102
  return e.can ? u(e.$slots, "default", { key: 0 }) : e.isLoading ? u(e.$slots, "loading", { key: 2 }) : u(e.$slots, "fallback", { key: 1 });
103
103
  }
104
- const x = /* @__PURE__ */ L(E, [["render", b]]), U = {
104
+ const U = /* @__PURE__ */ L(E, [["render", b]]), x = {
105
105
  async mounted(e, s) {
106
106
  const n = e.style.display;
107
107
  e._permission_data = {
108
108
  action: s.value,
109
109
  originalDisplay: n
110
- }, await d().can(s.value) || (e.style.display = "none");
110
+ }, await p().can(s.value) || (e.style.display = "none");
111
111
  },
112
112
  async updated(e, s) {
113
113
  (!e._permission_data || e._permission_data.action !== s.value) && (e._permission_data = {
114
114
  action: s.value,
115
115
  originalDisplay: e.style.display || ""
116
- }, await d().can(s.value) ? e.style.display = e._permission_data.originalDisplay : e.style.display = "none");
116
+ }, await p().can(s.value) ? e.style.display = e._permission_data.originalDisplay : e.style.display = "none");
117
117
  },
118
118
  unmounted(e) {
119
119
  e._permission_data && (e.style.display = e._permission_data.originalDisplay, delete e._permission_data);
120
120
  }
121
121
  }, A = {
122
122
  install(e, s) {
123
- e.use($, s), e.component("Check", x), e.directive("can", U);
123
+ e.use($, s), e.component("Check", U), e.directive("can", x);
124
124
  }
125
125
  };
126
126
  export {
127
- x as Check,
127
+ U as Check,
128
128
  A as default,
129
129
  C as setupPermissions,
130
130
  D as usePermissions,
131
- U as vCan
131
+ x as vCan
132
132
  };
133
+ //# sourceMappingURL=locator-ars-lib.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locator-ars-lib.es.js","sources":["../src/services/permissionsService.ts","../src/plugin.ts","../src/composables/usePermissions.ts","../src/components/Check.vue","../src/directives/vCan.ts","../src/index.ts"],"sourcesContent":["import axios, { AxiosInstance } from 'axios'\n\nexport interface PermissionsOptions {\n baseUrl?: string\n endpoint?: string\n}\n\nexport class PermissionsService {\n private axios: AxiosInstance\n private cache: Map<string, boolean> = new Map()\n private endpoint: string\n\n constructor(options?: PermissionsOptions) {\n this.axios = axios.create({\n baseURL: options?.baseUrl || ''\n })\n this.endpoint = options?.endpoint || '/api/v1/dashboard/access'\n }\n\n async can(action: string): Promise<boolean> {\n // Check if we have a cached result\n if (this.cache.has(action)) {\n return this.cache.get(action) as boolean\n }\n\n try {\n const response = await this.axios.get(this.endpoint, {\n params: { action }\n })\n\n const allowed = response.data.allowed || false\n\n // Cache the result\n this.cache.set(action, allowed)\n\n return allowed\n } catch (error) {\n console.error(`Error checking permission for ${action}:`, error)\n return false\n }\n }\n\n clearCache(action?: string): void {\n if (action) {\n this.cache.delete(action)\n } else {\n this.cache.clear()\n }\n }\n} ","import { App, inject, InjectionKey } from 'vue'\nimport { PermissionsService, PermissionsOptions } from './services/permissionsService'\n\nexport const PermissionsKey: InjectionKey<PermissionsService> = Symbol('Permissions')\n\nexport function setupPermissions(options?: PermissionsOptions): PermissionsService {\n return new PermissionsService(options)\n}\n\nexport const PermissionsPlugin = {\n install(app: App, options?: PermissionsOptions) {\n const permissionsService = setupPermissions(options)\n app.provide(PermissionsKey, permissionsService)\n }\n}\n\nexport function usePermissionsService(): PermissionsService {\n const permissionsService = inject(PermissionsKey)\n if (!permissionsService) {\n throw new Error('Permissions plugin not installed!')\n }\n return permissionsService\n} ","import { ref, computed, Ref, watch, onUnmounted } from 'vue'\nimport { usePermissionsService } from '../plugin'\n\nexport interface UsePermissionsOptions {\n autoCheck?: boolean\n}\n\nexport function usePermissions(action: string | Ref<string>, options: UsePermissionsOptions = {}) {\n const permissionsService = usePermissionsService()\n const isAllowed = ref<boolean | null>(null)\n const isLoading = ref(false)\n const error = ref<Error | null>(null)\n\n const actionValue = computed(() => {\n return typeof action === 'string' ? action : action.value\n })\n\n const checkPermission = async () => {\n if (!actionValue.value) return\n\n isLoading.value = true\n error.value = null\n\n try {\n isAllowed.value = await permissionsService.can(actionValue.value)\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err))\n isAllowed.value = false\n } finally {\n isLoading.value = false\n }\n }\n\n // Auto-check on mount if requested\n if (options.autoCheck !== false) {\n checkPermission()\n }\n\n // Re-check when action changes\n if (typeof action !== 'string') {\n const unwatch = watch(action, () => {\n checkPermission()\n })\n\n onUnmounted(() => {\n unwatch()\n })\n }\n\n return {\n isAllowed,\n isLoading,\n error,\n check: checkPermission,\n can: computed(() => isAllowed.value === true)\n }\n} ","<template>\n <slot v-if=\"can\" />\n <slot name=\"fallback\" v-else-if=\"!isLoading\" />\n <slot name=\"loading\" v-else />\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, toRefs, PropType } from 'vue';\nimport { usePermissions } from '../composables/usePermissions';\n\nexport default defineComponent({\n name: 'Check',\n props: {\n action: {\n type: String as PropType<string>,\n required: true\n },\n fallback: {\n type: Boolean,\n default: false\n }\n },\n setup(props) {\n const { action } = toRefs(props);\n const { can, isLoading } = usePermissions(action, { autoCheck: true });\n\n return {\n can,\n isLoading\n };\n }\n});\n</script> ","import { ObjectDirective, DirectiveBinding } from 'vue'\nimport { usePermissionsService } from '../plugin'\n\ninterface CanHTMLElement extends HTMLElement {\n _permission_data?: {\n action: string\n originalDisplay: string\n }\n}\n\nexport const vCan: ObjectDirective = {\n async mounted(el: CanHTMLElement, binding: DirectiveBinding) {\n // Store original display value\n const originalDisplay = el.style.display\n\n // Store action and original display for updates\n el._permission_data = {\n action: binding.value,\n originalDisplay\n }\n\n const permissionsService = usePermissionsService()\n const hasPermission = await permissionsService.can(binding.value)\n\n if (!hasPermission) {\n el.style.display = 'none'\n }\n },\n\n async updated(el: CanHTMLElement, binding: DirectiveBinding) {\n if (!el._permission_data || el._permission_data.action !== binding.value) {\n // Action has changed or directive is new\n el._permission_data = {\n action: binding.value,\n originalDisplay: el.style.display || ''\n }\n\n const permissionsService = usePermissionsService()\n const hasPermission = await permissionsService.can(binding.value)\n\n if (!hasPermission) {\n el.style.display = 'none'\n } else {\n el.style.display = el._permission_data.originalDisplay\n }\n }\n },\n\n unmounted(el: CanHTMLElement) {\n if (el._permission_data) {\n el.style.display = el._permission_data.originalDisplay\n delete el._permission_data\n }\n }\n} ","import { App } from 'vue'\nimport Check from './components/Check.vue'\nimport { usePermissions } from './composables/usePermissions'\nimport { PermissionsPlugin, setupPermissions } from './plugin'\nimport { vCan } from './directives/vCan'\n\n// Именованные экспорты\nexport {\n Check,\n usePermissions,\n setupPermissions,\n vCan\n}\n\n// Создаем основной объект плагина\nconst plugin = {\n install(app: App, options?: { baseUrl?: string }) {\n app.use(PermissionsPlugin, options)\n app.component('Check', Check)\n app.directive('can', vCan)\n }\n}\n\n// Экспортируем плагин как по умолчанию\nexport default plugin "],"names":["PermissionsService","options","__publicField","axios","action","allowed","error","PermissionsKey","setupPermissions","PermissionsPlugin","app","permissionsService","usePermissionsService","inject","usePermissions","isAllowed","ref","isLoading","actionValue","computed","checkPermission","err","unwatch","watch","onUnmounted","_sfc_main","defineComponent","props","toRefs","can","_ctx","_renderSlot","vCan","el","binding","originalDisplay","plugin","Check"],"mappings":"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"}
@@ -1 +1,2 @@
1
1
  (function(n,i){typeof exports=="object"&&typeof module<"u"?i(exports,require("vue"),require("axios")):typeof define=="function"&&define.amd?define(["exports","vue","axios"],i):(n=typeof globalThis<"u"?globalThis:n||self,i(n.LocatorArsLib={},n.Vue,n.axios))})(this,function(n,i,o){"use strict";var $=Object.defineProperty;var L=(n,i,o)=>i in n?$(n,i,{enumerable:!0,configurable:!0,writable:!0,value:o}):n[i]=o;var u=(n,i,o)=>L(n,typeof i!="symbol"?i+"":i,o);class P{constructor(s){u(this,"axios");u(this,"cache",new Map);u(this,"endpoint");this.axios=o.create({baseURL:(s==null?void 0:s.baseUrl)||""}),this.endpoint=(s==null?void 0:s.endpoint)||"/api/v1/dashboard/access"}async can(s){if(this.cache.has(s))return this.cache.get(s);try{const a=(await this.axios.get(this.endpoint,{params:{action:s}})).data.allowed||!1;return this.cache.set(s,a),a}catch(r){return console.error(`Error checking permission for ${s}:`,r),!1}}clearCache(s){s?this.cache.delete(s):this.cache.clear()}}const p=Symbol("Permissions");function m(e){return new P(e)}const S={install(e,s){const r=m(s);e.provide(p,r)}};function d(){const e=i.inject(p);if(!e)throw new Error("Permissions plugin not installed!");return e}function h(e,s={}){const r=d(),a=i.ref(null),t=i.ref(!1),l=i.ref(null),_=i.computed(()=>typeof e=="string"?e:e.value),f=async()=>{if(_.value){t.value=!0,l.value=null;try{a.value=await r.can(_.value)}catch(c){l.value=c instanceof Error?c:new Error(String(c)),a.value=!1}finally{t.value=!1}}};if(s.autoCheck!==!1&&f(),typeof e!="string"){const c=i.watch(e,()=>{f()});i.onUnmounted(()=>{c()})}return{isAllowed:a,isLoading:t,error:l,check:f,can:i.computed(()=>a.value===!0)}}const g=i.defineComponent({name:"Check",props:{action:{type:String,required:!0},fallback:{type:Boolean,default:!1}},setup(e){const{action:s}=i.toRefs(e),{can:r,isLoading:a}=h(s,{autoCheck:!0});return{can:r,isLoading:a}}}),k=(e,s)=>{const r=e.__vccOpts||e;for(const[a,t]of s)r[a]=t;return r};function w(e,s,r,a,t,l){return e.can?i.renderSlot(e.$slots,"default",{key:0}):e.isLoading?i.renderSlot(e.$slots,"loading",{key:2}):i.renderSlot(e.$slots,"fallback",{key:1})}const y=k(g,[["render",w]]),v={async mounted(e,s){const r=e.style.display;e._permission_data={action:s.value,originalDisplay:r},await d().can(s.value)||(e.style.display="none")},async updated(e,s){(!e._permission_data||e._permission_data.action!==s.value)&&(e._permission_data={action:s.value,originalDisplay:e.style.display||""},await d().can(s.value)?e.style.display=e._permission_data.originalDisplay:e.style.display="none")},unmounted(e){e._permission_data&&(e.style.display=e._permission_data.originalDisplay,delete e._permission_data)}},C={install(e,s){e.use(S,s),e.component("Check",y),e.directive("can",v)}};n.Check=y,n.default=C,n.setupPermissions=m,n.usePermissions=h,n.vCan=v,Object.defineProperties(n,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
2
+ //# sourceMappingURL=locator-ars-lib.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locator-ars-lib.umd.js","sources":["../src/services/permissionsService.ts","../src/plugin.ts","../src/composables/usePermissions.ts","../src/components/Check.vue","../src/directives/vCan.ts","../src/index.ts"],"sourcesContent":["import axios, { AxiosInstance } from 'axios'\n\nexport interface PermissionsOptions {\n baseUrl?: string\n endpoint?: string\n}\n\nexport class PermissionsService {\n private axios: AxiosInstance\n private cache: Map<string, boolean> = new Map()\n private endpoint: string\n\n constructor(options?: PermissionsOptions) {\n this.axios = axios.create({\n baseURL: options?.baseUrl || ''\n })\n this.endpoint = options?.endpoint || '/api/v1/dashboard/access'\n }\n\n async can(action: string): Promise<boolean> {\n // Check if we have a cached result\n if (this.cache.has(action)) {\n return this.cache.get(action) as boolean\n }\n\n try {\n const response = await this.axios.get(this.endpoint, {\n params: { action }\n })\n\n const allowed = response.data.allowed || false\n\n // Cache the result\n this.cache.set(action, allowed)\n\n return allowed\n } catch (error) {\n console.error(`Error checking permission for ${action}:`, error)\n return false\n }\n }\n\n clearCache(action?: string): void {\n if (action) {\n this.cache.delete(action)\n } else {\n this.cache.clear()\n }\n }\n} ","import { App, inject, InjectionKey } from 'vue'\nimport { PermissionsService, PermissionsOptions } from './services/permissionsService'\n\nexport const PermissionsKey: InjectionKey<PermissionsService> = Symbol('Permissions')\n\nexport function setupPermissions(options?: PermissionsOptions): PermissionsService {\n return new PermissionsService(options)\n}\n\nexport const PermissionsPlugin = {\n install(app: App, options?: PermissionsOptions) {\n const permissionsService = setupPermissions(options)\n app.provide(PermissionsKey, permissionsService)\n }\n}\n\nexport function usePermissionsService(): PermissionsService {\n const permissionsService = inject(PermissionsKey)\n if (!permissionsService) {\n throw new Error('Permissions plugin not installed!')\n }\n return permissionsService\n} ","import { ref, computed, Ref, watch, onUnmounted } from 'vue'\nimport { usePermissionsService } from '../plugin'\n\nexport interface UsePermissionsOptions {\n autoCheck?: boolean\n}\n\nexport function usePermissions(action: string | Ref<string>, options: UsePermissionsOptions = {}) {\n const permissionsService = usePermissionsService()\n const isAllowed = ref<boolean | null>(null)\n const isLoading = ref(false)\n const error = ref<Error | null>(null)\n\n const actionValue = computed(() => {\n return typeof action === 'string' ? action : action.value\n })\n\n const checkPermission = async () => {\n if (!actionValue.value) return\n\n isLoading.value = true\n error.value = null\n\n try {\n isAllowed.value = await permissionsService.can(actionValue.value)\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err))\n isAllowed.value = false\n } finally {\n isLoading.value = false\n }\n }\n\n // Auto-check on mount if requested\n if (options.autoCheck !== false) {\n checkPermission()\n }\n\n // Re-check when action changes\n if (typeof action !== 'string') {\n const unwatch = watch(action, () => {\n checkPermission()\n })\n\n onUnmounted(() => {\n unwatch()\n })\n }\n\n return {\n isAllowed,\n isLoading,\n error,\n check: checkPermission,\n can: computed(() => isAllowed.value === true)\n }\n} ","<template>\n <slot v-if=\"can\" />\n <slot name=\"fallback\" v-else-if=\"!isLoading\" />\n <slot name=\"loading\" v-else />\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, toRefs, PropType } from 'vue';\nimport { usePermissions } from '../composables/usePermissions';\n\nexport default defineComponent({\n name: 'Check',\n props: {\n action: {\n type: String as PropType<string>,\n required: true\n },\n fallback: {\n type: Boolean,\n default: false\n }\n },\n setup(props) {\n const { action } = toRefs(props);\n const { can, isLoading } = usePermissions(action, { autoCheck: true });\n\n return {\n can,\n isLoading\n };\n }\n});\n</script> ","import { ObjectDirective, DirectiveBinding } from 'vue'\nimport { usePermissionsService } from '../plugin'\n\ninterface CanHTMLElement extends HTMLElement {\n _permission_data?: {\n action: string\n originalDisplay: string\n }\n}\n\nexport const vCan: ObjectDirective = {\n async mounted(el: CanHTMLElement, binding: DirectiveBinding) {\n // Store original display value\n const originalDisplay = el.style.display\n\n // Store action and original display for updates\n el._permission_data = {\n action: binding.value,\n originalDisplay\n }\n\n const permissionsService = usePermissionsService()\n const hasPermission = await permissionsService.can(binding.value)\n\n if (!hasPermission) {\n el.style.display = 'none'\n }\n },\n\n async updated(el: CanHTMLElement, binding: DirectiveBinding) {\n if (!el._permission_data || el._permission_data.action !== binding.value) {\n // Action has changed or directive is new\n el._permission_data = {\n action: binding.value,\n originalDisplay: el.style.display || ''\n }\n\n const permissionsService = usePermissionsService()\n const hasPermission = await permissionsService.can(binding.value)\n\n if (!hasPermission) {\n el.style.display = 'none'\n } else {\n el.style.display = el._permission_data.originalDisplay\n }\n }\n },\n\n unmounted(el: CanHTMLElement) {\n if (el._permission_data) {\n el.style.display = el._permission_data.originalDisplay\n delete el._permission_data\n }\n }\n} ","import { App } from 'vue'\nimport Check from './components/Check.vue'\nimport { usePermissions } from './composables/usePermissions'\nimport { PermissionsPlugin, setupPermissions } from './plugin'\nimport { vCan } from './directives/vCan'\n\n// Именованные экспорты\nexport {\n Check,\n usePermissions,\n setupPermissions,\n vCan\n}\n\n// Создаем основной объект плагина\nconst plugin = {\n install(app: App, options?: { baseUrl?: string }) {\n app.use(PermissionsPlugin, options)\n app.component('Check', Check)\n app.directive('can', vCan)\n }\n}\n\n// Экспортируем плагин как по умолчанию\nexport default plugin "],"names":["PermissionsService","options","__publicField","axios","action","allowed","error","PermissionsKey","setupPermissions","PermissionsPlugin","app","permissionsService","usePermissionsService","inject","usePermissions","isAllowed","ref","isLoading","actionValue","computed","checkPermission","err","unwatch","watch","onUnmounted","_sfc_main","defineComponent","props","toRefs","can","_ctx","_renderSlot","vCan","el","binding","originalDisplay","plugin","Check"],"mappings":"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"}
package/package.json CHANGED
@@ -1,9 +1,22 @@
1
1
  {
2
2
  "name": "locator-ars-lib",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "Permissions library for Vue 3 applications",
5
- "main": "dist/index.js",
5
+ "type": "module",
6
+ "main": "./dist/locator-ars-lib.umd.js",
7
+ "module": "./dist/locator-ars-lib.es.js",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./types/index.d.ts",
11
+ "import": "./dist/locator-ars-lib.es.js",
12
+ "require": "./dist/locator-ars-lib.umd.js"
13
+ }
14
+ },
6
15
  "types": "types/index.d.ts",
16
+ "files": [
17
+ "dist",
18
+ "types"
19
+ ],
7
20
  "scripts": {
8
21
  "build": "vue-tsc && vite build",
9
22
  "test": "vitest run",
@@ -1,132 +0,0 @@
1
- <template>
2
- <div class="example-container">
3
- <h1>Permissions Examples</h1>
4
-
5
- <!-- Пример использования компонента Check -->
6
- <div class="example-block">
7
- <h2>Using Check Component</h2>
8
-
9
- <Check action="view_dashboard">
10
- <div class="dashboard-panel">
11
- <h3>Dashboard Content</h3>
12
- <p>This content is only visible for users with 'view_dashboard' permission</p>
13
- </div>
14
-
15
- <template #fallback>
16
- <div class="no-permission">
17
- <p>You don't have permission to view the dashboard</p>
18
- </div>
19
- </template>
20
-
21
- <template #loading>
22
- <div class="loading">
23
- <p>Loading permissions...</p>
24
- </div>
25
- </template>
26
- </Check>
27
- </div>
28
-
29
- <!-- Пример использования директивы v-can -->
30
- <div class="example-block">
31
- <h2>Using v-can Directive</h2>
32
-
33
- <button v-can="'edit_user'" class="action-button">
34
- Edit User
35
- </button>
36
-
37
- <button v-can="'delete_user'" class="action-button danger">
38
- Delete User
39
- </button>
40
- </div>
41
-
42
- <!-- Пример использования composable usePermissions -->
43
- <div class="example-block">
44
- <h2>Using usePermissions Composable</h2>
45
-
46
- <div class="permission-status">
47
- <p>Can create project: <span :class="canCreateProject ? 'allowed' : 'denied'">{{ canCreateProject ? 'Yes' : 'No' }}</span></p>
48
- <p>Is loading: {{ isLoadingPermission ? 'Yes' : 'No' }}</p>
49
- <button @click="checkPermissionManually" class="action-button">
50
- Check Again
51
- </button>
52
- </div>
53
-
54
- <div v-if="canCreateProject" class="action-panel">
55
- <button class="action-button primary">Create New Project</button>
56
- </div>
57
- </div>
58
- </div>
59
- </template>
60
-
61
- <script setup lang="ts">
62
- import { Check, usePermissions } from 'locator-ars-lib'
63
-
64
- // Использование composable
65
- const { can: canCreateProject, isLoading: isLoadingPermission, check: checkPermissionManually } = usePermissions('create_project')
66
- </script>
67
-
68
- <style scoped>
69
- .example-container {
70
- max-width: 800px;
71
- margin: 0 auto;
72
- padding: 20px;
73
- font-family: Arial, sans-serif;
74
- }
75
-
76
- .example-block {
77
- margin-bottom: 30px;
78
- padding: 20px;
79
- border: 1px solid #eee;
80
- border-radius: 5px;
81
- }
82
-
83
- .dashboard-panel {
84
- background-color: #f5f5f5;
85
- padding: 15px;
86
- border-radius: 4px;
87
- }
88
-
89
- .action-button {
90
- padding: 8px 16px;
91
- margin-right: 10px;
92
- border: none;
93
- border-radius: 4px;
94
- background-color: #4a90e2;
95
- color: white;
96
- cursor: pointer;
97
- }
98
-
99
- .action-button.danger {
100
- background-color: #e25c4a;
101
- }
102
-
103
- .action-button.primary {
104
- background-color: #42b983;
105
- }
106
-
107
- .permission-status {
108
- margin-bottom: 15px;
109
- }
110
-
111
- .allowed {
112
- color: #42b983;
113
- font-weight: bold;
114
- }
115
-
116
- .denied {
117
- color: #e25c4a;
118
- font-weight: bold;
119
- }
120
-
121
- .no-permission {
122
- padding: 15px;
123
- background-color: #ffeeee;
124
- border-left: 4px solid #e25c4a;
125
- }
126
-
127
- .loading {
128
- padding: 15px;
129
- background-color: #eeeeff;
130
- border-left: 4px solid #4a90e2;
131
- }
132
- </style>
@@ -1,33 +0,0 @@
1
- <template>
2
- <slot v-if="can" />
3
- <slot name="fallback" v-else-if="!isLoading" />
4
- <slot name="loading" v-else />
5
- </template>
6
-
7
- <script lang="ts">
8
- import { defineComponent, toRefs, PropType } from 'vue';
9
- import { usePermissions } from '../composables/usePermissions';
10
-
11
- export default defineComponent({
12
- name: 'Check',
13
- props: {
14
- action: {
15
- type: String as PropType<string>,
16
- required: true
17
- },
18
- fallback: {
19
- type: Boolean,
20
- default: false
21
- }
22
- },
23
- setup(props) {
24
- const { action } = toRefs(props);
25
- const { can, isLoading } = usePermissions(action, { autoCheck: true });
26
-
27
- return {
28
- can,
29
- isLoading
30
- };
31
- }
32
- });
33
- </script>
@@ -1,57 +0,0 @@
1
- import { ref, computed, Ref, watch, onUnmounted } from 'vue'
2
- import { usePermissionsService } from '../plugin'
3
-
4
- export interface UsePermissionsOptions {
5
- autoCheck?: boolean
6
- }
7
-
8
- export function usePermissions(action: string | Ref<string>, options: UsePermissionsOptions = {}) {
9
- const permissionsService = usePermissionsService()
10
- const isAllowed = ref<boolean | null>(null)
11
- const isLoading = ref(false)
12
- const error = ref<Error | null>(null)
13
-
14
- const actionValue = computed(() => {
15
- return typeof action === 'string' ? action : action.value
16
- })
17
-
18
- const checkPermission = async () => {
19
- if (!actionValue.value) return
20
-
21
- isLoading.value = true
22
- error.value = null
23
-
24
- try {
25
- isAllowed.value = await permissionsService.can(actionValue.value)
26
- } catch (err) {
27
- error.value = err instanceof Error ? err : new Error(String(err))
28
- isAllowed.value = false
29
- } finally {
30
- isLoading.value = false
31
- }
32
- }
33
-
34
- // Auto-check on mount if requested
35
- if (options.autoCheck !== false) {
36
- checkPermission()
37
- }
38
-
39
- // Re-check when action changes
40
- if (typeof action !== 'string') {
41
- const unwatch = watch(action, () => {
42
- checkPermission()
43
- })
44
-
45
- onUnmounted(() => {
46
- unwatch()
47
- })
48
- }
49
-
50
- return {
51
- isAllowed,
52
- isLoading,
53
- error,
54
- check: checkPermission,
55
- can: computed(() => isAllowed.value === true)
56
- }
57
- }
@@ -1,55 +0,0 @@
1
- import { ObjectDirective, DirectiveBinding } from 'vue'
2
- import { usePermissionsService } from '../plugin'
3
-
4
- interface CanHTMLElement extends HTMLElement {
5
- _permission_data?: {
6
- action: string
7
- originalDisplay: string
8
- }
9
- }
10
-
11
- export const vCan: ObjectDirective = {
12
- async mounted(el: CanHTMLElement, binding: DirectiveBinding) {
13
- // Store original display value
14
- const originalDisplay = el.style.display
15
-
16
- // Store action and original display for updates
17
- el._permission_data = {
18
- action: binding.value,
19
- originalDisplay
20
- }
21
-
22
- const permissionsService = usePermissionsService()
23
- const hasPermission = await permissionsService.can(binding.value)
24
-
25
- if (!hasPermission) {
26
- el.style.display = 'none'
27
- }
28
- },
29
-
30
- async updated(el: CanHTMLElement, binding: DirectiveBinding) {
31
- if (!el._permission_data || el._permission_data.action !== binding.value) {
32
- // Action has changed or directive is new
33
- el._permission_data = {
34
- action: binding.value,
35
- originalDisplay: el.style.display || ''
36
- }
37
-
38
- const permissionsService = usePermissionsService()
39
- const hasPermission = await permissionsService.can(binding.value)
40
-
41
- if (!hasPermission) {
42
- el.style.display = 'none'
43
- } else {
44
- el.style.display = el._permission_data.originalDisplay
45
- }
46
- }
47
- },
48
-
49
- unmounted(el: CanHTMLElement) {
50
- if (el._permission_data) {
51
- el.style.display = el._permission_data.originalDisplay
52
- delete el._permission_data
53
- }
54
- }
55
- }
package/src/index.ts DELETED
@@ -1,20 +0,0 @@
1
- import { App } from 'vue'
2
- import Check from './components/Check.vue'
3
- import { usePermissions } from './composables/usePermissions'
4
- import { PermissionsPlugin, setupPermissions } from './plugin'
5
- import { vCan } from './directives/vCan'
6
-
7
- export {
8
- Check,
9
- usePermissions,
10
- setupPermissions,
11
- vCan
12
- }
13
-
14
- export default {
15
- install(app: App, options?: { baseUrl?: string }) {
16
- app.use(PermissionsPlugin, options)
17
- app.component('Check', Check)
18
- app.directive('can', vCan)
19
- }
20
- }
package/src/plugin.ts DELETED
@@ -1,23 +0,0 @@
1
- import { App, inject, InjectionKey } from 'vue'
2
- import { PermissionsService, PermissionsOptions } from './services/permissionsService'
3
-
4
- export const PermissionsKey: InjectionKey<PermissionsService> = Symbol('Permissions')
5
-
6
- export function setupPermissions(options?: PermissionsOptions): PermissionsService {
7
- return new PermissionsService(options)
8
- }
9
-
10
- export const PermissionsPlugin = {
11
- install(app: App, options?: PermissionsOptions) {
12
- const permissionsService = setupPermissions(options)
13
- app.provide(PermissionsKey, permissionsService)
14
- }
15
- }
16
-
17
- export function usePermissionsService(): PermissionsService {
18
- const permissionsService = inject(PermissionsKey)
19
- if (!permissionsService) {
20
- throw new Error('Permissions plugin not installed!')
21
- }
22
- return permissionsService
23
- }
@@ -1,50 +0,0 @@
1
- import axios, { AxiosInstance } from 'axios'
2
-
3
- export interface PermissionsOptions {
4
- baseUrl?: string
5
- endpoint?: string
6
- }
7
-
8
- export class PermissionsService {
9
- private axios: AxiosInstance
10
- private cache: Map<string, boolean> = new Map()
11
- private endpoint: string
12
-
13
- constructor(options?: PermissionsOptions) {
14
- this.axios = axios.create({
15
- baseURL: options?.baseUrl || ''
16
- })
17
- this.endpoint = options?.endpoint || '/api/v1/dashboard/access'
18
- }
19
-
20
- async can(action: string): Promise<boolean> {
21
- // Check if we have a cached result
22
- if (this.cache.has(action)) {
23
- return this.cache.get(action) as boolean
24
- }
25
-
26
- try {
27
- const response = await this.axios.get(this.endpoint, {
28
- params: { action }
29
- })
30
-
31
- const allowed = response.data.allowed || false
32
-
33
- // Cache the result
34
- this.cache.set(action, allowed)
35
-
36
- return allowed
37
- } catch (error) {
38
- console.error(`Error checking permission for ${action}:`, error)
39
- return false
40
- }
41
- }
42
-
43
- clearCache(action?: string): void {
44
- if (action) {
45
- this.cache.delete(action)
46
- } else {
47
- this.cache.clear()
48
- }
49
- }
50
- }
package/tsconfig.json DELETED
@@ -1,32 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2020",
4
- "useDefineForClassFields": true,
5
- "module": "ESNext",
6
- "lib": ["ES2020", "DOM", "DOM.Iterable"],
7
- "skipLibCheck": true,
8
- "typeRoots": ["./node_modules/@types", "./types"],
9
-
10
- /* Bundler mode */
11
- "moduleResolution": "node",
12
- "allowImportingTsExtensions": true,
13
- "resolveJsonModule": true,
14
- "isolatedModules": true,
15
- "noEmit": true,
16
- "jsx": "preserve",
17
- "esModuleInterop": true,
18
-
19
- /* Linting */
20
- "strict": true,
21
- "noUnusedLocals": true,
22
- "noUnusedParameters": true,
23
- "noFallthroughCasesInSwitch": true,
24
-
25
- /* Type declarations */
26
- "declaration": true,
27
- "declarationDir": "dist",
28
- "outDir": "dist"
29
- },
30
- "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
31
- "references": [{ "path": "./tsconfig.node.json" }]
32
- }
@@ -1,10 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "composite": true,
4
- "skipLibCheck": true,
5
- "module": "ESNext",
6
- "moduleResolution": "node",
7
- "allowSyntheticDefaultImports": true
8
- },
9
- "include": ["vite.config.ts"]
10
- }
package/vite.config.ts DELETED
@@ -1,23 +0,0 @@
1
- import { defineConfig } from 'vite'
2
- import vue from '@vitejs/plugin-vue'
3
- import { resolve } from 'path'
4
-
5
- export default defineConfig({
6
- plugins: [vue()],
7
- build: {
8
- lib: {
9
- entry: resolve(__dirname, 'src/index.ts'),
10
- name: 'LocatorArsLib',
11
- fileName: (format) => `locator-ars-lib.${format}.js`
12
- },
13
- rollupOptions: {
14
- external: ['vue', 'axios'],
15
- output: {
16
- globals: {
17
- vue: 'Vue',
18
- axios: 'axios'
19
- }
20
- }
21
- }
22
- }
23
- })