@n8n/stores 2.33.0 → 2.34.0
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/dist/cloudPlan.store.cjs +5 -241
- package/dist/cloudPlan.store.d.cts +6 -0
- package/dist/cloudPlan.store.d.mts +72 -66
- package/dist/cloudPlan.store.mjs +5 -241
- package/dist/cloudPlan2.store.cjs +247 -0
- package/dist/cloudPlan2.store.cjs.map +1 -0
- package/dist/cloudPlan2.store.mjs +242 -0
- package/dist/cloudPlan2.store.mjs.map +1 -0
- package/dist/composables/useBasePageRedirectionHelper.cjs +87 -0
- package/dist/composables/useBasePageRedirectionHelper.cjs.map +1 -0
- package/dist/composables/useBasePageRedirectionHelper.d.cts +16 -0
- package/dist/composables/useBasePageRedirectionHelper.d.mts +16 -0
- package/dist/composables/useBasePageRedirectionHelper.mjs +87 -0
- package/dist/composables/useBasePageRedirectionHelper.mjs.map +1 -0
- package/dist/constants2.cjs +1 -0
- package/dist/constants2.cjs.map +1 -1
- package/dist/constants2.d.cts +1 -0
- package/dist/constants2.d.mts +1 -0
- package/dist/constants2.mjs +1 -0
- package/dist/constants2.mjs.map +1 -1
- package/dist/notifications.store.cjs +2 -8
- package/dist/notifications.store.cjs.map +1 -1
- package/dist/notifications.store.d.cts +3 -24
- package/dist/notifications.store.d.mts +3 -24
- package/dist/notifications.store.mjs +2 -8
- package/dist/notifications.store.mjs.map +1 -1
- package/dist/pageRedirection.d.cts +6 -0
- package/dist/pageRedirection.d.mts +6 -0
- package/dist/rbac.store.d.cts +123 -123
- package/dist/rbac.store.d.mts +123 -123
- package/dist/roles.store.d.cts +21 -21
- package/dist/roles.store.d.mts +19 -19
- package/dist/settings.store.d.cts +243 -237
- package/dist/settings.store.d.mts +243 -237
- package/dist/settings2.store.cjs +5 -5
- package/dist/settings2.store.cjs.map +1 -1
- package/dist/settings2.store.mjs +5 -5
- package/dist/settings2.store.mjs.map +1 -1
- package/dist/types/pageRedirection.cjs +0 -0
- package/dist/types/pageRedirection.d.cts +2 -0
- package/dist/types/pageRedirection.d.mts +2 -0
- package/dist/types/pageRedirection.mjs +1 -0
- package/dist/useAgentRequestStore.d.mts +6 -6
- package/dist/useRootStore.d.cts +72 -72
- package/dist/useRootStore.d.mts +70 -70
- package/dist/users.store.cjs +7 -352
- package/dist/users.store.d.cts +67 -55
- package/dist/users.store.d.mts +69 -57
- package/dist/users.store.mjs +7 -349
- package/dist/users2.store.cjs +362 -0
- package/dist/users2.store.cjs.map +1 -0
- package/dist/users2.store.mjs +353 -0
- package/dist/users2.store.mjs.map +1 -0
- package/dist/versions.store.cjs +11 -0
- package/dist/versions.store.d.cts +384 -0
- package/dist/versions.store.d.mts +384 -0
- package/dist/versions.store.mjs +10 -0
- package/dist/versions2.store.cjs +230 -0
- package/dist/versions2.store.cjs.map +1 -0
- package/dist/versions2.store.mjs +218 -0
- package/dist/versions2.store.mjs.map +1 -0
- package/package.json +14 -13
- package/dist/cloudPlan.store.cjs.map +0 -1
- package/dist/cloudPlan.store.mjs.map +0 -1
- package/dist/users.store.cjs.map +0 -1
- package/dist/users.store.mjs.map +0 -1
package/dist/users.store.mjs
CHANGED
|
@@ -1,351 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "./constants2.mjs";
|
|
2
2
|
import "./metaTagConfig2.mjs";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import { defineStore } from "pinia";
|
|
9
|
-
import { computed, ref } from "vue";
|
|
10
|
-
import { ROLE } from "@n8n/api-types";
|
|
11
|
-
import { useAsyncState } from "@vueuse/core";
|
|
12
|
-
import { BROWSER_ID_STORAGE_KEY } from "@n8n/constants";
|
|
13
|
-
import * as mfaApi from "@n8n/rest-api-client/api/mfa";
|
|
14
|
-
import * as usersApi from "@n8n/rest-api-client/api/users";
|
|
3
|
+
import "./useRootStore2.mjs";
|
|
4
|
+
import "./settings2.store.mjs";
|
|
5
|
+
import "./invitation2.api.mjs";
|
|
6
|
+
import "./onboarding2.api.mjs";
|
|
7
|
+
import { t as useUsersStore } from "./users2.store.mjs";
|
|
15
8
|
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Registration key of the app's personalization modal, passed to the injected
|
|
19
|
-
* modal opener. Mirrors `PERSONALIZATION_MODAL_KEY` in editor-ui's
|
|
20
|
-
* `users.constants`; kept as a literal so the store carries no `@/app` import.
|
|
21
|
-
*/
|
|
22
|
-
const PERSONALIZATION_MODAL_KEY = "personalization";
|
|
23
|
-
const _isPendingUser = (user) => !!user?.isPending;
|
|
24
|
-
const _isInstanceOwner = (user) => user?.role === ROLE.Owner;
|
|
25
|
-
const _isDefaultUser = (user) => _isInstanceOwner(user) && _isPendingUser(user);
|
|
26
|
-
const _isAdmin = (user) => user?.role === ROLE.Admin;
|
|
27
|
-
const useUsersStore = defineStore(STORES.USERS, () => {
|
|
28
|
-
const initialized = ref(false);
|
|
29
|
-
const currentUserId = ref(null);
|
|
30
|
-
const usersById = ref({});
|
|
31
|
-
const userQuota = ref(-1);
|
|
32
|
-
const loginHooks = ref([]);
|
|
33
|
-
const logoutHooks = ref([]);
|
|
34
|
-
const warnModalOpenerMissing = (action) => {
|
|
35
|
-
if (import.meta.env.DEV) console.warn(`[users.store] ${action} called before modal openers were registered; ignoring. Call registerModalOpeners() at app bootstrap.`);
|
|
36
|
-
};
|
|
37
|
-
const modalOpeners = ref({
|
|
38
|
-
openModal: (name) => warnModalOpenerMissing(`openModal(${String(name)})`),
|
|
39
|
-
openModalWithData: (payload) => warnModalOpenerMissing(`openModalWithData(${String(payload.name)})`)
|
|
40
|
-
});
|
|
41
|
-
const registerModalOpeners = (openers) => {
|
|
42
|
-
modalOpeners.value = openers;
|
|
43
|
-
};
|
|
44
|
-
const canListUsers = ref(() => false);
|
|
45
|
-
const setPermissionsResolvers = (resolvers) => {
|
|
46
|
-
canListUsers.value = resolvers.listUsers;
|
|
47
|
-
};
|
|
48
|
-
const rootStore = useRootStore();
|
|
49
|
-
const settingsStore = useSettingsStore();
|
|
50
|
-
const allUsers = computed(() => Object.values(usersById.value));
|
|
51
|
-
const currentUser = computed(() => currentUserId.value ? usersById.value[currentUserId.value] : null);
|
|
52
|
-
const userActivated = computed(() => Boolean(currentUser.value?.settings?.userActivated));
|
|
53
|
-
const isDefaultUser = computed(() => _isDefaultUser(currentUser.value));
|
|
54
|
-
const isInstanceOwner = computed(() => _isInstanceOwner(currentUser.value));
|
|
55
|
-
const isAdmin = computed(() => _isAdmin(currentUser.value));
|
|
56
|
-
const isAdminOrOwner = computed(() => isInstanceOwner.value || isAdmin.value);
|
|
57
|
-
const mfaEnabled = computed(() => currentUser.value?.mfaEnabled ?? false);
|
|
58
|
-
const globalRoleName = computed(() => currentUser.value?.role ?? "default");
|
|
59
|
-
const userClaimedAiCredits = computed(() => currentUser.value?.settings?.userClaimedAiCredits);
|
|
60
|
-
const isEasyAIWorkflowOnboardingDone = computed(() => Boolean(currentUser.value?.settings?.easyAIWorkflowOnboarded));
|
|
61
|
-
const canUserUpdateVersion = computed(() => {
|
|
62
|
-
return isInstanceOwner.value;
|
|
63
|
-
});
|
|
64
|
-
const setEasyAIWorkflowOnboardingDone = () => {
|
|
65
|
-
if (currentUser.value?.settings) currentUser.value.settings.easyAIWorkflowOnboarded = true;
|
|
66
|
-
};
|
|
67
|
-
const isCalloutDismissed = (callout) => Boolean(currentUser.value?.settings?.dismissedCallouts?.[callout]);
|
|
68
|
-
const setCalloutDismissed = (callout) => {
|
|
69
|
-
if (currentUser.value?.settings) {
|
|
70
|
-
currentUser.value.settings.dismissedCallouts ??= {};
|
|
71
|
-
currentUser.value.settings.dismissedCallouts[callout] = true;
|
|
72
|
-
}
|
|
73
|
-
};
|
|
74
|
-
const usersLimitNotReached = computed(() => userQuota.value === -1 || userQuota.value > allUsers.value.length);
|
|
75
|
-
const addUsers = (newUsers) => {
|
|
76
|
-
newUsers.forEach((userResponse) => {
|
|
77
|
-
const updatedUser = {
|
|
78
|
-
...usersById.value[userResponse.id] || {},
|
|
79
|
-
...userResponse
|
|
80
|
-
};
|
|
81
|
-
const user = {
|
|
82
|
-
...updatedUser,
|
|
83
|
-
fullName: userResponse.firstName ? `${updatedUser.firstName} ${updatedUser.lastName ?? ""}` : void 0,
|
|
84
|
-
isDefaultUser: _isDefaultUser(updatedUser),
|
|
85
|
-
isPendingUser: _isPendingUser(updatedUser)
|
|
86
|
-
};
|
|
87
|
-
usersById.value = {
|
|
88
|
-
...usersById.value,
|
|
89
|
-
[user.id]: user
|
|
90
|
-
};
|
|
91
|
-
});
|
|
92
|
-
};
|
|
93
|
-
const setCurrentUser = async (user) => {
|
|
94
|
-
addUsers([user]);
|
|
95
|
-
currentUserId.value = user.id;
|
|
96
|
-
for (const hook of loginHooks.value) try {
|
|
97
|
-
await hook(user);
|
|
98
|
-
} catch (error) {
|
|
99
|
-
console.error("Error executing login hook:", error);
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
const loginWithCookie = async () => {
|
|
103
|
-
const user = await usersApi.loginCurrentUser(rootStore.restApiContext);
|
|
104
|
-
if (!user) return;
|
|
105
|
-
await setCurrentUser(user);
|
|
106
|
-
};
|
|
107
|
-
const initialize = async () => {
|
|
108
|
-
if (initialized.value) return;
|
|
109
|
-
try {
|
|
110
|
-
await loginWithCookie();
|
|
111
|
-
initialized.value = true;
|
|
112
|
-
} catch {}
|
|
113
|
-
};
|
|
114
|
-
const unsetCurrentUser = () => {
|
|
115
|
-
currentUserId.value = null;
|
|
116
|
-
};
|
|
117
|
-
const deleteUserById = (userId) => {
|
|
118
|
-
const { [userId]: _, ...rest } = usersById.value;
|
|
119
|
-
usersById.value = rest;
|
|
120
|
-
};
|
|
121
|
-
const setPersonalizationAnswers = (answers) => {
|
|
122
|
-
if (!currentUser.value) return;
|
|
123
|
-
usersById.value = {
|
|
124
|
-
...usersById.value,
|
|
125
|
-
[currentUser.value.id]: {
|
|
126
|
-
...currentUser.value,
|
|
127
|
-
personalizationAnswers: answers
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
};
|
|
131
|
-
const loginWithCreds = async (params) => {
|
|
132
|
-
const user = await usersApi.login(rootStore.restApiContext, params);
|
|
133
|
-
if (!user) return;
|
|
134
|
-
await setCurrentUser(user);
|
|
135
|
-
};
|
|
136
|
-
const registerLoginHook = (hook) => {
|
|
137
|
-
loginHooks.value.push(hook);
|
|
138
|
-
};
|
|
139
|
-
const registerLogoutHook = (hook) => {
|
|
140
|
-
logoutHooks.value.push(hook);
|
|
141
|
-
};
|
|
142
|
-
const logout = async () => {
|
|
143
|
-
await usersApi.logout(rootStore.restApiContext);
|
|
144
|
-
unsetCurrentUser();
|
|
145
|
-
for (const hook of logoutHooks.value) try {
|
|
146
|
-
await hook();
|
|
147
|
-
} catch (error) {
|
|
148
|
-
console.error("Error executing logout hook:", error);
|
|
149
|
-
}
|
|
150
|
-
localStorage.removeItem(BROWSER_ID_STORAGE_KEY);
|
|
151
|
-
};
|
|
152
|
-
const createOwner = async (params) => {
|
|
153
|
-
const user = await usersApi.setupOwner(rootStore.restApiContext, params);
|
|
154
|
-
if (user) {
|
|
155
|
-
await setCurrentUser(user);
|
|
156
|
-
settingsStore.stopShowingSetupPage();
|
|
157
|
-
}
|
|
158
|
-
};
|
|
159
|
-
const validateSignupToken = async (params) => {
|
|
160
|
-
return await usersApi.validateSignupToken(rootStore.restApiContext, params);
|
|
161
|
-
};
|
|
162
|
-
const acceptInvitation$1 = async (params) => {
|
|
163
|
-
const user = await acceptInvitation(rootStore.restApiContext, params);
|
|
164
|
-
if (user) await setCurrentUser(user);
|
|
165
|
-
};
|
|
166
|
-
const sendForgotPasswordEmail = async (params) => {
|
|
167
|
-
await usersApi.sendForgotPasswordEmail(rootStore.restApiContext, params);
|
|
168
|
-
};
|
|
169
|
-
const validatePasswordToken = async (params) => {
|
|
170
|
-
await usersApi.validatePasswordToken(rootStore.restApiContext, params);
|
|
171
|
-
};
|
|
172
|
-
const changePassword = async (params) => {
|
|
173
|
-
await usersApi.changePassword(rootStore.restApiContext, params);
|
|
174
|
-
};
|
|
175
|
-
const updateUser = async (params) => {
|
|
176
|
-
const user = await usersApi.updateCurrentUser(rootStore.restApiContext, params);
|
|
177
|
-
addUsers([user]);
|
|
178
|
-
return user;
|
|
179
|
-
};
|
|
180
|
-
const updateUserName = async (params) => {
|
|
181
|
-
if (!currentUser.value) return;
|
|
182
|
-
return await updateUser({
|
|
183
|
-
email: currentUser.value.email,
|
|
184
|
-
...params
|
|
185
|
-
});
|
|
186
|
-
};
|
|
187
|
-
const updateUserSettings = async (settings) => {
|
|
188
|
-
const updatedSettings = await usersApi.updateCurrentUserSettings(rootStore.restApiContext, settings);
|
|
189
|
-
if (currentUser.value) {
|
|
190
|
-
currentUser.value.settings = updatedSettings;
|
|
191
|
-
addUsers([currentUser.value]);
|
|
192
|
-
}
|
|
193
|
-
};
|
|
194
|
-
const updateOtherUserSettings = async (userId, settings) => {
|
|
195
|
-
await usersApi.updateOtherUserSettings(rootStore.restApiContext, userId, settings);
|
|
196
|
-
};
|
|
197
|
-
const updateCurrentUserPassword = async (params) => {
|
|
198
|
-
await usersApi.updateCurrentUserPassword(rootStore.restApiContext, params);
|
|
199
|
-
};
|
|
200
|
-
const deleteUser = async (params) => {
|
|
201
|
-
await usersApi.deleteUser(rootStore.restApiContext, params);
|
|
202
|
-
deleteUserById(params.id);
|
|
203
|
-
};
|
|
204
|
-
const fetchUsers = async ({ take, skip, filter } = {}) => {
|
|
205
|
-
if (!canListUsers.value()) return;
|
|
206
|
-
const { items } = await usersApi.getUsers(rootStore.restApiContext, {
|
|
207
|
-
take: take ?? 50,
|
|
208
|
-
skip: skip ?? 0,
|
|
209
|
-
filter
|
|
210
|
-
});
|
|
211
|
-
addUsers(items);
|
|
212
|
-
};
|
|
213
|
-
const inviteUsers$1 = async (params) => {
|
|
214
|
-
const invitedUsers = await inviteUsers(rootStore.restApiContext, params);
|
|
215
|
-
addUsers(invitedUsers.map(({ user }) => ({
|
|
216
|
-
isPending: true,
|
|
217
|
-
...user
|
|
218
|
-
})));
|
|
219
|
-
return invitedUsers;
|
|
220
|
-
};
|
|
221
|
-
const reinviteUser = async ({ email, role }) => {
|
|
222
|
-
const invitationResponse = await inviteUsers(rootStore.restApiContext, [{
|
|
223
|
-
email,
|
|
224
|
-
role
|
|
225
|
-
}]);
|
|
226
|
-
if (!invitationResponse[0].user.emailSent) throw Error(invitationResponse[0].error);
|
|
227
|
-
};
|
|
228
|
-
const getUserPasswordResetLink = async (params) => {
|
|
229
|
-
return await usersApi.getPasswordResetLink(rootStore.restApiContext, params);
|
|
230
|
-
};
|
|
231
|
-
const generateInviteLink = async (params) => {
|
|
232
|
-
return await usersApi.generateInviteLink(rootStore.restApiContext, params);
|
|
233
|
-
};
|
|
234
|
-
const submitPersonalizationSurvey = async (results) => {
|
|
235
|
-
await usersApi.submitPersonalizationSurvey(rootStore.restApiContext, results);
|
|
236
|
-
setPersonalizationAnswers(results);
|
|
237
|
-
};
|
|
238
|
-
const showPersonalizationSurvey = () => {
|
|
239
|
-
if (settingsStore.isPersonalizationSurveyEnabled && currentUser.value && !currentUser.value.personalizationAnswers) modalOpeners.value.openModal(PERSONALIZATION_MODAL_KEY);
|
|
240
|
-
};
|
|
241
|
-
const fetchMfaQR = async () => {
|
|
242
|
-
return await mfaApi.getMfaQR(rootStore.restApiContext);
|
|
243
|
-
};
|
|
244
|
-
const verifyMfaCode = async (data) => {
|
|
245
|
-
return await mfaApi.verifyMfaCode(rootStore.restApiContext, data);
|
|
246
|
-
};
|
|
247
|
-
const canEnableMFA = async () => {
|
|
248
|
-
return await mfaApi.canEnableMFA(rootStore.restApiContext);
|
|
249
|
-
};
|
|
250
|
-
const enableMfa = async (data) => {
|
|
251
|
-
await mfaApi.enableMfa(rootStore.restApiContext, data);
|
|
252
|
-
if (currentUser.value) currentUser.value.mfaEnabled = true;
|
|
253
|
-
};
|
|
254
|
-
const disableMfa = async (data) => {
|
|
255
|
-
await mfaApi.disableMfa(rootStore.restApiContext, data);
|
|
256
|
-
if (currentUser.value) currentUser.value.mfaEnabled = false;
|
|
257
|
-
};
|
|
258
|
-
const updateEnforceMfa = async (enforce) => {
|
|
259
|
-
await mfaApi.updateEnforceMfa(rootStore.restApiContext, enforce);
|
|
260
|
-
settingsStore.isMFAEnforced = enforce;
|
|
261
|
-
};
|
|
262
|
-
const sendConfirmationEmail = async () => {
|
|
263
|
-
await cloudApi.sendConfirmationEmail(rootStore.restApiContext);
|
|
264
|
-
};
|
|
265
|
-
const updateGlobalRole = async ({ id, newRoleName }) => {
|
|
266
|
-
await usersApi.updateGlobalRole(rootStore.restApiContext, {
|
|
267
|
-
id,
|
|
268
|
-
newRoleName
|
|
269
|
-
});
|
|
270
|
-
await fetchUsers({ filter: { ids: [id] } });
|
|
271
|
-
};
|
|
272
|
-
const submitContactEmail = async (email, agree) => {
|
|
273
|
-
if (currentUser.value) return await submitEmailOnSignup(rootStore.instanceId, currentUser.value, email ?? currentUser.value.email, agree);
|
|
274
|
-
return null;
|
|
275
|
-
};
|
|
276
|
-
const usersList = useAsyncState(async (filter) => await usersApi.getUsers(rootStore.restApiContext, filter), {
|
|
277
|
-
count: 0,
|
|
278
|
-
items: []
|
|
279
|
-
}, {
|
|
280
|
-
immediate: false,
|
|
281
|
-
resetOnExecute: false
|
|
282
|
-
});
|
|
283
|
-
const setUserQuota = (quota) => {
|
|
284
|
-
if (typeof quota !== "undefined") userQuota.value = quota;
|
|
285
|
-
};
|
|
286
|
-
return {
|
|
287
|
-
initialized,
|
|
288
|
-
currentUserId,
|
|
289
|
-
usersById,
|
|
290
|
-
allUsers,
|
|
291
|
-
currentUser,
|
|
292
|
-
userActivated,
|
|
293
|
-
isDefaultUser,
|
|
294
|
-
isInstanceOwner,
|
|
295
|
-
isAdmin,
|
|
296
|
-
isAdminOrOwner,
|
|
297
|
-
mfaEnabled,
|
|
298
|
-
globalRoleName,
|
|
299
|
-
userClaimedAiCredits,
|
|
300
|
-
isEasyAIWorkflowOnboardingDone,
|
|
301
|
-
canUserUpdateVersion,
|
|
302
|
-
usersLimitNotReached,
|
|
303
|
-
addUsers,
|
|
304
|
-
loginWithCookie,
|
|
305
|
-
initialize,
|
|
306
|
-
setPersonalizationAnswers,
|
|
307
|
-
loginWithCreds,
|
|
308
|
-
logout,
|
|
309
|
-
registerLoginHook,
|
|
310
|
-
registerLogoutHook,
|
|
311
|
-
registerModalOpeners,
|
|
312
|
-
setPermissionsResolvers,
|
|
313
|
-
createOwner,
|
|
314
|
-
validateSignupToken,
|
|
315
|
-
acceptInvitation: acceptInvitation$1,
|
|
316
|
-
sendForgotPasswordEmail,
|
|
317
|
-
validatePasswordToken,
|
|
318
|
-
changePassword,
|
|
319
|
-
updateUser,
|
|
320
|
-
updateUserName,
|
|
321
|
-
updateUserSettings,
|
|
322
|
-
updateOtherUserSettings,
|
|
323
|
-
updateCurrentUserPassword,
|
|
324
|
-
deleteUser,
|
|
325
|
-
fetchUsers,
|
|
326
|
-
inviteUsers: inviteUsers$1,
|
|
327
|
-
reinviteUser,
|
|
328
|
-
getUserPasswordResetLink,
|
|
329
|
-
generateInviteLink,
|
|
330
|
-
submitPersonalizationSurvey,
|
|
331
|
-
showPersonalizationSurvey,
|
|
332
|
-
fetchMfaQR,
|
|
333
|
-
verifyMfaCode,
|
|
334
|
-
enableMfa,
|
|
335
|
-
disableMfa,
|
|
336
|
-
updateEnforceMfa,
|
|
337
|
-
canEnableMFA,
|
|
338
|
-
sendConfirmationEmail,
|
|
339
|
-
updateGlobalRole,
|
|
340
|
-
setEasyAIWorkflowOnboardingDone,
|
|
341
|
-
isCalloutDismissed,
|
|
342
|
-
setCalloutDismissed,
|
|
343
|
-
submitContactEmail,
|
|
344
|
-
setUserQuota,
|
|
345
|
-
usersList
|
|
346
|
-
};
|
|
347
|
-
});
|
|
348
|
-
|
|
349
|
-
//#endregion
|
|
350
|
-
export { useUsersStore };
|
|
351
|
-
//# sourceMappingURL=users.store.mjs.map
|
|
9
|
+
export { useUsersStore };
|