@vuetify/one 2.8.2 → 2.9.1

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.
@@ -0,0 +1,578 @@
1
+ import { merge as q } from "lodash-es";
2
+ import { defineStore as O } from "pinia";
3
+ import { ref as b, reactive as X, watch as I, toRefs as Y, computed as p, shallowRef as P, toRef as C, nextTick as G } from "vue";
4
+ import { useRoute as K, useRouter as V } from "vue-router";
5
+ const J = O("queue", () => {
6
+ const e = b([]);
7
+ function t(o) {
8
+ const r = typeof o == "string" ? { text: o } : o;
9
+ e.value.push(r);
10
+ }
11
+ function s(o) {
12
+ t({
13
+ color: "error",
14
+ text: o,
15
+ location: "top end",
16
+ timeout: -1
17
+ });
18
+ }
19
+ function i(o) {
20
+ t({
21
+ color: "success",
22
+ text: o,
23
+ location: "top end"
24
+ });
25
+ }
26
+ return {
27
+ queue: e,
28
+ show: t,
29
+ showError: s,
30
+ showSuccess: i
31
+ };
32
+ }), Z = [
33
+ (e) => (e.v || (e.pwaRefresh = !0, typeof e.api == "boolean" && (e.api = e.api ? "inline" : "link-only"), typeof e.rtl == "boolean" && (e.direction = e.rtl ? "rtl" : "ltr", delete e.rtl), typeof e.theme == "object" && (e.mixedTheme = e.theme.mixed, e.theme = e.theme.system ? "system" : e.theme.dark ? "dark" : "light"), Array.isArray(e.notifications) && (e.notifications = { read: e.notifications }), typeof e.last == "object" && (e.notifications = e.notifications || {}, e.notifications.last = e.last, delete e.last), e.v = 1), e),
34
+ (e) => (e.v === 1 && (Array.isArray(e.composition) && (e.composition = "composition"), Array.isArray(e.notifications?.last?.banner) || (e.notifications = e.notifications || {}, e.notifications.last = e.notifications.last || {}, e.notifications.last.banner = []), e.v = 2), e),
35
+ (e) => (e.v === 2 && (e.syncSettings = !0, e.disableAds = !1, e.v = 3), e),
36
+ (e) => (e.v === 3 && (e.quickbar = !1, e.v = 4), e),
37
+ (e) => (e.v === 4 && (e.suits = { show: !1, elements: ["app-bar"], suit: "" }, e.notifications = e.notifications || {}, e.notifications.banners = !0, e.v = 5), e)
38
+ ];
39
+ function D(e) {
40
+ return {
41
+ version: 6,
42
+ ecosystem: {
43
+ bin: {
44
+ wordWrap: !1
45
+ },
46
+ play: {
47
+ showErrors: !0,
48
+ wordWrap: !1
49
+ },
50
+ studio: {},
51
+ link: {},
52
+ docs: {
53
+ api: e.api || "link-only",
54
+ composition: e.composition || "composition",
55
+ pins: {
56
+ enabled: e.pins || !1,
57
+ pinned: Array.isArray(e.pinned) ? e.pinned.map((t) => t.name || t).filter(Boolean) : []
58
+ },
59
+ mixedTheme: e.mixedTheme ?? !0,
60
+ favorites: [],
61
+ slashSearch: e.slashSearch || !1,
62
+ railDrawer: e.railDrawer || !1
63
+ }
64
+ },
65
+ one: {
66
+ avatar: e.avatar || "",
67
+ ads: {
68
+ enabled: !e.disableAds,
69
+ house: e.showHouseAds || !1
70
+ },
71
+ command: {},
72
+ theme: e.theme || "system",
73
+ direction: e.direction || "ltr",
74
+ colors: {
75
+ primary: e.colors?.one || "surface-light"
76
+ },
77
+ suits: {
78
+ enabled: e.suits?.show || !1,
79
+ elements: e.suits?.elements || ["app-bar"],
80
+ suit: e.suits?.suit || ""
81
+ },
82
+ notifications: {
83
+ enabled: e.notifications?.show ?? !0,
84
+ read: e.notifications?.read || [],
85
+ last: ""
86
+ },
87
+ banners: {
88
+ enabled: e.notifications?.banners ?? !0,
89
+ read: e.notifications?.last?.banner || [],
90
+ last: ""
91
+ },
92
+ quicklinks: e.quickbar || !1,
93
+ sync: e.syncSettings ?? !0,
94
+ devmode: e.dev || !1
95
+ }
96
+ };
97
+ }
98
+ function F(e) {
99
+ return {
100
+ ...e,
101
+ version: 7,
102
+ ecosystem: {
103
+ ...e.ecosystem,
104
+ mcp: {
105
+ seen: !1
106
+ }
107
+ }
108
+ };
109
+ }
110
+ function ee(e) {
111
+ const t = Z.reduce((i, o) => o(i), e), s = D(t);
112
+ return F(s);
113
+ }
114
+ const H = typeof window < "u", g = {
115
+ version: 7,
116
+ ecosystem: {
117
+ bin: {
118
+ wordWrap: !0
119
+ },
120
+ play: {
121
+ showErrors: !0,
122
+ wordWrap: !1
123
+ },
124
+ studio: {},
125
+ link: {},
126
+ docs: {
127
+ api: "link-only",
128
+ composition: "composition",
129
+ pins: {
130
+ enabled: !1,
131
+ pinned: []
132
+ },
133
+ mixedTheme: !0,
134
+ favorites: [],
135
+ slashSearch: !1,
136
+ railDrawer: !1
137
+ },
138
+ mcp: {
139
+ seen: !1
140
+ }
141
+ },
142
+ one: {
143
+ avatar: "",
144
+ ads: {
145
+ enabled: !0,
146
+ house: !1
147
+ },
148
+ command: {},
149
+ theme: "system",
150
+ direction: "ltr",
151
+ colors: {
152
+ primary: "surface-light"
153
+ },
154
+ suits: {
155
+ enabled: !1,
156
+ elements: ["app-bar"],
157
+ suit: ""
158
+ },
159
+ notifications: {
160
+ enabled: !0,
161
+ read: [],
162
+ last: ""
163
+ },
164
+ banners: {
165
+ enabled: !0,
166
+ read: [],
167
+ last: ""
168
+ },
169
+ quicklinks: !1,
170
+ ecosystem: {
171
+ pinned: [],
172
+ seen: !1
173
+ },
174
+ sync: !0,
175
+ devmode: !1
176
+ }
177
+ }, te = O("user", () => {
178
+ const e = X(structuredClone(g));
179
+ I(e, s, { deep: !0 });
180
+ function t() {
181
+ if (!H)
182
+ return;
183
+ const o = localStorage.getItem("vuetify@user");
184
+ if (o)
185
+ try {
186
+ const r = JSON.parse(o);
187
+ if (r.version >= 7) {
188
+ const u = {
189
+ version: 7,
190
+ ecosystem: q(structuredClone(g.ecosystem), r.ecosystem || {}),
191
+ one: q(structuredClone(g.one), r.one || {})
192
+ };
193
+ Object.assign(e, u);
194
+ } else if (r.version === 6) {
195
+ const u = F(r), h = {
196
+ version: 7,
197
+ ecosystem: q(structuredClone(g.ecosystem), u.ecosystem || {}),
198
+ one: q(structuredClone(g.one), u.one || {})
199
+ };
200
+ Object.assign(e, h);
201
+ } else {
202
+ const u = ee(r);
203
+ Object.assign(e, u);
204
+ }
205
+ s();
206
+ } catch (r) {
207
+ console.error("Failed to load user settings:", r);
208
+ }
209
+ }
210
+ function s() {
211
+ H && localStorage.setItem("vuetify@user", JSON.stringify(e, null, 2));
212
+ }
213
+ function i() {
214
+ H && (Object.assign(e, structuredClone(g)), s());
215
+ }
216
+ return t(), {
217
+ ...Y(e),
218
+ load: t,
219
+ save: s,
220
+ reset: i
221
+ };
222
+ }), Q = O("http", {
223
+ state: () => ({
224
+ url: ""
225
+ }),
226
+ actions: {
227
+ async fetch(e, t = {}) {
228
+ const s = await fetch(`${this.url}${e}`, {
229
+ credentials: "include",
230
+ ...t
231
+ });
232
+ if (!s.ok) {
233
+ const i = await s.text();
234
+ let o = i || `HTTP ${s.status}`;
235
+ try {
236
+ const r = JSON.parse(i);
237
+ o = r.message || r.error || i;
238
+ } catch {
239
+ }
240
+ throw new Error(o);
241
+ }
242
+ return s.status === 204 ? {} : s.json();
243
+ },
244
+ async post(e, t, s = {}) {
245
+ return this.fetch(e, {
246
+ method: "POST",
247
+ headers: {
248
+ "Content-Type": "application/json"
249
+ },
250
+ body: JSON.stringify(t),
251
+ ...s
252
+ });
253
+ },
254
+ async form(e, t, s = {}) {
255
+ return this.fetch(e, {
256
+ method: "POST",
257
+ body: t,
258
+ ...s
259
+ });
260
+ },
261
+ async get(e, t = {}) {
262
+ return this.fetch(e, t);
263
+ },
264
+ async delete(e, t = {}) {
265
+ return this.fetch(e, {
266
+ method: "DELETE",
267
+ ...t
268
+ });
269
+ }
270
+ }
271
+ });
272
+ function B() {
273
+ const e = K();
274
+ return p(
275
+ () => e.query
276
+ );
277
+ }
278
+ const z = O("one", () => {
279
+ const e = B(), t = V(), s = M(), i = Q(), o = J(), r = P(!1), u = P(!1), h = b(null), v = b([]), S = p(() => e.value.session_id), R = p(() => h.value?.items[0].plan.interval), j = p(() => h.value?.items[0].plan.type), k = b([]), d = p(() => s.user?.sponsorships.find((n) => n.platform === "stripe" && n.tierName.startsWith("sub_"))), E = p(() => !!d.value?.tierName), a = p(() => s.user?.sponsorships.reduce((n, l) => {
280
+ if (!l.isActive || l.interval === "once")
281
+ return n;
282
+ const y = l.interval === "month" ? l.amount : l.amount / 12;
283
+ return n + y / 100;
284
+ }, 0) ?? 0), T = p(() => s.user?.sponsorships.find((n) => n.tierName.startsWith("sub_") && n.isActive)), N = p(() => s.user?.sponsorships.find((n) => n.platform === "github" && n.isActive)), U = p(() => s.user?.sponsorships.find((n) => n.platform === "discord" && n.isActive)), x = p(() => s.user?.identities.find((n) => n.provider === "shopify")), c = p(() => !i.url || s.isAdmin || d.value?.isActive || k.value.some((n) => ["one", "one/team"].includes(n)));
285
+ I(u, L), I(S, async (n) => {
286
+ n && await f();
287
+ }, { immediate: !0 }), I(e, (n) => {
288
+ if (n.one !== "subscribe" || s.user)
289
+ return;
290
+ s.dialog = !0;
291
+ const l = I(() => s.user, (y) => {
292
+ y && (s.dialog = !1, l());
293
+ });
294
+ }, { immediate: !0 });
295
+ async function f() {
296
+ try {
297
+ r.value = !0, await i.post("/one/activate", { sessionId: S.value }), await s.verify(!0), await w();
298
+ const n = new URL(window.location.href), l = n.searchParams;
299
+ l.delete("session_id"), l.delete("team"), history.pushState(null, "", n.toString());
300
+ } catch (n) {
301
+ o.showError(n?.message ?? "Error activating subscription, Please contact support");
302
+ } finally {
303
+ r.value = !1;
304
+ }
305
+ }
306
+ async function m() {
307
+ window.open(`${i.url}/one/manage`, "_blank");
308
+ }
309
+ async function $(n, l) {
310
+ r.value = !0;
311
+ const y = new URL("/one/subscribe", i.url);
312
+ y.searchParams.set("interval", n), y.searchParams.set("type", l), window.location.href = y.toString();
313
+ }
314
+ async function W() {
315
+ if (d.value)
316
+ try {
317
+ r.value = !0, await i.post(
318
+ `/one/cancel?subscriptionId=${d.value?.tierName}`
319
+ ), await s.verify(!0);
320
+ } catch (n) {
321
+ o.showError(n?.message ?? "Error cancelling subscription, Please contact support");
322
+ } finally {
323
+ r.value = !1;
324
+ }
325
+ }
326
+ async function _(n, l) {
327
+ if (d.value)
328
+ try {
329
+ r.value = !0, await i.post("/one/modify", {
330
+ subscriptionId: d.value.tierName,
331
+ interval: n,
332
+ type: l
333
+ }), await s.verify(!0);
334
+ } catch (y) {
335
+ o.showError(y?.message ?? "Error modifying subscription");
336
+ } finally {
337
+ r.value = !1;
338
+ }
339
+ }
340
+ async function w() {
341
+ try {
342
+ r.value = !0;
343
+ const n = await i.get("/one/info");
344
+ return h.value = n.subscription, v.value = n.invoices, n;
345
+ } catch (n) {
346
+ o.showError(n?.message ?? "Error fetching subscription info");
347
+ } finally {
348
+ r.value = !1;
349
+ }
350
+ }
351
+ function L() {
352
+ t.push({
353
+ query: {
354
+ ...e.value,
355
+ one: void 0
356
+ }
357
+ });
358
+ }
359
+ return {
360
+ info: h,
361
+ interval: R,
362
+ subscriptionType: j,
363
+ access: k,
364
+ invoices: v,
365
+ sessionId: S,
366
+ subscription: d,
367
+ monthlyTotal: a,
368
+ hasBilling: E,
369
+ isLoading: r,
370
+ isOpen: u,
371
+ isSubscriber: c,
372
+ github: N,
373
+ discord: U,
374
+ shopify: x,
375
+ one: T,
376
+ activate: f,
377
+ cancel: W,
378
+ manage: m,
379
+ modify: _,
380
+ resetQuery: L,
381
+ subscribe: $,
382
+ subscriptionInfo: w
383
+ };
384
+ }), se = O("team", () => {
385
+ const e = B(), t = M(), s = z(), i = Q(), o = J(), r = P(!1), u = b(null), h = b(!1), v = p(() => e.value.invite), S = p(
386
+ () => u.value ? s.access?.some((a) => ["one/team", "snips/team"].includes(a)) : !1
387
+ );
388
+ I(v, async () => {
389
+ if (v.value) {
390
+ t.user || (t.dialog = !0);
391
+ try {
392
+ r.value = !0;
393
+ const a = await i.get(`/one/team/${v.value}`);
394
+ u.value = a.team, h.value = !0;
395
+ } catch (a) {
396
+ d(), o.showError(a.message);
397
+ } finally {
398
+ r.value = !1;
399
+ }
400
+ }
401
+ }, { immediate: !0 });
402
+ async function R(a) {
403
+ try {
404
+ if (r.value = !0, !u.value)
405
+ return;
406
+ await i.post("/one/team/remove", { userId: a }), u.value.members = u.value.members.filter((T) => T.id !== a);
407
+ } catch (T) {
408
+ o.showError(T?.message ?? "Error removing user from team");
409
+ } finally {
410
+ r.value = !1;
411
+ }
412
+ }
413
+ async function j() {
414
+ try {
415
+ r.value = !0, await i.post("/one/team/leave", { teamId: u.value?.id }), await t.verify(!0);
416
+ } catch (a) {
417
+ o.showError(a?.message ?? "Error leaving team");
418
+ } finally {
419
+ r.value = !1;
420
+ }
421
+ }
422
+ async function k() {
423
+ try {
424
+ r.value = !0, await i.post("/one/team/join", { inviteCode: v.value }), await t.verify(!0), d();
425
+ } catch (a) {
426
+ o.showError(a?.message ?? "Error joining team");
427
+ } finally {
428
+ r.value = !1;
429
+ }
430
+ }
431
+ function d() {
432
+ h.value = !1;
433
+ const a = new URL(window.location.href);
434
+ a.searchParams.delete("invite"), window.history.replaceState({}, "", a.toString());
435
+ }
436
+ const E = p(() => t.user?.id === t.user?.team?.owner.id);
437
+ return {
438
+ team: u,
439
+ teamInviteDialog: h,
440
+ teamInviteCode: v,
441
+ hasTeamAccess: S,
442
+ isTeamOwner: E,
443
+ isLoading: r,
444
+ removeFromTeam: R,
445
+ leaveTeam: j,
446
+ joinTeam: k,
447
+ clearTeamQuery: d
448
+ };
449
+ }), M = O("auth", () => {
450
+ const e = b(!1), t = b(null), s = Q(), i = te(), o = V(), r = P(!1), u = z(), h = se(), v = J(), S = C(() => !!t.value), R = C(() => t.value?.role === "super"), j = C(() => ["super", "admin"].includes(t.value?.role ?? "")), k = C(() => ["super", "admin", "editor"].includes(t.value?.role ?? ""));
451
+ let d = !!x();
452
+ I(t, (c) => {
453
+ if (!c?.settings)
454
+ return;
455
+ const f = localStorage.getItem("vuetify@user") || "{}";
456
+ if (JSON.stringify(c.settings, null, 2) === f)
457
+ return;
458
+ d = !0;
459
+ let m = c.settings;
460
+ m.version === 6 && (m = F(m));
461
+ const $ = {
462
+ version: 7,
463
+ ecosystem: q(structuredClone(g.ecosystem), m.ecosystem || {}),
464
+ one: q(structuredClone(g.one), m.one || {})
465
+ };
466
+ Object.assign(i, $);
467
+ }), i.$subscribe(() => {
468
+ d || E(), d = !1;
469
+ });
470
+ async function E() {
471
+ if (await G(), !(!t.value || !i.one.sync))
472
+ try {
473
+ await s.post("/user/settings", { settings: i.$state }), await a(!0);
474
+ } catch (c) {
475
+ v.showError(c?.message ?? "Error syncing settings");
476
+ }
477
+ }
478
+ async function a(c = !1) {
479
+ if (a.promise)
480
+ return a.promise;
481
+ if (!c && !document.cookie.includes("sx=1") && location.hostname.match(/([^.]+\.[^.]+)$/)?.[1] === new URL(s.url).hostname.match(/([^.]+\.[^.]+)$/)?.[1]) {
482
+ t.value = null;
483
+ return;
484
+ }
485
+ r.value = !0, a.promise = fetch(`${s.url}/auth/verify`, {
486
+ credentials: "include",
487
+ cache: c ? "reload" : void 0
488
+ }).then(
489
+ async (f) => {
490
+ if (f.ok || f.status === 401) {
491
+ const m = await f.json();
492
+ t.value = m.user, u.access = m.access, h.team = m.user?.team;
493
+ } else
494
+ console.error(f.statusText);
495
+ },
496
+ () => {
497
+ }
498
+ ).finally(() => {
499
+ r.value = !1, a.promise = null;
500
+ });
501
+ }
502
+ a.promise = null;
503
+ async function T(c = "github") {
504
+ r.value = !0;
505
+ const f = `${s.url}/auth/${c}/redirect`;
506
+ if (c === "shopify") {
507
+ window.location.assign(f + "?next=" + encodeURIComponent(window.location.href));
508
+ return;
509
+ }
510
+ const m = 400, $ = 600, W = window.screenX + (window.innerWidth - m) / 2, _ = window.screenY + (window.innerHeight - $) / 2, w = window.open(
511
+ "",
512
+ "vuetify:authorize:popup",
513
+ `popup,left=${W},top=${_},width=${m},height=${$},resizable`
514
+ );
515
+ if (!w) {
516
+ console.error("Failed to open popup");
517
+ return;
518
+ }
519
+ w.location.href = f;
520
+ let L = -1, n = -1;
521
+ function l(A) {
522
+ A.origin === s.url && A.data?.type === "auth-response" && (A.data.status === "success" ? (t.value || (localStorage.setItem("vuetify@lastLoginProvider", c), e.value = !1, o.push("/user/dashboard")), t.value = A.data.body.user, u.access = A.data.body.access, h.team = A.data.body.user?.team, E()) : console.error(A.data.message), y());
523
+ }
524
+ function y() {
525
+ window.removeEventListener("message", l), window.clearInterval(L), window.clearTimeout(n), w?.close(), r.value = !1;
526
+ }
527
+ window.addEventListener("message", l), L = window.setInterval(() => {
528
+ !w || w.closed ? (console.error("Auth popup closed"), y()) : w.postMessage({ type: "auth-request" }, "*");
529
+ }, 1e3), n = window.setTimeout(() => {
530
+ y(), console.error("Auth timed out");
531
+ }, 120 * 1e3);
532
+ }
533
+ async function N(c) {
534
+ r.value = !0;
535
+ const f = c ? `/auth/${c}/logout` : "/auth/logout";
536
+ try {
537
+ await s.post(f), await a(!0), t.value = null;
538
+ } catch (m) {
539
+ v.showError(m?.message ?? "Error logging out");
540
+ } finally {
541
+ o.push({
542
+ path: "/",
543
+ query: o.currentRoute.value.query
544
+ }), r.value = !1;
545
+ }
546
+ }
547
+ function U(c) {
548
+ return t.value?.identities.find((f) => f.provider === c);
549
+ }
550
+ function x() {
551
+ return localStorage.getItem("vuetify@lastLoginProvider");
552
+ }
553
+ return a(), {
554
+ user: t,
555
+ url: s.url,
556
+ dialog: e,
557
+ isLoading: r,
558
+ isAuthenticated: S,
559
+ isSuper: R,
560
+ isAdmin: j,
561
+ isEditor: k,
562
+ verify: a,
563
+ findIdentity: U,
564
+ login: T,
565
+ logout: N,
566
+ lastLoginProvider: x,
567
+ sync: E
568
+ };
569
+ });
570
+ export {
571
+ M as a,
572
+ te as b,
573
+ z as c,
574
+ B as d,
575
+ Q as e,
576
+ se as f,
577
+ J as u
578
+ };
package/dist/index.d.ts CHANGED
@@ -156,10 +156,11 @@ interface VOneIdentity {
156
156
  userHandle: string;
157
157
  primary: boolean;
158
158
  }
