@aerogel/plugin-local-first 0.0.0-next.004d5deedf15bedf609a660bfd4543d3c0df9d9d

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.
Files changed (45) hide show
  1. package/dist/aerogel-plugin-local-first.d.ts +299 -0
  2. package/dist/aerogel-plugin-local-first.js +1661 -0
  3. package/dist/aerogel-plugin-local-first.js.map +1 -0
  4. package/package.json +50 -0
  5. package/src/components/Account.vue +9 -0
  6. package/src/components/AccountLoggedIn.vue +85 -0
  7. package/src/components/AccountLoggedOut.vue +26 -0
  8. package/src/components/AccountLoginModal.vue +36 -0
  9. package/src/components/AccountModal.vue +206 -0
  10. package/src/components/index.ts +5 -0
  11. package/src/components/settings/PurgeData.vue +43 -0
  12. package/src/components/settings/index.ts +10 -0
  13. package/src/index.css +1 -0
  14. package/src/index.ts +33 -0
  15. package/src/jobs/Backup.ts +98 -0
  16. package/src/jobs/Migrate.test.ts +217 -0
  17. package/src/jobs/Migrate.ts +186 -0
  18. package/src/jobs/Sync.test.ts +1198 -0
  19. package/src/jobs/Sync.ts +696 -0
  20. package/src/jobs/mixins/LoadsChildren.ts +229 -0
  21. package/src/jobs/mixins/LoadsTypeIndex.ts +25 -0
  22. package/src/jobs/mixins/TracksLocalModels.ts +32 -0
  23. package/src/lib/SyncQueue.ts +94 -0
  24. package/src/lib/inference.ts +124 -0
  25. package/src/lib/mirroring.ts +352 -0
  26. package/src/lib/utils.ts +21 -0
  27. package/src/services/Cloud.state.ts +111 -0
  28. package/src/services/Cloud.ts +494 -0
  29. package/src/services/DocumentsCache.ts +39 -0
  30. package/src/testing/cloud.ts +193 -0
  31. package/src/testing/mocks/Solid.mock.ts +34 -0
  32. package/src/testing/setup.ts +33 -0
  33. package/src/testing/stubs/LegacyTask.schema.ts +15 -0
  34. package/src/testing/stubs/Movie.schema.ts +15 -0
  35. package/src/testing/stubs/Movie.ts +3 -0
  36. package/src/testing/stubs/MoviesContainer.ts +20 -0
  37. package/src/testing/stubs/Person.schema.ts +9 -0
  38. package/src/testing/stubs/Person.ts +18 -0
  39. package/src/testing/stubs/Post.schema.ts +17 -0
  40. package/src/testing/stubs/Post.ts +18 -0
  41. package/src/testing/stubs/Task.schema.ts +12 -0
  42. package/src/testing/stubs/Task.ts +3 -0
  43. package/src/testing/stubs/TasksList.ts +20 -0
  44. package/src/testing/stubs/Workspace.ts +15 -0
  45. package/src/types/shims.d.ts +7 -0
