locator-ars-lib 1.1.5 → 1.1.7

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
@@ -82,7 +82,23 @@ app.mount("#app");
82
82
  </template>
83
83
  ```
84
84
 
85
+ С массивом разрешений:
86
+
87
+ ```vue
88
+ <template>
89
+ <Check :action="['edit_user', 'manage_users']">
90
+ <button>Edit User</button>
91
+
92
+ <template #fallback>
93
+ <span>You need edit_user or manage_users permission</span>
94
+ </template>
95
+ </Check>
96
+ </template>
97
+ ```
98
+
85
99
  > **Важно:** Компонент Check изначально скрывает основной контент до получения подтверждения о правах доступа. Только после успешной проверки прав происходит отображение контента. До этого момента отображается слот `loading`, если он предоставлен.
100
+ >
101
+ > **Массив разрешений:** При передаче массива разрешений компонент отобразит основной контент, если у пользователя есть хотя бы одно из указанных разрешений. Это позволяет реализовать логику "ИЛИ" для проверки прав.
86
102
 
87
103
  ### 2. Директивы v-can и v-cant
88
104
 
@@ -97,10 +113,15 @@ app.mount("#app");
97
113
  <div v-can="'view_analytics'">
98
114
  <!-- Аналитика будет видна только при наличии прав -->
99
115
  </div>
116
+
117
+ <!-- Использование массива разрешений -->
118
+ <button v-can="['edit_user', 'manage_users']">Edit User</button>
100
119
  </template>
101
120
  ```
102
121
 
103
122
  > **Важно:** Директива v-can изначально скрывает элементы, к которым она применена. Элементы отображаются только после успешной проверки прав доступа.
123
+ >
124
+ > **Массив разрешений:** При передаче массива разрешений элемент будет отображен, если у пользователя есть хотя бы одно из указанных разрешений. Это позволяет реализовать логику "ИЛИ" для проверки прав.
104
125
 
105
126
  #### Директива v-cant
106
127
 
@@ -112,6 +133,11 @@ app.mount("#app");
112
133
  <div v-cant="'edit_user'" class="no-permission-message">
113
134
  У вас нет прав на редактирование
114
135
  </div>
136
+
137
+ <!-- Использование массива разрешений -->
138
+ <div v-cant="['edit_user', 'manage_users']" class="no-permission-message">
139
+ У вас нет ни одного из необходимых прав
140
+ </div>
115
141
  </template>
116
142
  ```
117
143
 
@@ -152,28 +178,28 @@ function handleDelete() {
152
178
 
153
179
  ### Компонент Check
154
180
 
155
- | Prop | Тип | По умолчанию | Описание |
156
- | -------- | ------- | ------------ | ----------------------------------------------- |
157
- | action | string | | Название действия для проверки |
158
- | fallback | boolean | false | Показывать ли fallback слот при отсутствии прав |
181
+ | Prop | Тип | По умолчанию | Описание |
182
+ | -------- | ------------------ | ------------ | -------------------------------------------------- |
183
+ | action | string \| string[] | | Название действия или массив действий для проверки |
184
+ | fallback | boolean | false | Показывать ли fallback слот при отсутствии прав |
159
185
 
160
186
  ### Директивы
161
187
 
162
188
  #### Директива v-can
163
189
 
164
190
  ```vue
165
- v-can="'action_name'"
191
+ v-can="'action_name'" // или v-can="['action_name1', 'action_name2']"
166
192
  ```
167
193
 
168
- Показывает элемент только при наличии прав доступа.
194
+ Показывает элемент только при наличии прав доступа. При передаче массива разрешений элемент будет отображен, если у пользователя есть хотя бы одно из указанных разрешений.
169
195
 
170
196
  #### Директива v-cant
171
197
 
172
198
  ```vue
173
- v-cant="'action_name'"
199
+ v-cant="'action_name'" // или v-cant="['action_name1', 'action_name2']"
174
200
  ```
175
201
 
176
- Показывает элемент только при отсутствии прав доступа (противоположность v-can).
202
+ Показывает элемент только при отсутствии прав доступа (противоположность v-can). При передаче массива разрешений элемент будет отображен только если у пользователя нет ни одного из указанных разрешений.
177
203
 
178
204
  ### usePermissions composable
179
205
 
@@ -186,10 +212,10 @@ const {
186
212
  } = usePermissions(action, options);
187
213
  ```
188
214
 
189
- | Параметр | Тип | По умолчанию | Описание |
190
- | ----------------- | --------------------- | ------------ | ------------------------------------ |
191
- | action | string \| Ref<string> | | Название действия для проверки |
192
- | options.autoCheck | boolean | true | Автоматически проверять при создании |
215
+ | Параметр | Тип | По умолчанию | Описание |
216
+ | ----------------- | --------------------------------------------- | ------------ | -------------------------------------------------- |
217
+ | action | string \| string[] \| Ref<string \| string[]> | | Название действия или массив действий для проверки |
218
+ | options.autoCheck | boolean | true | Автоматически проверять при создании |
193
219
 
194
220
  ## Особенности реализации
195
221
 
@@ -1,49 +1,64 @@
1
1
  var v = Object.defineProperty;
