@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,186 @@
1
+ import { PropertyOperation, isContainer } from 'soukai-solid';
2
+ import { Job } from '@aerogel/core';
3
+ import { isInstanceOf, map, mixed, objectMap, tap } from '@noeldemartin/utils';
4
+ import type { JobListener, JobStatus } from '@aerogel/core';
5
+ import type { Nullable } from '@noeldemartin/utils';
6
+ import type { SolidModel, SolidTypeIndex } from 'soukai-solid';
7
+
8
+ import {
9
+ clearSchemaMigrations,
10
+ getRemoteClass,
11
+ getSchemaMigration,
12
+ getSchemaMigrations,
13
+ } from '@aerogel/plugin-local-first/lib/mirroring';
14
+ import { getContainerRegisteredClasses } from '@aerogel/plugin-local-first/lib/inference';
15
+
16
+ import LoadsChildren from './mixins/LoadsChildren';
17
+ import LoadsTypeIndex from './mixins/LoadsTypeIndex';
18
+ import TracksLocalModels from './mixins/TracksLocalModels';
19
+
20
+ const BaseJob = Job as typeof Job<JobListener, MigrateJobStatus, MigrateJobStatus>;
21
+
22
+ export interface MigrateJobStatus extends JobStatus {
23
+ children?: MigrateModelJobStatus[];
24
+ }
25
+
26
+ export interface MigrateModelJobStatus extends JobStatus {
27
+ modelUrl: string;
28
+ children?: MigrateModelJobStatus[];
29
+ }
30
+
31
+ export default class Migrate extends mixed(BaseJob, [LoadsChildren, LoadsTypeIndex, TracksLocalModels]) {
32
+
33
+ public static restore(status: MigrateJobStatus): Migrate {
34
+ return tap(new Migrate(), (job) => {
35
+ job.status = status;
36
+ });
37
+ }
38
+
39
+ constructor() {
40
+ super();
41
+
42
+ this.localModels = map([], 'url');
43
+ }
44
+
45
+ protected _models?: SolidModel[];
46
+
47
+ public get models(): SolidModel[] | undefined {
48
+ return this._models;
49
+ }
50
+
51
+ public set models(models: SolidModel[] | undefined) {
52
+ if (!models) {
53
+ delete this._models;
54
+
55
+ this.localModels = map([], 'url');
56
+
57
+ return;
58
+ }
59
+
60
+ const childrenStatus = objectMap(this.status.children ?? [], 'modelUrl');
61
+
62
+ this._models = models;
63
+ this.localModels = map([], 'url');
64
+ this.status.children = models.map(
65
+ (model) =>
66
+ childrenStatus[model.url] ?? {
67
+ modelUrl: model.url,
68
+ completed: false,
69
+ },
70
+ );
71
+ }
72
+
73
+ protected async run(): Promise<void> {
74
+ if (!this.models) {
75
+ throw new Error('Cant start migration without models');
76
+ }
77
+
78
+ await this.indexLocalModels(this.models);
79
+
80
+ const modelStatuses = this.status.children ?? [];
81
+ const typeIndex = await this.loadTypeIndex();
82
+
83
+ for (const modelStatus of modelStatuses) {
84
+ const model = this.models.find(({ url }) => modelStatus.modelUrl === url);
85
+
86
+ if (!model || modelStatus.completed) {
87
+ continue;
88
+ }
89
+
90
+ await this.migrateRegisteredModel(model, modelStatus, typeIndex);
91
+ await this.updateProgress(() => (modelStatus.completed = true));
92
+ }
93
+
94
+ for (const [modelClass, schema] of getSchemaMigrations()) {
95
+ await modelClass.updateSchema(schema);
96
+ }
97
+
98
+ clearSchemaMigrations();
99
+ }
100
+
101
+ protected async migrateRegisteredModel(
102
+ model: SolidModel,
103
+ status: MigrateModelJobStatus,
104
+ typeIndex?: Nullable<SolidTypeIndex>,
105
+ ): Promise<void> {
106
+ await this.migrate(model, status);
107
+
108
+ if (!isContainer(model)) {
109
+ return;
110
+ }
111
+
112
+ const registeredClasses = getContainerRegisteredClasses(model.static());
113
+ const registration = typeIndex?.registrations.find(({ instanceContainer }) => instanceContainer === model.url);
114
+
115
+ if (!typeIndex || !registration || registeredClasses.length === 0) {
116
+ return;
117
+ }
118
+
119
+ registration.setAttribute(
120
+ 'forClass',
121
+ registeredClasses
122
+ .map((modelClass) => getSchemaMigration(modelClass)?.rdfsClasses ?? modelClass.rdfsClass)
123
+ .flat(),
124
+ );
125
+
126
+ await typeIndex.save();
127
+ }
128
+
129
+ protected async migrate(localModel: SolidModel, status: MigrateModelJobStatus): Promise<void> {
130
+ this.assertNotCancelled();
131
+
132
+ await this.migrateChildren(localModel, status);
133
+
134
+ const schema = getSchemaMigration(localModel.static());
135
+
136
+ if (!schema) {
137
+ return;
138
+ }
139
+
140
+ const remoteModel = await getRemoteClass(localModel.static()).find(localModel.url);
141
+ const migratedModel = await remoteModel?.migrateSchema(schema);
142
+
143
+ await localModel.migrateSchema(schema, {
144
+ mintOperationUrl: (operation) => {
145
+ return migratedModel?.operations?.find((migratedOperation) => {
146
+ if (
147
+ !isInstanceOf(operation, PropertyOperation) ||
148
+ !isInstanceOf(migratedOperation, PropertyOperation)
149
+ ) {
150
+ return false;
151
+ }
152
+
153
+ return (
154
+ operation.property === migratedOperation.property &&
155
+ operation.date.getTime() === migratedOperation.date.getTime()
156
+ );
157
+ })?.url;
158
+ },
159
+ });
160
+ }
161
+
162
+ protected async migrateChildren(localModel: SolidModel, status: MigrateModelJobStatus): Promise<void> {
163
+ if (!isContainer(localModel)) {
164
+ return;
165
+ }
166
+
167
+ const children = await this.loadContainedModels(localModel, { ignoreTombstones: true });
168
+
169
+ status.children ??= children.map((child) => ({
170
+ modelUrl: child.url,
171
+ completed: false,
172
+ }));
173
+
174
+ for (const childStatus of status.children) {
175
+ const child = children.find(({ url }) => childStatus.modelUrl === url);
176
+
177
+ if (!child || childStatus.completed) {
178
+ continue;
179
+ }
180
+
181
+ await this.migrate(child, childStatus);
182
+ await this.updateProgress(() => (childStatus.completed = true));
183
+ }
184
+ }
185
+
186
+ }