@@ -0,0 +1,1661 @@
1
+ var Ze = Object.defineProperty;
2
+ var Ge = (o, s, e) => s in o ? Ze(o, s, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[s] = e;
3
+ var w = (o, s, e) => Ge(o, typeof s != "symbol" ? s + "" : s, e);
4
+ import { Service as Xe, appNamespace as et, Events as D, App as se, Job as ye, Errors as Z, defineServiceState as tt, replaceExisting as ve, translateWithDefault as $, dispatch as re, Modal as ze, Markdown as T, Link as ue, Button as q, UI as ae, Storage as nt, defineSettings as st, useEvent as ot, SettingsModal as Ee, ProgressBar as it, AdvancedOptions as rt, Checkbox as le, EditableContent as at, DropdownMenu as lt, bootServices as ct } from "@aerogel/core";
5
+ import { facade as we, IndexedDBMap as dt, arrayFilter as ut, isInstanceOf as E, after as G, arrayRemove as ht, required as A, tap as Te, urlRoute as qe, urlResolveDirectory as ft, objectWithout as mt, requireUrlParentDirectory as X, fail as Pe, arrayFrom as gt, map as L, arrayChunk as pt, mixed as Oe, objectMap as yt, round as wt, toString as Mt, Semaphore as bt, isArray as Ct, isTesting as $e, hasLocationQueryParameter as Se, parseBoolean as De, getLocationQueryParameter as ke } from "@noeldemartin/utils";
6
+ import { Solid as C, SolidLogin as vt, SolidAvatar as _e } from "@aerogel/plugin-solid";
7
+ import { SolidModel as N, SolidContainsRelation as xe, isContainerClass as x, SolidContainer as j, SolidACLAuthorization as $t, SolidDocument as St, Metadata as Dt, Operation as kt, isContainer as U, Tombstone as W, PropertyOperation as ee, isSolidModel as Rt } from "soukai-solid";
8
+ import { getTrackedModels as Me, trackModelsCollection as te, ignoreModelsCollection as Lt, trackModels as Ut } from "@aerogel/plugin-soukai";
9
+ import { watchEffect as At, markRaw as O, createElementBlock as M, openBlock as h, createElementVNode as f, defineComponent as B, createBlock as R, unref as d, withCtx as b, createVNode as u, createTextVNode as K, toDisplayString as S, createCommentVNode as _, useTemplateRef as It, ref as zt, computed as Y, normalizeClass as Et } from "vue";
10
+ import { bootModels as Tt, requireEngine as qt, DocumentNotFound as Pt, InvalidModelAttributes as Ot, requireBootedModel as _t, getBootedModels as xt } from "soukai";
11
+ import { MalformedSolidDocumentError as Jt } from "@noeldemartin/solid-utils";
12
+ class Nt extends Xe {
13
+ constructor() {
14
+ super(...arguments);
15
+ w(this, "cache", new dt(`${et()}-documents-cache`));
16
+ }
17
+ async isFresh(e, t) {
18
+ const n = await this.cache.get(e), i = typeof t != "number" ? t.getTime() : t;
19
+ return !!(n != null && n.modifiedAt) && n.modifiedAt >= i;
20
+ }
21
+ async remember(e, t) {
22
+ await this.cache.set(e, {
23
+ modifiedAt: typeof t != "number" ? t.getTime() : t
24
+ });
25
+ }
26
+ async forget(e) {
27
+ await this.cache.delete(e);
28
+ }
29
+ async clear() {
30
+ await this.cache.clear();
31
+ }
32
+ async boot() {
33
+ D.on("auth:logout", async () => {
34
+ await this.cache.clear(), this.cache.close();
35
+ });
36
+ }
37
+ }
38
+ const P = we(Nt), ce = /* @__PURE__ */ new WeakMap();
39
+ function he(o) {
40
+ return ut(
41
+ k(o).map((s) => {
42
+ const e = o.instance().requireRelation(s).relatedClass;
43
+ return x(e) ? !1 : e;
44
+ })
45
+ );
46
+ }
47
+ function k(o) {
48
+ return ce.has(o) || ce.set(
49
+ o,
50
+ o.relations.filter((s) => N.reservedRelations.includes(s) ? !1 : o.instance().requireRelation(s) instanceof xe)
51
+ ), ce.get(o) ?? [];
52
+ }
53
+ function Je(o) {
54
+ return k(o.static()).reduce(
55
+ (e, t) => e.concat(o.getRelationModels(t) ?? []),
56
+ []
57
+ );
58
+ }
59
+ function Re(o) {
60
+ const s = /* @__PURE__ */ new Set(), e = o.instance();
61
+ s.add(o);
62
+ for (const t of o.relations)
63
+ o.reservedRelations.includes(t) || s.add(e.requireRelation(t).relatedClass);
64
+ return [...s.values()];
65
+ }
66
+ function fe(o) {
67
+ return o.getRelatedModels().filter(
68
+ (s) => !E(s, $t) && !E(s, St) && !E(s, Dt) && !E(s, kt) && s.static() !== j
69
+ );
70
+ }
71
+ function Ne(o) {
72
+ if (o.isDirty())
73
+ return !0;
74
+ if (!(o instanceof j))
75
+ return !1;
76
+ const s = (e) => {
77
+ var t;
78
+ return (t = o.getRelationModels(e)) == null ? void 0 : t.some((n) => Ne(n));
79
+ };
80
+ return k(o.static()).some(s);
81
+ }
82
+ const Wt = A(() => se.service("$cloud"));
83
+ class jt {
84
+ constructor() {
85
+ w(this, "models", /* @__PURE__ */ new Set());
86
+ w(this, "promises", []);
87
+ }
88
+ push(s) {
89
+ this.models.add(s), this.syncAfter(G({ seconds: 1 }));
90
+ }
91
+ clear(s) {
92
+ if (!s) {
93
+ this.models = /* @__PURE__ */ new Set();
94
+ return;
95
+ }
96
+ for (const e of s)
97
+ this.models.delete(e);
98
+ }
99
+ async syncAfter(s) {
100
+ const e = typeof s == "function" ? s() : s;
101
+ return this.promises.push(e), e.then(() => ht(this.promises, e)), this.promises.length === 1 && this.schedule(), e;
102
+ }
103
+ schedule() {
104
+ Promise.all(this.promises).then(() => G()).then(() => {
105
+ if (this.promises.length !== 0) {
106
+ this.schedule();
107
+ return;
108
+ }
109
+ const s = this.consume();
110
+ s.length !== 0 && Wt.syncIfOnline(s);
111
+ });
112
+ }
113
+ consume() {
114
+ const s = [], e = /* @__PURE__ */ new Set();
115
+ for (const t of this.models)
116
+ U(t) && (this.models.delete(t), Je(t).forEach((n) => e.add(n)), s.push(t));
117
+ for (const t of this.models)
118
+ this.models.delete(t), !e.has(t) && s.push(t);
119
+ return s;
120
+ }
121
+ }
122
+ const ne = we(jt), y = A(() => se.service("$cloud")), We = /* @__PURE__ */ new WeakMap(), be = /* @__PURE__ */ new WeakMap();
123
+ function Bt(o) {
124
+ const s = o.getRelatedModels().concat([o]);
125
+ for (const e of s)
126
+ e.cleanDirty(!0);
127
+ }
128
+ function Vt(o) {
129
+ const s = fe(o).concat([o]);
130
+ for (const e of s) {
131
+ if (!e.operations || e.operations.length === 0)
132
+ continue;
133
+ const t = (e.operations ?? []).filter((n) => !(n instanceof ee) || !e.ignoreRdfPropertyHistory(n.property, !0));
134
+ if (!t.some((n) => !n.isInception(e))) {
135
+ e.setRelationModels("operations", []);
136
+ continue;
137
+ }
138
+ e.setRelationModels("operations", t);
139
+ }
140
+ }
141
+ async function Le(o) {
142
+ y.setState({
143
+ localModelUpdates: {
144
+ ...y.localModelUpdates,
145
+ [o.url]: 1
146
+ }
147
+ }), Xt(o.static()) && await me(o.static(), X(o.url)), y.autoPush && y.ready && !y.syncing && ne.push(o);
148
+ }
149
+ async function me(o, s) {
150
+ var e, t;
151
+ (e = y.modelCollections[o.modelName]) != null && e.includes(s) || (y.setState("modelCollections", {
152
+ ...y.modelCollections,
153
+ [o.modelName]: (y.modelCollections[o.modelName] ?? []).concat(s)
154
+ }), (t = y.modelCollections[o.modelName]) != null && t.includes(o.collection) || (o.collection = s), await te(o, s));
155
+ }
156
+ async function Ue(o) {
157
+ if (Ft(o))
158
+ return;
159
+ const s = y.localModelUpdates[o.url] ?? 0;
160
+ y.setState({
161
+ localModelUpdates: o.isSoftDeleted() ? mt(y.localModelUpdates, o.url) : {
162
+ ...y.localModelUpdates,
163
+ [o.url]: s + 1
164
+ }
165
+ }), await P.forget(o.requireDocumentUrl()), y.autoPush && y.ready && !y.syncing && ne.push(o);
166
+ }
167
+ function ge(o, s) {
168
+ const e = {}, t = Array.from(o);
169
+ for (const [n, i] of Object.entries(y.localModelUpdates)) {
170
+ const l = qe(n);
171
+ (o.has(n) || t.some((r) => r.endsWith("/") && n.startsWith(r))) && !(s != null && s.has(l)) || (e[n] = i);
172
+ }
173
+ y.setState({ localModelUpdates: e });
174
+ }
175
+ function Ce(o, s = {}) {
176
+ const e = /* @__PURE__ */ new Set();
177
+ if (e.add(o.static()), o instanceof j)
178
+ for (const n of k(o.static()))
179
+ e.add(o.requireRelation(n).relatedClass);
180
+ const t = [...e.values()].map(
181
+ (n) => [n, z(n)]
182
+ );
183
+ return Te(o.clone({ constructors: t }), (n) => {
184
+ Vt(n), s.clean && Bt(n);
185
+ });
186
+ }
187
+ function je(o) {
188
+ const s = /* @__PURE__ */ new Set();
189
+ if (s.add(o.static()), o instanceof j)
190
+ for (const t of k(o.static()))
191
+ s.add(o.requireRelation(t).relatedClass);
192
+ const e = [...s.values()].map(
193
+ (t) => [t, tn(t)]
194
+ );
195
+ return o.clone({ constructors: e });
196
+ }
197
+ async function Ae(o, s, e) {
198
+ const t = z(W), n = s.map((a) => a.url), i = o.filter((a) => !n.includes(a.url)).map((a) => a.requireDocumentUrl()).filter((a) => !e.has(a)), l = await t.all({ $in: i });
199
+ return s.concat(l);
200
+ }
201
+ function Ft(o) {
202
+ const s = o.getDocumentModels(), e = s.flatMap(
203
+ (n) => {
204
+ var i;
205
+ return ((i = n.operations) == null ? void 0 : i.map((l) => [n, l])) ?? [];
206
+ }
207
+ ), t = Math.max(...s.map((n) => {
208
+ var i, l;
209
+ return ((l = (i = n.metadata) == null ? void 0 : i.updatedAt) == null ? void 0 : l.getTime()) ?? 0;
210
+ }));
211
+ return !e.some(([n, i]) => i.date.getTime() !== t ? !1 : i instanceof ee ? !n.ignoreRdfPropertyHistory(i.property, !0) : !0);
212
+ }
213
+ function Ht(o, s) {
214
+ return s.get(o.url) ?? je(o);
215
+ }
216
+ function pe() {
217
+ return [...y.registeredModels].map(({ modelClass: o }) => Me(o, { includeSoftDeleted: !0 })).flat();
218
+ }
219
+ function Kt() {
220
+ return y.schemaMigrations;
221
+ }
222
+ function Yt() {
223
+ y.schemaMigrations.clear();
224
+ }
225
+ function Ie(o) {
226
+ return y.schemaMigrations.get(o);
227
+ }
228
+ function z(o) {
229
+ return We.get(o) ?? en(o);
230
+ }
231
+ function de(o, s) {
232
+ const e = C.requireUser().storageUrls[0], t = x(o) && k(o).map((n) => {
233
+ const i = o.instance().requireRelation(n).relatedClass;
234
+ return x(i) ? null : i;
235
+ }).filter(Boolean)[0];
236
+ return s ?? (s = `/${(t || o).modelName.toLowerCase()}s/`), ft((s.startsWith("/") ? e.slice(0, -1) : e) + s);
237
+ }
238
+ function Qt(o, s) {
239
+ return s.get(o.url) ?? Ce(o);
240
+ }
241
+ function Zt(o) {
242
+ for (const { modelClass: s } of y.registeredModels)
243
+ if (Me(s).some((t) => t.url === o.url))
244
+ return !0;
245
+ return !1;
246
+ }
247
+ function Q(o) {
248
+ return be.has(o.static());
249
+ }
250
+ function Gt(o) {
251
+ return !Q(o);
252
+ }
253
+ function Xt(o) {
254
+ return y.registeredModels.some(({ modelClass: s }) => s === o);
255
+ }
256
+ function en(o) {
257
+ var n;
258
+ const s = o, e = (i, l) => {
259
+ i.timestamps = s.timestamps, i.history = s.history, l(), i.timestamps = [], i.history = !1;
260
+ }, t = (n = class extends s {
261
+ initialize(i, l) {
262
+ e(this._proxy.static(), () => super.initialize(i, l));
263
+ }
264
+ initializeRelations() {
265
+ super.initializeRelations();
266
+ for (const i of Object.values(this._relations))
267
+ i instanceof xe && (i.relatedClass = z(i.relatedClass));
268
+ }
269
+ fixMalformedAttributes() {
270
+ e(this.static(), () => super.fixMalformedAttributes());
271
+ }
272
+ }, w(n, "timestamps", !1), w(n, "history", !1), n);
273
+ return We.set(s, t), be.set(t, s), s.on("schema-updated", async (i) => {
274
+ await t.updateSchema({
275
+ ...i,
276
+ timestamps: !1,
277
+ history: !1
278
+ });
279
+ }), Tt({ [`Remote${o.modelName}`]: t }), t;
280
+ }
281
+ function tn(o) {
282
+ return be.get(o) ?? Pe(`Couldn't find local class for ${o.modelName}`);
283
+ }
284
+ class nn extends ye {
285
+ constructor() {
286
+ super(...arguments);
287
+ w(this, "urlMigrations", []);
288
+ w(this, "collectionMigrations", []);
289
+ }
290
+ migrateUrl(e, t, n) {
291
+ this.urlMigrations.push({
292
+ modelClass: e,
293
+ local: t,
294
+ remote: n
295
+ });
296
+ }
297
+ migrateCollection(e, t, n) {
298
+ this.collectionMigrations.push({
299
+ modelClass: e,
300
+ local: t,
301
+ remote: n
302
+ });
303
+ }
304
+ async run() {
305
+ const e = qt(), t = await e.getCollections();
306
+ for (const n of t) {
307
+ const i = await e.readMany(n);
308
+ for (const [l, a] of Object.entries(i)) {
309
+ const r = this.replaceUrl(l);
310
+ await e.create(X(r), this.replaceDocumentUrls(a), r), await e.delete(n, l);
311
+ }
312
+ }
313
+ for (const { modelClass: n, remote: i } of this.urlMigrations)
314
+ te(n, X(i), { refresh: !1 });
315
+ for (const { modelClass: n, local: i, remote: l } of this.collectionMigrations)
316
+ Lt(n, i), te(n, l, { refresh: !1 });
317
+ }
318
+ replaceDocumentUrls(e) {
319
+ for (const [t, n] of Object.entries(e)) {
320
+ if (t === "@id" && typeof n == "string") {
321
+ e[t] = this.replaceUrl(n);
322
+ continue;
323
+ }
324
+ typeof n != "object" || n === null || (e[t] = this.replaceDocumentUrls(n));
325
+ }
326
+ return e;
327
+ }
328
+ replaceUrl(e) {
329
+ for (const { local: t, remote: n } of this.urlMigrations)
330
+ if (e.startsWith(t))
331
+ return e.replace(t, n);
332
+ for (const { local: t, remote: n } of this.collectionMigrations)
333
+ if (e.startsWith(t))
334
+ return e.replace(t, n);
335
+ return e;
336
+ }
337
+ }
338
+ function sn(o) {
339
+ const s = {};
340
+ return async () => ("value" in s || (s.value = await o()), s.value);
341
+ }
342
+ class Be {
343
+ async loadContainedModels(s, e = {}) {
344
+ var p;
345
+ if (Gt(s)) {
346
+ const m = [];
347
+ for (const g of k(s.static())) {
348
+ const J = await s.loadRelationIfUnloaded(g) ?? [];
349
+ m.push(...gt(J));
350
+ }
351
+ return m;
352
+ }
353
+ const t = {}, n = [], i = L(s.documents, "url"), l = pt(s.resourceUrls, 10), a = l.flat().map((m) => ({
354
+ documentUrl: m,
355
+ completed: !1
356
+ })), r = L(a, "documentUrl");
357
+ e.status && (e.status.children = a);
358
+ for (const m of l) {
359
+ await Promise.all(
360
+ m.map(async (g) => {
361
+ const { children: J, tombstones: Ye } = await this.loadDocumentChildren(
362
+ s,
363
+ g,
364
+ i,
365
+ e.onDocumentError,
366
+ e.onDocumentRead
367
+ );
368
+ n.push(...Ye);
369
+ for (const [ie, Qe] of Object.entries(J))
370
+ (t[ie] ?? (t[ie] = [])).push(...Qe);
371
+ })
372
+ );
373
+ for (const g of m)
374
+ g.endsWith("/") || (A(r.get(g)).completed = !0);
375
+ await ((p = e.onDocumentsLoaded) == null ? void 0 : p.call(e, m));
376
+ }
377
+ for (const [m, g] of Object.entries(t))
378
+ s.setRelationModels(m, g);
379
+ const c = e.ignoreTombstones ? Object.values(t).flat() : Object.values(t).flat().concat(n);
380
+ return e.status && (e.status.children = c.map((m) => A(r.get(m.requireDocumentUrl())))), c;
381
+ }
382
+ async loadDocumentChildren(s, e, t, n, i) {
383
+ var a;
384
+ const l = t.get(e);
385
+ return l && l.updatedAt && await P.isFresh(l.url, l.updatedAt) && ((a = this.localModels) != null && a.hasKey(s.url)) ? {
386
+ children: await this.loadDocumentChildrenFromLocal(s, l),
387
+ tombstones: []
388
+ } : this.loadDocumentChildrenFromRemote(s, e, n, i);
389
+ }
390
+ async loadDocumentChildrenFromLocal(s, e) {
391
+ var n, i;
392
+ const t = {};
393
+ for (const l of k(s.static())) {
394
+ const a = s.requireRelation(l);
395
+ if (a.loaded) {
396
+ t[l] = a.getLoadedModels();
397
+ continue;
398
+ }
399
+ const r = ((i = (n = this.localModels) == null ? void 0 : n.get(s.url)) == null ? void 0 : i.getRelationModels(l)) ?? [];
400
+ t[l] = r.filter((c) => c.getDocumentUrl() === e.url).map((c) => Ce(c, { clean: !0 }));
401
+ }
402
+ return t;
403
+ }
404
+ async loadDocumentChildrenFromRemote(s, e, t, n) {
405
+ const i = {}, l = [], a = sn(async () => {
406
+ try {
407
+ const r = s.documents.find((m) => m.url === e), c = await s.requireEngine().readOne(s.static("collection"), e), p = await W.createManyFromEngineDocuments({
408
+ [e]: c
409
+ });
410
+ return l.push(...p), r && (n == null || n(r)), c;
411
+ } catch (r) {
412
+ if (E(r, Pt))
413
+ return null;
414
+ if (!t)
415
+ throw r;
416
+ return t(r), null;
417
+ }
418
+ });
419
+ for (const r of k(s.static())) {
420
+ const c = s.requireRelation(r);
421
+ if (c.loaded) {
422
+ i[r] = c.getLoadedModels();
423
+ continue;
424
+ }
425
+ const p = await a();
426
+ if (p)
427
+ try {
428
+ const m = await c.relatedClass.createManyFromEngineDocuments({
429
+ [e]: p
430
+ });
431
+ i[r] = m;
432
+ } catch (m) {
433
+ if (!t)
434
+ throw m;
435
+ t(m);
436
+ }
437
+ }
438
+ return { children: i, tombstones: l };
439
+ }
440
+ }
441
+ const V = /* @__PURE__ */ new WeakMap();
442
+ class Ve {
443
+ async loadTypeIndex(s = {}) {
444
+ const e = C.requireUser();
445
+ return (s.fresh || !V.has(e)) && V.set(e, await C.findPrivateTypeIndex({ fresh: s.fresh })), s.create && !V.get(e) && V.set(e, await C.findOrCreatePrivateTypeIndex()), V.get(e) ?? null;
446
+ }
447
+ }
448
+ class Fe {
449
+ async indexLocalModels(s) {
450
+ for (const e of s)
451
+ await this.addLocalModel(e);
452
+ }
453
+ async addLocalModel(s) {
454
+ if (!this.localModels.hasKey(s.url)) {
455
+ this.localModels.add(s);
456
+ for (const e of k(s.static()))
457
+ await s.loadRelationIfUnloaded(e);
458
+ for (const e of s.getRelatedModels())
459
+ this.localModels.add(e);
460
+ }
461
+ }
462
+ }
463
+ const on = ye;
464
+ class oe extends Oe(on, [Be, Ve, Fe]) {
465
+ constructor() {
466
+ super();
467
+ w(this, "_models");
468
+ this.localModels = L([], "url");
469
+ }
470
+ static restore(e) {
471
+ return Te(new oe(), (t) => {
472
+ t.status = e;
473
+ });
474
+ }
475
+ get models() {
476
+ return this._models;
477
+ }
478
+ set models(e) {
479
+ if (!e) {
480
+ delete this._models, this.localModels = L([], "url");
481
+ return;
482
+ }
483
+ const t = yt(this.status.children ?? [], "modelUrl");
484
+ this._models = e, this.localModels = L([], "url"), this.status.children = e.map(
485
+ (n) => t[n.url] ?? {
486
+ modelUrl: n.url,
487
+ completed: !1
488
+ }
489
+ );
490
+ }
491
+ async run() {
492
+ if (!this.models)
493
+ throw new Error("Cant start migration without models");
494
+ await this.indexLocalModels(this.models);
495
+ const e = this.status.children ?? [], t = await this.loadTypeIndex();
496
+ for (const n of e) {
497
+ const i = this.models.find(({ url: l }) => n.modelUrl === l);
498
+ !i || n.completed || (await this.migrateRegisteredModel(i, n, t), await this.updateProgress(() => n.completed = !0));
499
+ }
500
+ for (const [n, i] of Kt())
501
+ await n.updateSchema(i);
502
+ Yt();
503
+ }
504
+ async migrateRegisteredModel(e, t, n) {
505
+ if (await this.migrate(e, t), !U(e))
506
+ return;
507
+ const i = he(e.static()), l = n == null ? void 0 : n.registrations.find(({ instanceContainer: a }) => a === e.url);
508
+ !n || !l || i.length === 0 || (l.setAttribute(
509
+ "forClass",
510
+ i.map((a) => {
511
+ var r;
512
+ return ((r = Ie(a)) == null ? void 0 : r.rdfsClasses) ?? a.rdfsClass;
513
+ }).flat()
514
+ ), await n.save());
515
+ }
516
+ async migrate(e, t) {
517
+ this.assertNotCancelled(), await this.migrateChildren(e, t);
518
+ const n = Ie(e.static());
519
+ if (!n)
520
+ return;
521
+ const i = await z(e.static()).find(e.url), l = await (i == null ? void 0 : i.migrateSchema(n));
522
+ await e.migrateSchema(n, {
523
+ mintOperationUrl: (a) => {
524
+ var r, c;
525
+ return (c = (r = l == null ? void 0 : l.operations) == null ? void 0 : r.find((p) => !E(a, ee) || !E(p, ee) ? !1 : a.property === p.property && a.date.getTime() === p.date.getTime())) == null ? void 0 : c.url;
526
+ }
527
+ });
528
+ }
529
+ async migrateChildren(e, t) {
530
+ if (!U(e))
531
+ return;
532
+ const n = await this.loadContainedModels(e, { ignoreTombstones: !0 });
533
+ t.children ?? (t.children = n.map((i) => ({
534
+ modelUrl: i.url,
535
+ completed: !1
536
+ })));
537
+ for (const i of t.children) {
538
+ const l = n.find(({ url: a }) => i.modelUrl === a);
539
+ !l || i.completed || (await this.migrate(l, i), await this.updateProgress(() => i.completed = !0));
540
+ }
541
+ }
542
+ }
543
+ const rn = A(() => se.service("$cloud")), an = ye;
544
+ function ln(o) {
545
+ return !!o && "root" in o;
546
+ }
547
+ class cn extends Oe(an, [Be, Ve, Fe]) {
548
+ constructor(e) {
549
+ super();
550
+ w(this, "models");
551
+ w(this, "dirtyRemoteModels");
552
+ w(this, "rootLocalModels");
553
+ w(this, "tombstones");
554
+ w(this, "documentsWithErrors");
555
+ w(this, "syncedModelUrls");
556
+ w(this, "documentsModifiedAt");
557
+ w(this, "screenLock", null);
558
+ w(this, "localModels");
559
+ this.models = e, this.rootLocalModels = [], this.localModels = L([], "url"), this.tombstones = L([], "resourceUrl"), this.documentsWithErrors = /* @__PURE__ */ new Set(), this.syncedModelUrls = /* @__PURE__ */ new Set(), this.documentsModifiedAt = {};
560
+ }
561
+ async run() {
562
+ const e = C.requireAuthenticator().engine, t = (i, { headers: l }, a) => {
563
+ const r = (l == null ? void 0 : l.get("last-modified")) ?? a;
564
+ !r || i.endsWith("/") || (this.documentsModifiedAt[i] = new Date(r));
565
+ }, n = e.listeners.add({
566
+ onDocumentRead: (i, l) => t(i, l),
567
+ onDocumentUpdated: (i, l) => t(i, l, /* @__PURE__ */ new Date())
568
+ });
569
+ try {
570
+ this.lockScreen(), this.rootLocalModels = this.models ?? pe(), await this.indexLocalModels(this.rootLocalModels), await this.pullChanges(), await this.pushChanges();
571
+ } finally {
572
+ this.releaseScreen(), n();
573
+ }
574
+ }
575
+ lockScreen() {
576
+ const e = navigator;
577
+ if (e.wakeLock)
578
+ try {
579
+ this.screenLock = e.wakeLock.request("screen").catch((t) => {
580
+ Z.reportDevelopmentError(t, "Could not request screen wake lock");
581
+ });
582
+ } catch (t) {
583
+ Z.reportDevelopmentError(t, "Could not request screen wake lock");
584
+ }
585
+ }
586
+ releaseScreen() {
587
+ this.screenLock && (this.screenLock.then((e) => e == null ? void 0 : e.release()), this.screenLock = null);
588
+ }
589
+ getInitialStatus() {
590
+ return {
591
+ root: !0,
592
+ completed: !1,
593
+ children: [{ completed: !1 }, { completed: !1 }]
594
+ };
595
+ }
596
+ calculateCurrentProgress(e) {
597
+ return e ?? (e = this.status), ln(e) ? wt(
598
+ this.calculateCurrentProgress(e.children[0]) * 0.9 + this.calculateCurrentProgress(e.children[1]) * 0.1,
599
+ 2
600
+ ) : super.calculateCurrentProgress(e);
601
+ }
602
+ async pullChanges() {
603
+ const e = this.models ? await this.fetchRemoteModelsForLocal(this.models) : await this.fetchRemoteModels(), t = L(e, (n) => n instanceof W ? n.resourceUrl : n.url);
604
+ this.dirtyRemoteModels = await this.synchronizeModels(t), await this.updateProgress((n) => n.children[0].completed = !0);
605
+ }
606
+ async pushChanges() {
607
+ const e = this.dirtyRemoteModels ?? [], t = this.status.children[1].children = e.map(() => ({ completed: !1 }));
608
+ for (let n = 0; n < e.length; n++) {
609
+ const i = e[n], l = t[n];
610
+ if (i.isSoftDeleted()) {
611
+ i.enableHistory(), i.enableTombstone(), await i.forceDelete(), await this.updateProgress(() => l.completed = !0);
612
+ return;
613
+ }
614
+ await this.saveModelAndChildren(i, l), await this.updateTypeRegistrations(i), await this.updateProgress(() => l.completed = !0);
615
+ }
616
+ for (const [n, i] of Object.entries(this.documentsModifiedAt))
617
+ await P.remember(n, i);
618
+ ge(this.syncedModelUrls, this.documentsWithErrors), await this.updateProgress((n) => n.children[1].completed = !0);
619
+ }
620
+ async fetchRemoteModels() {
621
+ const e = this.status.children[0], t = await this.loadTypeIndex({ fresh: !0 });
622
+ if (!t)
623
+ return [];
624
+ const n = [], i = this.getTypeRegistrations(t);
625
+ e.children = i.map(() => ({ completed: !1 }));
626
+ for (let l = 0; l < i.length; l++)
627
+ await this.ignoringDocumentErrors(async () => {
628
+ var p;
629
+ const { registration: a, registeredModel: r } = A(i[l]), c = z(r.modelClass);
630
+ if (a.instanceContainer) {
631
+ if (x(c)) {
632
+ await me(
633
+ r.modelClass,
634
+ X(a.instanceContainer)
635
+ );
636
+ const m = await c.find(a.instanceContainer);
637
+ m && (await this.loadChildren(m, A((p = e.children) == null ? void 0 : p[l])), n.push(m)), await this.updateProgress(() => {
638
+ var g;
639
+ return A((g = e.children) == null ? void 0 : g[l]).completed = !0;
640
+ });
641
+ return;
642
+ }
643
+ await me(r.modelClass, a.instanceContainer), n.push(...await c.from(a.instanceContainer).all()), await this.updateProgress(() => {
644
+ var m;
645
+ return A((m = e.children) == null ? void 0 : m[l]).completed = !0;
646
+ });
647
+ }
648
+ });
649
+ return Ae(this.rootLocalModels, n, this.documentsWithErrors);
650
+ }
651
+ async fetchRemoteModelsForLocal(e) {
652
+ const t = [], n = this.status.children[0].children = e.map(() => ({ completed: !1 }));
653
+ for (let i = 0; i < e.length; i++)
654
+ await this.ignoringDocumentErrors(async () => {
655
+ const l = e[i], a = n[i], r = await z(l.static()).find(l.url);
656
+ if (!r) {
657
+ await this.updateProgress(() => a.completed = !0);
658
+ return;
659
+ }
660
+ U(r) && await this.loadChildren(r, a), t.push(r), await this.updateProgress(() => a.completed = !0);
661
+ });
662
+ return Ae(e, t, this.documentsWithErrors);
663
+ }
664
+ getTypeRegistrations(e) {
665
+ const t = /* @__PURE__ */ new Set(), n = [...rn.registeredModels].map(({ modelClass: a }) => {
666
+ const r = x(a) ? he(a) : [];
667
+ return {
668
+ modelClass: a,
669
+ rdfsClasses: r.length > 0 ? r.map((c) => c.rdfsClasses).flat() : a.rdfsClasses
670
+ };
671
+ }), i = e.registrations.map((a) => {
672
+ const r = n.find(
673
+ ({ rdfsClasses: c }) => !!a.instanceContainer && c.some((p) => a.forClass.includes(p))
674
+ );
675
+ return !r || !a.instanceContainer || t.has(a.instanceContainer) ? null : (t.add(a.instanceContainer), { registration: a, registeredModel: r });
676
+ }).filter((a) => !!a), l = i.map(({ registration: a }) => a.instanceContainer);
677
+ return i.filter(({ registration: a }) => !l.some(
678
+ (r) => {
679
+ var c;
680
+ return r && r !== a.instanceContainer && ((c = a.instanceContainer) == null ? void 0 : c.startsWith(r));
681
+ }
682
+ ));
683
+ }
684
+ async updateTypeRegistrations(e) {
685
+ if (!Zt(e))
686
+ return;
687
+ const t = U(e) ? he(e.static()) : [e.static()], n = z(j), i = U(e) ? e : new n({ url: e.requireContainerUrl() });
688
+ if (t.length === 0)
689
+ return;
690
+ const l = await this.loadTypeIndex({ create: !0 });
691
+ l.registrations.some((a) => a.instanceContainer === e.url) || await i.register(l, t);
692
+ }
693
+ async loadChildren(e, t) {
694
+ var i, l;
695
+ if (this.assertNotCancelled(), !U(e))
696
+ return;
697
+ const n = await this.loadContainedModels(e, {
698
+ status: t,
699
+ onDocumentError: (a) => this.handleDocumentError(a),
700
+ onDocumentRead: (a) => {
701
+ a.url.endsWith("/") || !a.updatedAt || a.url in this.documentsModifiedAt || (this.documentsModifiedAt[a.url] = a.updatedAt);
702
+ },
703
+ onDocumentsLoaded: async () => {
704
+ this.assertNotCancelled(), await this.updateProgress();
705
+ }
706
+ });
707
+ for (let a = 0; a < n.length; a++) {
708
+ const r = n[a];
709
+ if (r instanceof W) {
710
+ this.tombstones.add(r);
711
+ continue;
712
+ }
713
+ if (this.tombstones.hasKey(r.url)) {
714
+ await this.deleteChild(e, r);
715
+ continue;
716
+ }
717
+ await this.loadChildren(r, (i = t == null ? void 0 : t.children) == null ? void 0 : i[a]), (l = t == null ? void 0 : t.children) != null && l[a] && await this.updateProgress(() => {
718
+ var c;
719
+ return A((c = t.children) == null ? void 0 : c[a]).completed = !0;
720
+ });
721
+ }
722
+ }
723
+ async deleteChild(e, t) {
724
+ for (const n of e.static("relations")) {
725
+ const i = e.requireRelation(n);
726
+ if (i.related) {
727
+ if (Array.isArray(i.related)) {
728
+ i.related = i.related.filter((l) => l !== t);
729
+ continue;
730
+ }
731
+ if (i.related === t) {
732
+ i.related = null;
733
+ continue;
734
+ }
735
+ }
736
+ }
737
+ await t.forceDelete();
738
+ }
739
+ async saveModelAndChildren(e, t) {
740
+ if (this.assertNotCancelled(), Q(e) && e.isSoftDeleted()) {
741
+ e.enableHistory(), e.enableTombstone(), await e.forceDelete();
742
+ return;
743
+ }
744
+ if (this.documentsWithErrors.has(e.requireDocumentUrl()))
745
+ return;
746
+ const n = e.isDirty();
747
+ if (await e.save(), (n || Q(e)) && this.syncedModelUrls.add(e.url), !U(e)) {
748
+ if (Q(e)) {
749
+ const a = e.requireDocumentUrl(), r = this.documentsModifiedAt[a];
750
+ r && (await P.remember(a, r), delete this.documentsModifiedAt[a]);
751
+ }
752
+ return;
753
+ }
754
+ const i = k(e.static()).map((a) => e.getRelationModels(a) ?? []).flat(), l = t ? i.map(() => ({ completed: !1 })) : [];
755
+ t && (t.children = l);
756
+ for (let a = 0; a < i.length; a++) {
757
+ const r = i[a], c = l[a];
758
+ await this.saveModelAndChildren(r, c), c && await this.updateProgress(() => c.completed = !0);
759
+ }
760
+ }
761
+ async synchronizeModels(e) {
762
+ const t = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set();
763
+ for (const l of e.items()) {
764
+ if (l instanceof W) {
765
+ const r = this.localModels.get(l.resourceUrl);
766
+ r && (await r.forceDelete(), n.add(r));
767
+ continue;
768
+ }
769
+ const a = Ht(l, this.localModels);
770
+ a.exists() || this.syncedModelUrls.add(a.url), await this.loadChildren(a), await N.synchronize(a, l), await this.reconcileInconsistencies(a, l), await this.saveModelAndChildren(a), await this.addLocalModel(a), this.rootLocalModels.push(a), t.add(a.url);
771
+ }
772
+ for (const l of this.rootLocalModels) {
773
+ if (n.has(l) || t.has(l.url))
774
+ continue;
775
+ await this.loadChildren(l);
776
+ const a = Qt(l, e);
777
+ await N.synchronize(l, a), e.add(a);
778
+ }
779
+ const i = [];
780
+ for (const l of e.getItems()) {
781
+ if (Ne(l)) {
782
+ i.push(l);
783
+ continue;
784
+ }
785
+ await this.rememberModelDocuments(l);
786
+ }
787
+ return i;
788
+ }
789
+ async reconcileInconsistencies(e, t, n) {
790
+ e.rebuildAttributesFromHistory(), e.setAttributes(t.getAttributes(!0)), n ?? (n = /* @__PURE__ */ new Set()), n.add(e);
791
+ for (const l of k(e.static()))
792
+ await this.synchronizeContainerDocuments(
793
+ e.requireRelation(l),
794
+ t.requireRelation(l)
795
+ );
796
+ const i = L(fe(t), "url");
797
+ for (const l of fe(e))
798
+ n.has(l) || !l.isRelationLoaded("operations") || !i.hasKey(l.url) || await this.reconcileInconsistencies(
799
+ l,
800
+ i.require(l.url),
801
+ n
802
+ );
803
+ e.isDirty() && await N.synchronize(e, t);
804
+ }
805
+ async synchronizeContainerDocuments(e, t) {
806
+ const n = L(e.related ?? [], "url"), i = L(t.related ?? [], "url"), l = n.getKeys().filter((r) => !i.hasKey(r) && !i.hasKey(encodeURI(r))), a = i.getKeys().filter((r) => !n.hasKey(r) && !n.hasKey(encodeURI(r)));
807
+ for (const r of l) {
808
+ const c = n.require(r), p = Ce(c);
809
+ t.addRelated(p), i.add(p);
810
+ }
811
+ for (const r of a) {
812
+ const c = i.require(r), p = je(c);
813
+ e.addRelated(p), n.add(p), this.syncedModelUrls.add(p.url);
814
+ }
815
+ for (const r of n.items()) {
816
+ const c = i.require(r.url);
817
+ await N.synchronize(r, c), await this.saveModelAndChildren(r);
818
+ }
819
+ }
820
+ async rememberModelDocuments(e) {
821
+ if (!U(e)) {
822
+ const n = e.requireDocumentUrl(), i = this.documentsModifiedAt[n];
823
+ i && (await P.remember(n, i), delete this.documentsModifiedAt[n]);
824
+ return;
825
+ }
826
+ const t = k(e.static()).map((n) => e.getRelationModels(n) ?? []).flat();
827
+ for (const n of t)
828
+ await this.rememberModelDocuments(n);
829
+ }
830
+ async ignoringDocumentErrors(e) {
831
+ try {
832
+ await e();
833
+ } catch (t) {
834
+ this.handleDocumentError(t);
835
+ }
836
+ }
837
+ handleDocumentError(e) {
838
+ if (E(e, Jt)) {
839
+ console.warn(e.message), e.documentUrl && this.documentsWithErrors.add(e.documentUrl);
840
+ return;
841
+ }
842
+ if (E(e, Ot)) {
843
+ console.warn(e.message);
844
+ const t = e.attributes[_t(e.modelName).primaryKey], n = t && qe(Mt(t));
845
+ n && this.documentsWithErrors.add(n);
846
+ return;
847
+ }
848
+ throw e;
849
+ }
850
+ }
851
+ const v = {
852
+ Disconnected: "disconnected",
853
+ Online: "online",
854
+ Syncing: "syncing",
855
+ Migrating: "migrating"
856
+ }, dn = tt({
857
+ name: "cloud",
858
+ persist: [
859
+ "localModelUpdates",
860
+ "migrationDismissed",
861
+ "migrationJob",
862
+ "modelCollections",
863
+ "pollingEnabled",
864
+ "pollingMinutes",
865
+ "ready",
866
+ "startupSync"
867
+ ],
868
+ initialState: () => ({
869
+ autoPush: !0,
870
+ localModelUpdates: {},
871
+ migrationDismissed: !1,
872
+ migrationJob: null,
873
+ migrationPostponed: !1,
874
+ modelCollections: {},
875
+ pollingEnabled: !0,
876
+ pollingMinutes: 10,
877
+ ready: !1,
878
+ registeredModels: [],
879
+ schemaMigrations: /* @__PURE__ */ new Map(),
880
+ setupDismissed: !1,
881
+ setupOngoing: !1,
882
+ startupSync: !0,
883
+ status: v.Disconnected,
884
+ syncError: null,
885
+ syncJob: null
886
+ }),
887
+ serialize: (o) => {
888
+ var s;
889
+ return ve(o, { migrationJob: (s = o.migrationJob) == null ? void 0 : s.serialize() });
890
+ },
891
+ restore: (o) => ve(o, {
892
+ migrationJob: o.migrationJob && oe.restore(o.migrationJob)
893
+ }),
894
+ watch: {
895
+ migrationJob(o) {
896
+ o == null || o.listeners.add({ onUpdated: () => this.updatePersistedState("migrationJob") });
897
+ }
898
+ },
899
+ computed: {
900
+ disconnected: ({ status: o }) => o === v.Disconnected,
901
+ online: ({ status: o }) => o === v.Online,
902
+ syncing: ({ status: o }) => o === v.Syncing,
903
+ migrating: ({ status: o }) => o === v.Migrating,
904
+ localChanges({ localModelUpdates: o }) {
905
+ return Object.values(o).reduce((s, e) => s + e, 0);
906
+ },
907
+ dirty() {
908
+ return this.localChanges > 0;
909
+ },
910
+ migrationStarted({ migrationJob: o }) {
911
+ return !!o;
912
+ },
913
+ migrationDisabledReason({ status: o, ready: s }) {
914
+ return C.isLoggedIn() ? s ? o === v.Syncing || o === v.Migrating ? $(
915
+ "cloud.migrationNotSyncing",
916
+ "Wait for syncing to finish before starting the migration"
917
+ ) : this.online ? null : $(
918
+ "cloud.migrationNotOnline",
919
+ "You need to be online in order to start the migration"
920
+ ) : $(
921
+ "cloud.migrationNotReady",
922
+ "You need to backup your data before starting the migration"
923
+ ) : $(
924
+ "cloud.migrationNotLoggedIn",
925
+ "You need to reconnect before starting the migration"
926
+ );
927
+ }
928
+ }
929
+ });
930
+ class un extends dn {
931
+ constructor() {
932
+ super(...arguments);
933
+ w(this, "asyncLock", new bt());
934
+ w(this, "engine", null);
935
+ w(this, "pollingInterval", null);
936
+ }
937
+ async whenReady(e) {
938
+ return this.ready ? e() : new Promise((t) => {
939
+ const n = () => t(e());
940
+ D.once("cloud:ready", n);
941
+ });
942
+ }
943
+ async setup(e) {
944
+ this.setupOngoing = !0;
945
+ try {
946
+ await this.backup(e), await this.setReady(!0), await this.sync();
947
+ } finally {
948
+ this.setupOngoing = !1;
949
+ }
950
+ }
951
+ dismissSetup() {
952
+ this.setupDismissed = !0;
953
+ }
954
+ dismissMigration() {
955
+ this.migrationDismissed = !0;
956
+ }
957
+ postponeMigration() {
958
+ this.migrationPostponed = !0;
959
+ }
960
+ async syncIfOnline(e = {}) {
961
+ this.online && await this.sync(e);
962
+ }
963
+ async sync(e = {}) {
964
+ const t = Ct(e) ? { models: e } : e instanceof N ? { model: e } : e;
965
+ !C.isLoggedIn() || !this.ready || !this.online || await this.asyncLock.run(async () => {
966
+ const n = Date.now(), i = t.model ? [t.model] : t.models;
967
+ this.syncError = null, this.status = v.Syncing, ne.clear(i);
968
+ try {
969
+ if (await D.emit("cloud:sync-started", i), t.refreshUserProfile && await C.refreshUserProfile(), this.syncJob = new cn(i), this.syncJob.listeners.add(t), await re(this.syncJob), this.syncJob.cancelled)
970
+ return;
971
+ $e("unit") || await G({ milliseconds: Math.max(500, 1e3 - (Date.now() - n)) }), this.syncJob = null;
972
+ } catch (l) {
973
+ if ($e())
974
+ throw l;
975
+ this.syncJob = null, this.syncError = l, await Z.report(l, $("cloud.syncFailed", "Sync failed"));
976
+ } finally {
977
+ this.status = v.Online, await D.emit("cloud:sync-completed", i);
978
+ }
979
+ });
980
+ }
981
+ shouldMigrate() {
982
+ return this.schemaMigrations.size > 0;
983
+ }
984
+ async migrate(e) {
985
+ if (!this.online || !C.isLoggedIn() || !this.ready)
986
+ throw new Error("Data cannot be migrated at the moment");
987
+ this.shouldMigrate() && await this.asyncLock.run(async () => {
988
+ var l;
989
+ this.status = v.Migrating, this.migrationJob ?? (this.migrationJob = new oe());
990
+ const t = Date.now(), n = [], i = (l = this.migrationJob).models ?? (l.models = pe());
991
+ ne.clear(i);
992
+ try {
993
+ if (e && n.push(this.migrationJob.listeners.add(e)), await D.emit("cloud:migration-started", i), await re(this.migrationJob), this.migrationJob.cancelled) {
994
+ await D.emit("cloud:migration-cancelled", i);
995
+ return;
996
+ }
997
+ this.migrationJob = null, this.migrationDismissed = !1, this.migrationPostponed = !1, await G({ milliseconds: Math.max(0, 1e3 - (Date.now() - t)) }), await D.emit("cloud:migration-completed", i);
998
+ } catch (a) {
999
+ await Z.report(a, $("cloud.migrationFailed", "Migration failed"));
1000
+ } finally {
1001
+ this.status = v.Online, n.forEach((a) => a == null ? void 0 : a());
1002
+ }
1003
+ });
1004
+ }
1005
+ async register(e, t = {}) {
1006
+ if (this.registeredModels.find((i) => e === i.modelClass))
1007
+ return;
1008
+ const n = this.engine;
1009
+ n && Re(e).forEach((i) => z(i).setEngine(n)), this.whenReady(() => {
1010
+ const [i] = this.modelCollections[e.modelName] ?? [];
1011
+ e.useSoftDeletes(!0), e.collection = i ?? de(e, t.path);
1012
+ }), await Ut(e, {
1013
+ created: (i) => this.ready && Le(i),
1014
+ updated: (i) => this.ready && Ue(i),
1015
+ deleted: (i) => this.ready && ge(/* @__PURE__ */ new Set([i.url ?? i.getDeletedPrimaryKey()]))
1016
+ }), x(e) && k(e).forEach((i) => {
1017
+ const l = e.instance().requireRelation(i).relatedClass;
1018
+ l.on("created", (a) => this.ready && Le(a)), l.on("updated", (a) => this.ready && Ue(a)), l.on(
1019
+ "deleted",
1020
+ (a) => this.ready && ge(/* @__PURE__ */ new Set([a.url ?? a.getDeletedPrimaryKey()]))
1021
+ );
1022
+ }), this.registeredModels.push({ modelClass: e, path: t.path });
1023
+ for (const i of this.modelCollections[e.modelName] ?? [])
1024
+ await te(e, i);
1025
+ }
1026
+ registerSchemaMigration(e, t) {
1027
+ this.schemaMigrations.set(e, t);
1028
+ }
1029
+ requireRemoteCollection(e) {
1030
+ for (const t of this.registeredModels)
1031
+ if (e === t.modelClass)
1032
+ return de(t.modelClass, t.path);
1033
+ throw new Error(`Failed resolving remote collection for '${e.modelName}' model`);
1034
+ }
1035
+ async boot() {
1036
+ await C.booted, C.isLoggedIn() && this.login(C.authenticator), D.on("auth:login", ({ authenticator: e }) => this.login(e)), D.on("auth:logout", () => this.logout()), D.once("application-ready", () => this.onApplicationReady()), D.once("application-mounted", () => this.onApplicationMounted()), At(() => {
1037
+ if (this.pollingInterval && clearInterval(this.pollingInterval), !this.pollingEnabled || this.migrationJob) {
1038
+ this.pollingInterval = null;
1039
+ return;
1040
+ }
1041
+ this.pollingInterval = setInterval(() => this.sync(), this.pollingMinutes * 60 * 1e3);
1042
+ }), await this.bustDocumentsCache(), await this.registerModels();
1043
+ }
1044
+ getDirtyLocalModels() {
1045
+ const e = Object.keys(this.localModelUpdates), t = [];
1046
+ for (const { modelClass: n } of this.registeredModels)
1047
+ for (const i of Me(n, { includeSoftDeleted: !0 }))
1048
+ t.push(...this.getModelsIn(e, i));
1049
+ return t;
1050
+ }
1051
+ getModelsIn(e, t) {
1052
+ const n = [];
1053
+ return e.includes(t.url) && n.push(t), U(t) && n.push(
1054
+ ...Je(t).map((i) => this.getModelsIn(e, i)).flat()
1055
+ ), n;
1056
+ }
1057
+ requireEngine() {
1058
+ return this.engine ?? Pe("Could not get required Engine");
1059
+ }
1060
+ async setReady(e) {
1061
+ this.ready || !e || (await D.emit("cloud:ready"), this.ready = !0);
1062
+ }
1063
+ async backup(e) {
1064
+ await D.emit("cloud:backup-started"), e ?? (e = /* @__PURE__ */ new WeakMap());
1065
+ const t = new nn();
1066
+ for (const { modelClass: n, path: i } of this.registeredModels) {
1067
+ if (!x(n))
1068
+ continue;
1069
+ for (const [r, c] of Object.entries(e.get(n) ?? {}))
1070
+ t.migrateUrl(n, r, c);
1071
+ const l = n.collection, a = de(n, i);
1072
+ n.collection = a, t.migrateCollection(n, l, a);
1073
+ }
1074
+ await re(t), await D.emit("cloud:backup-completed");
1075
+ }
1076
+ async onApplicationReady() {
1077
+ this.ready || !C.isLoggedIn() || await this.setReady(!pe().some((e) => e.url.startsWith("solid://")));
1078
+ }
1079
+ async onApplicationMounted() {
1080
+ this.syncOnStartup() && await this.sync();
1081
+ }
1082
+ login(e) {
1083
+ const t = [...this.registeredModels].map(({ modelClass: n }) => Re(n)).flat().concat([W]);
1084
+ this.status = v.Online, this.engine = e.engine, z(j).setEngine(this.engine);
1085
+ for (const n of t)
1086
+ z(n).setEngine(this.engine);
1087
+ }
1088
+ logout() {
1089
+ this.setState({
1090
+ localModelUpdates: {},
1091
+ migrationDismissed: !1,
1092
+ migrationJob: null,
1093
+ migrationPostponed: !1,
1094
+ modelCollections: {},
1095
+ pollingEnabled: !0,
1096
+ pollingMinutes: 10,
1097
+ ready: !1,
1098
+ setupDismissed: !1,
1099
+ setupOngoing: !1,
1100
+ startupSync: !0,
1101
+ status: v.Disconnected
1102
+ });
1103
+ }
1104
+ syncOnStartup() {
1105
+ return Se("startupSync") ? De(ke("startupSync")) : this.migrationJob ? !1 : this.startupSync;
1106
+ }
1107
+ async bustDocumentsCache() {
1108
+ !Se("bustDocumentsCache") || !De(ke("bustDocumentsCache")) || (await P.booted, await P.clear());
1109
+ }
1110
+ async registerModels() {
1111
+ const e = xt();
1112
+ for (const t of e.values())
1113
+ !Rt(t) || !t.cloud || await this.register(t, typeof t.cloud == "boolean" ? {} : t.cloud);
1114
+ }
1115
+ }
1116
+ const I = we(un), hn = {
1117
+ viewBox: "0 0 20 20",
1118
+ width: "1.2em",
1119
+ height: "1.2em"
1120
+ };
1121
+ function fn(o, s) {
1122
+ return h(), M("svg", hn, s[0] || (s[0] = [
1123
+ f("path", {
1124
+ fill: "currentColor",
1125
+ d: "m6 2l2-2h4l2 2h4v2H2V2zM3 6h14l-1 14H4zm5 2v10h1V8zm3 0v10h1V8z"
1126
+ }, null, -1)
1127
+ ]));
1128
+ }
1129
+ const mn = O({ name: "zondicons-trash", render: fn }), He = /* @__PURE__ */ B({
1130
+ __name: "AccountLoginModal",
1131
+ setup(o) {
1132
+ return (s, e) => (h(), R(d(ze), {
1133
+ title: s.$td("cloud.logIn.title", "Connect account")
1134
+ }, {
1135
+ default: b(() => [
1136
+ u(d(T), {
1137
+ "lang-key": "cloud.logIn.info",
1138
+ "lang-default": "Log in to your [Solid account](https://solidproject.org) to keep data safe across devices."
1139
+ }),
1140
+ u(d(ue), {
1141
+ class: "text-sm",
1142
+ onClick: e[0] || (e[0] = (t) => s.$ui.alert(
1143
+ s.$td("cloud.logIn.learnMore", "What is Solid?"),
1144
+ s.$td(
1145
+ "cloud.logIn.learnMoreMessage",
1146
+ `Solid is a decentralized storage protocol built on top of web standards. If you want to use this app across devices, you can use Solid to keep changes in sync. Even if you use it in a single device, this will also keep your data secure in case your device is lost.
1147
+
1148
+ In any case, Focus works 100% offline and you can connect your Solid POD later on. If you've never heard of Solid and you're just trying things out, you can keep using it without an account.
1149
+
1150
+ [Learn more](https://solidproject.org)`
1151
+ )
1152
+ ))
1153
+ }, {
1154
+ default: b(() => [
1155
+ K(S(s.$td("cloud.logIn.learnMore", "What is Solid?")), 1)
1156
+ ]),
1157
+ _: 1
1158
+ }),
1159
+ u(d(vt), {
1160
+ "no-loading": "",
1161
+ class: "mt-4"
1162
+ })
1163
+ ]),
1164
+ _: 1
1165
+ }, 8, ["title"]));
1166
+ }
1167
+ }), gn = {
1168
+ key: 0,
1169
+ class: "mt-4"
1170
+ }, pn = { class: "text-base font-semibold" }, yn = { class: "ml-1" }, wn = /* @__PURE__ */ B({
1171
+ __name: "PurgeData",
1172
+ setup(o) {
1173
+ async function s() {
1174
+ await ae.confirm(
1175
+ $("settings.purgeConfirmTitle", "Delete everything?"),
1176
+ $(
1177
+ "settings.purgeConfirmMessage",
1178
+ "If you proceed, all your data will be deleted forever. If you want to save it before wiping this device, you can [connect to your Solid account](#action:connect) first."
1179
+ ),
1180
+ {
1181
+ acceptVariant: "danger",
1182
+ acceptText: $("settings.purgeConfirmAccept", "Purge data"),
1183
+ actions: { connect: () => ae.modal(He) }
1184
+ }
1185
+ ) && (await ae.closeAllModals(), await nt.purge());
1186
+ }
1187
+ return (e, t) => e.$solid.hasLoggedIn() ? _("", !0) : (h(), M("details", gn, [
1188
+ f("summary", null, [
1189
+ f("span", pn, S(e.$td("settings.dangerZone", "Danger zone")), 1)
1190
+ ]),
1191
+ u(d(q), {
1192
+ variant: "danger",
1193
+ class: "mt-4",
1194
+ onClick: t[0] || (t[0] = (n) => s())
1195
+ }, {
1196
+ default: b(() => [
1197
+ u(d(mn), { class: "size-4" }),
1198
+ f("span", yn, S(e.$td("settings.purge", "Purge data")), 1)
1199
+ ]),
1200
+ _: 1
1201
+ })
1202
+ ]));
1203
+ }
1204
+ }), Mn = st([
1205
+ {
1206
+ priority: 0,
1207
+ component: wn
1208
+ }
1209
+ ]), bn = {
1210
+ viewBox: "0 0 20 20",
1211
+ width: "1.2em",
1212
+ height: "1.2em"
1213
+ };
1214
+ function Cn(o, s) {
1215
+ return h(), M("svg", bn, s[0] || (s[0] = [
1216
+ f("path", {
1217
+ fill: "currentColor",
1218
+ d: "M2.93 17.07A10 10 0 1 1 17.07 2.93A10 10 0 0 1 2.93 17.07m12.73-1.41A8 8 0 1 0 4.34 4.34a8 8 0 0 0 11.32 11.32M6.7 9.29L9 11.6l4.3-4.3l1.4 1.42L9 14.4l-3.7-3.7l1.4-1.42z"
1219
+ }, null, -1)
1220
+ ]));
1221
+ }
1222
+ const vn = O({ name: "zondicons-checkmark-outline", render: Cn }), $n = {
1223
+ viewBox: "0 0 24 24",
1224
+ width: "1.2em",
1225
+ height: "1.2em"
1226
+ };
1227
+ function Sn(o, s) {
1228
+ return h(), M("svg", $n, s[0] || (s[0] = [
1229
+ f("path", {
1230
+ fill: "currentColor",
1231
+ d: "M19.35 10.04A7.49 7.49 0 0 0 12 4C9.11 4 6.6 5.64 5.35 8.04A5.994 5.994 0 0 0 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5c0-2.64-2.05-4.78-4.65-4.96M14 13v4h-4v-4H7l5-5l5 5z"
1232
+ }, null, -1)
1233
+ ]));
1234
+ }
1235
+ const Dn = O({ name: "ic-sharp-cloud-upload", render: Sn }), kn = {
1236
+ viewBox: "0 0 20 20",
1237
+ width: "1.2em",
1238
+ height: "1.2em"
1239
+ };
1240
+ function Rn(o, s) {
1241
+ return h(), M("svg", kn, s[0] || (s[0] = [
1242
+ f("path", {
1243
+ fill: "currentColor",
1244
+ d: "M3.94 6.5L2.22 3.64l1.42-1.42L6.5 3.94c.52-.3 1.1-.54 1.7-.7L9 0h2l.8 3.24c.6.16 1.18.4 1.7.7l2.86-1.72l1.42 1.42l-1.72 2.86c.3.52.54 1.1.7 1.7L20 9v2l-3.24.8c-.16.6-.4 1.18-.7 1.7l1.72 2.86l-1.42 1.42l-2.86-1.72c-.52.3-1.1.54-1.7.7L11 20H9l-.8-3.24c-.6-.16-1.18-.4-1.7-.7l-2.86 1.72l-1.42-1.42l1.72-2.86c-.3-.52-.54-1.1-.7-1.7L0 11V9l3.24-.8c.16-.6.4-1.18.7-1.7M10 13a3 3 0 1 0 0-6a3 3 0 0 0 0 6"
1245
+ }, null, -1)
1246
+ ]));
1247
+ }
1248
+ const Ke = O({ name: "zondicons-cog", render: Rn }), Ln = {
1249
+ viewBox: "0 0 24 24",
1250
+ width: "1.2em",
1251
+ height: "1.2em"
1252
+ };
1253
+ function Un(o, s) {
1254
+ return h(), M("svg", Ln, s[0] || (s[0] = [
1255
+ f("path", {
1256
+ fill: "currentColor",
1257
+ d: "M5 21q-.825 0-1.412-.587T3 19V5q0-.825.588-1.412T5 3h6q.425 0 .713.288T12 4t-.288.713T11 5H5v14h6q.425 0 .713.288T12 20t-.288.713T11 21zm12.175-8H10q-.425 0-.712-.288T9 12t.288-.712T10 11h7.175L15.3 9.125q-.275-.275-.275-.675t.275-.7t.7-.313t.725.288L20.3 11.3q.3.3.3.7t-.3.7l-3.575 3.575q-.3.3-.712.288t-.713-.313q-.275-.3-.262-.712t.287-.688z"
1258
+ }, null, -1)
1259
+ ]));
1260
+ }
1261
+ const An = O({ name: "material-symbols-logout-rounded", render: Un }), In = {
1262
+ viewBox: "0 0 20 20",
1263
+ width: "1.2em",
1264
+ height: "1.2em"
1265
+ };
1266
+ function zn(o, s) {
1267
+ return h(), M("svg", In, s[0] || (s[0] = [
1268
+ f("path", {
1269
+ fill: "currentColor",
1270
+ d: "M10 3v2a5 5 0 0 0-3.54 8.54l-1.41 1.41A7 7 0 0 1 10 3m4.95 2.05A7 7 0 0 1 10 17v-2a5 5 0 0 0 3.54-8.54zM10 20l-4-4l4-4zm0-12V0l4 4z"
1271
+ }, null, -1)
1272
+ ]));
1273
+ }
1274
+ const F = O({ name: "zondicons-refresh", render: zn }), En = {
1275
+ viewBox: "0 0 24 24",
1276
+ width: "1.2em",
1277
+ height: "1.2em"
1278
+ };
1279
+ function Tn(o, s) {
1280
+ return h(), M("svg", En, s[0] || (s[0] = [
1281
+ f("path", {
1282
+ fill: "currentColor",
1283
+ d: "M6 6h12v12H6z"
1284
+ }, null, -1)
1285
+ ]));
1286
+ }
1287
+ const qn = O({ name: "ic-baseline-stop", render: Tn }), Pn = {
1288
+ viewBox: "0 0 512 512",
1289
+ width: "1.2em",
1290
+ height: "1.2em"
1291
+ };
1292
+ function On(o, s) {
1293
+ return h(), M("svg", Pn, s[0] || (s[0] = [
1294
+ f("path", {
1295
+ fill: "currentColor",
1296
+ d: "M449.07 399.08L278.64 82.58c-12.08-22.44-44.26-22.44-56.35 0L51.87 399.08A32 32 0 0 0 80 446.25h340.89a32 32 0 0 0 28.18-47.17m-198.6-1.83a20 20 0 1 1 20-20a20 20 0 0 1-20 20m21.72-201.15l-5.74 122a16 16 0 0 1-32 0l-5.74-121.95a21.73 21.73 0 0 1 21.5-22.69h.21a21.74 21.74 0 0 1 21.73 22.7Z"
1297
+ }, null, -1)
1298
+ ]));
1299
+ }
1300
+ const H = O({ name: "ion-warning", render: On }), _n = { class: "relative flex items-center rounded-md bg-gray-100 p-4 pr-12" }, xn = { class: "flex flex-col overflow-hidden" }, Jn = { class: "font-semibold" }, Nn = { class: "px-2" }, Wn = {
1301
+ key: 0,
1302
+ class: "mt-4 flex items-center gap-2"
1303
+ }, jn = { class: "flex w-full flex-col" }, Bn = {
1304
+ key: 1,
1305
+ class: "mt-4 flex items-center gap-2"
1306
+ }, Vn = {
1307
+ key: 2,
1308
+ class: "mt-4 flex items-center gap-2"
1309
+ }, Fn = {
1310
+ key: 3,
1311
+ class: "mt-4 flex items-center gap-2"
1312
+ }, Hn = {
1313
+ key: 4,
1314
+ class: "mt-4 flex items-center gap-2"
1315
+ }, Kn = {
1316
+ key: 5,
1317
+ class: "mt-4 flex items-center gap-2"
1318
+ }, Yn = {
1319
+ key: 6,
1320
+ class: "mt-4 flex items-center gap-2"
1321
+ }, Qn = { class: "flex flex-col gap-2" }, Zn = { class: "flex items-center" }, Gn = { "aria-hidden": "true" }, Xn = {
1322
+ key: 0,
1323
+ "aria-hidden": "true"
1324
+ }, es = {
1325
+ key: 0,
1326
+ class: "mt-4 flex flex-row-reverse justify-start gap-2"
1327
+ }, ts = /* @__PURE__ */ B({
1328
+ __name: "AccountModal",
1329
+ setup(o) {
1330
+ const s = It("$modalRef"), e = zt(!1), t = $("cloud.advanced.polling", "Synchronize every {minutes} minutes", {
1331
+ minutes: "%%separator%%"
1332
+ }).split("%%separator%%"), n = Y(() => C.error ?? I.syncError), i = Y(() => {
1333
+ if (n.value)
1334
+ return typeof n.value == "string" ? n.value : $("cloud.info.error", "There has been an error connecting.");
1335
+ }), l = Y(() => n.value && typeof n.value != "string");
1336
+ async function a() {
1337
+ I.syncJob && (e.value = !0, await Promise.race([I.syncJob.cancel(), I.syncJob.completed]), e.value = !1);
1338
+ }
1339
+ return ot("auth:logout", () => {
1340
+ var r;
1341
+ return (r = s.value) == null ? void 0 : r.close();
1342
+ }), (r, c) => (h(), R(d(ze), {
1343
+ ref: "$modalRef",
1344
+ "title-hidden": "",
1345
+ "close-hidden": "",
1346
+ title: r.$td("account.title", "Account")
1347
+ }, {
1348
+ default: b(() => {
1349
+ var p, m;
1350
+ return [
1351
+ f("div", _n, [
1352
+ u(d(_e), { class: "mr-2 size-16 shrink-0" }),
1353
+ f("div", xn, [
1354
+ f("span", Jn, S(((p = r.$solid.user) == null ? void 0 : p.name) ?? r.$td("user.anonymous", "Anonymous")), 1),
1355
+ u(d(ue), {
1356
+ href: (m = r.$solid.user) == null ? void 0 : m.webId,
1357
+ class: "mt-0.5 truncate text-sm font-light text-gray-500"
1358
+ }, {
1359
+ default: b(() => {
1360
+ var g;
1361
+ return [
1362
+ K(S((g = r.$solid.user) == null ? void 0 : g.webId), 1)
1363
+ ];
1364
+ }),
1365
+ _: 1
1366
+ }, 8, ["href"])
1367
+ ]),
1368
+ u(d(q), {
1369
+ size: "icon",
1370
+ variant: "ghost",
1371
+ class: "absolute top-1 right-1 hover:bg-gray-200",
1372
+ "aria-label": r.$td("user.settings", "Settings"),
1373
+ title: r.$td("user.settings", "Settings"),
1374
+ onClick: c[0] || (c[0] = (g) => r.$ui.modal(d(Ee)))
1375
+ }, {
1376
+ default: b(() => [
1377
+ u(d(Ke), { class: "size-5" })
1378
+ ]),
1379
+ _: 1
1380
+ }, 8, ["aria-label", "title"])
1381
+ ]),
1382
+ f("div", Nn, [
1383
+ r.$cloud.syncing ? (h(), M("div", Wn, [
1384
+ u(d(F), { class: "mt-0.5 size-6 shrink-0 animate-spin self-start text-green-500" }),
1385
+ f("div", jn, [
1386
+ u(d(T), {
1387
+ "lang-key": "cloud.info.syncing",
1388
+ "lang-default": "Synchronizing..."
1389
+ }),
1390
+ r.$cloud.syncJob ? (h(), R(d(it), {
1391
+ key: 0,
1392
+ job: r.$cloud.syncJob,
1393
+ "filled-class": "bg-green-500"
1394
+ }, null, 8, ["job"])) : _("", !0)
1395
+ ])
1396
+ ])) : r.$solid.loginOngoing ? (h(), M("div", Bn, [
1397
+ u(d(F), { class: "mt-0.5 size-6 shrink-0 animate-spin self-start text-green-500" }),
1398
+ u(d(T), {
1399
+ "lang-key": "cloud.info.reconnecting",
1400
+ "lang-default": "Reconnecting..."
1401
+ })
1402
+ ])) : n.value ? (h(), M("div", Vn, [
1403
+ u(d(H), { class: "mt-0.5 size-6 shrink-0 self-start text-red-500" }),
1404
+ f("div", null, [
1405
+ u(d(T), { text: i.value }, null, 8, ["text"]),
1406
+ l.value ? (h(), R(d(ue), {
1407
+ key: 0,
1408
+ class: "text-sm text-red-700 opacity-50 hover:opacity-75 focus-visible:opacity-75",
1409
+ onClick: c[1] || (c[1] = (g) => r.$errors.inspect(n.value))
1410
+ }, {
1411
+ default: b(() => [
1412
+ K(S(r.$td("errors.viewDetails", "View details")), 1)
1413
+ ]),
1414
+ _: 1
1415
+ })) : _("", !0)
1416
+ ])
1417
+ ])) : r.$cloud.ready ? r.$cloud.dirty ? (h(), M("div", Hn, [
1418
+ u(d(H), { class: "mt-0.5 size-6 shrink-0 self-start text-yellow-500" }),
1419
+ u(d(T), {
1420
+ "lang-key": "cloud.info.changes",
1421
+ "lang-default": "Everything is up to date. | There is one local change. | There are {n} local changes.",
1422
+ "lang-params": r.$cloud.localChanges
1423
+ }, null, 8, ["lang-params"])
1424
+ ])) : r.$cloud.online ? (h(), M("div", Kn, [
1425
+ u(d(vn), { class: "mt-0.5 size-6 shrink-0 self-start text-green-500" }),
1426
+ u(d(T), {
1427
+ "lang-key": "cloud.info.changes",
1428
+ "lang-default": "Everything is up to date.",
1429
+ "lang-params": 0
1430
+ })
1431
+ ])) : (h(), M("div", Yn, [
1432
+ u(d(H), { class: "mt-0.5 size-6 shrink-0 self-start text-yellow-500" }),
1433
+ u(d(T), {
1434
+ "lang-key": "cloud.info.disconnected",
1435
+ "lang-default": "You are disconnected from your Solid account, all the changes you make will remain in your device."
1436
+ })
1437
+ ])) : (h(), M("div", Fn, [
1438
+ u(d(H), { class: "mt-0.5 size-6 shrink-0 self-start text-yellow-500" }),
1439
+ u(d(T), {
1440
+ "lang-key": "cloud.info.setup",
1441
+ "lang-default": "Your data is not backed up yet."
1442
+ })
1443
+ ])),
1444
+ u(d(rt), { class: "mt-2" }, {
1445
+ default: b(() => [
1446
+ f("ul", Qn, [
1447
+ f("li", null, [
1448
+ u(d(le), {
1449
+ modelValue: r.$solid.autoReconnect,
1450
+ "onUpdate:modelValue": c[2] || (c[2] = (g) => r.$solid.autoReconnect = g),
1451
+ "label-class": "text-base",
1452
+ label: r.$td("cloud.advanced.reconnect", "Reconnect on startup")
1453
+ }, null, 8, ["modelValue", "label"])
1454
+ ]),
1455
+ f("li", null, [
1456
+ u(d(le), {
1457
+ modelValue: r.$cloud.startupSync,
1458
+ "onUpdate:modelValue": c[3] || (c[3] = (g) => r.$cloud.startupSync = g),
1459
+ "label-class": "text-base",
1460
+ label: r.$td("cloud.advanced.startupSync", "Synchronize on startup")
1461
+ }, null, 8, ["modelValue", "label"])
1462
+ ]),
1463
+ f("li", null, [
1464
+ u(d(le), {
1465
+ modelValue: r.$cloud.pollingEnabled,
1466
+ "onUpdate:modelValue": c[5] || (c[5] = (g) => r.$cloud.pollingEnabled = g),
1467
+ "label-class": "text-base"
1468
+ }, {
1469
+ default: b(() => [
1470
+ f("div", Zn, [
1471
+ f("span", Gn, S(d(t)[0]), 1),
1472
+ u(d(at), {
1473
+ type: "number",
1474
+ text: `${r.$cloud.pollingMinutes}`,
1475
+ "aria-label": r.$td("cloud.advanced.pollingMinutes", "Synchronization interval (in minutes)"),
1476
+ class: "focus-within:border-primary-600 mx-1 -mb-px border-b",
1477
+ onUpdate: c[4] || (c[4] = (g) => r.$cloud.pollingMinutes = g)
1478
+ }, {
1479
+ default: b(() => [
1480
+ K(S(r.$cloud.pollingMinutes), 1)
1481
+ ]),
1482
+ _: 1
1483
+ }, 8, ["text", "aria-label"]),
1484
+ d(t).length > 1 ? (h(), M("span", Xn, S(d(t)[1]), 1)) : _("", !0)
1485
+ ])
1486
+ ]),
1487
+ _: 1
1488
+ }, 8, ["modelValue"])
1489
+ ])
1490
+ ])
1491
+ ]),
1492
+ _: 1
1493
+ })
1494
+ ]),
1495
+ r.$solid.loginOngoing ? _("", !0) : (h(), M("div", es, [
1496
+ r.$cloud.syncing ? (h(), R(d(q), {
1497
+ key: 0,
1498
+ variant: "secondary",
1499
+ disabled: e.value,
1500
+ onClick: c[6] || (c[6] = (g) => a())
1501
+ }, {
1502
+ default: b(() => [
1503
+ u(d(qn), { class: "size-5" }),
1504
+ f("span", null, S(e.value ? r.$td("cloud.stopping", "Stopping...") : r.$td("cloud.stop", "Stop synchronization")), 1)
1505
+ ]),
1506
+ _: 1
1507
+ }, 8, ["disabled"])) : r.$solid.isLoggedIn() ? r.$cloud.ready ? (h(), R(d(q), {
1508
+ key: 2,
1509
+ onClick: c[8] || (c[8] = (g) => r.$cloud.sync({ refreshUserProfile: !0 }))
1510
+ }, {
1511
+ default: b(() => [
1512
+ u(d(F), { class: "size-5" }),
1513
+ f("span", null, S(r.$td("cloud.sync", "Synchronize")), 1)
1514
+ ]),
1515
+ _: 1
1516
+ })) : (h(), R(d(q), {
1517
+ key: 3,
1518
+ onClick: c[9] || (c[9] = (g) => {
1519
+ var J;
1520
+ return r.$cloud.setupDismissed = !1, (J = d(s)) == null ? void 0 : J.close();
1521
+ })
1522
+ }, {
1523
+ default: b(() => [
1524
+ u(d(Dn), { class: "size-5" }),
1525
+ f("span", null, S(r.$td("cloud.setup.submit", "Back up now")), 1)
1526
+ ]),
1527
+ _: 1
1528
+ })) : (h(), R(d(q), {
1529
+ key: 1,
1530
+ onClick: c[7] || (c[7] = (g) => r.$solid.reconnect({ force: !0 }))
1531
+ }, {
1532
+ default: b(() => [
1533
+ u(d(F), { class: "size-5" }),
1534
+ f("span", null, S(r.$td("cloud.reconnect", "Reconnect")), 1)
1535
+ ]),
1536
+ _: 1
1537
+ })),
1538
+ r.$cloud.syncing ? _("", !0) : (h(), R(d(q), {
1539
+ key: 4,
1540
+ variant: "secondary",
1541
+ onClick: c[10] || (c[10] = (g) => r.$solid.logout())
1542
+ }, {
1543
+ default: b(() => [
1544
+ u(d(An), { class: "size-5" }),
1545
+ f("span", null, S(r.$cloud.ready ? r.$td("cloud.logOut", "Log out") : r.$td("cloud.disconnect", "Disconnect")), 1)
1546
+ ]),
1547
+ _: 1
1548
+ }))
1549
+ ]))
1550
+ ];
1551
+ }),
1552
+ _: 1
1553
+ }, 8, ["title"]));
1554
+ }
1555
+ }), ns = { class: "relative size-12" }, ss = ["aria-label", "title"], os = {
1556
+ key: 0,
1557
+ class: "absolute -inset-1 animate-spin rounded-full border-2 border-[currentColor_transparent] text-green-500"
1558
+ }, is = { class: "sr-only" }, rs = /* @__PURE__ */ B({
1559
+ __name: "AccountLoggedIn",
1560
+ setup(o) {
1561
+ const s = Y(() => I.syncing || C.loginOngoing ? {
1562
+ loading: !0,
1563
+ classes: "bg-green-500 sr-only",
1564
+ message: e() ?? ""
1565
+ } : C.error || I.syncError ? {
1566
+ classes: "bg-red-500",
1567
+ message: $("account.error", "There has been an error connecting with your account.")
1568
+ } : !C.isLoggedIn() || I.dirty || !I.ready ? {
1569
+ classes: "bg-yellow-500",
1570
+ message: $(
1571
+ "account.dirty",
1572
+ "There are local changes that haven't been synchronized yet."
1573
+ )
1574
+ } : {
1575
+ classes: "bg-green-500",
1576
+ message: e() ?? ""
1577
+ });
1578
+ function e() {
1579
+ switch (I.status) {
1580
+ case v.Syncing:
1581
+ return $("cloud.status.syncing", "Synchronization in progress");
1582
+ case v.Migrating:
1583
+ return $("cloud.status.migrating", "Migration in progress");
1584
+ case v.Online:
1585
+ return $("cloud.status.online", "Online");
1586
+ case v.Disconnected:
1587
+ return $("cloud.status.disconnected", "Disconnected");
1588
+ }
1589
+ }
1590
+ return (t, n) => (h(), M("div", ns, [
1591
+ f("button", {
1592
+ class: "clickable focus-visible:outline-primary-600 flex size-full rounded-full focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2",
1593
+ type: "button",
1594
+ "aria-label": t.$td("account.open", "Open account"),
1595
+ title: t.$td("account.open", "Open account"),
1596
+ onClick: n[0] || (n[0] = (i) => t.$ui.modal(ts))
1597
+ }, [
1598
+ u(d(_e), { class: "size-full" }),
1599
+ s.value.loading ? (h(), M("div", os)) : _("", !0)
1600
+ ], 8, ss),
1601
+ f("div", {
1602
+ class: Et(["pointer-events-none absolute right-0 bottom-0 size-3 rounded-full border-2 border-white", s.value.classes])
1603
+ }, [
1604
+ f("span", is, S(s.value.message), 1)
1605
+ ], 2)
1606
+ ]));
1607
+ }
1608
+ }), as = /* @__PURE__ */ B({
1609
+ __name: "AccountLoggedOut",
1610
+ setup(o) {
1611
+ return (s, e) => (h(), R(d(lt), {
1612
+ align: "start",
1613
+ options: [
1614
+ { label: s.$td("user.logIn", "Connect account"), click: () => s.$ui.modal(He) },
1615
+ { label: s.$td("user.settings", "Settings"), click: () => s.$ui.modal(d(Ee)) }
1616
+ ]
1617
+ }, {
1618
+ default: b(() => [
1619
+ u(d(q), {
1620
+ size: "icon",
1621
+ variant: "ghost",
1622
+ "aria-label": s.$td("user.menu", "Configuration"),
1623
+ title: s.$td("user.menu", "Configuration")
1624
+ }, {
1625
+ default: b(() => [
1626
+ u(d(Ke), { class: "size-5" })
1627
+ ]),
1628
+ _: 1
1629
+ }, 8, ["aria-label", "title"])
1630
+ ]),
1631
+ _: 1
1632
+ }, 8, ["options"]));
1633
+ }
1634
+ }), Ms = /* @__PURE__ */ B({
1635
+ __name: "Account",
1636
+ setup(o) {
1637
+ return (s, e) => s.$solid.hasLoggedIn() ? (h(), R(rs, { key: 0 })) : (h(), R(as, { key: 1 }));
1638
+ }
1639
+ }), ls = { $cloud: I };
1640
+ function bs() {
1641
+ return {
1642
+ name: "@aerogel/local-first",
1643
+ async install(o) {
1644
+ Mn.forEach((s) => se.addSetting(s)), await ct(o, {
1645
+ ...ls,
1646
+ $_documentsCache: P
1647
+ });
1648
+ }
1649
+ };
1650
+ }
1651
+ export {
1652
+ Ms as Account,
1653
+ rs as AccountLoggedIn,
1654
+ as as AccountLoggedOut,
1655
+ He as AccountLoginModal,
1656
+ ts as AccountModal,
1657
+ I as Cloud,
1658
+ un as CloudService,
1659
+ bs as default
1660
+ };
1661
+ //# sourceMappingURL=aerogel-plugin-local-first.js.map