159
+ type VOneRole = 'super' | 'admin' | 'editor' | 'user';
159
160
  interface VOneUser {
160
161
  id: string;
161
162
  isAdmin: boolean;
162
- role: 'super' | 'admin' | 'editor' | 'user';
163
+ role: VOneRole;
163
164
  name: string;
164
165
  shortid: string;
165
166
  picture: string;
@@ -174,6 +175,10 @@ interface AuthState {
174
175
  url: string;
175
176
  dialog: Ref<boolean>;
176
177
  isLoading: ShallowRef<boolean>;
178
+ isAuthenticated: Ref<boolean>;
179
+ isSuper: Ref<boolean>;
180
+ isAdmin: Ref<boolean>;
181
+ isEditor: Ref<boolean>;
177
182
  verify: (force?: boolean) => Promise<void>;
178
183
  findIdentity: (provider: string) => VOneIdentity | undefined;
179
184
  login: (provider?: 'github' | 'discord' | 'shopify') => Promise<void>;
@@ -181,7 +186,7 @@ interface AuthState {
181
186
  lastLoginProvider: () => string | null;
182
187
  sync: () => Promise<void>;
183
188
  }
184
- declare const useAuthStore: pinia.StoreDefinition<"auth", Pick<AuthState, "isLoading" | "user" | "url" | "dialog">, Pick<AuthState, never>, Pick<AuthState, "sync" | "verify" | "findIdentity" | "login" | "logout" | "lastLoginProvider">>;
189
+ declare const useAuthStore: pinia.StoreDefinition<"auth", Pick<AuthState, "isLoading" | "user" | "url" | "dialog" | "isAuthenticated" | "isSuper" | "isAdmin" | "isEditor">, Pick<AuthState, never>, Pick<AuthState, "sync" | "verify" | "findIdentity" | "login" | "logout" | "lastLoginProvider">>;
185
190
 
186
191
  interface VOneBanner {
187
192
  id: string;
@@ -428,7 +433,7 @@ interface LinksState {
428
433
  index: () => Promise<VOneLink[]>;
429
434
  create: (options: CreateLinkOptions) => Promise<VOneLink | undefined>;
430
435
  }
431
- declare const useLinksStore: pinia.StoreDefinition<"links", Pick<LinksState, "isLoading" | "all" | "isSaving">, Pick<LinksState, "favorites" | "pinned" | "canCreate">, Pick<LinksState, "index" | "create">>;
436
+ declare const useLinksStore: pinia.StoreDefinition<"links", Pick<LinksState, "isLoading" | "all" | "isSaving">, Pick<LinksState, "favorites" | "pinned" | "canCreate">, Pick<LinksState, "create" | "index">>;
432
437
 
433
438
  interface VOneNotification {
434
439
  id: string;