@aerogel/plugin-local-first 0.0.0-next.0d1cf82f9dfbe1d3e7ec5644f85f97a43c8c2334

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,1098 @@
1
+ var ke = Object.defineProperty;
2
+ var Ee = (s, i, e) => i in s ? ke(s, i, { enumerable: !0, configurable: !0, writable: !0, value: e }) : s[i] = e;
3
+ var h = (s, i, e) => Ee(s, typeof i != "symbol" ? i + "" : i, e);
4
+ import { App as Z, Job as ee, Service as qe, Events as m, defineServiceState as xe, replaceExisting as oe, translateWithDefault as U, dispatch as F, Errors as re, AGMarkdown as ae, AGButton as ce, bootServices as Oe } from "@aerogel/core";
5
+ import { arrayFilter as Te, isInstanceOf as S, facade as te, after as q, arrayRemove as $e, required as M, tap as we, toString as Je, urlRoute as Ne, urlResolveDirectory as ze, objectWithout as Fe, requireUrlParentDirectory as x, fail as Me, IndexedDBMap as We, arrayFrom as je, map as b, arrayChunk as Ke, mixed as Ce, objectMap as Be, round as He, Semaphore as _e, isArray as Ge, isTesting as le, hasLocationQueryParameter as Qe, parseBoolean as Ye, getLocationQueryParameter as Ve } from "@noeldemartin/utils";
6
+ import { Solid as g, AGSolidStatus as Xe } from "@aerogel/plugin-solid";
7
+ import { SolidModel as L, SolidContainsRelation as be, isContainerClass as A, SolidContainer as J, SolidACLAuthorization as Ze, SolidDocument as et, Metadata as tt, Operation as nt, isContainer as R, Tombstone as v, PropertyOperation as O } from "soukai-solid";
8
+ import { getTrackedModels as ne, trackModelsCollection as T, ignoreModelsCollection as st, trackModels as it } from "@aerogel/plugin-soukai";
9
+ import { watchEffect as ot, defineComponent as rt, createBlock as de, openBlock as W, unref as I, withCtx as j, createElementBlock as at, createVNode as K, createTextVNode as ue, toDisplayString as he } from "vue";
10
+ import { bootModels as ct, requireEngine as lt, DocumentNotFound as dt } from "soukai";
11
+ import { MalformedSolidDocumentError as Re } from "@noeldemartin/solid-utils";
12
+ const B = /* @__PURE__ */ new WeakMap();
13
+ function _(s) {
14
+ return Te(
15
+ y(s).map((i) => {
16
+ const e = s.instance().requireRelation(i).relatedClass;
17
+ return A(e) ? !1 : e;
18
+ })
19
+ );
20
+ }
21
+ function y(s) {
22
+ return B.has(s) || B.set(
23
+ s,
24
+ s.relations.filter((i) => L.reservedRelations.includes(i) ? !1 : s.instance().requireRelation(i) instanceof be)
25
+ ), B.get(s) ?? [];
26
+ }
27
+ function Se(s) {
28
+ return y(s.static()).reduce(
29
+ (e, t) => e.concat(s.getRelationModels(t) ?? []),
30
+ []
31
+ );
32
+ }
33
+ function fe(s) {
34
+ const i = /* @__PURE__ */ new Set(), e = s.instance();
35
+ i.add(s);
36
+ for (const t of s.relations)
37
+ s.reservedRelations.includes(t) || i.add(e.requireRelation(t).relatedClass);
38
+ return [...i.values()];
39
+ }
40
+ function G(s) {
41
+ return s.getRelatedModels().filter(
42
+ (i) => !S(i, Ze) && !S(i, et) && !S(i, tt) && !S(i, nt) && i.static() !== J
43
+ );
44
+ }
45
+ function De(s) {
46
+ if (s.isDirty())
47
+ return !0;
48
+ if (!(s instanceof J))
49
+ return !1;
50
+ const i = (e) => {
51
+ var t;
52
+ return (t = s.getRelationModels(e)) == null ? void 0 : t.some((n) => De(n));
53
+ };
54
+ return y(s.static()).some(i);
55
+ }
56
+ const ut = M(() => Z.service("$cloud"));
57
+ class ht {
58
+ constructor() {
59
+ h(this, "models", /* @__PURE__ */ new Set());
60
+ h(this, "promises", []);
61
+ }
62
+ push(i) {
63
+ this.models.add(i), this.syncAfter(q({ seconds: 1 }));
64
+ }
65
+ clear(i) {
66
+ if (!i) {
67
+ this.models = /* @__PURE__ */ new Set();
68
+ return;
69
+ }
70
+ for (const e of i)
71
+ this.models.delete(e);
72
+ }
73
+ async syncAfter(i) {
74
+ const e = typeof i == "function" ? i() : i;
75
+ return this.promises.push(e), e.then(() => $e(this.promises, e)), this.promises.length === 1 && this.schedule(), e;
76
+ }
77
+ schedule() {
78
+ Promise.all(this.promises).then(() => q()).then(() => {
79
+ if (this.promises.length !== 0) {
80
+ this.schedule();
81
+ return;
82
+ }
83
+ const i = this.consume();
84
+ i.length !== 0 && ut.syncIfOnline(i);
85
+ });
86
+ }
87
+ consume() {
88
+ const i = [], e = /* @__PURE__ */ new Set();
89
+ for (const t of this.models)
90
+ R(t) && (this.models.delete(t), Se(t).forEach((n) => e.add(n)), i.push(t));
91
+ for (const t of this.models)
92
+ this.models.delete(t), !e.has(t) && i.push(t);
93
+ return i;
94
+ }
95
+ }
96
+ const $ = te(ht), d = M(() => Z.service("$cloud")), Ue = /* @__PURE__ */ new WeakMap(), se = /* @__PURE__ */ new WeakMap();
97
+ function ft(s) {
98
+ const i = s.getRelatedModels().concat([s]);
99
+ for (const e of i)
100
+ e.cleanDirty(!0);
101
+ }
102
+ function mt(s) {
103
+ const i = G(s).concat([s]);
104
+ for (const e of i) {
105
+ if (!e.operations || e.operations.length === 0)
106
+ continue;
107
+ const t = (e.operations ?? []).filter((n) => !(n instanceof O) || !e.ignoreRdfPropertyHistory(n.property, !0));
108
+ if (!t.some((n) => !n.isInception(e))) {
109
+ e.setRelationModels("operations", []);
110
+ continue;
111
+ }
112
+ e.setRelationModels("operations", t);
113
+ }
114
+ }
115
+ async function me(s) {
116
+ d.setState({
117
+ localModelUpdates: {
118
+ ...d.localModelUpdates,
119
+ [s.url]: 1
120
+ }
121
+ }), Rt(s.static()) && await Q(s.static(), x(s.url)), d.autoPush && d.ready && !d.syncing && $.push(s);
122
+ }
123
+ async function Q(s, i) {
124
+ var e;
125
+ (e = d.modelCollections[s.modelName]) != null && e.includes(i) || (d.setState("modelCollections", {
126
+ ...d.modelCollections,
127
+ [s.modelName]: (d.modelCollections[s.modelName] ?? []).concat(i)
128
+ }), await T(s, i));
129
+ }
130
+ async function ge(s) {
131
+ if (gt(s))
132
+ return;
133
+ const i = d.localModelUpdates[s.url] ?? 0;
134
+ d.setState({
135
+ localModelUpdates: s.isSoftDeleted() ? Fe(d.localModelUpdates, s.url) : {
136
+ ...d.localModelUpdates,
137
+ [s.url]: i + 1
138
+ }
139
+ }), d.autoPush && d.ready && !d.syncing && $.push(s);
140
+ }
141
+ function Y(s, i) {
142
+ const e = s == null ? void 0 : s.map((n) => Je(n.getDeletedPrimaryKey() ?? n.getPrimaryKey())), t = {};
143
+ for (const [n, o] of Object.entries(d.localModelUpdates)) {
144
+ const r = Ne(n);
145
+ (!e || e.some(
146
+ (c) => n === c || c.endsWith("/") && n.startsWith(c)
147
+ )) && !(i != null && i.has(r)) || (t[n] = o);
148
+ }
149
+ d.setState({ localModelUpdates: t });
150
+ }
151
+ function ie(s, i = {}) {
152
+ const e = /* @__PURE__ */ new Set();
153
+ if (e.add(s.static()), s instanceof J)
154
+ for (const n of y(s.static()))
155
+ e.add(s.requireRelation(n).relatedClass);
156
+ const t = [...e.values()].map(
157
+ (n) => [n, D(n)]
158
+ );
159
+ return we(s.clone({ constructors: t }), (n) => {
160
+ mt(n), i.clean && ft(n);
161
+ });
162
+ }
163
+ function Le(s) {
164
+ const i = /* @__PURE__ */ new Set();
165
+ if (i.add(s.static()), s instanceof J)
166
+ for (const t of y(s.static()))
167
+ i.add(s.requireRelation(t).relatedClass);
168
+ const e = [...i.values()].map(
169
+ (t) => [t, Dt(t)]
170
+ );
171
+ return s.clone({ constructors: e });
172
+ }
173
+ async function pe(s, i, e) {
174
+ const t = D(v), n = i.map((a) => a.url), o = s.filter((a) => !n.includes(a.url)).map((a) => a.requireDocumentUrl()).filter((a) => !e.has(a)), r = await t.all({ $in: o });
175
+ return i.concat(r);
176
+ }
177
+ function gt(s) {
178
+ var e;
179
+ const i = (e = s.metadata.updatedAt) == null ? void 0 : e.getTime();
180
+ return !s.operations.some((t) => t.date.getTime() !== i ? !1 : t instanceof O ? !s.ignoreRdfPropertyHistory(t.property, !0) : !0);
181
+ }
182
+ function pt(s, i) {
183
+ return i.get(s.url) ?? Le(s);
184
+ }
185
+ function V() {
186
+ return [...d.registeredModels].map(({ modelClass: s }) => ne(s)).flat();
187
+ }
188
+ function yt() {
189
+ return d.schemaMigrations;
190
+ }
191
+ function wt() {
192
+ d.schemaMigrations.clear();
193
+ }
194
+ function ye(s) {
195
+ return d.schemaMigrations.get(s);
196
+ }
197
+ function D(s) {
198
+ return Ue.get(s) ?? St(s);
199
+ }
200
+ function H(s) {
201
+ const i = g.requireUser().storageUrls[0];
202
+ return s ? ze((s.startsWith("/") ? i.slice(0, -1) : i) + s) : i;
203
+ }
204
+ function Mt(s, i) {
205
+ return i.get(s.url) ?? ie(s);
206
+ }
207
+ function Ct(s) {
208
+ for (const { modelClass: i } of d.registeredModels)
209
+ if (ne(i).some((t) => t.url === s.url))
210
+ return !0;
211
+ return !1;
212
+ }
213
+ function X(s) {
214
+ return se.has(s.static());
215
+ }
216
+ function bt(s) {
217
+ return !X(s);
218
+ }
219
+ function Rt(s) {
220
+ return d.registeredModels.some(({ modelClass: i }) => i === s);
221
+ }
222
+ function St(s) {
223
+ var n;
224
+ const i = s, e = (o, r) => {
225
+ o.timestamps = i.timestamps, o.history = i.history, r(), o.timestamps = [], o.history = !1;
226
+ }, t = (n = class extends i {
227
+ initialize(o, r) {
228
+ e(this._proxy.static(), () => super.initialize(o, r));
229
+ }
230
+ initializeRelations() {
231
+ super.initializeRelations();
232
+ for (const o of Object.values(this._relations))
233
+ o instanceof be && (o.relatedClass = D(o.relatedClass));
234
+ }
235
+ fixMalformedAttributes() {
236
+ e(this.static(), () => super.fixMalformedAttributes());
237
+ }
238
+ }, h(n, "timestamps", !1), h(n, "history", !1), n);
239
+ return Ue.set(i, t), se.set(t, i), i.on("schema-updated", async (o) => {
240
+ await t.updateSchema({
241
+ ...o,
242
+ timestamps: !1,
243
+ history: !1
244
+ });
245
+ }), ct({ [`Remote${s.modelName}`]: t }), t;
246
+ }
247
+ function Dt(s) {
248
+ return se.get(s) ?? Me(`Couldn't find local class for ${s.modelName}`);
249
+ }
250
+ class Ut extends ee {
251
+ constructor() {
252
+ super(...arguments);
253
+ h(this, "urlMigrations", []);
254
+ h(this, "collectionMigrations", []);
255
+ }
256
+ migrateUrl(e, t, n) {
257
+ this.urlMigrations.push({
258
+ modelClass: e,
259
+ local: t,
260
+ remote: n
261
+ });
262
+ }
263
+ migrateCollection(e, t, n) {
264
+ this.collectionMigrations.push({
265
+ modelClass: e,
266
+ local: t,
267
+ remote: n
268
+ });
269
+ }
270
+ async run() {
271
+ const e = lt(), t = await e.getCollections();
272
+ for (const n of t) {
273
+ const o = await e.readMany(n);
274
+ for (const [r, a] of Object.entries(o)) {
275
+ const c = this.replaceUrl(r);
276
+ await e.create(x(c), this.replaceDocumentUrls(a), c), await e.delete(n, r);
277
+ }
278
+ }
279
+ for (const { modelClass: n, remote: o } of this.urlMigrations)
280
+ T(n, x(o), { refresh: !1 });
281
+ for (const { modelClass: n, local: o, remote: r } of this.collectionMigrations)
282
+ st(n, o), T(n, r, { refresh: !1 });
283
+ }
284
+ replaceDocumentUrls(e) {
285
+ for (const [t, n] of Object.entries(e)) {
286
+ if (t === "@id" && typeof n == "string") {
287
+ e[t] = this.replaceUrl(n);
288
+ continue;
289
+ }
290
+ typeof n != "object" || n === null || (e[t] = this.replaceDocumentUrls(n));
291
+ }
292
+ return e;
293
+ }
294
+ replaceUrl(e) {
295
+ for (const { local: t, remote: n } of this.urlMigrations)
296
+ if (e.startsWith(t))
297
+ return e.replace(t, n);
298
+ for (const { local: t, remote: n } of this.collectionMigrations)
299
+ if (e.startsWith(t))
300
+ return e.replace(t, n);
301
+ return e;
302
+ }
303
+ }
304
+ class Lt extends qe {
305
+ constructor() {
306
+ super(...arguments);
307
+ h(this, "cache", new We("documents-cache"));
308
+ }
309
+ async isFresh(e, t) {
310
+ const n = await this.cache.get(e), o = typeof t != "number" ? t.getTime() : t;
311
+ return !!(n != null && n.modifiedAt) && n.modifiedAt >= o;
312
+ }
313
+ async remember(e, t) {
314
+ await this.cache.set(e, {
315
+ modifiedAt: typeof t != "number" ? t.getTime() : t
316
+ });
317
+ }
318
+ async forget(e) {
319
+ await this.cache.delete(e);
320
+ }
321
+ async boot() {
322
+ m.on("auth:logout", async () => {
323
+ await this.cache.clear(), this.cache.close();
324
+ });
325
+ }
326
+ }
327
+ const k = te(Lt);
328
+ function At(s) {
329
+ const i = {};
330
+ return async () => ("value" in i || (i.value = await s()), i.value);
331
+ }
332
+ class Ae {
333
+ async loadContainedModels(i, e = {}) {
334
+ var u;
335
+ if (bt(i)) {
336
+ const f = [];
337
+ for (const w of y(i.static())) {
338
+ const C = await i.loadRelationIfUnloaded(w) ?? [];
339
+ f.push(...je(C));
340
+ }
341
+ return f;
342
+ }
343
+ const t = {}, n = [], o = b(i.documents, "url"), r = Ke(i.resourceUrls, 10), a = r.flat().map((f) => ({
344
+ documentUrl: f,
345
+ completed: !1
346
+ })), c = b(a, "documentUrl");
347
+ e.status && (e.status.children = a);
348
+ for (const f of r) {
349
+ await Promise.all(
350
+ f.map(async (w) => {
351
+ const { children: C, tombstones: E } = await this.loadDocumentChildren(i, w, o, e.onMalformedDocument);
352
+ n.push(...E);
353
+ for (const [z, Pe] of Object.entries(C))
354
+ (t[z] ?? (t[z] = [])).push(...Pe);
355
+ })
356
+ );
357
+ for (const w of f)
358
+ w.endsWith("/") || (M(c.get(w)).completed = !0);
359
+ await ((u = e.onLoaded) == null ? void 0 : u.call(e, f));
360
+ }
361
+ for (const [f, w] of Object.entries(t))
362
+ i.setRelationModels(f, w);
363
+ const l = e.ignoreTombstones ? Object.values(t).flat() : Object.values(t).flat().concat(n);
364
+ return e.status && (e.status.children = l.map((f) => M(c.get(f.requireDocumentUrl())))), l;
365
+ }
366
+ async loadDocumentChildren(i, e, t, n) {
367
+ var r;
368
+ const o = t.get(e);
369
+ return o && await k.isFresh(o.url, o.updatedAt ?? /* @__PURE__ */ new Date()) && ((r = this.localModels) != null && r.hasKey(i.url)) ? {
370
+ children: await this.loadDocumentChildrenFromLocal(i, o),
371
+ tombstones: []
372
+ } : this.loadDocumentChildrenFromRemote(i, e, n);
373
+ }
374
+ async loadDocumentChildrenFromLocal(i, e) {
375
+ var n, o;
376
+ const t = {};
377
+ for (const r of y(i.static())) {
378
+ const a = i.requireRelation(r);
379
+ if (a.loaded) {
380
+ t[r] = a.getLoadedModels();
381
+ continue;
382
+ }
383
+ const c = ((o = (n = this.localModels) == null ? void 0 : n.get(i.url)) == null ? void 0 : o.getRelationModels(r)) ?? [];
384
+ t[r] = c.filter((l) => l.getDocumentUrl() === e.url).map((l) => ie(l, { clean: !0 }));
385
+ }
386
+ return t;
387
+ }
388
+ async loadDocumentChildrenFromRemote(i, e, t) {
389
+ const n = {}, o = [], r = At(async () => {
390
+ try {
391
+ const a = await i.requireEngine().readOne(i.static("collection"), e), c = await v.createManyFromEngineDocuments({
392
+ [e]: a
393
+ });
394
+ return o.push(...c), a;
395
+ } catch (a) {
396
+ if (S(a, dt))
397
+ return null;
398
+ if (S(a, Re))
399
+ return console.warn(a.message), await (t == null ? void 0 : t(e)), null;
400
+ throw a;
401
+ }
402
+ });
403
+ for (const a of y(i.static())) {
404
+ const c = i.requireRelation(a);
405
+ if (c.loaded) {
406
+ n[a] = c.getLoadedModels();
407
+ continue;
408
+ }
409
+ const l = await r();
410
+ if (!l)
411
+ continue;
412
+ const u = await c.relatedClass.createManyFromEngineDocuments({
413
+ [e]: l
414
+ });
415
+ n[a] = u;
416
+ }
417
+ return { children: n, tombstones: o };
418
+ }
419
+ }
420
+ const P = /* @__PURE__ */ new WeakMap();
421
+ class ve {
422
+ async loadTypeIndex(i = {}) {
423
+ const e = g.requireUser();
424
+ return i.create && !P.get(e) ? P.set(e, await g.findOrCreatePrivateTypeIndex()) : P.has(e) || P.set(e, await g.findPrivateTypeIndex()), P.get(e) ?? null;
425
+ }
426
+ }
427
+ class Ie {
428
+ async indexLocalModels(i) {
429
+ for (const e of i)
430
+ await this.addLocalModel(e);
431
+ }
432
+ async addLocalModel(i) {
433
+ if (!(!this.localModels || this.localModels.hasKey(i.url))) {
434
+ this.localModels.add(i);
435
+ for (const e of y(i.static()))
436
+ await i.loadRelationIfUnloaded(e);
437
+ for (const e of i.getRelatedModels())
438
+ await this.addLocalModel(e);
439
+ }
440
+ }
441
+ }
442
+ const vt = ee;
443
+ class N extends Ce(vt, [Ae, ve, Ie]) {
444
+ constructor() {
445
+ super(...arguments);
446
+ h(this, "_models");
447
+ }
448
+ static restore(e) {
449
+ return we(new N(), (t) => {
450
+ t.status = e;
451
+ });
452
+ }
453
+ get models() {
454
+ return this._models;
455
+ }
456
+ set models(e) {
457
+ if (!e) {
458
+ delete this._models, delete this.localModels;
459
+ return;
460
+ }
461
+ const t = Be(this.status.children ?? [], "modelUrl");
462
+ this._models = e, this.localModels = b([], "url"), this.status.children = e.map(
463
+ (n) => t[n.url] ?? {
464
+ modelUrl: n.url,
465
+ completed: !1
466
+ }
467
+ );
468
+ }
469
+ async run() {
470
+ if (!this.models)
471
+ throw new Error("Cant start migration without models");
472
+ await this.indexLocalModels(this.models);
473
+ const e = this.status.children ?? [], t = await this.loadTypeIndex();
474
+ for (const n of e) {
475
+ const o = this.models.find(({ url: r }) => n.modelUrl === r);
476
+ !o || n.completed || (await this.migrateRegisteredModel(o, n, t), await this.updateProgress(() => n.completed = !0));
477
+ }
478
+ for (const [n, o] of yt())
479
+ await n.updateSchema(o);
480
+ wt();
481
+ }
482
+ async migrateRegisteredModel(e, t, n) {
483
+ if (await this.migrate(e, t), !R(e))
484
+ return;
485
+ const o = _(e.static()), r = n == null ? void 0 : n.registrations.find(({ instanceContainer: a }) => a === e.url);
486
+ !n || !r || o.length === 0 || (r.setAttribute(
487
+ "forClass",
488
+ o.map((a) => {
489
+ var c;
490
+ return ((c = ye(a)) == null ? void 0 : c.rdfsClasses) ?? a.rdfsClass;
491
+ }).flat()
492
+ ), await n.save());
493
+ }
494
+ async migrate(e, t) {
495
+ this.assertNotCancelled(), await this.migrateChildren(e, t);
496
+ const n = ye(e.static());
497
+ if (!n)
498
+ return;
499
+ const o = await D(e.static()).find(e.url), r = await (o == null ? void 0 : o.migrateSchema(n));
500
+ await e.migrateSchema(n, {
501
+ mintOperationUrl: (a) => {
502
+ var c, l;
503
+ return (l = (c = r == null ? void 0 : r.operations) == null ? void 0 : c.find((u) => !S(a, O) || !S(u, O) ? !1 : a.property === u.property && a.date.getTime() === u.date.getTime())) == null ? void 0 : l.url;
504
+ }
505
+ });
506
+ }
507
+ async migrateChildren(e, t) {
508
+ if (!R(e))
509
+ return;
510
+ const n = await this.loadContainedModels(e, { ignoreTombstones: !0 });
511
+ t.children ?? (t.children = n.map((o) => ({
512
+ modelUrl: o.url,
513
+ completed: !1
514
+ })));
515
+ for (const o of t.children) {
516
+ const r = n.find(({ url: a }) => o.modelUrl === a);
517
+ !r || o.completed || (await this.migrate(r, o), await this.updateProgress(() => o.completed = !0));
518
+ }
519
+ }
520
+ }
521
+ const It = M(() => Z.service("$cloud")), Pt = ee;
522
+ function kt(s) {
523
+ return !!s && "root" in s;
524
+ }
525
+ class Et extends Ce(Pt, [Ae, ve, Ie]) {
526
+ constructor(e) {
527
+ super();
528
+ h(this, "models");
529
+ h(this, "dirtyRemoteModels");
530
+ h(this, "rootLocalModels");
531
+ h(this, "tombstones");
532
+ h(this, "malformedDocuments");
533
+ h(this, "documentsModifiedAt");
534
+ h(this, "localModels");
535
+ this.models = e, this.rootLocalModels = [], this.localModels = b([], "url"), this.tombstones = b([], "resourceUrl"), this.malformedDocuments = /* @__PURE__ */ new Set(), this.documentsModifiedAt = {};
536
+ }
537
+ async run() {
538
+ const e = g.requireAuthenticator().engine, t = (o, { headers: r }) => {
539
+ const a = r == null ? void 0 : r.get("last-modified");
540
+ !a || o.endsWith("/") || (this.documentsModifiedAt[o] = new Date(a));
541
+ }, n = e.listeners.add({
542
+ onDocumentRead: t,
543
+ onDocumentUpdated: t
544
+ });
545
+ try {
546
+ this.rootLocalModels = this.models ?? V(), await this.indexLocalModels(this.rootLocalModels), await this.pullChanges(), await this.pushChanges();
547
+ } finally {
548
+ n();
549
+ }
550
+ }
551
+ getInitialStatus() {
552
+ return {
553
+ root: !0,
554
+ completed: !1,
555
+ children: [{ completed: !1 }, { completed: !1 }]
556
+ };
557
+ }
558
+ calculateCurrentProgress(e) {
559
+ return e ?? (e = this.status), kt(e) ? He(
560
+ this.calculateCurrentProgress(e.children[0]) * 0.9 + this.calculateCurrentProgress(e.children[1]) * 0.1,
561
+ 2
562
+ ) : super.calculateCurrentProgress(e);
563
+ }
564
+ async pullChanges() {
565
+ const e = this.models ? await this.fetchRemoteModelsForLocal(this.models) : await this.fetchRemoteModels(), t = b(e, (n) => n instanceof v ? n.resourceUrl : n.url);
566
+ this.dirtyRemoteModels = await this.synchronizeModels(t), await this.updateProgress((n) => n.children[0].completed = !0);
567
+ }
568
+ async pushChanges() {
569
+ const e = this.dirtyRemoteModels ?? [], t = this.status.children[1].children = e.map(() => ({ completed: !1 }));
570
+ for (let n = 0; n < e.length; n++) {
571
+ const o = e[n], r = t[n];
572
+ if (o.isSoftDeleted()) {
573
+ o.enableHistory(), o.enableTombstone(), await o.delete(), await this.updateProgress(() => r.completed = !0);
574
+ return;
575
+ }
576
+ await this.saveModelAndChildren(o, r), await this.updateTypeRegistrations(o), await this.updateProgress(() => r.completed = !0);
577
+ }
578
+ for (const [n, o] of Object.entries(this.documentsModifiedAt))
579
+ await k.remember(n, o);
580
+ Y(this.models, this.malformedDocuments), await this.updateProgress((n) => n.children[1].completed = !0);
581
+ }
582
+ async fetchRemoteModels() {
583
+ const e = this.status.children[0], t = await this.loadTypeIndex();
584
+ if (!t)
585
+ return [];
586
+ const n = [], o = /* @__PURE__ */ new Set(), r = [...It.registeredModels].map(({ modelClass: c }) => {
587
+ const l = A(c) ? _(c) : [];
588
+ return {
589
+ modelClass: c,
590
+ rdfsClasses: l.length > 0 ? l.map((u) => u.rdfsClasses).flat() : c.rdfsClasses
591
+ };
592
+ }), a = t.registrations.map((c) => {
593
+ const l = r.find(
594
+ ({ rdfsClasses: u }) => !!c.instanceContainer && u.some((f) => c.forClass.includes(f))
595
+ );
596
+ return !l || !c.instanceContainer || o.has(c.instanceContainer) ? null : (o.add(c.instanceContainer), [c, l]);
597
+ }).filter((c) => !!c);
598
+ e.children = a.map(() => ({ completed: !1 }));
599
+ for (let c = 0; c < a.length; c++)
600
+ await this.ignoringMalformedDocumentErrors(async () => {
601
+ var w;
602
+ const l = M(a[c])[0], u = M(a[c])[1], f = D(u.modelClass);
603
+ if (l.instanceContainer) {
604
+ if (A(f)) {
605
+ await Q(
606
+ u.modelClass,
607
+ x(l.instanceContainer)
608
+ );
609
+ const C = await f.find(l.instanceContainer);
610
+ C && (await this.loadChildren(C, M((w = e.children) == null ? void 0 : w[c])), n.push(C)), await this.updateProgress(() => {
611
+ var E;
612
+ return M((E = e.children) == null ? void 0 : E[c]).completed = !0;
613
+ });
614
+ return;
615
+ }
616
+ await Q(u.modelClass, l.instanceContainer), n.push(...await f.from(l.instanceContainer).all()), await this.updateProgress(() => {
617
+ var C;
618
+ return M((C = e.children) == null ? void 0 : C[c]).completed = !0;
619
+ });
620
+ }
621
+ });
622
+ return pe(this.rootLocalModels, n, this.malformedDocuments);
623
+ }
624
+ async fetchRemoteModelsForLocal(e) {
625
+ const t = [], n = this.status.children[0].children = e.map(() => ({ completed: !1 }));
626
+ for (let o = 0; o < e.length; o++)
627
+ await this.ignoringMalformedDocumentErrors(async () => {
628
+ const r = e[o], a = n[o], c = await D(r.static()).find(r.url);
629
+ if (!c) {
630
+ await this.updateProgress(() => a.completed = !0);
631
+ return;
632
+ }
633
+ R(c) && await this.loadChildren(c, a), t.push(c), await this.updateProgress(() => a.completed = !0);
634
+ });
635
+ return pe(e, t, this.malformedDocuments);
636
+ }
637
+ async updateTypeRegistrations(e) {
638
+ if (!R(e) || !Ct(e))
639
+ return;
640
+ const t = _(e.static());
641
+ if (t.length === 0)
642
+ return;
643
+ const n = await this.loadTypeIndex({ create: !0 });
644
+ n.registrations.some((o) => o.instanceContainer === e.url) || await e.register(n, t);
645
+ }
646
+ async loadChildren(e, t) {
647
+ var o, r;
648
+ if (this.assertNotCancelled(), !R(e))
649
+ return;
650
+ const n = await this.loadContainedModels(e, {
651
+ status: t,
652
+ onLoaded: async () => {
653
+ this.assertNotCancelled(), await this.updateProgress();
654
+ },
655
+ onMalformedDocument: (a) => this.malformedDocuments.add(a)
656
+ });
657
+ for (let a = 0; a < n.length; a++) {
658
+ const c = n[a];
659
+ if (c instanceof v) {
660
+ this.tombstones.add(c);
661
+ continue;
662
+ }
663
+ if (this.tombstones.hasKey(c.url)) {
664
+ await this.deleteChild(e, c);
665
+ continue;
666
+ }
667
+ await this.loadChildren(c, (o = t == null ? void 0 : t.children) == null ? void 0 : o[a]), (r = t == null ? void 0 : t.children) != null && r[a] && await this.updateProgress(() => {
668
+ var l;
669
+ return M((l = t.children) == null ? void 0 : l[a]).completed = !0;
670
+ });
671
+ }
672
+ }
673
+ async deleteChild(e, t) {
674
+ for (const n of e.static("relations")) {
675
+ const o = e.requireRelation(n);
676
+ if (o.related) {
677
+ if (Array.isArray(o.related)) {
678
+ o.related = o.related.filter((r) => r !== t);
679
+ continue;
680
+ }
681
+ if (o.related === t) {
682
+ o.related = null;
683
+ continue;
684
+ }
685
+ }
686
+ }
687
+ await t.delete();
688
+ }
689
+ async saveModelAndChildren(e, t) {
690
+ if (this.assertNotCancelled(), X(e) && e.isSoftDeleted()) {
691
+ e.enableHistory(), e.enableTombstone(), await e.delete();
692
+ return;
693
+ }
694
+ if (this.malformedDocuments.has(e.requireDocumentUrl()))
695
+ return;
696
+ if (await e.save(), !R(e)) {
697
+ if (X(e)) {
698
+ const r = e.requireDocumentUrl(), a = this.documentsModifiedAt[r] ?? /* @__PURE__ */ new Date();
699
+ await k.remember(r, a), delete this.documentsModifiedAt[r];
700
+ }
701
+ return;
702
+ }
703
+ const n = y(e.static()).map((r) => e.getRelationModels(r) ?? []).flat(), o = t ? n.map(() => ({ completed: !1 })) : [];
704
+ t && (t.children = o);
705
+ for (let r = 0; r < n.length; r++) {
706
+ const a = n[r], c = o[r];
707
+ await this.saveModelAndChildren(a, c), c && await this.updateProgress(() => c.completed = !0);
708
+ }
709
+ }
710
+ async synchronizeModels(e) {
711
+ const t = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set();
712
+ for (const r of e.items()) {
713
+ if (r instanceof v) {
714
+ const c = this.localModels.get(r.resourceUrl);
715
+ c && (await c.delete(), n.add(c));
716
+ continue;
717
+ }
718
+ const a = pt(r, this.localModels);
719
+ await this.loadChildren(a), await L.synchronize(a, r), await this.reconcileInconsistencies(a, r), await this.saveModelAndChildren(a), await this.addLocalModel(a), this.rootLocalModels.push(a), t.add(a.url);
720
+ }
721
+ for (const r of this.rootLocalModels) {
722
+ if (n.has(r) || t.has(r.url))
723
+ continue;
724
+ await this.loadChildren(r);
725
+ const a = Mt(r, e);
726
+ await L.synchronize(r, a), e.add(a);
727
+ }
728
+ const o = [];
729
+ for (const r of e.getItems()) {
730
+ if (De(r)) {
731
+ o.push(r);
732
+ continue;
733
+ }
734
+ await this.rememberModelDocuments(r);
735
+ }
736
+ return o;
737
+ }
738
+ async reconcileInconsistencies(e, t, n) {
739
+ e.rebuildAttributesFromHistory(), e.setAttributes(t.getAttributes(!0)), n ?? (n = /* @__PURE__ */ new Set()), n.add(e);
740
+ for (const r of y(e.static()))
741
+ await this.synchronizeContainerDocuments(
742
+ e.requireRelation(r),
743
+ t.requireRelation(r)
744
+ );
745
+ const o = b(G(t), "url");
746
+ for (const r of G(e))
747
+ n.has(r) || !r.isRelationLoaded("operations") || !o.hasKey(r.url) || await this.reconcileInconsistencies(r, o.require(r.url));
748
+ e.isDirty() && (await e.save(), await L.synchronize(e, t));
749
+ }
750
+ async synchronizeContainerDocuments(e, t) {
751
+ const n = b(e.related ?? [], "url"), o = b(t.related ?? [], "url"), r = n.getKeys().filter((c) => !o.hasKey(c) && !o.hasKey(encodeURI(c))), a = o.getKeys().filter((c) => !n.hasKey(c) && !n.hasKey(encodeURI(c)));
752
+ for (const c of r) {
753
+ const l = n.require(c), u = ie(l);
754
+ t.addRelated(u), o.add(u);
755
+ }
756
+ for (const c of a) {
757
+ const l = o.require(c), u = Le(l);
758
+ e.addRelated(u), n.add(u);
759
+ }
760
+ for (const c of n.items()) {
761
+ const l = o.require(c.url);
762
+ await L.synchronize(c, l), await this.saveModelAndChildren(c);
763
+ }
764
+ }
765
+ async rememberModelDocuments(e) {
766
+ if (!R(e)) {
767
+ const n = e.requireDocumentUrl(), o = this.documentsModifiedAt[n] ?? /* @__PURE__ */ new Date();
768
+ await k.remember(n, o), delete this.documentsModifiedAt[n];
769
+ return;
770
+ }
771
+ const t = y(e.static()).map((n) => e.getRelationModels(n) ?? []).flat();
772
+ for (const n of t)
773
+ await this.rememberModelDocuments(n);
774
+ }
775
+ async ignoringMalformedDocumentErrors(e) {
776
+ try {
777
+ await e();
778
+ } catch (t) {
779
+ if (S(t, Re)) {
780
+ console.warn(t.message), t.documentUrl && this.malformedDocuments.add(t.documentUrl);
781
+ return;
782
+ }
783
+ throw t;
784
+ }
785
+ }
786
+ }
787
+ const p = {
788
+ Disconnected: "disconnected",
789
+ Online: "online",
790
+ Syncing: "syncing",
791
+ Migrating: "migrating"
792
+ }, qt = xe({
793
+ name: "cloud",
794
+ persist: [
795
+ "localModelUpdates",
796
+ "migrationDismissed",
797
+ "migrationJob",
798
+ "modelCollections",
799
+ "pollingEnabled",
800
+ "pollingMinutes",
801
+ "ready",
802
+ "startupSync"
803
+ ],
804
+ initialState: () => ({
805
+ autoPush: !0,
806
+ localModelUpdates: {},
807
+ migrationDismissed: !1,
808
+ migrationJob: null,
809
+ migrationPostponed: !1,
810
+ modelCollections: {},
811
+ pollingEnabled: !0,
812
+ pollingMinutes: 10,
813
+ ready: !1,
814
+ registeredModels: [],
815
+ schemaMigrations: /* @__PURE__ */ new Map(),
816
+ setupDismissed: !1,
817
+ setupOngoing: !1,
818
+ startupSync: !0,
819
+ status: p.Disconnected,
820
+ syncError: null,
821
+ syncJob: null
822
+ }),
823
+ serialize: (s) => {
824
+ var i;
825
+ return oe(s, { migrationJob: (i = s.migrationJob) == null ? void 0 : i.serialize() });
826
+ },
827
+ restore: (s) => oe(s, {
828
+ migrationJob: s.migrationJob && N.restore(s.migrationJob)
829
+ }),
830
+ watch: {
831
+ migrationJob(s) {
832
+ s == null || s.listeners.add({ onUpdated: () => this.updatePersistedState("migrationJob") });
833
+ }
834
+ },
835
+ computed: {
836
+ disconnected: ({ status: s }) => s === p.Disconnected,
837
+ online: ({ status: s }) => s === p.Online,
838
+ syncing: ({ status: s }) => s === p.Syncing,
839
+ migrating: ({ status: s }) => s === p.Migrating,
840
+ localChanges({ localModelUpdates: s }) {
841
+ return Object.values(s).reduce((i, e) => i + e, 0);
842
+ },
843
+ dirty() {
844
+ return this.localChanges > 0;
845
+ },
846
+ migrationStarted({ migrationJob: s }) {
847
+ return !!s;
848
+ },
849
+ migrationDisabledReason({ status: s, ready: i }) {
850
+ return g.isLoggedIn() ? i ? s === p.Syncing || s === p.Migrating ? U(
851
+ "cloud.migrationNotSyncing",
852
+ "Wait for syncing to finish before starting the migration"
853
+ ) : this.online ? null : U(
854
+ "cloud.migrationNotOnline",
855
+ "You need to be online in order to start the migration"
856
+ ) : U(
857
+ "cloud.migrationNotReady",
858
+ "You need to backup your data before starting the migration"
859
+ ) : U(
860
+ "cloud.migrationNotLoggedIn",
861
+ "You need to reconnect before starting the migration"
862
+ );
863
+ }
864
+ }
865
+ });
866
+ class xt extends qt {
867
+ constructor() {
868
+ super(...arguments);
869
+ h(this, "asyncLock", new _e());
870
+ h(this, "engine", null);
871
+ h(this, "pollingInterval", null);
872
+ }
873
+ async whenReady(e) {
874
+ return this.ready ? e() : new Promise((t) => {
875
+ const n = () => t(e());
876
+ m.once("cloud:ready", n);
877
+ });
878
+ }
879
+ async setup(e) {
880
+ this.setupOngoing = !0;
881
+ try {
882
+ await this.backup(e), await this.setReady(!0), await this.sync();
883
+ } finally {
884
+ this.setupOngoing = !1;
885
+ }
886
+ }
887
+ dismissSetup() {
888
+ this.setupDismissed = !0;
889
+ }
890
+ dismissMigration() {
891
+ this.migrationDismissed = !0;
892
+ }
893
+ postponeMigration() {
894
+ this.migrationPostponed = !0;
895
+ }
896
+ async syncIfOnline(e = {}) {
897
+ this.online && await this.sync(e);
898
+ }
899
+ async sync(e = {}) {
900
+ const t = Ge(e) ? { models: e } : e instanceof L ? { model: e } : e;
901
+ !g.isLoggedIn() || !this.ready || !this.online || await this.asyncLock.run(async () => {
902
+ const n = Date.now(), o = t.model ? [t.model] : t.models;
903
+ this.syncError = null, this.status = p.Syncing, $.clear(o);
904
+ try {
905
+ if (await m.emit("cloud:sync-started", o), t.refreshUserProfile && await g.refreshUserProfile(), this.syncJob = new Et(o), this.syncJob.listeners.add(t), await F(this.syncJob), this.syncJob.cancelled)
906
+ return;
907
+ le() || await q({ milliseconds: Math.max(500, 1e3 - (Date.now() - n)) }), this.syncJob = null;
908
+ } catch (r) {
909
+ if (le())
910
+ throw r;
911
+ this.syncJob = null, this.syncError = r, await re.report(r, U("cloud.syncFailed", "Sync failed"));
912
+ } finally {
913
+ this.status = p.Online, await m.emit("cloud:sync-completed", o);
914
+ }
915
+ });
916
+ }
917
+ shouldMigrate() {
918
+ return this.schemaMigrations.size > 0;
919
+ }
920
+ async migrate(e) {
921
+ if (!this.online || !g.isLoggedIn() || !this.ready)
922
+ throw new Error("Data cannot be migrated at the moment");
923
+ this.shouldMigrate() && await this.asyncLock.run(async () => {
924
+ var r;
925
+ this.status = p.Migrating, this.migrationJob ?? (this.migrationJob = new N());
926
+ const t = Date.now(), n = [], o = (r = this.migrationJob).models ?? (r.models = V());
927
+ $.clear(o);
928
+ try {
929
+ if (e && n.push(this.migrationJob.listeners.add(e)), await m.emit("cloud:migration-started", o), await F(this.migrationJob), this.migrationJob.cancelled) {
930
+ await m.emit("cloud:migration-cancelled", o);
931
+ return;
932
+ }
933
+ this.migrationJob = null, this.migrationDismissed = !1, this.migrationPostponed = !1, await q({ milliseconds: Math.max(0, 1e3 - (Date.now() - t)) }), await m.emit("cloud:migration-completed", o);
934
+ } catch (a) {
935
+ await re.report(a, U("cloud.migrationFailed", "Migration failed"));
936
+ } finally {
937
+ this.status = p.Online, n.forEach((a) => a == null ? void 0 : a());
938
+ }
939
+ });
940
+ }
941
+ async register(e, t = {}) {
942
+ if (this.registeredModels.find((o) => e === o.modelClass))
943
+ return;
944
+ const n = this.engine;
945
+ n && fe(e).forEach((o) => D(o).setEngine(n)), this.whenReady(() => {
946
+ A(e) && (e.collection = H(t.path));
947
+ }), await it(e, {
948
+ created: (o) => me(o),
949
+ updated: (o) => ge(o),
950
+ deleted: (o) => Y([o])
951
+ }), A(e) && y(e).forEach((o) => {
952
+ const r = e.instance().requireRelation(o).relatedClass;
953
+ r.on("created", (a) => me(a)), r.on("updated", (a) => ge(a)), r.on("deleted", (a) => Y([a]));
954
+ }), this.registeredModels.push({ modelClass: e, path: t.path });
955
+ for (const o of this.modelCollections[e.modelName] ?? [])
956
+ await T(e, o);
957
+ }
958
+ registerSchemaMigration(e, t) {
959
+ this.schemaMigrations.set(e, t);
960
+ }
961
+ requireRemoteCollection(e) {
962
+ for (const t of this.registeredModels)
963
+ if (e === t.modelClass)
964
+ return H(t.path);
965
+ throw new Error(`Failed resolving remote collection for '${e.modelName}' model`);
966
+ }
967
+ async boot() {
968
+ await g.booted, g.isLoggedIn() && this.login(g.authenticator), m.on("auth:login", ({ authenticator: e }) => this.login(e)), m.on("auth:logout", () => this.logout()), m.once("application-ready", () => this.onApplicationReady()), m.once("application-mounted", () => this.onApplicationMounted()), ot(() => {
969
+ if (this.pollingInterval && clearInterval(this.pollingInterval), !this.pollingEnabled || this.migrationJob) {
970
+ this.pollingInterval = null;
971
+ return;
972
+ }
973
+ this.pollingInterval = setInterval(() => this.sync(), this.pollingMinutes * 60 * 1e3);
974
+ });
975
+ }
976
+ getDirtyLocalModels() {
977
+ const e = Object.keys(this.localModelUpdates), t = [];
978
+ for (const { modelClass: n } of this.registeredModels)
979
+ for (const o of ne(n))
980
+ t.push(...this.getModelsIn(e, o));
981
+ return t;
982
+ }
983
+ getModelsIn(e, t) {
984
+ const n = [];
985
+ return e.includes(t.url) && n.push(t), R(t) && n.push(
986
+ ...Se(t).map((o) => this.getModelsIn(e, o)).flat()
987
+ ), n;
988
+ }
989
+ requireEngine() {
990
+ return this.engine ?? Me("Could not get required Engine");
991
+ }
992
+ async setReady(e) {
993
+ this.ready || !e || (await m.emit("cloud:ready"), this.ready = !0);
994
+ }
995
+ async backup(e) {
996
+ await m.emit("cloud:backup-started"), e ?? (e = /* @__PURE__ */ new WeakMap());
997
+ const t = new Ut();
998
+ for (const { modelClass: n, path: o } of this.registeredModels) {
999
+ if (!A(n))
1000
+ continue;
1001
+ for (const [c, l] of Object.entries(e.get(n) ?? {}))
1002
+ t.migrateUrl(n, c, l);
1003
+ const r = n.collection, a = H(o);
1004
+ n.collection = a, t.migrateCollection(n, r, a);
1005
+ }
1006
+ await F(t), await m.emit("cloud:backup-completed");
1007
+ }
1008
+ async onApplicationReady() {
1009
+ this.ready || !g.isLoggedIn() || await this.setReady(!V().some((e) => e.url.startsWith("solid://")));
1010
+ }
1011
+ async onApplicationMounted() {
1012
+ this.syncOnStartup() && await this.sync();
1013
+ }
1014
+ login(e) {
1015
+ const t = [...this.registeredModels].map(({ modelClass: n }) => fe(n)).flat().concat([v]);
1016
+ this.status = p.Online, this.engine = e.engine;
1017
+ for (const n of t)
1018
+ D(n).setEngine(this.engine);
1019
+ }
1020
+ logout() {
1021
+ this.setState({
1022
+ localModelUpdates: {},
1023
+ migrationDismissed: !1,
1024
+ migrationJob: null,
1025
+ migrationPostponed: !1,
1026
+ modelCollections: {},
1027
+ pollingEnabled: !0,
1028
+ pollingMinutes: 10,
1029
+ ready: !1,
1030
+ setupDismissed: !1,
1031
+ setupOngoing: !1,
1032
+ startupSync: !0,
1033
+ status: p.Disconnected
1034
+ });
1035
+ }
1036
+ syncOnStartup() {
1037
+ return Qe("startupSync") ? Ye(Ve("startupSync")) : this.migrationJob ? !1 : this.startupSync;
1038
+ }
1039
+ }
1040
+ const Ot = te(xt), Tt = {
1041
+ key: 1,
1042
+ class: "flex flex-col gap-3"
1043
+ }, Gt = /* @__PURE__ */ rt({
1044
+ __name: "AGCloudStatus",
1045
+ emits: ["sync"],
1046
+ setup(s) {
1047
+ return (i, e) => (W(), de(I(Xe), null, {
1048
+ "logged-in": j(({ session: t }) => [
1049
+ i.$cloud.syncing ? (W(), de(I(ae), {
1050
+ key: 0,
1051
+ text: i.$td("cloud.syncing", "Syncing...")
1052
+ }, null, 8, ["text"])) : (W(), at("div", Tt, [
1053
+ K(I(ae), {
1054
+ text: i.$td("solid.loggedIn", "You are logged in as [{userName}]({userWebId})", {
1055
+ userName: t.user.name ?? t.user.webId,
1056
+ userWebId: t.user.webId
1057
+ })
1058
+ }, null, 8, ["text"]),
1059
+ K(I(ce), {
1060
+ onClick: e[0] || (e[0] = (n) => (i.$cloud.sync(), i.$emit("sync")))
1061
+ }, {
1062
+ default: j(() => [
1063
+ ue(he(i.$td("cloud.sync", "Synchronize")), 1)
1064
+ ]),
1065
+ _: 1
1066
+ }),
1067
+ K(I(ce), {
1068
+ onClick: e[1] || (e[1] = (n) => i.$solid.logout())
1069
+ }, {
1070
+ default: j(() => [
1071
+ ue(he(i.$td("solid.logout", "Logout")), 1)
1072
+ ]),
1073
+ _: 1
1074
+ })
1075
+ ]))
1076
+ ]),
1077
+ _: 1
1078
+ }));
1079
+ }
1080
+ }), $t = { $cloud: Ot };
1081
+ function Qt() {
1082
+ return {
1083
+ name: "@aerogel/local-first",
1084
+ async install(s) {
1085
+ await Oe(s, {
1086
+ ...$t,
1087
+ $_documentsCache: k
1088
+ });
1089
+ }
1090
+ };
1091
+ }
1092
+ export {
1093
+ Gt as AGCloudStatus,
1094
+ Ot as Cloud,
1095
+ xt as CloudService,
1096
+ Qt as default
1097
+ };
1098
+ //# sourceMappingURL=aerogel-plugin-local-first.js.map