2
- var g = (e, s, i) => s in e ? v(e, s, { enumerable: !0, configurable: !0, writable: !0, value: i }) : e[s] = i;
3
- var o = (e, s, i) => g(e, typeof s != "symbol" ? s + "" : s, i);
4
- import { inject as _, ref as l, computed as h, watch as k, onUnmounted as P, defineComponent as w, toRefs as C, onMounted as S, renderSlot as p, createCommentVNode as L } from "vue";
5
- import $ from "axios";
6
- class E {
2
+ var _ = (e, s, i) => s in e ? v(e, s, { enumerable: !0, configurable: !0, writable: !0, value: i }) : e[s] = i;
3
+ var c = (e, s, i) => _(e, typeof s != "symbol" ? s + "" : s, i);
4
+ import { inject as g, ref as u, computed as m, watch as k, onUnmounted as P, defineComponent as S, toRefs as w, onMounted as C, renderSlot as y, createCommentVNode as A } from "vue";
5
+ import L from "axios";
6
+ class N {
7
7
  constructor(s) {
8
- o(this, "axios");
9
- o(this, "cache", /* @__PURE__ */ new Map());
10
- o(this, "endpoint");
11
- o(this, "application");
12
- this.axios = $.create({
8
+ c(this, "axios");
9
+ c(this, "cache", /* @__PURE__ */ new Map());
10
+ c(this, "endpoint");
11
+ c(this, "application");
12
+ this.axios = L.create({
13
13
  baseURL: (s == null ? void 0 : s.baseUrl) || ""
14
14
  }), this.endpoint = (s == null ? void 0 : s.endpoint) || "/api/v1/dashboard/access", this.application = s == null ? void 0 : s.application, this.application && (this.axios.defaults.headers.common.Application = this.application);
15
15
  }
16
16
  async can(s) {
17
- if (this.cache.has(s))
18
- return this.cache.get(s);
17
+ const i = Array.isArray(s) ? JSON.stringify(s) : s;
18
+ if (this.cache.has(i))
19
+ return this.cache.get(i);
19
20
  try {
20
- const a = (await this.axios.get(this.endpoint, {
21
- params: { action: s }
22
- })).data.allowed || !1;
23
- return this.cache.set(s, a), a;
24
- } catch (i) {
25
- return console.error(`Error checking permission for ${s}:`, i), !1;
21
+ let a = { action: s };
22
+ Array.isArray(s) && (a = { action: JSON.stringify(s) });
23
+ const n = (await this.axios.get(this.endpoint, { params: a })).data.allowed || !1;
24
+ return this.cache.set(i, n), n;
25
+ } catch (a) {
26
+ return console.error(`Error checking permission for ${Array.isArray(s) ? JSON.stringify(s) : s}:`, a), !1;
26
27
  }
27
28
  }
28
29
  clearCache(s) {
29
30
  s ? this.cache.delete(s) : this.cache.clear();
30
31
  }
31
32
  }
32
- let m = null;
33
- const c = /* @__PURE__ */ new Map();
34
- function b(e) {
35
- m = e;
33
+ let l = null;
34
+ const t = /* @__PURE__ */ new Map();
35
+ function O(e) {
36
+ l = e;
36
37
  }
37
- async function I(e) {
38
- if (!m)
38
+ async function $(e) {
39
+ if (!l)
39
40
  return console.warn("Permissions service not initialized yet."), !1;
40
- if (!c.has(e)) {
41
- const s = m.can(e).catch((i) => (console.error("Error checking permission:", i), c.delete(e), !1));
42
- c.set(e, s);
41
+ if (!t.has(e)) {
42
+ const s = l.can(e).catch((i) => (console.error("Error checking permission:", i), t.delete(e), !1));
43
+ t.set(e, s);
43
44
  }
44
- return c.get(e);
45
+ return t.get(e);
45
46
  }
46
- async function u(e, s, i) {
47
+ async function E(e) {
48
+ if (!l)
49
+ return console.warn("Permissions service not initialized yet."), !1;
50
+ if (typeof e == "string")
51
+ return $(e);
52
+ if (e.length === 0)
53
+ return !1;
54
+ const s = JSON.stringify(e);
55
+ if (!t.has(s)) {
56
+ const i = l.can(e).catch((a) => (console.error("Error checking permissions:", a), t.delete(s), !1));
57
+ t.set(s, i);
58
+ }
59
+ return t.get(s);
60
+ }
61
+ async function f(e, s, i) {
47
62
  const a = e.style.display;
48
63
  e._permission_data = {
49
64
  action: s,
@@ -51,83 +66,83 @@ async function u(e, s, i) {
51
66
  permissionChecked: !1
52
67
  }, e.style.display = "none";
53
68
  try {
54
- const n = await I(s);
55
- (i && n || !i && !n) && (e.style.display = a || ""), e._permission_data.permissionChecked = !0;
56
- } catch (n) {
57
- console.error("Error in directive processing:", n), i || (e.style.display = a || "");
69
+ const r = await E(s);
70
+ (i && r || !i && !r) && (e.style.display = a || ""), e._permission_data.permissionChecked = !0;
71
+ } catch (r) {
72
+ console.error("Error in directive processing:", r), i || (e.style.display = a || "");
58
73
  }
59
74
  }
60
- const D = {
75
+ const J = {
61
76
  async mounted(e, s) {
62
- await u(e, s.value, !0);
77
+ await f(e, s.value, !0);
63
78
  },
64
79
  async updated(e, s) {
65
- (!e._permission_data || e._permission_data.action !== s.value) && await u(e, s.value, !0);
80
+ (!e._permission_data || typeof e._permission_data.action != typeof s.value || typeof s.value == "string" && e._permission_data.action !== s.value || Array.isArray(s.value) && (!Array.isArray(e._permission_data.action) || JSON.stringify(e._permission_data.action) !== JSON.stringify(s.value))) && await f(e, s.value, !0);
66
81
  },
67
82
  unmounted(e) {
68
83
  e._permission_data && (e.style.display = e._permission_data.originalDisplay, delete e._permission_data);
69
84
  }
70
- }, M = {
85
+ }, I = {
71
86
  async mounted(e, s) {
72
- await u(e, s.value, !1);
87
+ await f(e, s.value, !1);
73
88
  },
74
89
  async updated(e, s) {
75
- (!e._permission_data || e._permission_data.action !== s.value) && await u(e, s.value, !1);
90
+ (!e._permission_data || typeof e._permission_data.action != typeof s.value || typeof s.value == "string" && e._permission_data.action !== s.value || Array.isArray(s.value) && (!Array.isArray(e._permission_data.action) || JSON.stringify(e._permission_data.action) !== JSON.stringify(s.value))) && await f(e, s.value, !1);
76
91
  },
77
92
  unmounted(e) {
78
93
  e._permission_data && (e.style.display = e._permission_data.originalDisplay, delete e._permission_data);
79
94
  }
80
- }, y = Symbol("Permissions");
81
- function U(e) {
82
- const s = new E(e);
83
- return b(s), s;
95
+ }, h = Symbol("Permissions");
96
+ function j(e) {
97
+ const s = new N(e);
98
+ return O(s), s;
84
99
  }
85
- const R = {
100
+ const D = {
86
101
  install(e, s) {
87
- const i = U(s);
88
- e.provide(y, i), e.config.globalProperties.$permissions = i;
102
+ const i = j(s);
103
+ e.provide(h, i), e.config.globalProperties.$permissions = i;
89
104
  }
90
105
  };
91
- function V() {
92
- const e = _(y);
106
+ function K() {
107
+ const e = g(h);
93
108
  if (!e)
94
109
  throw new Error("Permissions plugin not installed!");
95
110
  return e;
96
111
  }
97
- function j(e, s = {}) {
98
- const i = V(), a = l(null), n = l(!1), r = l(null), f = h(() => typeof e == "string" ? e : e.value), d = async () => {
99
- if (f.value) {
100
- n.value = !0, r.value = null;
112
+ function M(e, s = {}) {
113
+ const i = K(), a = u(null), r = u(!1), n = u(null), d = m(() => typeof e == "object" && "value" in e ? e.value : e), p = async () => {
114
+ if (d.value) {
115
+ r.value = !0, n.value = null;
101
116
  try {
102
- a.value = await i.can(f.value);
103
- } catch (t) {
104
- r.value = t instanceof Error ? t : new Error(String(t)), a.value = !1;
117
+ a.value = await i.can(d.value);
118
+ } catch (o) {
119
+ n.value = o instanceof Error ? o : new Error(String(o)), a.value = !1;
105
120
  } finally {
106
- n.value = !1;
121
+ r.value = !1;
107
122
  }
108
123
  }
109
124
  };
110
- if (s.autoCheck !== !1 && d(), typeof e != "string") {
111
- const t = k(e, () => {
112
- d();
125
+ if (s.autoCheck !== !1 && p(), typeof e == "object" && "value" in e) {
126
+ const o = k(e, () => {
127
+ p();
113
128
  });
114
129
  P(() => {
115
- t();
130
+ o();
116
131
  });
117
132
  }
118
133
  return {
119
134
  isAllowed: a,
120
- isLoading: n,
121
- error: r,
122
- check: d,
123
- can: h(() => a.value === !0)
135
+ isLoading: r,
136
+ error: n,
137
+ check: p,
138
+ can: m(() => a.value === !0)
124
139
  };
125
140
  }
126
- const q = w({
141
+ const U = S({
127
142
  name: "Check",
128
143
  props: {
129
144
  action: {
130
- type: String,
145
+ type: [String, Array],
131
146
  required: !0
132
147
  },
133
148
  fallback: {
@@ -136,37 +151,37 @@ const q = w({
136
151
  }
137
152
  },
138
153
  setup(e) {
139
- const { action: s } = C(e), i = l(!0), { can: a, isLoading: n, check: r } = j(s, { autoCheck: !1 });
140
- return S(async () => {
141
- await r(), i.value = !1;
154
+ const { action: s } = w(e), i = u(!0), { can: a, isLoading: r, check: n } = M(s, { autoCheck: !1 });
155
+ return C(async () => {
156
+ await n(), i.value = !1;
142
157
  }), {
143
158
  can: a,
144
- isLoading: n,
159
+ isLoading: r,
145
160
  isInitialLoading: i
146
161
  };
147
162
  }
148
163
  }), z = (e, s) => {
149
164
  const i = e.__vccOpts || e;
150
- for (const [a, n] of s)
151
- i[a] = n;
165
+ for (const [a, r] of s)
166
+ i[a] = r;
152
167
  return i;
153
168
  };
154
- function B(e, s, i, a, n, r) {
155
- return e.can && !e.isInitialLoading ? p(e.$slots, "default", { key: 0 }) : !e.isLoading && !e.isInitialLoading && !e.can ? p(e.$slots, "fallback", { key: 1 }) : e.isLoading || e.isInitialLoading ? p(e.$slots, "loading", { key: 2 }) : L("", !0);
169
+ function R(e, s, i, a, r, n) {
170
+ return e.can && !e.isInitialLoading ? y(e.$slots, "default", { key: 0 }) : !e.isLoading && !e.isInitialLoading && !e.can ? y(e.$slots, "fallback", { key: 1 }) : e.isLoading || e.isInitialLoading ? y(e.$slots, "loading", { key: 2 }) : A("", !0);
156
171
  }
157
- const K = /* @__PURE__ */ z(q, [["render", B]]), F = {
172
+ const V = /* @__PURE__ */ z(U, [["render", R]]), F = {
158
173
  install(e, s) {
159
- e.use(R, s), e.component("Check", K), e.directive("can", D), e.directive("cant", M);
174
+ e.use(D, s), e.component("Check", V), e.directive("can", J), e.directive("cant", I);
160
175
  }
161
176
  };
162
177
  export {
163
- K as Check,
178
+ V as Check,
164
179
  F as default,
165
- b as setPermissionsService,
166
- U as setupPermissions,
167
- j as usePermissions,
168
- V as usePermissionsService,
169
- D as vCan,
170
- M as vCant
180
+ O as setPermissionsService,
181
+ j as setupPermissions,
182
+ M as usePermissions,
183
+ K as usePermissionsService,
184
+ J as vCan,
185
+ I as vCant
171
186
  };
172
187
  //# sourceMappingURL=locator-ars-lib.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"locator-ars-lib.es.js","sources":["../src/services/permissionsService.ts","../src/directives/vCan.ts","../src/plugin.ts","../src/composables/usePermissions.ts","../src/components/Check.vue","../src/index.ts"],"sourcesContent":["import axios, { AxiosInstance } from 'axios'\n\nexport interface PermissionsOptions {\n baseUrl?: string\n endpoint?: string\n application?: string\n}\n\nexport class PermissionsService {\n private axios: AxiosInstance\n private cache: Map<string, boolean> = new Map()\n private endpoint: string\n private application?: 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 this.application = options?.application\n\n // Если указано application, добавляем его в заголовки по умолчанию\n if (this.application) {\n this.axios.defaults.headers.common['Application'] = this.application\n }\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 { ObjectDirective, DirectiveBinding } from 'vue'\nimport { PermissionsService } from '../services/permissionsService'\n\ninterface CanHTMLElement extends HTMLElement {\n _permission_data?: {\n action: string\n originalDisplay: string\n permissionChecked?: boolean\n }\n}\n\n// Глобальный сервис проверки прав\nlet globalPermissionsService: PermissionsService | null = null;\n\n// Кэш результатов проверки прав для избежания дублирования запросов\nconst permissionsCache: Map<string, Promise<boolean>> = new Map();\n\n// Функция для установки экземпляра сервиса (будет вызываться при инициализации плагина)\nexport function setPermissionsService(service: PermissionsService): void {\n globalPermissionsService = service;\n}\n\n// Общая функция проверки прав для обеих директив\nasync function checkPermission(action: string): Promise<boolean> {\n if (!globalPermissionsService) {\n console.warn('Permissions service not initialized yet.');\n return false;\n }\n\n // Проверяем есть ли запрос с таким же action уже в процессе выполнения\n if (!permissionsCache.has(action)) {\n // Создаем Promise для проверки прав и сохраняем в кэш\n const permissionPromise = globalPermissionsService.can(action)\n .catch(error => {\n console.error('Error checking permission:', error);\n permissionsCache.delete(action);\n return false;\n });\n\n permissionsCache.set(action, permissionPromise);\n }\n\n // Возвращаем результат из кэша (либо готовый, либо ожидающий Promise)\n return permissionsCache.get(action) as Promise<boolean>;\n}\n\n// Общая логика для обработки элементов, применяемая обеими директивами\nasync function processElement(el: CanHTMLElement, action: string, showWhenAllowed: boolean) {\n const originalDisplay = el.style.display;\n\n // Store action and original display for updates\n el._permission_data = {\n action,\n originalDisplay,\n permissionChecked: false\n };\n\n // Скрываем элемент изначально до проверки прав\n el.style.display = 'none';\n\n try {\n const hasPermission = await checkPermission(action);\n\n // Показываем элемент в зависимости от режима и результата проверки\n if ((showWhenAllowed && hasPermission) || (!showWhenAllowed && !hasPermission)) {\n el.style.display = originalDisplay || '';\n }\n\n el._permission_data.permissionChecked = true;\n } catch (error) {\n console.error('Error in directive processing:', error);\n // При ошибке для v-cant показываем элемент\n if (!showWhenAllowed) {\n el.style.display = originalDisplay || '';\n }\n }\n}\n\nexport const vCan: ObjectDirective = {\n async mounted(el: CanHTMLElement, binding: DirectiveBinding) {\n await processElement(el, binding.value, true);\n },\n\n async updated(el: CanHTMLElement, binding: DirectiveBinding) {\n if (!el._permission_data || el._permission_data.action !== binding.value) {\n await processElement(el, binding.value, true);\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}\n\n// Директива vCant - противоположность vCan, показывает элемент только если прав НЕТ\nexport const vCant: ObjectDirective = {\n async mounted(el: CanHTMLElement, binding: DirectiveBinding) {\n await processElement(el, binding.value, false);\n },\n\n async updated(el: CanHTMLElement, binding: DirectiveBinding) {\n if (!el._permission_data || el._permission_data.action !== binding.value) {\n await processElement(el, binding.value, false);\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, inject, InjectionKey } from 'vue'\nimport { PermissionsService, PermissionsOptions } from './services/permissionsService'\nimport { setPermissionsService } from './directives/vCan'\n\nexport const PermissionsKey: InjectionKey<PermissionsService> = Symbol('Permissions')\n\n/**\n * Setup permissions service with provided options\n * @param options Configuration options\n * @param options.baseUrl Base URL for API requests\n * @param options.endpoint Custom endpoint for permission checks\n * @param options.application Application identifier to be sent as a header\n * @returns Configured PermissionsService instance\n */\nexport function setupPermissions(options?: PermissionsOptions): PermissionsService {\n const service = new PermissionsService(options);\n // Устанавливаем глобальный сервис для директивы\n setPermissionsService(service);\n return service;\n}\n\nexport const PermissionsPlugin = {\n install(app: App, options?: PermissionsOptions) {\n const permissionsService = setupPermissions(options);\n app.provide(PermissionsKey, permissionsService);\n\n // Добавим сервис в глобальные свойства Vue для доступа откуда угодно\n app.config.globalProperties.$permissions = 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 && !isInitialLoading\" />\n <slot name=\"fallback\" v-else-if=\"!isLoading && !isInitialLoading && !can\" />\n <slot name=\"loading\" v-else-if=\"isLoading || isInitialLoading\" />\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, toRefs, PropType, ref, onMounted } 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 isInitialLoading = ref(true);\n const { can, isLoading, check } = usePermissions(action, { autoCheck: false });\n \n onMounted(async () => {\n await check();\n isInitialLoading.value = false;\n });\n\n return {\n can,\n isLoading,\n isInitialLoading\n };\n }\n});\n</script> ","import { App } from 'vue'\nimport Check from './components/Check.vue'\nimport { usePermissions } from './composables/usePermissions'\nimport { PermissionsPlugin, setupPermissions, usePermissionsService } from './plugin'\nimport { vCan, vCant, setPermissionsService } from './directives/vCan'\n\n// Именованные экспорты\nexport {\n Check,\n usePermissions,\n setupPermissions,\n vCan,\n vCant,\n usePermissionsService,\n setPermissionsService\n}\n\n// Создаем основной объект плагина\nconst plugin = {\n install(app: App, options?: { baseUrl?: string }) {\n // Важно: сначала нужно инициализировать PermissionsPlugin для provide/inject механизма\n app.use(PermissionsPlugin, options)\n\n // Затем регистрируем компонент и директивы\n app.component('Check', Check)\n app.directive('can', vCan)\n app.directive('cant', vCant)\n }\n}\n\n// Экспортируем плагин как по умолчанию\nexport default plugin "],"names":["PermissionsService","options","__publicField","axios","action","allowed","error","globalPermissionsService","permissionsCache","setPermissionsService","service","checkPermission","permissionPromise","processElement","el","showWhenAllowed","originalDisplay","hasPermission","vCan","binding","vCant","PermissionsKey","setupPermissions","PermissionsPlugin","app","permissionsService","usePermissionsService","inject","usePermissions","isAllowed","ref","isLoading","actionValue","computed","err","unwatch","watch","onUnmounted","_sfc_main","defineComponent","props","toRefs","isInitialLoading","can","check","onMounted","_ctx","_renderSlot","_createCommentVNode","plugin","Check"],"mappings":"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"}
1
+ {"version":3,"file":"locator-ars-lib.es.js","sources":["../src/services/permissionsService.ts","../src/directives/vCan.ts","../src/plugin.ts","../src/composables/usePermissions.ts","../src/components/Check.vue","../src/index.ts"],"sourcesContent":["import axios, { AxiosInstance } from 'axios'\n\nexport interface PermissionsOptions {\n baseUrl?: string\n endpoint?: string\n application?: string\n}\n\nexport class PermissionsService {\n private axios: AxiosInstance\n private cache: Map<string, boolean | string> = new Map()\n private endpoint: string\n private application?: 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 this.application = options?.application\n\n // Если указано application, добавляем его в заголовки по умолчанию\n if (this.application) {\n this.axios.defaults.headers.common['Application'] = this.application\n }\n }\n\n async can(action: string | string[]): Promise<boolean> {\n // Преобразуем массив в строку вида ['value1','value2','value3']\n const actionKey = Array.isArray(action) ? JSON.stringify(action) : action;\n\n // Check if we have a cached result\n if (this.cache.has(actionKey)) {\n return this.cache.get(actionKey) as boolean;\n }\n\n try {\n let params: { action: string | string[] } = { action };\n\n // Если это массив, преобразуем его в строку вида ['value1','value2','value3']\n if (Array.isArray(action)) {\n params = { action: JSON.stringify(action) };\n }\n\n const response = await this.axios.get(this.endpoint, { params });\n const allowed = response.data.allowed || false;\n\n // Cache the result\n this.cache.set(actionKey, allowed);\n\n return allowed;\n } catch (error) {\n console.error(`Error checking permission for ${Array.isArray(action) ? JSON.stringify(action) : 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 { ObjectDirective, DirectiveBinding } from 'vue'\nimport { PermissionsService } from '../services/permissionsService'\n\ninterface CanHTMLElement extends HTMLElement {\n _permission_data?: {\n action: string | string[]\n originalDisplay: string\n permissionChecked?: boolean\n }\n}\n\n// Глобальный сервис проверки прав\nlet globalPermissionsService: PermissionsService | null = null;\n\n// Кэш результатов проверки прав для избежания дублирования запросов\nconst permissionsCache: Map<string, Promise<boolean>> = new Map();\n\n// Функция для установки экземпляра сервиса (будет вызываться при инициализации плагина)\nexport function setPermissionsService(service: PermissionsService): void {\n globalPermissionsService = service;\n}\n\n// Общая функция проверки прав для обеих директив\nasync function checkPermission(action: string): Promise<boolean> {\n if (!globalPermissionsService) {\n console.warn('Permissions service not initialized yet.');\n return false;\n }\n\n // Проверяем есть ли запрос с таким же action уже в процессе выполнения\n if (!permissionsCache.has(action)) {\n // Создаем Promise для проверки прав и сохраняем в кэш\n const permissionPromise = globalPermissionsService.can(action)\n .catch(error => {\n console.error('Error checking permission:', error);\n permissionsCache.delete(action);\n return false;\n });\n\n permissionsCache.set(action, permissionPromise);\n }\n\n // Возвращаем результат из кэша (либо готовый, либо ожидающий Promise)\n return permissionsCache.get(action) as Promise<boolean>;\n}\n\n// Функция для проверки массива разрешений\nasync function checkPermissions(actions: string | string[]): Promise<boolean> {\n if (!globalPermissionsService) {\n console.warn('Permissions service not initialized yet.');\n return false;\n }\n\n if (typeof actions === 'string') {\n return checkPermission(actions);\n }\n\n // Если передан пустой массив, считаем что прав нет\n if (actions.length === 0) {\n return false;\n }\n\n // Используем кэш для массива, чтобы избежать повторных запросов\n const cacheKey = JSON.stringify(actions);\n if (!permissionsCache.has(cacheKey)) {\n // Отправляем один запрос с массивом разрешений\n const permissionPromise = globalPermissionsService.can(actions)\n .catch(error => {\n console.error('Error checking permissions:', error);\n permissionsCache.delete(cacheKey);\n return false;\n });\n\n permissionsCache.set(cacheKey, permissionPromise);\n }\n\n return permissionsCache.get(cacheKey) as Promise<boolean>;\n}\n\n// Общая логика для обработки элементов, применяемая обеими директивами\nasync function processElement(el: CanHTMLElement, action: string | string[], showWhenAllowed: boolean) {\n const originalDisplay = el.style.display;\n\n // Store action and original display for updates\n el._permission_data = {\n action,\n originalDisplay,\n permissionChecked: false\n };\n\n // Скрываем элемент изначально до проверки прав\n el.style.display = 'none';\n\n try {\n const hasPermission = await checkPermissions(action);\n\n // Показываем элемент в зависимости от режима и результата проверки\n if ((showWhenAllowed && hasPermission) || (!showWhenAllowed && !hasPermission)) {\n el.style.display = originalDisplay || '';\n }\n\n el._permission_data.permissionChecked = true;\n } catch (error) {\n console.error('Error in directive processing:', error);\n // При ошибке для v-cant показываем элемент\n if (!showWhenAllowed) {\n el.style.display = originalDisplay || '';\n }\n }\n}\n\nexport const vCan: ObjectDirective = {\n async mounted(el: CanHTMLElement, binding: DirectiveBinding) {\n await processElement(el, binding.value, true);\n },\n\n async updated(el: CanHTMLElement, binding: DirectiveBinding) {\n // Проверяем изменение значения, учитывая возможность массива\n const actionChanged = !el._permission_data ||\n (typeof el._permission_data.action !== typeof binding.value) ||\n (typeof binding.value === 'string' && el._permission_data.action !== binding.value) ||\n (Array.isArray(binding.value) &&\n (!Array.isArray(el._permission_data.action) ||\n JSON.stringify(el._permission_data.action) !== JSON.stringify(binding.value)));\n\n if (actionChanged) {\n await processElement(el, binding.value, true);\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}\n\n// Директива vCant - противоположность vCan, показывает элемент только если прав НЕТ\nexport const vCant: ObjectDirective = {\n async mounted(el: CanHTMLElement, binding: DirectiveBinding) {\n await processElement(el, binding.value, false);\n },\n\n async updated(el: CanHTMLElement, binding: DirectiveBinding) {\n // Проверяем изменение значения, учитывая возможность массива\n const actionChanged = !el._permission_data ||\n (typeof el._permission_data.action !== typeof binding.value) ||\n (typeof binding.value === 'string' && el._permission_data.action !== binding.value) ||\n (Array.isArray(binding.value) &&\n (!Array.isArray(el._permission_data.action) ||\n JSON.stringify(el._permission_data.action) !== JSON.stringify(binding.value)));\n\n if (actionChanged) {\n await processElement(el, binding.value, false);\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, inject, InjectionKey } from 'vue'\nimport { PermissionsService, PermissionsOptions } from './services/permissionsService'\nimport { setPermissionsService } from './directives/vCan'\n\nexport const PermissionsKey: InjectionKey<PermissionsService> = Symbol('Permissions')\n\n/**\n * Setup permissions service with provided options\n * @param options Configuration options\n * @param options.baseUrl Base URL for API requests\n * @param options.endpoint Custom endpoint for permission checks\n * @param options.application Application identifier to be sent as a header\n * @returns Configured PermissionsService instance\n */\nexport function setupPermissions(options?: PermissionsOptions): PermissionsService {\n const service = new PermissionsService(options);\n // Устанавливаем глобальный сервис для директивы\n setPermissionsService(service);\n return service;\n}\n\nexport const PermissionsPlugin = {\n install(app: App, options?: PermissionsOptions) {\n const permissionsService = setupPermissions(options);\n app.provide(PermissionsKey, permissionsService);\n\n // Добавим сервис в глобальные свойства Vue для доступа откуда угодно\n app.config.globalProperties.$permissions = 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\ntype ActionType = string | string[] | Ref<string | string[]>\n\nexport function usePermissions(action: ActionType, 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 === 'object' && 'value' in action ? action.value : action\n })\n\n const checkPermission = async () => {\n if (!actionValue.value) return\n\n isLoading.value = true\n error.value = null\n\n try {\n // Передаем разрешения напрямую в метод can, который теперь поддерживает массивы\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 === 'object' && 'value' in action) {\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 && !isInitialLoading\" />\n <slot name=\"fallback\" v-else-if=\"!isLoading && !isInitialLoading && !can\" />\n <slot name=\"loading\" v-else-if=\"isLoading || isInitialLoading\" />\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, toRefs, PropType, ref, onMounted } from 'vue';\nimport { usePermissions } from '../composables/usePermissions';\n\nexport default defineComponent({\n name: 'Check',\n props: {\n action: {\n type: [String, Array] as PropType<string | 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 isInitialLoading = ref(true);\n const { can, isLoading, check } = usePermissions(action, { autoCheck: false });\n\n onMounted(async () => {\n await check();\n isInitialLoading.value = false;\n });\n\n return {\n can,\n isLoading,\n isInitialLoading\n };\n }\n});\n</script>","import { App } from 'vue'\nimport Check from './components/Check.vue'\nimport { usePermissions } from './composables/usePermissions'\nimport { PermissionsPlugin, setupPermissions, usePermissionsService } from './plugin'\nimport { vCan, vCant, setPermissionsService } from './directives/vCan'\n\n// Именованные экспорты\nexport {\n Check,\n usePermissions,\n setupPermissions,\n vCan,\n vCant,\n usePermissionsService,\n setPermissionsService\n}\n\n// Создаем основной объект плагина\nconst plugin = {\n install(app: App, options?: { baseUrl?: string }) {\n // Важно: сначала нужно инициализировать PermissionsPlugin для provide/inject механизма\n app.use(PermissionsPlugin, options)\n\n // Затем регистрируем компонент и директивы\n app.component('Check', Check)\n app.directive('can', vCan)\n app.directive('cant', vCant)\n }\n}\n\n// Экспортируем плагин как по умолчанию\nexport default plugin "],"names":["PermissionsService","options","__publicField","axios","action","actionKey","params","allowed","error","globalPermissionsService","permissionsCache","setPermissionsService","service","checkPermission","permissionPromise","checkPermissions","actions","cacheKey","processElement","el","showWhenAllowed","originalDisplay","hasPermission","vCan","binding","vCant","PermissionsKey","setupPermissions","PermissionsPlugin","app","permissionsService","usePermissionsService","inject","usePermissions","isAllowed","ref","isLoading","actionValue","computed","err","unwatch","watch","onUnmounted","_sfc_main","defineComponent","props","toRefs","isInitialLoading","can","check","onMounted","_ctx","_renderSlot","_createCommentVNode","plugin","Check"],"mappings":"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"}
@@ -1,2 +1,2 @@
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 j=Object.defineProperty;var q=(n,i,o)=>i in n?j(n,i,{enumerable:!0,configurable:!0,writable:!0,value:o}):n[i]=o;var u=(n,i,o)=>q(n,typeof i!="symbol"?i+"":i,o);class C{constructor(s){u(this,"axios");u(this,"cache",new Map);u(this,"endpoint");u(this,"application");this.axios=o.create({baseURL:(s==null?void 0:s.baseUrl)||""}),this.endpoint=(s==null?void 0:s.endpoint)||"/api/v1/dashboard/access",this.application=s==null?void 0:s.application,this.application&&(this.axios.defaults.headers.common.Application=this.application)}async can(s){if(this.cache.has(s))return this.cache.get(s);try{const r=(await this.axios.get(this.endpoint,{params:{action:s}})).data.allowed||!1;return this.cache.set(s,r),r}catch(a){return console.error(`Error checking permission for ${s}:`,a),!1}}clearCache(s){s?this.cache.delete(s):this.cache.clear()}}let m=null;const d=new Map;function h(e){m=e}async function L(e){if(!m)return console.warn("Permissions service not initialized yet."),!1;if(!d.has(e)){const s=m.can(e).catch(a=>(console.error("Error checking permission:",a),d.delete(e),!1));d.set(e,s)}return d.get(e)}async function f(e,s,a){const r=e.style.display;e._permission_data={action:s,originalDisplay:r,permissionChecked:!1},e.style.display="none";try{const t=await L(s);(a&&t||!a&&!t)&&(e.style.display=r||""),e._permission_data.permissionChecked=!0}catch(t){console.error("Error in directive processing:",t),a||(e.style.display=r||"")}}const y={async mounted(e,s){await f(e,s.value,!0)},async updated(e,s){(!e._permission_data||e._permission_data.action!==s.value)&&await f(e,s.value,!0)},unmounted(e){e._permission_data&&(e.style.display=e._permission_data.originalDisplay,delete e._permission_data)}},v={async mounted(e,s){await f(e,s.value,!1)},async updated(e,s){(!e._permission_data||e._permission_data.action!==s.value)&&await f(e,s.value,!1)},unmounted(e){e._permission_data&&(e.style.display=e._permission_data.originalDisplay,delete e._permission_data)}},g=Symbol("Permissions");function _(e){const s=new C(e);return h(s),s}const $={install(e,s){const a=_(s);e.provide(g,a),e.config.globalProperties.$permissions=a}};function P(){const e=i.inject(g);if(!e)throw new Error("Permissions plugin not installed!");return e}function k(e,s={}){const a=P(),r=i.ref(null),t=i.ref(!1),c=i.ref(null),w=i.computed(()=>typeof e=="string"?e:e.value),p=async()=>{if(w.value){t.value=!0,c.value=null;try{r.value=await a.can(w.value)}catch(l){c.value=l instanceof Error?l:new Error(String(l)),r.value=!1}finally{t.value=!1}}};if(s.autoCheck!==!1&&p(),typeof e!="string"){const l=i.watch(e,()=>{p()});i.onUnmounted(()=>{l()})}return{isAllowed:r,isLoading:t,error:c,check:p,can:i.computed(()=>r.value===!0)}}const b=i.defineComponent({name:"Check",props:{action:{type:String,required:!0},fallback:{type:Boolean,default:!1}},setup(e){const{action:s}=i.toRefs(e),a=i.ref(!0),{can:r,isLoading:t,check:c}=k(s,{autoCheck:!1});return i.onMounted(async()=>{await c(),a.value=!1}),{can:r,isLoading:t,isInitialLoading:a}}}),E=(e,s)=>{const a=e.__vccOpts||e;for(const[r,t]of s)a[r]=t;return a};function M(e,s,a,r,t,c){return e.can&&!e.isInitialLoading?i.renderSlot(e.$slots,"default",{key:0}):!e.isLoading&&!e.isInitialLoading&&!e.can?i.renderSlot(e.$slots,"fallback",{key:1}):e.isLoading||e.isInitialLoading?i.renderSlot(e.$slots,"loading",{key:2}):i.createCommentVNode("",!0)}const S=E(b,[["render",M]]),I={install(e,s){e.use($,s),e.component("Check",S),e.directive("can",y),e.directive("cant",v)}};n.Check=S,n.default=I,n.setPermissionsService=h,n.setupPermissions=_,n.usePermissions=k,n.usePermissionsService=P,n.vCan=y,n.vCant=v,Object.defineProperties(n,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
1
+ (function(a,i){typeof exports=="object"&&typeof module<"u"?i(exports,require("vue"),require("axios")):typeof define=="function"&&define.amd?define(["exports","vue","axios"],i):(a=typeof globalThis<"u"?globalThis:a||self,i(a.LocatorArsLib={},a.Vue,a.axios))})(this,function(a,i,l){"use strict";var j=Object.defineProperty;var M=(a,i,l)=>i in a?j(a,i,{enumerable:!0,configurable:!0,writable:!0,value:l}):a[i]=l;var d=(a,i,l)=>M(a,typeof i!="symbol"?i+"":i,l);class w{constructor(s){d(this,"axios");d(this,"cache",new Map);d(this,"endpoint");d(this,"application");this.axios=l.create({baseURL:(s==null?void 0:s.baseUrl)||""}),this.endpoint=(s==null?void 0:s.endpoint)||"/api/v1/dashboard/access",this.application=s==null?void 0:s.application,this.application&&(this.axios.defaults.headers.common.Application=this.application)}async can(s){const r=Array.isArray(s)?JSON.stringify(s):s;if(this.cache.has(r))return this.cache.get(r);try{let n={action:s};Array.isArray(s)&&(n={action:JSON.stringify(s)});const o=(await this.axios.get(this.endpoint,{params:n})).data.allowed||!1;return this.cache.set(r,o),o}catch(n){return console.error(`Error checking permission for ${Array.isArray(s)?JSON.stringify(s):s}:`,n),!1}}clearCache(s){s?this.cache.delete(s):this.cache.clear()}}let u=null;const c=new Map;function p(e){u=e}async function A(e){if(!u)return console.warn("Permissions service not initialized yet."),!1;if(!c.has(e)){const s=u.can(e).catch(r=>(console.error("Error checking permission:",r),c.delete(e),!1));c.set(e,s)}return c.get(e)}async function L(e){if(!u)return console.warn("Permissions service not initialized yet."),!1;if(typeof e=="string")return A(e);if(e.length===0)return!1;const s=JSON.stringify(e);if(!c.has(s)){const r=u.can(e).catch(n=>(console.error("Error checking permissions:",n),c.delete(s),!1));c.set(s,r)}return c.get(s)}async function y(e,s,r){const n=e.style.display;e._permission_data={action:s,originalDisplay:n,permissionChecked:!1},e.style.display="none";try{const t=await L(s);(r&&t||!r&&!t)&&(e.style.display=n||""),e._permission_data.permissionChecked=!0}catch(t){console.error("Error in directive processing:",t),r||(e.style.display=n||"")}}const h={async mounted(e,s){await y(e,s.value,!0)},async updated(e,s){(!e._permission_data||typeof e._permission_data.action!=typeof s.value||typeof s.value=="string"&&e._permission_data.action!==s.value||Array.isArray(s.value)&&(!Array.isArray(e._permission_data.action)||JSON.stringify(e._permission_data.action)!==JSON.stringify(s.value)))&&await y(e,s.value,!0)},unmounted(e){e._permission_data&&(e.style.display=e._permission_data.originalDisplay,delete e._permission_data)}},v={async mounted(e,s){await y(e,s.value,!1)},async updated(e,s){(!e._permission_data||typeof e._permission_data.action!=typeof s.value||typeof s.value=="string"&&e._permission_data.action!==s.value||Array.isArray(s.value)&&(!Array.isArray(e._permission_data.action)||JSON.stringify(e._permission_data.action)!==JSON.stringify(s.value)))&&await y(e,s.value,!1)},unmounted(e){e._permission_data&&(e.style.display=e._permission_data.originalDisplay,delete e._permission_data)}},_=Symbol("Permissions");function g(e){const s=new w(e);return p(s),s}const O={install(e,s){const r=g(s);e.provide(_,r),e.config.globalProperties.$permissions=r}};function P(){const e=i.inject(_);if(!e)throw new Error("Permissions plugin not installed!");return e}function S(e,s={}){const r=P(),n=i.ref(null),t=i.ref(!1),o=i.ref(null),C=i.computed(()=>typeof e=="object"&&"value"in e?e.value:e),m=async()=>{if(C.value){t.value=!0,o.value=null;try{n.value=await r.can(C.value)}catch(f){o.value=f instanceof Error?f:new Error(String(f)),n.value=!1}finally{t.value=!1}}};if(s.autoCheck!==!1&&m(),typeof e=="object"&&"value"in e){const f=i.watch(e,()=>{m()});i.onUnmounted(()=>{f()})}return{isAllowed:n,isLoading:t,error:o,check:m,can:i.computed(()=>n.value===!0)}}const N=i.defineComponent({name:"Check",props:{action:{type:[String,Array],required:!0},fallback:{type:Boolean,default:!1}},setup(e){const{action:s}=i.toRefs(e),r=i.ref(!0),{can:n,isLoading:t,check:o}=S(s,{autoCheck:!1});return i.onMounted(async()=>{await o(),r.value=!1}),{can:n,isLoading:t,isInitialLoading:r}}}),$=(e,s)=>{const r=e.__vccOpts||e;for(const[n,t]of s)r[n]=t;return r};function E(e,s,r,n,t,o){return e.can&&!e.isInitialLoading?i.renderSlot(e.$slots,"default",{key:0}):!e.isLoading&&!e.isInitialLoading&&!e.can?i.renderSlot(e.$slots,"fallback",{key:1}):e.isLoading||e.isInitialLoading?i.renderSlot(e.$slots,"loading",{key:2}):i.createCommentVNode("",!0)}const k=$(N,[["render",E]]),J={install(e,s){e.use(O,s),e.component("Check",k),e.directive("can",h),e.directive("cant",v)}};a.Check=k,a.default=J,a.setPermissionsService=p,a.setupPermissions=g,a.usePermissions=S,a.usePermissionsService=P,a.vCan=h,a.vCant=v,Object.defineProperties(a,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
2
2
  //# sourceMappingURL=locator-ars-lib.umd.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"locator-ars-lib.umd.js","sources":["../src/services/permissionsService.ts","../src/directives/vCan.ts","../src/plugin.ts","../src/composables/usePermissions.ts","../src/components/Check.vue","../src/index.ts"],"sourcesContent":["import axios, { AxiosInstance } from 'axios'\n\nexport interface PermissionsOptions {\n baseUrl?: string\n endpoint?: string\n application?: string\n}\n\nexport class PermissionsService {\n private axios: AxiosInstance\n private cache: Map<string, boolean> = new Map()\n private endpoint: string\n private application?: 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 this.application = options?.application\n\n // Если указано application, добавляем его в заголовки по умолчанию\n if (this.application) {\n this.axios.defaults.headers.common['Application'] = this.application\n }\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 { ObjectDirective, DirectiveBinding } from 'vue'\nimport { PermissionsService } from '../services/permissionsService'\n\ninterface CanHTMLElement extends HTMLElement {\n _permission_data?: {\n action: string\n originalDisplay: string\n permissionChecked?: boolean\n }\n}\n\n// Глобальный сервис проверки прав\nlet globalPermissionsService: PermissionsService | null = null;\n\n// Кэш результатов проверки прав для избежания дублирования запросов\nconst permissionsCache: Map<string, Promise<boolean>> = new Map();\n\n// Функция для установки экземпляра сервиса (будет вызываться при инициализации плагина)\nexport function setPermissionsService(service: PermissionsService): void {\n globalPermissionsService = service;\n}\n\n// Общая функция проверки прав для обеих директив\nasync function checkPermission(action: string): Promise<boolean> {\n if (!globalPermissionsService) {\n console.warn('Permissions service not initialized yet.');\n return false;\n }\n\n // Проверяем есть ли запрос с таким же action уже в процессе выполнения\n if (!permissionsCache.has(action)) {\n // Создаем Promise для проверки прав и сохраняем в кэш\n const permissionPromise = globalPermissionsService.can(action)\n .catch(error => {\n console.error('Error checking permission:', error);\n permissionsCache.delete(action);\n return false;\n });\n\n permissionsCache.set(action, permissionPromise);\n }\n\n // Возвращаем результат из кэша (либо готовый, либо ожидающий Promise)\n return permissionsCache.get(action) as Promise<boolean>;\n}\n\n// Общая логика для обработки элементов, применяемая обеими директивами\nasync function processElement(el: CanHTMLElement, action: string, showWhenAllowed: boolean) {\n const originalDisplay = el.style.display;\n\n // Store action and original display for updates\n el._permission_data = {\n action,\n originalDisplay,\n permissionChecked: false\n };\n\n // Скрываем элемент изначально до проверки прав\n el.style.display = 'none';\n\n try {\n const hasPermission = await checkPermission(action);\n\n // Показываем элемент в зависимости от режима и результата проверки\n if ((showWhenAllowed && hasPermission) || (!showWhenAllowed && !hasPermission)) {\n el.style.display = originalDisplay || '';\n }\n\n el._permission_data.permissionChecked = true;\n } catch (error) {\n console.error('Error in directive processing:', error);\n // При ошибке для v-cant показываем элемент\n if (!showWhenAllowed) {\n el.style.display = originalDisplay || '';\n }\n }\n}\n\nexport const vCan: ObjectDirective = {\n async mounted(el: CanHTMLElement, binding: DirectiveBinding) {\n await processElement(el, binding.value, true);\n },\n\n async updated(el: CanHTMLElement, binding: DirectiveBinding) {\n if (!el._permission_data || el._permission_data.action !== binding.value) {\n await processElement(el, binding.value, true);\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}\n\n// Директива vCant - противоположность vCan, показывает элемент только если прав НЕТ\nexport const vCant: ObjectDirective = {\n async mounted(el: CanHTMLElement, binding: DirectiveBinding) {\n await processElement(el, binding.value, false);\n },\n\n async updated(el: CanHTMLElement, binding: DirectiveBinding) {\n if (!el._permission_data || el._permission_data.action !== binding.value) {\n await processElement(el, binding.value, false);\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, inject, InjectionKey } from 'vue'\nimport { PermissionsService, PermissionsOptions } from './services/permissionsService'\nimport { setPermissionsService } from './directives/vCan'\n\nexport const PermissionsKey: InjectionKey<PermissionsService> = Symbol('Permissions')\n\n/**\n * Setup permissions service with provided options\n * @param options Configuration options\n * @param options.baseUrl Base URL for API requests\n * @param options.endpoint Custom endpoint for permission checks\n * @param options.application Application identifier to be sent as a header\n * @returns Configured PermissionsService instance\n */\nexport function setupPermissions(options?: PermissionsOptions): PermissionsService {\n const service = new PermissionsService(options);\n // Устанавливаем глобальный сервис для директивы\n setPermissionsService(service);\n return service;\n}\n\nexport const PermissionsPlugin = {\n install(app: App, options?: PermissionsOptions) {\n const permissionsService = setupPermissions(options);\n app.provide(PermissionsKey, permissionsService);\n\n // Добавим сервис в глобальные свойства Vue для доступа откуда угодно\n app.config.globalProperties.$permissions = 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 && !isInitialLoading\" />\n <slot name=\"fallback\" v-else-if=\"!isLoading && !isInitialLoading && !can\" />\n <slot name=\"loading\" v-else-if=\"isLoading || isInitialLoading\" />\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, toRefs, PropType, ref, onMounted } 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 isInitialLoading = ref(true);\n const { can, isLoading, check } = usePermissions(action, { autoCheck: false });\n \n onMounted(async () => {\n await check();\n isInitialLoading.value = false;\n });\n\n return {\n can,\n isLoading,\n isInitialLoading\n };\n }\n});\n</script> ","import { App } from 'vue'\nimport Check from './components/Check.vue'\nimport { usePermissions } from './composables/usePermissions'\nimport { PermissionsPlugin, setupPermissions, usePermissionsService } from './plugin'\nimport { vCan, vCant, setPermissionsService } from './directives/vCan'\n\n// Именованные экспорты\nexport {\n Check,\n usePermissions,\n setupPermissions,\n vCan,\n vCant,\n usePermissionsService,\n setPermissionsService\n}\n\n// Создаем основной объект плагина\nconst plugin = {\n install(app: App, options?: { baseUrl?: string }) {\n // Важно: сначала нужно инициализировать PermissionsPlugin для provide/inject механизма\n app.use(PermissionsPlugin, options)\n\n // Затем регистрируем компонент и директивы\n app.component('Check', Check)\n app.directive('can', vCan)\n app.directive('cant', vCant)\n }\n}\n\n// Экспортируем плагин как по умолчанию\nexport default plugin "],"names":["PermissionsService","options","__publicField","axios","action","allowed","error","globalPermissionsService","permissionsCache","setPermissionsService","service","checkPermission","permissionPromise","processElement","el","showWhenAllowed","originalDisplay","hasPermission","vCan","binding","vCant","PermissionsKey","setupPermissions","PermissionsPlugin","app","permissionsService","usePermissionsService","inject","usePermissions","isAllowed","ref","isLoading","actionValue","computed","err","unwatch","watch","onUnmounted","_sfc_main","defineComponent","props","toRefs","isInitialLoading","can","check","onMounted","_ctx","_renderSlot","_createCommentVNode","plugin","Check"],"mappings":"ycAQO,MAAMA,CAAmB,CAM5B,YAAYC,EAA8B,CALlCC,EAAA,cACAA,EAAA,iBAAkC,KAClCA,EAAA,iBACAA,EAAA,oBAGC,KAAA,MAAQC,EAAM,OAAO,CACtB,SAASF,GAAA,YAAAA,EAAS,UAAW,EAAA,CAChC,EACI,KAAA,UAAWA,GAAA,YAAAA,EAAS,WAAY,2BACrC,KAAK,YAAcA,GAAA,YAAAA,EAAS,YAGxB,KAAK,cACL,KAAK,MAAM,SAAS,QAAQ,OAAO,YAAiB,KAAK,YAC7D,CAGJ,MAAM,IAAIG,EAAkC,CAExC,GAAI,KAAK,MAAM,IAAIA,CAAM,EACd,OAAA,KAAK,MAAM,IAAIA,CAAM,EAG5B,GAAA,CAKM,MAAAC,GAJW,MAAM,KAAK,MAAM,IAAI,KAAK,SAAU,CACjD,OAAQ,CAAE,OAAAD,CAAO,CAAA,CACpB,GAEwB,KAAK,SAAW,GAGpC,YAAA,MAAM,IAAIA,EAAQC,CAAO,EAEvBA,QACFC,EAAO,CACZ,eAAQ,MAAM,iCAAiCF,CAAM,IAAKE,CAAK,EACxD,EAAA,CACX,CAGJ,WAAWF,EAAuB,CAC1BA,EACK,KAAA,MAAM,OAAOA,CAAM,EAExB,KAAK,MAAM,MAAM,CACrB,CAER,CC7CA,IAAIG,EAAsD,KAG1D,MAAMC,MAAsD,IAGrD,SAASC,EAAsBC,EAAmC,CAC1CH,EAAAG,CAC/B,CAGA,eAAeC,EAAgBP,EAAkC,CAC7D,GAAI,CAACG,EACD,eAAQ,KAAK,0CAA0C,EAChD,GAIX,GAAI,CAACC,EAAiB,IAAIJ,CAAM,EAAG,CAE/B,MAAMQ,EAAoBL,EAAyB,IAAIH,CAAM,EACxD,MAAeE,IACJ,QAAA,MAAM,6BAA8BA,CAAK,EACjDE,EAAiB,OAAOJ,CAAM,EACvB,GACV,EAEYI,EAAA,IAAIJ,EAAQQ,CAAiB,CAAA,CAI3C,OAAAJ,EAAiB,IAAIJ,CAAM,CACtC,CAGA,eAAeS,EAAeC,EAAoBV,EAAgBW,EAA0B,CAClF,MAAAC,EAAkBF,EAAG,MAAM,QAGjCA,EAAG,iBAAmB,CAClB,OAAAV,EACA,gBAAAY,EACA,kBAAmB,EACvB,EAGAF,EAAG,MAAM,QAAU,OAEf,GAAA,CACM,MAAAG,EAAgB,MAAMN,EAAgBP,CAAM,GAG7CW,GAAmBE,GAAmB,CAACF,GAAmB,CAACE,KACzDH,EAAA,MAAM,QAAUE,GAAmB,IAG1CF,EAAG,iBAAiB,kBAAoB,SACnCR,EAAO,CACJ,QAAA,MAAM,iCAAkCA,CAAK,EAEhDS,IACED,EAAA,MAAM,QAAUE,GAAmB,GAC1C,CAER,CAEO,MAAME,EAAwB,CACjC,MAAM,QAAQJ,EAAoBK,EAA2B,CACzD,MAAMN,EAAeC,EAAIK,EAAQ,MAAO,EAAI,CAChD,EAEA,MAAM,QAAQL,EAAoBK,EAA2B,EACrD,CAACL,EAAG,kBAAoBA,EAAG,iBAAiB,SAAWK,EAAQ,QAC/D,MAAMN,EAAeC,EAAIK,EAAQ,MAAO,EAAI,CAEpD,EAEA,UAAUL,EAAoB,CACtBA,EAAG,mBACAA,EAAA,MAAM,QAAUA,EAAG,iBAAiB,gBACvC,OAAOA,EAAG,iBACd,CAER,EAGaM,EAAyB,CAClC,MAAM,QAAQN,EAAoBK,EAA2B,CACzD,MAAMN,EAAeC,EAAIK,EAAQ,MAAO,EAAK,CACjD,EAEA,MAAM,QAAQL,EAAoBK,EAA2B,EACrD,CAACL,EAAG,kBAAoBA,EAAG,iBAAiB,SAAWK,EAAQ,QAC/D,MAAMN,EAAeC,EAAIK,EAAQ,MAAO,EAAK,CAErD,EAEA,UAAUL,EAAoB,CACtBA,EAAG,mBACAA,EAAA,MAAM,QAAUA,EAAG,iBAAiB,gBACvC,OAAOA,EAAG,iBACd,CAER,EC/GaO,EAAmD,OAAO,aAAa,EAU7E,SAASC,EAAiBrB,EAAkD,CACzE,MAAAS,EAAU,IAAIV,EAAmBC,CAAO,EAE9C,OAAAQ,EAAsBC,CAAO,EACtBA,CACX,CAEO,MAAMa,EAAoB,CAC7B,QAAQC,EAAUvB,EAA8B,CACtC,MAAAwB,EAAqBH,EAAiBrB,CAAO,EAC/CuB,EAAA,QAAQH,EAAgBI,CAAkB,EAG1CD,EAAA,OAAO,iBAAiB,aAAeC,CAAA,CAEnD,EAEO,SAASC,GAA4C,CAClD,MAAAD,EAAqBE,SAAON,CAAc,EAChD,GAAI,CAACI,EACK,MAAA,IAAI,MAAM,mCAAmC,EAEhD,OAAAA,CACX,CC9BO,SAASG,EAAexB,EAA8BH,EAAiC,GAAI,CAC9F,MAAMwB,EAAqBC,EAAsB,EAC3CG,EAAYC,MAAoB,IAAI,EACpCC,EAAYD,MAAI,EAAK,EACrBxB,EAAQwB,MAAkB,IAAI,EAE9BE,EAAcC,EAAAA,SAAS,IAClB,OAAO7B,GAAW,SAAWA,EAASA,EAAO,KACvD,EAEKO,EAAkB,SAAY,CAC5B,GAACqB,EAAY,MAEjB,CAAAD,EAAU,MAAQ,GAClBzB,EAAM,MAAQ,KAEV,GAAA,CACAuB,EAAU,MAAQ,MAAMJ,EAAmB,IAAIO,EAAY,KAAK,QAC3DE,EAAK,CACJ5B,EAAA,MAAQ4B,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,EAChEL,EAAU,MAAQ,EAAA,QACpB,CACEE,EAAU,MAAQ,EAAA,EAE1B,EAQI,GALA9B,EAAQ,YAAc,IACNU,EAAA,EAIhB,OAAOP,GAAW,SAAU,CACtB,MAAA+B,EAAUC,QAAMhC,EAAQ,IAAM,CAChBO,EAAA,CAAA,CACnB,EAED0B,EAAAA,YAAY,IAAM,CACNF,EAAA,CAAA,CACX,CAAA,CAGE,MAAA,CACH,UAAAN,EACA,UAAAE,EACA,MAAAzB,EACA,MAAOK,EACP,IAAKsB,EAAA,SAAS,IAAMJ,EAAU,QAAU,EAAI,CAChD,CACJ,CC9CA,MAAAS,EAAeC,kBAAgB,CAC7B,KAAM,QACN,MAAO,CACL,OAAQ,CACN,KAAM,OACN,SAAU,EACZ,EACA,SAAU,CACR,KAAM,QACN,QAAS,EAAA,CAEb,EACA,MAAMC,EAAO,CACX,KAAM,CAAE,OAAApC,CAAA,EAAWqC,EAAA,OAAOD,CAAK,EACzBE,EAAmBZ,MAAI,EAAI,EAC3B,CAAE,IAAAa,EAAK,UAAAZ,EAAW,MAAAa,CAAM,EAAIhB,EAAexB,EAAQ,CAAE,UAAW,GAAO,EAE7EyC,OAAAA,EAAAA,UAAU,SAAY,CACpB,MAAMD,EAAM,EACZF,EAAiB,MAAQ,EAAA,CAC1B,EAEM,CACL,IAAAC,EACA,UAAAZ,EACA,iBAAAW,CACF,CAAA,CAEJ,CAAC,+FArCa,OAAAI,EAAA,KAAG,CAAKA,EAApB,iBAAAC,aAAwCD,EAD1C,OAAA,UAAA,CAAA,IAAA,CAAA,CAAA,EAAA,CAEoCA,aAAS,CAAKA,EAAA,kBAAgB,CAAKA,EAAA,IAArEC,EAAAA,WAA4ED,EAF9E,OAAA,WAAA,CAAA,IAAA,CAAA,CAAA,EAGkCA,EAAa,WAAAA,EAAA,iBAA7CC,aAAiED,EAHnE,OAAA,UAAA,CAAA,IAAA,CAAA,CAAA,EAAAE,EAAAA,mBAAA,GAAA,EAAA,8BCkBMC,EAAS,CACX,QAAQzB,EAAUvB,EAAgC,CAE1CuB,EAAA,IAAID,EAAmBtB,CAAO,EAG9BuB,EAAA,UAAU,QAAS0B,CAAK,EACxB1B,EAAA,UAAU,MAAON,CAAI,EACrBM,EAAA,UAAU,OAAQJ,CAAK,CAAA,CAEnC"}
1
+ {"version":3,"file":"locator-ars-lib.umd.js","sources":["../src/services/permissionsService.ts","../src/directives/vCan.ts","../src/plugin.ts","../src/composables/usePermissions.ts","../src/components/Check.vue","../src/index.ts"],"sourcesContent":["import axios, { AxiosInstance } from 'axios'\n\nexport interface PermissionsOptions {\n baseUrl?: string\n endpoint?: string\n application?: string\n}\n\nexport class PermissionsService {\n private axios: AxiosInstance\n private cache: Map<string, boolean | string> = new Map()\n private endpoint: string\n private application?: 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 this.application = options?.application\n\n // Если указано application, добавляем его в заголовки по умолчанию\n if (this.application) {\n this.axios.defaults.headers.common['Application'] = this.application\n }\n }\n\n async can(action: string | string[]): Promise<boolean> {\n // Преобразуем массив в строку вида ['value1','value2','value3']\n const actionKey = Array.isArray(action) ? JSON.stringify(action) : action;\n\n // Check if we have a cached result\n if (this.cache.has(actionKey)) {\n return this.cache.get(actionKey) as boolean;\n }\n\n try {\n let params: { action: string | string[] } = { action };\n\n // Если это массив, преобразуем его в строку вида ['value1','value2','value3']\n if (Array.isArray(action)) {\n params = { action: JSON.stringify(action) };\n }\n\n const response = await this.axios.get(this.endpoint, { params });\n const allowed = response.data.allowed || false;\n\n // Cache the result\n this.cache.set(actionKey, allowed);\n\n return allowed;\n } catch (error) {\n console.error(`Error checking permission for ${Array.isArray(action) ? JSON.stringify(action) : 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 { ObjectDirective, DirectiveBinding } from 'vue'\nimport { PermissionsService } from '../services/permissionsService'\n\ninterface CanHTMLElement extends HTMLElement {\n _permission_data?: {\n action: string | string[]\n originalDisplay: string\n permissionChecked?: boolean\n }\n}\n\n// Глобальный сервис проверки прав\nlet globalPermissionsService: PermissionsService | null = null;\n\n// Кэш результатов проверки прав для избежания дублирования запросов\nconst permissionsCache: Map<string, Promise<boolean>> = new Map();\n\n// Функция для установки экземпляра сервиса (будет вызываться при инициализации плагина)\nexport function setPermissionsService(service: PermissionsService): void {\n globalPermissionsService = service;\n}\n\n// Общая функция проверки прав для обеих директив\nasync function checkPermission(action: string): Promise<boolean> {\n if (!globalPermissionsService) {\n console.warn('Permissions service not initialized yet.');\n return false;\n }\n\n // Проверяем есть ли запрос с таким же action уже в процессе выполнения\n if (!permissionsCache.has(action)) {\n // Создаем Promise для проверки прав и сохраняем в кэш\n const permissionPromise = globalPermissionsService.can(action)\n .catch(error => {\n console.error('Error checking permission:', error);\n permissionsCache.delete(action);\n return false;\n });\n\n permissionsCache.set(action, permissionPromise);\n }\n\n // Возвращаем результат из кэша (либо готовый, либо ожидающий Promise)\n return permissionsCache.get(action) as Promise<boolean>;\n}\n\n// Функция для проверки массива разрешений\nasync function checkPermissions(actions: string | string[]): Promise<boolean> {\n if (!globalPermissionsService) {\n console.warn('Permissions service not initialized yet.');\n return false;\n }\n\n if (typeof actions === 'string') {\n return checkPermission(actions);\n }\n\n // Если передан пустой массив, считаем что прав нет\n if (actions.length === 0) {\n return false;\n }\n\n // Используем кэш для массива, чтобы избежать повторных запросов\n const cacheKey = JSON.stringify(actions);\n if (!permissionsCache.has(cacheKey)) {\n // Отправляем один запрос с массивом разрешений\n const permissionPromise = globalPermissionsService.can(actions)\n .catch(error => {\n console.error('Error checking permissions:', error);\n permissionsCache.delete(cacheKey);\n return false;\n });\n\n permissionsCache.set(cacheKey, permissionPromise);\n }\n\n return permissionsCache.get(cacheKey) as Promise<boolean>;\n}\n\n// Общая логика для обработки элементов, применяемая обеими директивами\nasync function processElement(el: CanHTMLElement, action: string | string[], showWhenAllowed: boolean) {\n const originalDisplay = el.style.display;\n\n // Store action and original display for updates\n el._permission_data = {\n action,\n originalDisplay,\n permissionChecked: false\n };\n\n // Скрываем элемент изначально до проверки прав\n el.style.display = 'none';\n\n try {\n const hasPermission = await checkPermissions(action);\n\n // Показываем элемент в зависимости от режима и результата проверки\n if ((showWhenAllowed && hasPermission) || (!showWhenAllowed && !hasPermission)) {\n el.style.display = originalDisplay || '';\n }\n\n el._permission_data.permissionChecked = true;\n } catch (error) {\n console.error('Error in directive processing:', error);\n // При ошибке для v-cant показываем элемент\n if (!showWhenAllowed) {\n el.style.display = originalDisplay || '';\n }\n }\n}\n\nexport const vCan: ObjectDirective = {\n async mounted(el: CanHTMLElement, binding: DirectiveBinding) {\n await processElement(el, binding.value, true);\n },\n\n async updated(el: CanHTMLElement, binding: DirectiveBinding) {\n // Проверяем изменение значения, учитывая возможность массива\n const actionChanged = !el._permission_data ||\n (typeof el._permission_data.action !== typeof binding.value) ||\n (typeof binding.value === 'string' && el._permission_data.action !== binding.value) ||\n (Array.isArray(binding.value) &&\n (!Array.isArray(el._permission_data.action) ||\n JSON.stringify(el._permission_data.action) !== JSON.stringify(binding.value)));\n\n if (actionChanged) {\n await processElement(el, binding.value, true);\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}\n\n// Директива vCant - противоположность vCan, показывает элемент только если прав НЕТ\nexport const vCant: ObjectDirective = {\n async mounted(el: CanHTMLElement, binding: DirectiveBinding) {\n await processElement(el, binding.value, false);\n },\n\n async updated(el: CanHTMLElement, binding: DirectiveBinding) {\n // Проверяем изменение значения, учитывая возможность массива\n const actionChanged = !el._permission_data ||\n (typeof el._permission_data.action !== typeof binding.value) ||\n (typeof binding.value === 'string' && el._permission_data.action !== binding.value) ||\n (Array.isArray(binding.value) &&\n (!Array.isArray(el._permission_data.action) ||\n JSON.stringify(el._permission_data.action) !== JSON.stringify(binding.value)));\n\n if (actionChanged) {\n await processElement(el, binding.value, false);\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, inject, InjectionKey } from 'vue'\nimport { PermissionsService, PermissionsOptions } from './services/permissionsService'\nimport { setPermissionsService } from './directives/vCan'\n\nexport const PermissionsKey: InjectionKey<PermissionsService> = Symbol('Permissions')\n\n/**\n * Setup permissions service with provided options\n * @param options Configuration options\n * @param options.baseUrl Base URL for API requests\n * @param options.endpoint Custom endpoint for permission checks\n * @param options.application Application identifier to be sent as a header\n * @returns Configured PermissionsService instance\n */\nexport function setupPermissions(options?: PermissionsOptions): PermissionsService {\n const service = new PermissionsService(options);\n // Устанавливаем глобальный сервис для директивы\n setPermissionsService(service);\n return service;\n}\n\nexport const PermissionsPlugin = {\n install(app: App, options?: PermissionsOptions) {\n const permissionsService = setupPermissions(options);\n app.provide(PermissionsKey, permissionsService);\n\n // Добавим сервис в глобальные свойства Vue для доступа откуда угодно\n app.config.globalProperties.$permissions = 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\ntype ActionType = string | string[] | Ref<string | string[]>\n\nexport function usePermissions(action: ActionType, 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 === 'object' && 'value' in action ? action.value : action\n })\n\n const checkPermission = async () => {\n if (!actionValue.value) return\n\n isLoading.value = true\n error.value = null\n\n try {\n // Передаем разрешения напрямую в метод can, который теперь поддерживает массивы\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 === 'object' && 'value' in action) {\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 && !isInitialLoading\" />\n <slot name=\"fallback\" v-else-if=\"!isLoading && !isInitialLoading && !can\" />\n <slot name=\"loading\" v-else-if=\"isLoading || isInitialLoading\" />\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, toRefs, PropType, ref, onMounted } from 'vue';\nimport { usePermissions } from '../composables/usePermissions';\n\nexport default defineComponent({\n name: 'Check',\n props: {\n action: {\n type: [String, Array] as PropType<string | 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 isInitialLoading = ref(true);\n const { can, isLoading, check } = usePermissions(action, { autoCheck: false });\n\n onMounted(async () => {\n await check();\n isInitialLoading.value = false;\n });\n\n return {\n can,\n isLoading,\n isInitialLoading\n };\n }\n});\n</script>","import { App } from 'vue'\nimport Check from './components/Check.vue'\nimport { usePermissions } from './composables/usePermissions'\nimport { PermissionsPlugin, setupPermissions, usePermissionsService } from './plugin'\nimport { vCan, vCant, setPermissionsService } from './directives/vCan'\n\n// Именованные экспорты\nexport {\n Check,\n usePermissions,\n setupPermissions,\n vCan,\n vCant,\n usePermissionsService,\n setPermissionsService\n}\n\n// Создаем основной объект плагина\nconst plugin = {\n install(app: App, options?: { baseUrl?: string }) {\n // Важно: сначала нужно инициализировать PermissionsPlugin для provide/inject механизма\n app.use(PermissionsPlugin, options)\n\n // Затем регистрируем компонент и директивы\n app.component('Check', Check)\n app.directive('can', vCan)\n app.directive('cant', vCant)\n }\n}\n\n// Экспортируем плагин как по умолчанию\nexport default plugin "],"names":["PermissionsService","options","__publicField","axios","action","actionKey","params","allowed","error","globalPermissionsService","permissionsCache","setPermissionsService","service","checkPermission","permissionPromise","checkPermissions","actions","cacheKey","processElement","el","showWhenAllowed","originalDisplay","hasPermission","vCan","binding","vCant","PermissionsKey","setupPermissions","PermissionsPlugin","app","permissionsService","usePermissionsService","inject","usePermissions","isAllowed","ref","isLoading","actionValue","computed","err","unwatch","watch","onUnmounted","_sfc_main","defineComponent","props","toRefs","isInitialLoading","can","check","onMounted","_ctx","_renderSlot","_createCommentVNode","plugin","Check"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "locator-ars-lib",
3
- "version": "1.1.5",
3
+ "version": "1.1.7",
4
4
  "description": "Permissions library for Vue 3 applications",
5
5
  "type": "module",
6
6
  "main": "./dist/locator-ars-lib.umd.js",
package/types/index.d.ts CHANGED
@@ -20,7 +20,7 @@ export interface UsePermissionsResult {
20
20
 
21
21
  export class PermissionsService {
22
22
  constructor(options?: PermissionsOptions)
23
- can(action: string): Promise<boolean>
23
+ can(action: string | string[]): Promise<boolean>
24
24
  clearCache(action?: string): void
25
25
  }
26
26
 
@@ -28,7 +28,7 @@ export const Check: Component
28
28
  export const vCan: ObjectDirective
29
29
 
30
30
  export function usePermissions(
31
- action: string | Ref<string>,
31
+ action: string | string[] | Ref<string | string[]>,
32
32
  options?: UsePermissionsOptions
33
33
  ): UsePermissionsResult
34
34
 
@@ -21,7 +21,7 @@ declare module 'locator-ars-lib' {
21
21
 
22
22
  export class PermissionsService {
23
23
  constructor(options?: PermissionsOptions)
24
- can(action: string): Promise<boolean>
24
+ can(action: string | string[]): Promise<boolean>
25
25
  clearCache(action?: string): void
26
26
  }
27
27
 
@@ -29,7 +29,7 @@ declare module 'locator-ars-lib' {
29
29
  export const vCan: ObjectDirective
30
30
 
31
31
  export function usePermissions(
32
- action: string | Ref<string>,
32
+ action: string | string[] | Ref<string | string[]>,
33
33
  options?: UsePermissionsOptions
34
34
  ): UsePermissionsResult
35
35