@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 @@
1
+ {"version":3,"file":"aerogel-plugin-local-first.js","sources":["../src/lib/inference.ts","../src/lib/SyncQueue.ts","../src/lib/mirroring.ts","../src/jobs/Backup.ts","../src/services/DocumentsCache.ts","../src/lib/utils.ts","../src/jobs/mixins/LoadsChildren.ts","../src/jobs/mixins/LoadsTypeIndex.ts","../src/jobs/mixins/TracksLocalModels.ts","../src/jobs/Migrate.ts","../src/jobs/Sync.ts","../src/services/Cloud.state.ts","../src/services/Cloud.ts","../src/index.ts"],"sourcesContent":["import {\n Metadata,\n Operation,\n SolidACLAuthorization,\n SolidContainer,\n SolidContainsRelation,\n SolidDocument,\n SolidModel,\n isContainerClass,\n isSolidDocumentRelation,\n} from 'soukai-solid';\nimport { arrayFilter, isInstanceOf } from '@noeldemartin/utils';\n\nimport type { SolidContainerConstructor, SolidModelConstructor } from 'soukai-solid';\n\nconst containerRelations: WeakMap<typeof SolidModel, string[]> = new WeakMap();\nconst sameDocumentRelations: WeakMap<typeof SolidModel, string[]> = new WeakMap();\n\nexport function getContainerRegisteredClasses(modelClass: SolidContainerConstructor): SolidModelConstructor[] {\n return arrayFilter(\n getContainerRelations(modelClass).map((relation) => {\n const relatedClass = modelClass.instance().requireRelation<SolidContainsRelation>(relation).relatedClass;\n\n if (isContainerClass(relatedClass)) {\n return false;\n }\n\n return relatedClass;\n }),\n );\n}\n\nexport function getContainerRelations(modelClass: typeof SolidModel): string[] {\n if (!containerRelations.has(modelClass)) {\n containerRelations.set(\n modelClass,\n modelClass.relations.filter((relation) => {\n if (SolidModel.reservedRelations.includes(relation)) {\n return false;\n }\n\n const relationInstance = modelClass.instance().requireRelation(relation);\n\n return relationInstance instanceof SolidContainsRelation;\n }),\n );\n }\n\n return containerRelations.get(modelClass) ?? [];\n}\n\nexport function getContainedModels(model: SolidContainer): SolidModel[] {\n const relations = getContainerRelations(model.static());\n\n return relations.reduce(\n (models, relation) => models.concat(model.getRelationModels(relation) ?? []),\n [] as SolidModel[],\n );\n}\n\nexport function getRelatedClasses(modelClass: SolidModelConstructor): SolidModelConstructor[] {\n const relatedClasses = new Set<SolidModelConstructor>();\n const instance = modelClass.instance();\n\n relatedClasses.add(modelClass);\n\n for (const relation of modelClass.relations) {\n if (modelClass.reservedRelations.includes(relation)) {\n continue;\n }\n\n relatedClasses.add(instance.requireRelation(relation).relatedClass);\n }\n\n return [...relatedClasses.values()];\n}\n\nexport function getRelatedAppModels(model: SolidModel): SolidModel[] {\n return model\n .getRelatedModels()\n .filter(\n (related) =>\n !isInstanceOf(related, SolidACLAuthorization) &&\n !isInstanceOf(related, SolidDocument) &&\n !isInstanceOf(related, Metadata) &&\n !isInstanceOf(related, Operation) &&\n related.static() !== SolidContainer,\n );\n}\n\nexport function getSameDocumentRelations(modelClass: typeof SolidModel): string[] {\n if (!sameDocumentRelations.has(modelClass)) {\n sameDocumentRelations.set(\n modelClass,\n modelClass.relations.filter((relation) => {\n if (SolidModel.reservedRelations.includes(relation)) {\n return false;\n }\n\n const relationInstance = modelClass.instance().requireRelation(relation);\n\n return isSolidDocumentRelation(relationInstance) && relationInstance.useSameDocument;\n }),\n );\n }\n\n return sameDocumentRelations.get(modelClass) ?? [];\n}\n\nexport function isDirtyOrHasDirtyChildren(model: SolidModel): boolean {\n if (model.isDirty()) {\n return true;\n }\n\n if (!(model instanceof SolidContainer)) {\n return false;\n }\n\n const relationHasDirtyModels = (relation: string) => {\n return model.getRelationModels(relation)?.some((relatedModel) => isDirtyOrHasDirtyChildren(relatedModel));\n };\n\n return getContainerRelations(model.static()).some(relationHasDirtyModels);\n}\n","import { after, arrayRemove, facade, required } from '@noeldemartin/utils';\nimport { App } from '@aerogel/core';\nimport { type SolidModel, isContainer } from 'soukai-solid';\n\nimport { getContainedModels } from '@aerogel/plugin-local-first/lib/inference';\n\nconst Cloud = required(() => App.service('$cloud'));\n\nclass SyncQueue {\n\n private models: Set<SolidModel> = new Set();\n private promises: Promise<unknown>[] = [];\n\n public push(model: SolidModel): void {\n this.models.add(model);\n this.syncAfter(after({ seconds: 1 }));\n }\n\n public clear(models?: SolidModel[]): void {\n if (!models) {\n this.models = new Set();\n\n return;\n }\n\n for (const model of models) {\n this.models.delete(model);\n }\n }\n\n protected async syncAfter<T = void>(operationOrPromise: Promise<T> | (() => Promise<T>)): Promise<T> {\n const promise = typeof operationOrPromise === 'function' ? operationOrPromise() : operationOrPromise;\n\n this.promises.push(promise);\n\n promise.then(() => arrayRemove(this.promises, promise));\n\n if (this.promises.length === 1) {\n this.schedule();\n }\n\n return promise as Promise<T>;\n }\n\n private schedule(): void {\n Promise.all(this.promises)\n .then(() => after())\n .then(() => {\n if (this.promises.length !== 0) {\n this.schedule();\n\n return;\n }\n\n const models = this.consume();\n\n if (models.length === 0) {\n return;\n }\n\n Cloud.syncIfOnline(models);\n });\n }\n\n private consume(): SolidModel[] {\n const models: SolidModel[] = [];\n const children: Set<SolidModel> = new Set();\n\n for (const model of this.models) {\n if (!isContainer(model)) {\n continue;\n }\n\n this.models.delete(model);\n getContainedModels(model).forEach((child) => children.add(child));\n models.push(model);\n }\n\n for (const model of this.models) {\n this.models.delete(model);\n\n if (children.has(model)) {\n continue;\n }\n\n models.push(model);\n }\n\n return models;\n }\n\n}\n\nexport default facade(SyncQueue);\n","import { bootModels } from 'soukai';\nimport {\n fail,\n objectWithout,\n requireUrlParentDirectory,\n required,\n tap,\n toString,\n urlResolveDirectory,\n urlRoute,\n} from '@noeldemartin/utils';\nimport { App } from '@aerogel/core';\nimport { getTrackedModels, trackModelsCollection as trackSoukaiModelsCollection } from '@aerogel/plugin-soukai';\nimport { Solid } from '@aerogel/plugin-solid';\nimport { PropertyOperation, SolidContainer, SolidContainsRelation, Tombstone } from 'soukai-solid';\nimport type { ObjectsMap } from '@noeldemartin/utils';\nimport type { Attributes } from 'soukai';\nimport type { SolidModel, SolidModelConstructor, SolidSchemaDefinition } from 'soukai-solid';\n\nimport SyncQueue from '@aerogel/plugin-local-first/lib/SyncQueue';\nimport { getContainerRelations, getRelatedAppModels } from '@aerogel/plugin-local-first/lib/inference';\n\ninterface CloneOptions {\n clean?: boolean;\n}\n\nconst Cloud = required(() => App.service('$cloud'));\nconst remoteClasses: WeakMap<SolidModelConstructor, SolidModelConstructor> = new WeakMap();\nconst localClasses: WeakMap<SolidModelConstructor, SolidModelConstructor> = new WeakMap();\n\nfunction cleanRemoteModelClone(remoteModel: SolidModel): void {\n const relatedModels = remoteModel.getRelatedModels().concat([remoteModel]);\n\n for (const relatedModel of relatedModels) {\n relatedModel.cleanDirty(true);\n }\n}\n\nfunction fixRemoteModelClone(remoteModel: SolidModel): void {\n const relatedModels = getRelatedAppModels(remoteModel).concat([remoteModel]);\n\n for (const relatedModel of relatedModels) {\n if (!relatedModel.operations || relatedModel.operations.length === 0) {\n continue;\n }\n\n const operations = (relatedModel.operations ?? []).filter((operation) => {\n return (\n !(operation instanceof PropertyOperation) ||\n !relatedModel.ignoreRdfPropertyHistory(operation.property, true)\n );\n });\n\n if (!operations.some((operation) => !operation.isInception(relatedModel))) {\n relatedModel.setRelationModels('operations', []);\n\n continue;\n }\n\n relatedModel.setRelationModels('operations', operations);\n }\n}\n\nexport async function createRemoteModel(localModel: SolidModel): Promise<void> {\n Cloud.setState({\n localModelUpdates: {\n ...Cloud.localModelUpdates,\n [localModel.url]: 1,\n },\n });\n\n if (isRegisteredModelClass(localModel.static())) {\n await trackModelsCollection(localModel.static(), requireUrlParentDirectory(localModel.url));\n }\n\n if (Cloud.autoPush && Cloud.ready && !Cloud.syncing) {\n SyncQueue.push(localModel);\n }\n}\n\nexport async function trackModelsCollection(modelClass: SolidModelConstructor, collection: string): Promise<void> {\n if (Cloud.modelCollections[modelClass.modelName]?.includes(collection)) {\n return;\n }\n\n Cloud.setState('modelCollections', {\n ...Cloud.modelCollections,\n [modelClass.modelName]: (Cloud.modelCollections[modelClass.modelName] ?? []).concat(collection),\n });\n\n await trackSoukaiModelsCollection(modelClass, collection);\n}\n\nexport async function updateRemoteModel(localModel: SolidModel): Promise<void> {\n if (ignoreModelUpdates(localModel)) {\n return;\n }\n\n const modelUpdates = Cloud.localModelUpdates[localModel.url] ?? 0;\n\n Cloud.setState({\n localModelUpdates: localModel.isSoftDeleted()\n ? objectWithout(Cloud.localModelUpdates, localModel.url)\n : {\n ...Cloud.localModelUpdates,\n [localModel.url]: modelUpdates + 1,\n },\n });\n\n if (Cloud.autoPush && Cloud.ready && !Cloud.syncing) {\n SyncQueue.push(localModel);\n }\n}\n\nexport function clearLocalModelUpdates(models?: SolidModel[], malformedDocuments?: Set<string>): void {\n const syncedModelUrls = models?.map((model) => toString(model.getDeletedPrimaryKey() ?? model.getPrimaryKey()));\n const localModelUpdates = {} as Record<string, number>;\n\n for (const [url, count] of Object.entries(Cloud.localModelUpdates)) {\n const documentUrl = urlRoute(url);\n const wasSynced =\n !syncedModelUrls ||\n syncedModelUrls.some(\n (modelUrl) => url === modelUrl || (modelUrl.endsWith('/') && url.startsWith(modelUrl)),\n );\n\n if (wasSynced && !malformedDocuments?.has(documentUrl)) {\n continue;\n }\n\n localModelUpdates[url] = count;\n }\n\n Cloud.setState({ localModelUpdates });\n}\n\nexport function cloneLocalModel(localModel: SolidModel, options: CloneOptions = {}): SolidModel {\n const localModelClasses = new Set<typeof SolidModel>();\n\n localModelClasses.add(localModel.static());\n\n if (localModel instanceof SolidContainer) {\n for (const relation of getContainerRelations(localModel.static())) {\n localModelClasses.add(localModel.requireRelation<SolidContainsRelation>(relation).relatedClass);\n }\n }\n\n const constructors = [...localModelClasses.values()].map(\n (localClass) => [localClass, getRemoteClass(localClass)] as [typeof SolidModel, typeof SolidModel],\n );\n\n return tap(localModel.clone({ constructors }), (model) => {\n fixRemoteModelClone(model);\n\n options.clean && cleanRemoteModelClone(model);\n });\n}\n\nexport function cloneRemoteModel(remoteModel: SolidModel): SolidModel {\n const remoteModelClasses = new Set<typeof SolidModel>();\n\n remoteModelClasses.add(remoteModel.static());\n\n if (remoteModel instanceof SolidContainer) {\n for (const relation of getContainerRelations(remoteModel.static())) {\n remoteModelClasses.add(remoteModel.requireRelation<SolidContainsRelation>(relation).relatedClass);\n }\n }\n\n const constructors = [...remoteModelClasses.values()].map(\n (remoteClass) => [remoteClass, getLocalClass(remoteClass)] as [typeof SolidModel, typeof SolidModel],\n );\n\n return remoteModel.clone({ constructors });\n}\n\nexport async function completeRemoteModels(\n localModels: SolidModel[],\n remoteModels: SolidModel[],\n malformedDocuments: Set<string>,\n): Promise<SolidModel[]> {\n const RemoteTombstone = getRemoteClass(Tombstone);\n const remoteModelUrls = remoteModels.map((remoteModel) => remoteModel.url);\n const missingModelDocumentUrls = localModels\n .filter((localModel) => !remoteModelUrls.includes(localModel.url))\n .map((localModel) => localModel.requireDocumentUrl())\n .filter((documentUrl) => !malformedDocuments.has(documentUrl));\n const tombstones = await RemoteTombstone.all({ $in: missingModelDocumentUrls });\n\n return remoteModels.concat(tombstones);\n}\n\nexport function ignoreModelUpdates(localModel: SolidModel): boolean {\n const updatedAt = localModel.metadata.updatedAt?.getTime();\n\n return !localModel.operations.some((operation) => {\n if (operation.date.getTime() !== updatedAt) {\n return false;\n }\n\n if (!(operation instanceof PropertyOperation)) {\n return true;\n }\n\n return !localModel.ignoreRdfPropertyHistory(operation.property, true);\n });\n}\n\nexport function getLocalModel(remoteModel: SolidModel, localModels: ObjectsMap<SolidModel>): SolidModel {\n return localModels.get(remoteModel.url) ?? cloneRemoteModel(remoteModel);\n}\n\nexport function getLocalModels(): SolidModel[] {\n return [...Cloud.registeredModels].map(({ modelClass }) => getTrackedModels(modelClass)).flat();\n}\n\nexport function getSchemaMigrations(): Map<SolidModelConstructor, SolidModelConstructor | SolidSchemaDefinition> {\n return Cloud.schemaMigrations;\n}\n\nexport function clearSchemaMigrations(): void {\n Cloud.schemaMigrations.clear();\n}\n\nexport function getSchemaMigration(\n modelClass: SolidModelConstructor,\n): SolidModelConstructor | SolidSchemaDefinition | undefined {\n return Cloud.schemaMigrations.get(modelClass);\n}\n\nexport function getRemoteClass<T extends SolidModelConstructor>(localClass: T): T {\n return (remoteClasses.get(localClass) as T) ?? makeRemoteClass(localClass);\n}\n\nexport function getRemoteContainersCollection(path?: string): string {\n const rootStorage = Solid.requireUser().storageUrls[0];\n\n return path\n ? urlResolveDirectory((path.startsWith('/') ? rootStorage.slice(0, -1) : rootStorage) + path)\n : rootStorage;\n}\n\nexport function getRemoteModel(localModel: SolidModel, remoteModels: ObjectsMap<SolidModel>): SolidModel {\n return remoteModels.get(localModel.url) ?? cloneLocalModel(localModel);\n}\n\nexport function isRegisteredModel(model: SolidModel): boolean {\n for (const { modelClass } of Cloud.registeredModels) {\n const models = getTrackedModels(modelClass);\n\n if (models.some((registeredModel) => registeredModel.url === model.url)) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function isRemoteModel(model: SolidModel): boolean {\n return localClasses.has(model.static());\n}\n\nexport function isLocalModel(model: SolidModel): boolean {\n return !isRemoteModel(model);\n}\n\nexport function isRegisteredModelClass(modelClass: SolidModelConstructor): boolean {\n return Cloud.registeredModels.some(({ modelClass: registeredModelClass }) => registeredModelClass === modelClass);\n}\n\nexport function makeRemoteClass<T extends SolidModelConstructor>(localClass: T): T {\n const LocalClass = localClass as typeof SolidModel;\n const withLocalHistoryConfig = (modelClass: typeof SolidModel, operation: () => unknown) => {\n modelClass.timestamps = LocalClass.timestamps;\n modelClass.history = LocalClass.history;\n\n operation();\n\n modelClass.timestamps = [];\n modelClass.history = false;\n };\n const RemoteClass = class extends LocalClass {\n\n public static override timestamps = false;\n public static override history = false;\n\n protected override initialize(attributes: Attributes, exists: boolean): void {\n withLocalHistoryConfig(this._proxy.static(), () => super.initialize(attributes, exists));\n }\n\n protected override initializeRelations(): void {\n super.initializeRelations();\n\n for (const relation of Object.values(this._relations)) {\n if (!(relation instanceof SolidContainsRelation)) {\n continue;\n }\n\n relation.relatedClass = getRemoteClass(relation.relatedClass);\n }\n }\n\n public override fixMalformedAttributes(): void {\n withLocalHistoryConfig(this.static(), () => super.fixMalformedAttributes());\n }\n \n } as unknown as T;\n\n remoteClasses.set(LocalClass, RemoteClass);\n localClasses.set(RemoteClass, LocalClass);\n\n LocalClass.on('schema-updated', async (schema) => {\n await RemoteClass.updateSchema({\n ...schema,\n timestamps: false,\n history: false,\n });\n });\n\n bootModels({ [`Remote${localClass.modelName}`]: RemoteClass });\n\n return RemoteClass;\n}\n\nexport function getLocalClass<T extends SolidModelConstructor>(remoteClass: T): T {\n return (localClasses.get(remoteClass) as T) ?? fail(`Couldn't find local class for ${remoteClass.modelName}`);\n}\n","import { Job } from '@aerogel/core';\nimport { requireEngine } from 'soukai';\nimport { requireUrlParentDirectory } from '@noeldemartin/utils';\nimport { ignoreModelsCollection, trackModelsCollection } from '@aerogel/plugin-soukai';\nimport type { EngineDocument, IndexedDBEngine } from 'soukai';\nimport type { SolidModelConstructor } from 'soukai-solid';\n\ninterface Migration {\n modelClass: SolidModelConstructor;\n local: string;\n remote: string;\n}\n\nexport default class Backup extends Job {\n\n private urlMigrations: Migration[] = [];\n private collectionMigrations: Migration[] = [];\n\n public migrateUrl(modelClass: SolidModelConstructor, local: string, remote: string): void {\n this.urlMigrations.push({\n modelClass,\n local,\n remote,\n });\n }\n\n public migrateCollection(modelClass: SolidModelConstructor, local: string, remote: string): void {\n this.collectionMigrations.push({\n modelClass,\n local,\n remote,\n });\n }\n\n protected async run(): Promise<void> {\n const engine = requireEngine<IndexedDBEngine>();\n const collections = await engine.getCollections();\n\n for (const collection of collections) {\n const documents = await engine.readMany(collection);\n\n for (const [id, document] of Object.entries(documents)) {\n const url = this.replaceUrl(id);\n\n await engine.create(requireUrlParentDirectory(url), this.replaceDocumentUrls(document), url);\n await engine.delete(collection, id);\n }\n }\n\n for (const { modelClass, remote } of this.urlMigrations) {\n trackModelsCollection(modelClass, requireUrlParentDirectory(remote), { refresh: false });\n }\n\n for (const { modelClass, local, remote } of this.collectionMigrations) {\n ignoreModelsCollection(modelClass, local);\n trackModelsCollection(modelClass, remote, { refresh: false });\n }\n }\n\n protected replaceDocumentUrls(document: EngineDocument): EngineDocument {\n for (const [key, value] of Object.entries(document)) {\n if (key === '@id' && typeof value === 'string') {\n document[key] = this.replaceUrl(value);\n\n continue;\n }\n\n if (typeof value !== 'object' || value === null) {\n continue;\n }\n\n document[key] = this.replaceDocumentUrls(value as EngineDocument);\n }\n\n return document;\n }\n\n protected replaceUrl(url: string): string {\n for (const { local, remote } of this.urlMigrations) {\n if (!url.startsWith(local)) {\n continue;\n }\n\n return url.replace(local, remote);\n }\n\n for (const { local, remote } of this.collectionMigrations) {\n if (!url.startsWith(local)) {\n continue;\n }\n\n return url.replace(local, remote);\n }\n\n return url;\n }\n\n}\n","import { Events, Service } from '@aerogel/core';\nimport { IndexedDBMap, facade } from '@noeldemartin/utils';\n\nexport class DocumentsCacheService extends Service {\n\n private cache = new IndexedDBMap<{ modifiedAt: number }>('documents-cache');\n\n public async isFresh(documentUrl: string, modifiedAt: Date | number): Promise<boolean> {\n const meta = await this.cache.get(documentUrl);\n const modifiedAtTime = typeof modifiedAt !== 'number' ? modifiedAt.getTime() : modifiedAt;\n\n return !!meta?.modifiedAt && meta.modifiedAt >= modifiedAtTime;\n }\n\n public async remember(documentUrl: string, modifiedAt: Date | number): Promise<void> {\n await this.cache.set(documentUrl, {\n modifiedAt: typeof modifiedAt !== 'number' ? modifiedAt.getTime() : modifiedAt,\n });\n }\n\n public async forget(documentUrl: string): Promise<void> {\n await this.cache.delete(documentUrl);\n }\n\n protected override async boot(): Promise<void> {\n Events.on('auth:logout', async () => {\n await this.cache.clear();\n\n this.cache.close();\n });\n }\n\n}\n\nexport default facade(DocumentsCacheService);\n","export function mapFromArray<K, V>(items: [K, V][]): Map<K, V> {\n const itemsMap = new Map();\n\n for (const [key, value] of items) {\n itemsMap.set(key, value);\n }\n\n return itemsMap;\n}\n\nexport function lazy<T>(getter: () => Promise<T>): () => Promise<T> {\n const result: { value?: T } = {};\n\n return async () => {\n if (!('value' in result)) {\n result.value = await getter();\n }\n\n return result.value as T;\n };\n}\n","import { arrayChunk, arrayFrom, isInstanceOf, map, required } from '@noeldemartin/utils';\nimport { DocumentNotFound } from 'soukai';\nimport { MalformedSolidDocumentError } from '@noeldemartin/solid-utils';\nimport { Tombstone } from 'soukai-solid';\nimport type { JobStatus } from '@aerogel/core';\nimport type { ObjectsMap } from '@noeldemartin/utils';\nimport type { SolidContainer, SolidContainsRelation, SolidDocument, SolidModel } from 'soukai-solid';\n\nimport DocumentsCache from '@aerogel/plugin-local-first/services/DocumentsCache';\nimport { cloneLocalModel, isLocalModel } from '@aerogel/plugin-local-first/lib/mirroring';\nimport { getContainerRelations } from '@aerogel/plugin-local-first/lib/inference';\nimport { lazy } from '@aerogel/plugin-local-first/lib/utils';\n\nexport interface ResourceJobStatus extends JobStatus {\n documentUrl?: string;\n children?: ResourceJobStatus[];\n}\n\nexport default class LoadsChildren {\n\n declare protected localModels?: ObjectsMap<SolidModel>;\n\n protected async loadContainedModels(\n model: SolidContainer,\n options: {\n ignoreTombstones?: boolean;\n status?: ResourceJobStatus;\n onLoaded?: (urls: string[]) => unknown;\n onMalformedDocument?: (url: string) => unknown;\n } = {},\n ): Promise<SolidModel[]> {\n if (isLocalModel(model)) {\n const children = [];\n\n for (const relation of getContainerRelations(model.static())) {\n const relationModels =\n (await model.loadRelationIfUnloaded<SolidModel | SolidModel[] | null>(relation)) ?? [];\n\n children.push(...arrayFrom(relationModels));\n }\n\n return children;\n }\n\n const children: Record<string, SolidModel[]> = {};\n const tombstones: Tombstone[] = [];\n const documents = map(model.documents, 'url');\n const documentUrlChunks = arrayChunk(model.resourceUrls, 10);\n const statusChildren = documentUrlChunks.flat().map((url) => ({\n documentUrl: url,\n completed: false,\n }));\n const statusChildrenMap = map(statusChildren, 'documentUrl');\n\n if (options.status) {\n options.status.children = statusChildren;\n }\n\n for (const documentUrls of documentUrlChunks) {\n await Promise.all(\n documentUrls.map(async (documentUrl) => {\n const { children: documentChildren, tombstones: documentTombstones } =\n await this.loadDocumentChildren(model, documentUrl, documents, options.onMalformedDocument);\n\n tombstones.push(...documentTombstones);\n\n for (const [relation, documentModels] of Object.entries(documentChildren)) {\n const relationChildren = (children[relation] ??= []);\n\n relationChildren.push(...documentModels);\n }\n }),\n );\n\n for (const documentUrl of documentUrls) {\n if (documentUrl.endsWith('/')) {\n continue;\n }\n\n required(statusChildrenMap.get(documentUrl)).completed = true;\n }\n\n await options.onLoaded?.(documentUrls);\n }\n\n for (const [relation, relationModels] of Object.entries(children)) {\n model.setRelationModels(relation, relationModels);\n }\n\n const childrenArray = options.ignoreTombstones\n ? Object.values(children).flat()\n : Object.values(children).flat().concat(tombstones);\n\n if (options.status) {\n options.status.children = childrenArray.map((child) => {\n return required(statusChildrenMap.get(child.requireDocumentUrl()));\n });\n }\n\n return childrenArray;\n }\n\n protected async loadDocumentChildren(\n model: SolidModel,\n documentUrl: string,\n documents: ObjectsMap<SolidDocument>,\n onMalformedDocument?: (url: string) => unknown,\n ): Promise<{ children: Record<string, SolidModel[]>; tombstones: Tombstone[] }> {\n const document = documents.get(documentUrl);\n\n if (\n document &&\n (await DocumentsCache.isFresh(document.url, document.updatedAt ?? new Date())) &&\n this.localModels?.hasKey(model.url)\n ) {\n return {\n children: await this.loadDocumentChildrenFromLocal(model, document),\n tombstones: [],\n };\n }\n\n return this.loadDocumentChildrenFromRemote(model, documentUrl, onMalformedDocument);\n }\n\n protected async loadDocumentChildrenFromLocal(\n model: SolidModel,\n document: SolidDocument,\n ): Promise<Record<string, SolidModel[]>> {\n const children: Record<string, SolidModel[]> = {};\n\n for (const relation of getContainerRelations(model.static())) {\n const relationInstance = model.requireRelation<SolidContainsRelation>(relation);\n\n if (relationInstance.loaded) {\n children[relation] = relationInstance.getLoadedModels();\n\n continue;\n }\n\n const relatedLocalModels = this.localModels?.get(model.url)?.getRelationModels(relation) ?? [];\n\n children[relation] = relatedLocalModels\n .filter((relatedLocalModel) => relatedLocalModel.getDocumentUrl() === document.url)\n .map((relatedLocalModel) => cloneLocalModel(relatedLocalModel, { clean: true }));\n }\n\n return children;\n }\n\n protected async loadDocumentChildrenFromRemote(\n model: SolidModel,\n documentUrl: string,\n onMalformedDocument?: (url: string) => unknown,\n ): Promise<{ children: Record<string, SolidModel[]>; tombstones: Tombstone[] }> {\n const children: Record<string, SolidModel[]> = {};\n const tombstones: Tombstone[] = [];\n const readDocument = lazy(async () => {\n try {\n const document = await model.requireEngine().readOne(model.static('collection'), documentUrl);\n const documentTombstones = await Tombstone.createManyFromEngineDocuments({\n [documentUrl]: document,\n });\n\n tombstones.push(...documentTombstones);\n\n return document;\n } catch (error) {\n if (isInstanceOf(error, DocumentNotFound)) {\n return null;\n }\n\n if (isInstanceOf(error, MalformedSolidDocumentError)) {\n // eslint-disable-next-line no-console\n console.warn(error.message);\n\n await onMalformedDocument?.(documentUrl);\n\n return null;\n }\n\n throw error;\n }\n });\n\n for (const relation of getContainerRelations(model.static())) {\n const relationInstance = model.requireRelation<SolidContainsRelation>(relation);\n\n if (relationInstance.loaded) {\n children[relation] = relationInstance.getLoadedModels();\n\n continue;\n }\n\n const document = await readDocument();\n\n if (!document) {\n continue;\n }\n\n const documentChildren = await relationInstance.relatedClass.createManyFromEngineDocuments({\n [documentUrl]: document,\n });\n\n children[relation] = documentChildren;\n }\n\n return { children, tombstones };\n }\n\n}\n","import { Solid } from '@aerogel/plugin-solid';\nimport type { SolidTypeIndex } from 'soukai-solid';\nimport type { SolidUserProfile } from '@noeldemartin/solid-utils';\n\nconst typeIndexes: WeakMap<SolidUserProfile, SolidTypeIndex | null> = new WeakMap();\n\nexport default class LoadsTypeIndex {\n\n protected async loadTypeIndex(options: { create: true }): Promise<SolidTypeIndex>;\n protected async loadTypeIndex(options?: { create: false }): Promise<SolidTypeIndex | null>;\n protected async loadTypeIndex(options: { create?: boolean } = {}): Promise<SolidTypeIndex | null> {\n const user = Solid.requireUser();\n\n if (options.create && !typeIndexes.get(user)) {\n typeIndexes.set(user, await Solid.findOrCreatePrivateTypeIndex());\n } else if (!typeIndexes.has(user)) {\n typeIndexes.set(user, await Solid.findPrivateTypeIndex());\n }\n\n return typeIndexes.get(user) ?? null;\n }\n\n}\n","import type { ObjectsMap } from '@noeldemartin/utils';\nimport type { SolidModel } from 'soukai-solid';\n\nimport { getContainerRelations } from '@aerogel/plugin-local-first/lib/inference';\n\nexport default class TracksLocalModels {\n\n declare protected localModels?: ObjectsMap<SolidModel>;\n\n protected async indexLocalModels(models: SolidModel[]): Promise<void> {\n for (const localModel of models) {\n await this.addLocalModel(localModel);\n }\n }\n\n protected async addLocalModel(localModel: SolidModel): Promise<void> {\n if (!this.localModels || this.localModels.hasKey(localModel.url)) {\n return;\n }\n\n this.localModels.add(localModel);\n\n for (const relation of getContainerRelations(localModel.static())) {\n await localModel.loadRelationIfUnloaded(relation);\n }\n\n for (const relatedModel of localModel.getRelatedModels()) {\n await this.addLocalModel(relatedModel);\n }\n }\n\n}\n","import { PropertyOperation, isContainer } from 'soukai-solid';\nimport { Job } from '@aerogel/core';\nimport { isInstanceOf, map, mixed, objectMap, tap } from '@noeldemartin/utils';\nimport type { JobListener, JobStatus } from '@aerogel/core';\nimport type { Nullable } from '@noeldemartin/utils';\nimport type { SolidModel, SolidTypeIndex } from 'soukai-solid';\n\nimport {\n clearSchemaMigrations,\n getRemoteClass,\n getSchemaMigration,\n getSchemaMigrations,\n} from '@aerogel/plugin-local-first/lib/mirroring';\nimport { getContainerRegisteredClasses } from '@aerogel/plugin-local-first/lib/inference';\n\nimport LoadsChildren from './mixins/LoadsChildren';\nimport LoadsTypeIndex from './mixins/LoadsTypeIndex';\nimport TracksLocalModels from './mixins/TracksLocalModels';\n\nconst BaseJob = Job as typeof Job<JobListener, MigrateJobStatus, MigrateJobStatus>;\n\nexport interface MigrateJobStatus extends JobStatus {\n children?: MigrateModelJobStatus[];\n}\n\nexport interface MigrateModelJobStatus extends JobStatus {\n modelUrl: string;\n children?: MigrateModelJobStatus[];\n}\n\nexport default class Migrate extends mixed(BaseJob, [LoadsChildren, LoadsTypeIndex, TracksLocalModels]) {\n\n public static restore(status: MigrateJobStatus): Migrate {\n return tap(new Migrate(), (job) => {\n job.status = status;\n });\n }\n\n protected _models?: SolidModel[];\n\n public get models(): SolidModel[] | undefined {\n return this._models;\n }\n\n public set models(models: SolidModel[] | undefined) {\n if (!models) {\n delete this._models;\n delete this.localModels;\n\n return;\n }\n\n const childrenStatus = objectMap(this.status.children ?? [], 'modelUrl');\n\n this._models = models;\n this.localModels = map([], 'url');\n this.status.children = models.map(\n (model) =>\n childrenStatus[model.url] ?? {\n modelUrl: model.url,\n completed: false,\n },\n );\n }\n\n protected async run(): Promise<void> {\n if (!this.models) {\n throw new Error('Cant start migration without models');\n }\n\n await this.indexLocalModels(this.models);\n\n const modelStatuses = this.status.children ?? [];\n const typeIndex = await this.loadTypeIndex();\n\n for (const modelStatus of modelStatuses) {\n const model = this.models.find(({ url }) => modelStatus.modelUrl === url);\n\n if (!model || modelStatus.completed) {\n continue;\n }\n\n await this.migrateRegisteredModel(model, modelStatus, typeIndex);\n await this.updateProgress(() => (modelStatus.completed = true));\n }\n\n for (const [modelClass, schema] of getSchemaMigrations()) {\n await modelClass.updateSchema(schema);\n }\n\n clearSchemaMigrations();\n }\n\n protected async migrateRegisteredModel(\n model: SolidModel,\n status: MigrateModelJobStatus,\n typeIndex?: Nullable<SolidTypeIndex>,\n ): Promise<void> {\n await this.migrate(model, status);\n\n if (!isContainer(model)) {\n return;\n }\n\n const registeredClasses = getContainerRegisteredClasses(model.static());\n const registration = typeIndex?.registrations.find(({ instanceContainer }) => instanceContainer === model.url);\n\n if (!typeIndex || !registration || registeredClasses.length === 0) {\n return;\n }\n\n registration.setAttribute(\n 'forClass',\n registeredClasses\n .map((modelClass) => getSchemaMigration(modelClass)?.rdfsClasses ?? modelClass.rdfsClass)\n .flat(),\n );\n\n await typeIndex.save();\n }\n\n protected async migrate(localModel: SolidModel, status: MigrateModelJobStatus): Promise<void> {\n this.assertNotCancelled();\n\n await this.migrateChildren(localModel, status);\n\n const schema = getSchemaMigration(localModel.static());\n\n if (!schema) {\n return;\n }\n\n const remoteModel = await getRemoteClass(localModel.static()).find(localModel.url);\n const migratedModel = await remoteModel?.migrateSchema(schema);\n\n await localModel.migrateSchema(schema, {\n mintOperationUrl: (operation) => {\n return migratedModel?.operations?.find((migratedOperation) => {\n if (\n !isInstanceOf(operation, PropertyOperation) ||\n !isInstanceOf(migratedOperation, PropertyOperation)\n ) {\n return false;\n }\n\n return (\n operation.property === migratedOperation.property &&\n operation.date.getTime() === migratedOperation.date.getTime()\n );\n })?.url;\n },\n });\n }\n\n protected async migrateChildren(localModel: SolidModel, status: MigrateModelJobStatus): Promise<void> {\n if (!isContainer(localModel)) {\n return;\n }\n\n const children = await this.loadContainedModels(localModel, { ignoreTombstones: true });\n\n status.children ??= children.map((child) => ({\n modelUrl: child.url,\n completed: false,\n }));\n\n for (const childStatus of status.children) {\n const child = children.find(({ url }) => childStatus.modelUrl === url);\n\n if (!child || childStatus.completed) {\n continue;\n }\n\n await this.migrate(child, childStatus);\n await this.updateProgress(() => (childStatus.completed = true));\n }\n }\n\n}\n","import { App, Job } from '@aerogel/core';\nimport { isInstanceOf, map, mixed, requireUrlParentDirectory, required, round } from '@noeldemartin/utils';\nimport { MalformedSolidDocumentError } from '@noeldemartin/solid-utils';\nimport { Solid } from '@aerogel/plugin-solid';\nimport { SolidModel, Tombstone, isContainer, isContainerClass } from 'soukai-solid';\nimport type { ObjectsMap } from '@noeldemartin/utils';\nimport type { JobListener, JobStatus } from '@aerogel/core';\nimport type { SolidContainsRelation, SolidEngine, SolidTypeRegistration } from 'soukai-solid';\n\nimport {\n clearLocalModelUpdates,\n cloneLocalModel,\n cloneRemoteModel,\n completeRemoteModels,\n getLocalModel,\n getLocalModels,\n getRemoteClass,\n getRemoteModel,\n isRegisteredModel,\n isRemoteModel,\n trackModelsCollection,\n} from '@aerogel/plugin-local-first/lib/mirroring';\nimport {\n getContainerRegisteredClasses,\n getContainerRelations,\n getRelatedAppModels,\n isDirtyOrHasDirtyChildren,\n} from '@aerogel/plugin-local-first/lib/inference';\nimport DocumentsCache from '@aerogel/plugin-local-first/services/DocumentsCache';\n\nimport LoadsChildren from './mixins/LoadsChildren';\nimport LoadsTypeIndex from './mixins/LoadsTypeIndex';\nimport TracksLocalModels from './mixins/TracksLocalModels';\nimport type { ResourceJobStatus } from './mixins/LoadsChildren';\n\nconst Cloud = required(() => App.service('$cloud'));\nconst BaseJob = Job as typeof Job<JobListener, SyncJobStatus, SyncJobStatus>;\n\ninterface SyncJobStatus extends JobStatus {\n root: true;\n children: [SyncPullJobStatus, JobStatus];\n}\n\ninterface SyncPullJobStatus extends JobStatus {\n children?: ResourceJobStatus[];\n}\n\nfunction isRootStatus(status?: JobStatus): status is SyncJobStatus {\n return !!status && 'root' in status;\n}\n\nexport default class Sync extends mixed(BaseJob, [LoadsChildren, LoadsTypeIndex, TracksLocalModels]) {\n\n protected models?: SolidModel[];\n protected dirtyRemoteModels?: SolidModel[];\n protected rootLocalModels: SolidModel[];\n protected tombstones: ObjectsMap<Tombstone>;\n protected malformedDocuments: Set<string>;\n protected documentsModifiedAt: Record<string, Date>;\n protected override localModels: ObjectsMap<SolidModel>;\n\n constructor(models?: SolidModel[]) {\n super();\n\n this.models = models;\n this.rootLocalModels = [];\n this.localModels = map([], 'url');\n this.tombstones = map([], 'resourceUrl');\n this.malformedDocuments = new Set();\n this.documentsModifiedAt = {};\n }\n\n protected async run(): Promise<void> {\n const engine = Solid.requireAuthenticator().engine as SolidEngine;\n const updateDocumentDate = (url: string, { headers }: { headers: Headers }) => {\n const date = headers?.get('last-modified');\n\n if (!date || url.endsWith('/')) {\n return;\n }\n\n this.documentsModifiedAt[url] = new Date(date);\n };\n const clearListener = engine.listeners.add({\n onDocumentRead: updateDocumentDate,\n onDocumentUpdated: updateDocumentDate,\n });\n\n try {\n this.rootLocalModels = this.models ?? getLocalModels();\n\n await this.indexLocalModels(this.rootLocalModels);\n await this.pullChanges();\n await this.pushChanges();\n } finally {\n clearListener();\n }\n }\n\n protected override getInitialStatus(): SyncJobStatus {\n return {\n root: true,\n completed: false,\n children: [{ completed: false }, { completed: false }],\n };\n }\n\n protected override calculateCurrentProgress(status?: JobStatus): number {\n status ??= this.status;\n\n if (isRootStatus(status)) {\n return round(\n this.calculateCurrentProgress(status.children[0]) * 0.9 +\n this.calculateCurrentProgress(status.children[1]) * 0.1,\n 2,\n );\n }\n\n return super.calculateCurrentProgress(status);\n }\n\n private async pullChanges(): Promise<void> {\n const remoteModelsArray = this.models\n ? await this.fetchRemoteModelsForLocal(this.models)\n : await this.fetchRemoteModels();\n const remoteModels = map(remoteModelsArray, (model) => {\n if (model instanceof Tombstone) {\n return model.resourceUrl;\n }\n\n return model.url;\n });\n\n this.dirtyRemoteModels = await this.synchronizeModels(remoteModels);\n\n await this.updateProgress((status) => (status.children[0].completed = true));\n }\n\n private async pushChanges(): Promise<void> {\n const remoteModels = this.dirtyRemoteModels ?? [];\n const childrenStatus = (this.status.children[1].children = remoteModels.map(() => ({ completed: false })));\n\n for (let index = 0; index < remoteModels.length; index++) {\n const remoteModel = remoteModels[index] as SolidModel;\n const childStatus = childrenStatus[index] as JobStatus;\n\n if (remoteModel.isSoftDeleted()) {\n remoteModel.enableHistory();\n remoteModel.enableTombstone();\n\n await remoteModel.delete();\n await this.updateProgress(() => (childStatus.completed = true));\n\n return;\n }\n\n await this.saveModelAndChildren(remoteModel, childStatus);\n await this.updateTypeRegistrations(remoteModel);\n await this.updateProgress(() => (childStatus.completed = true));\n }\n\n for (const [documentUrl, modifiedAt] of Object.entries(this.documentsModifiedAt)) {\n await DocumentsCache.remember(documentUrl, modifiedAt);\n }\n\n clearLocalModelUpdates(this.models, this.malformedDocuments);\n\n await this.updateProgress((status) => (status.children[1].completed = true));\n }\n\n private async fetchRemoteModels(): Promise<SolidModel[]> {\n const pullStatus = this.status.children[0];\n const typeIndex = await this.loadTypeIndex();\n\n if (!typeIndex) {\n return [];\n }\n\n const remoteModels: SolidModel[] = [];\n const processedContainerUrls = new Set();\n const registeredModels = [...Cloud.registeredModels].map(({ modelClass }) => {\n const registeredChildren = isContainerClass(modelClass) ? getContainerRegisteredClasses(modelClass) : [];\n\n return {\n modelClass,\n rdfsClasses:\n registeredChildren.length > 0\n ? registeredChildren.map((childrenClass) => childrenClass.rdfsClasses).flat()\n : modelClass.rdfsClasses,\n };\n });\n const registrations = typeIndex.registrations\n .map((registration) => {\n const registeredModel = registeredModels.find(\n ({ rdfsClasses }) =>\n !!registration.instanceContainer &&\n rdfsClasses.some((rdfsClass) => registration.forClass.includes(rdfsClass)),\n );\n\n if (\n !registeredModel ||\n !registration.instanceContainer ||\n processedContainerUrls.has(registration.instanceContainer)\n ) {\n return null;\n }\n\n processedContainerUrls.add(registration.instanceContainer);\n\n return [registration, registeredModel] as [SolidTypeRegistration, (typeof registeredModels)[number]];\n })\n .filter((match) => !!match);\n\n pullStatus.children = registrations.map(() => ({ completed: false }));\n\n for (let index = 0; index < registrations.length; index++) {\n await this.ignoringMalformedDocumentErrors(async () => {\n const registration = required(registrations[index])[0];\n const registeredModel = required(registrations[index])[1];\n const remoteClass = getRemoteClass(registeredModel.modelClass);\n\n if (!registration.instanceContainer) {\n return;\n }\n\n if (isContainerClass(remoteClass)) {\n await trackModelsCollection(\n registeredModel.modelClass,\n requireUrlParentDirectory(registration.instanceContainer),\n );\n\n const container = await remoteClass.find(registration.instanceContainer);\n\n if (container) {\n await this.loadChildren(container, required(pullStatus.children?.[index]));\n\n remoteModels.push(container);\n }\n\n await this.updateProgress(() => (required(pullStatus.children?.[index]).completed = true));\n\n return;\n }\n\n await trackModelsCollection(registeredModel.modelClass, registration.instanceContainer);\n\n remoteModels.push(...(await remoteClass.from(registration.instanceContainer).all()));\n\n await this.updateProgress(() => (required(pullStatus.children?.[index]).completed = true));\n });\n }\n\n return completeRemoteModels(this.rootLocalModels, remoteModels, this.malformedDocuments);\n }\n\n private async fetchRemoteModelsForLocal(models: SolidModel[]): Promise<SolidModel[]> {\n const remoteModels = [] as SolidModel[];\n const statusChildren = (this.status.children[0].children = models.map(() => ({ completed: false })));\n\n for (let index = 0; index < models.length; index++) {\n await this.ignoringMalformedDocumentErrors(async () => {\n const localModel = models[index] as SolidModel;\n const childStatus = statusChildren[index] as JobStatus;\n const remoteModel = await getRemoteClass(localModel.static()).find(localModel.url);\n\n if (!remoteModel) {\n await this.updateProgress(() => (childStatus.completed = true));\n\n return;\n }\n\n isContainer(remoteModel) && (await this.loadChildren(remoteModel, childStatus));\n\n remoteModels.push(remoteModel);\n\n await this.updateProgress(() => (childStatus.completed = true));\n });\n }\n\n return completeRemoteModels(models, remoteModels, this.malformedDocuments);\n }\n\n private async updateTypeRegistrations(remoteModel: SolidModel): Promise<void> {\n if (!isContainer(remoteModel) || !isRegisteredModel(remoteModel)) {\n return;\n }\n\n const registeredChildren = getContainerRegisteredClasses(remoteModel.static());\n\n if (registeredChildren.length === 0) {\n return;\n }\n\n const typeIndex = await this.loadTypeIndex({ create: true });\n\n if (typeIndex.registrations.some((registration) => registration.instanceContainer === remoteModel.url)) {\n return;\n }\n\n await remoteModel.register(typeIndex, registeredChildren);\n }\n\n private async loadChildren(model: SolidModel, childStatus?: JobStatus): Promise<void> {\n this.assertNotCancelled();\n\n if (!isContainer(model)) {\n return;\n }\n\n const children = await this.loadContainedModels(model, {\n status: childStatus,\n onLoaded: async () => {\n this.assertNotCancelled();\n\n await this.updateProgress();\n },\n onMalformedDocument: (url) => this.malformedDocuments.add(url),\n });\n\n for (let index = 0; index < children.length; index++) {\n const child = children[index] as SolidModel;\n\n if (child instanceof Tombstone) {\n this.tombstones.add(child);\n\n continue;\n }\n\n if (this.tombstones.hasKey(child.url)) {\n await this.deleteChild(model, child);\n\n continue;\n }\n\n await this.loadChildren(child, childStatus?.children?.[index]);\n\n if (childStatus?.children?.[index]) {\n await this.updateProgress(() => (required(childStatus.children?.[index]).completed = true));\n }\n }\n }\n\n private async deleteChild(model: SolidModel, child: SolidModel): Promise<void> {\n for (const relation of model.static('relations')) {\n const relationInstance = model.requireRelation(relation);\n\n if (!relationInstance.related) {\n continue;\n }\n\n if (Array.isArray(relationInstance.related)) {\n relationInstance.related = relationInstance.related.filter((relatedModel) => relatedModel !== child);\n\n continue;\n }\n\n if (relationInstance.related === child) {\n relationInstance.related = null;\n\n continue;\n }\n }\n\n await child.delete();\n }\n\n private async saveModelAndChildren(model: SolidModel, status?: JobStatus): Promise<void> {\n this.assertNotCancelled();\n\n if (isRemoteModel(model) && model.isSoftDeleted()) {\n model.enableHistory();\n model.enableTombstone();\n await model.delete();\n\n return;\n }\n\n if (this.malformedDocuments.has(model.requireDocumentUrl())) {\n return;\n }\n\n await model.save();\n\n if (!isContainer(model)) {\n if (isRemoteModel(model)) {\n const documentUrl = model.requireDocumentUrl();\n const modifiedAt = this.documentsModifiedAt[documentUrl] ?? new Date();\n\n await DocumentsCache.remember(documentUrl, modifiedAt);\n\n delete this.documentsModifiedAt[documentUrl];\n }\n\n return;\n }\n\n const children = getContainerRelations(model.static())\n .map((relation) => model.getRelationModels(relation) ?? [])\n .flat();\n\n const childrenStatuses = status ? children.map(() => ({ completed: false })) : [];\n\n if (status) {\n status.children = childrenStatuses;\n }\n\n for (let index = 0; index < children.length; index++) {\n const child = children[index] as SolidModel;\n const childStatus = childrenStatuses[index];\n\n await this.saveModelAndChildren(child, childStatus);\n\n if (childStatus) {\n await this.updateProgress(() => (childStatus.completed = true));\n }\n }\n }\n\n private async synchronizeModels(remoteModels: ObjectsMap<SolidModel>): Promise<SolidModel[]> {\n const synchronizedModelUrls = new Set<string>();\n const deletedModels = new Set<SolidModel>();\n\n for (const remoteModel of remoteModels.items()) {\n if (remoteModel instanceof Tombstone) {\n const localModel = this.localModels.get(remoteModel.resourceUrl);\n\n if (localModel) {\n await localModel.delete();\n\n deletedModels.add(localModel);\n }\n\n continue;\n }\n\n const localModel = getLocalModel(remoteModel, this.localModels);\n\n await this.loadChildren(localModel);\n await SolidModel.synchronize(localModel, remoteModel);\n await this.reconcileInconsistencies(localModel, remoteModel);\n await this.saveModelAndChildren(localModel);\n await this.addLocalModel(localModel);\n\n this.rootLocalModels.push(localModel);\n synchronizedModelUrls.add(localModel.url);\n }\n\n for (const localModel of this.rootLocalModels) {\n if (deletedModels.has(localModel) || synchronizedModelUrls.has(localModel.url)) {\n continue;\n }\n\n await this.loadChildren(localModel);\n\n const remoteModel = getRemoteModel(localModel, remoteModels);\n\n await SolidModel.synchronize(localModel, remoteModel);\n\n remoteModels.add(remoteModel);\n }\n\n const dirtyRemoteModels = [];\n\n for (const remoteModel of remoteModels.getItems()) {\n if (isDirtyOrHasDirtyChildren(remoteModel)) {\n dirtyRemoteModels.push(remoteModel);\n\n continue;\n }\n\n await this.rememberModelDocuments(remoteModel);\n }\n\n return dirtyRemoteModels;\n }\n\n private async reconcileInconsistencies(\n localModel: SolidModel,\n remoteModel: SolidModel,\n processedModels?: Set<SolidModel>,\n ): Promise<void> {\n localModel.rebuildAttributesFromHistory();\n localModel.setAttributes(remoteModel.getAttributes(true));\n\n processedModels ??= new Set();\n processedModels.add(localModel);\n\n for (const relation of getContainerRelations(localModel.static())) {\n await this.synchronizeContainerDocuments(\n localModel.requireRelation<SolidContainsRelation>(relation),\n remoteModel.requireRelation<SolidContainsRelation>(relation),\n );\n }\n\n const remoteRelatedModels = map(getRelatedAppModels(remoteModel), 'url');\n\n for (const localRelatedModel of getRelatedAppModels(localModel)) {\n if (\n processedModels.has(localRelatedModel) ||\n !localRelatedModel.isRelationLoaded('operations') ||\n !remoteRelatedModels.hasKey(localRelatedModel.url)\n ) {\n continue;\n }\n\n await this.reconcileInconsistencies(localRelatedModel, remoteRelatedModels.require(localRelatedModel.url));\n }\n\n if (localModel.isDirty()) {\n await localModel.save();\n await SolidModel.synchronize(localModel, remoteModel);\n }\n }\n\n private async synchronizeContainerDocuments(\n localRelation: SolidContainsRelation,\n remoteRelation: SolidContainsRelation,\n ): Promise<void> {\n const localModels = map(localRelation.related ?? [], 'url');\n const remoteModels = map(remoteRelation.related ?? [], 'url');\n const newLocalModelUrls = localModels\n .getKeys()\n .filter((url) => !remoteModels.hasKey(url) && !remoteModels.hasKey(encodeURI(url)));\n const newRemoteModelUrls = remoteModels\n .getKeys()\n .filter((url) => !localModels.hasKey(url) && !localModels.hasKey(encodeURI(url)));\n\n for (const url of newLocalModelUrls) {\n const localModel = localModels.require(url);\n const remoteModel = cloneLocalModel(localModel);\n\n remoteRelation.addRelated(remoteModel);\n remoteModels.add(remoteModel);\n }\n\n for (const url of newRemoteModelUrls) {\n const remoteModel = remoteModels.require(url);\n const localModel = cloneRemoteModel(remoteModel);\n\n localRelation.addRelated(localModel);\n localModels.add(localModel);\n }\n\n for (const localModel of localModels.items()) {\n const remoteModel = remoteModels.require(localModel.url);\n\n await SolidModel.synchronize(localModel, remoteModel);\n await this.saveModelAndChildren(localModel);\n }\n }\n\n private async rememberModelDocuments(model: SolidModel): Promise<void> {\n if (!isContainer(model)) {\n const documentUrl = model.requireDocumentUrl();\n const modifiedAt = this.documentsModifiedAt[documentUrl] ?? new Date();\n\n await DocumentsCache.remember(documentUrl, modifiedAt);\n\n delete this.documentsModifiedAt[documentUrl];\n\n return;\n }\n\n const children = getContainerRelations(model.static())\n .map((relation) => model.getRelationModels(relation) ?? [])\n .flat();\n\n for (const child of children) {\n await this.rememberModelDocuments(child);\n }\n }\n\n private async ignoringMalformedDocumentErrors(operation: Function): Promise<void> {\n try {\n await operation();\n } catch (error) {\n if (isInstanceOf(error, MalformedSolidDocumentError)) {\n // eslint-disable-next-line no-console\n console.warn(error.message);\n\n error.documentUrl && this.malformedDocuments.add(error.documentUrl);\n\n return;\n }\n\n throw error;\n }\n }\n\n}\n","import { defineServiceState, replaceExisting, translateWithDefault } from '@aerogel/core';\nimport { Solid } from '@aerogel/plugin-solid';\nimport type { ErrorSource } from '@aerogel/core';\nimport type { Nullable } from '@noeldemartin/utils';\nimport type { SolidModelConstructor, SolidSchemaDefinition } from 'soukai-solid';\n\nimport Migrate from '@aerogel/plugin-local-first/jobs/Migrate';\nimport type Sync from '@aerogel/plugin-local-first/jobs/Sync';\n\nexport const CloudStatus = {\n Disconnected: 'disconnected',\n Online: 'online',\n Syncing: 'syncing',\n Migrating: 'migrating',\n} as const;\n\nexport interface ModelRegistration {\n modelClass: SolidModelConstructor;\n path?: string;\n}\n\nexport type TCloudStatus = (typeof CloudStatus)[keyof typeof CloudStatus];\n\nexport default defineServiceState({\n name: 'cloud',\n persist: [\n 'localModelUpdates',\n 'migrationDismissed',\n 'migrationJob',\n 'modelCollections',\n 'pollingEnabled',\n 'pollingMinutes',\n 'ready',\n 'startupSync',\n ],\n initialState: () => ({\n autoPush: true,\n localModelUpdates: {} as Record<string, number>,\n migrationDismissed: false,\n migrationJob: null as Nullable<Migrate>,\n migrationPostponed: false,\n modelCollections: {} as Record<string, string[]>,\n pollingEnabled: true,\n pollingMinutes: 10,\n ready: false,\n registeredModels: [] as ModelRegistration[],\n schemaMigrations: new Map<SolidModelConstructor, SolidModelConstructor | SolidSchemaDefinition>(),\n setupDismissed: false,\n setupOngoing: false,\n startupSync: true,\n status: CloudStatus.Disconnected as TCloudStatus,\n syncError: null as Nullable<ErrorSource>,\n syncJob: null as Nullable<Sync>,\n }),\n serialize: (state) => replaceExisting(state, { migrationJob: state.migrationJob?.serialize() }),\n restore: (state) =>\n replaceExisting(state, {\n migrationJob: state.migrationJob && Migrate.restore(state.migrationJob),\n }),\n watch: {\n migrationJob(migrationJob) {\n migrationJob?.listeners.add({ onUpdated: () => this.updatePersistedState('migrationJob') });\n },\n },\n computed: {\n disconnected: ({ status }) => status === CloudStatus.Disconnected,\n online: ({ status }) => status === CloudStatus.Online,\n syncing: ({ status }) => status === CloudStatus.Syncing,\n migrating: ({ status }) => status === CloudStatus.Migrating,\n localChanges({ localModelUpdates }) {\n return Object.values(localModelUpdates).reduce((total, count) => total + count, 0);\n },\n dirty(): boolean {\n return this.localChanges > 0;\n },\n migrationStarted({ migrationJob }): boolean {\n return !!migrationJob;\n },\n migrationDisabledReason({ status, ready }): string | null {\n if (!Solid.isLoggedIn()) {\n return translateWithDefault(\n 'cloud.migrationNotLoggedIn',\n 'You need to reconnect before starting the migration',\n );\n }\n\n if (!ready) {\n return translateWithDefault(\n 'cloud.migrationNotReady',\n 'You need to backup your data before starting the migration',\n );\n }\n\n if (status === CloudStatus.Syncing || status === CloudStatus.Migrating) {\n return translateWithDefault(\n 'cloud.migrationNotSyncing',\n 'Wait for syncing to finish before starting the migration',\n );\n }\n\n if (!this.online) {\n return translateWithDefault(\n 'cloud.migrationNotOnline',\n 'You need to be online in order to start the migration',\n );\n }\n\n return null;\n },\n },\n});\n","import {\n Semaphore,\n after,\n facade,\n fail,\n getLocationQueryParameter,\n hasLocationQueryParameter,\n isArray,\n isTesting,\n parseBoolean,\n} from '@noeldemartin/utils';\nimport { Errors, Events, dispatch, translateWithDefault } from '@aerogel/core';\nimport { Solid } from '@aerogel/plugin-solid';\nimport { SolidModel, Tombstone, isContainer, isContainerClass } from 'soukai-solid';\nimport { getTrackedModels, trackModels, trackModelsCollection } from '@aerogel/plugin-soukai';\nimport { watchEffect } from 'vue';\nimport type { Authenticator } from '@aerogel/plugin-solid';\nimport type { Engine } from 'soukai';\nimport type { JobListener } from '@aerogel/core';\nimport type { SolidContainsRelation, SolidModelConstructor, SolidSchemaDefinition } from 'soukai-solid';\n\nimport {\n clearLocalModelUpdates,\n createRemoteModel,\n getLocalModels,\n getRemoteClass,\n getRemoteContainersCollection,\n updateRemoteModel,\n} from '@aerogel/plugin-local-first/lib/mirroring';\nimport Backup from '@aerogel/plugin-local-first/jobs/Backup';\nimport Migrate from '@aerogel/plugin-local-first/jobs/Migrate';\nimport Sync from '@aerogel/plugin-local-first/jobs/Sync';\nimport SyncQueue from '@aerogel/plugin-local-first/lib/SyncQueue';\nimport {\n getContainedModels,\n getContainerRelations,\n getRelatedClasses,\n} from '@aerogel/plugin-local-first/lib/inference';\n\nimport Service, { CloudStatus } from './Cloud.state';\n\nexport interface RegisterOptions {\n path?: string;\n}\n\nexport interface SyncOptions extends JobListener {\n refreshUserProfile?: boolean;\n model?: SolidModel;\n models?: SolidModel[];\n}\n\nexport class CloudService extends Service {\n\n protected asyncLock: Semaphore = new Semaphore();\n protected engine: Engine | null = null;\n protected pollingInterval: NodeJS.Timeout | null = null;\n\n public async whenReady<T>(callback: () => T): Promise<T> {\n if (this.ready) {\n return callback();\n }\n\n return new Promise((resolve) => {\n const onReady = () => resolve(callback());\n\n Events.once('cloud:ready', onReady);\n });\n }\n\n public async setup(modelUrlMappings?: WeakMap<SolidModelConstructor, Record<string, string>>): Promise<void> {\n this.setupOngoing = true;\n\n try {\n await this.backup(modelUrlMappings);\n await this.setReady(true);\n await this.sync();\n } finally {\n this.setupOngoing = false;\n }\n }\n\n public dismissSetup(): void {\n this.setupDismissed = true;\n }\n\n public dismissMigration(): void {\n this.migrationDismissed = true;\n }\n\n public postponeMigration(): void {\n this.migrationPostponed = true;\n }\n\n public async syncIfOnline(options?: SyncOptions): Promise<void>;\n public async syncIfOnline(model: SolidModel): Promise<void>;\n public async syncIfOnline(models: SolidModel[]): Promise<void>;\n public async syncIfOnline(config: SyncOptions | SolidModel | SolidModel[] = {}): Promise<void> {\n if (!this.online) {\n return;\n }\n\n await this.sync(config as SyncOptions);\n }\n\n public async sync(options?: SyncOptions): Promise<void>;\n public async sync(model: SolidModel): Promise<void>;\n public async sync(models: SolidModel[]): Promise<void>;\n public async sync(config: SyncOptions | SolidModel | SolidModel[] = {}): Promise<void> {\n const options = isArray(config)\n ? { models: config }\n : config instanceof SolidModel\n ? { model: config }\n : config;\n\n if (!Solid.isLoggedIn() || !this.ready || !this.online) {\n return;\n }\n\n await this.asyncLock.run(async () => {\n const start = Date.now();\n const models = options.model ? [options.model] : options.models;\n\n this.syncError = null;\n this.status = CloudStatus.Syncing;\n\n SyncQueue.clear(models);\n\n try {\n await Events.emit('cloud:sync-started', models);\n\n if (options.refreshUserProfile) {\n await Solid.refreshUserProfile();\n }\n\n this.syncJob = new Sync(models);\n\n this.syncJob.listeners.add(options);\n\n await dispatch(this.syncJob);\n\n if (this.syncJob.cancelled) {\n return;\n }\n\n if (!isTesting()) {\n await after({ milliseconds: Math.max(500, 1000 - (Date.now() - start)) });\n }\n\n this.syncJob = null;\n } catch (error) {\n if (isTesting()) {\n throw error;\n }\n\n this.syncJob = null;\n this.syncError = error;\n\n await Errors.report(error, translateWithDefault('cloud.syncFailed', 'Sync failed'));\n } finally {\n this.status = CloudStatus.Online;\n\n await Events.emit('cloud:sync-completed', models);\n }\n });\n }\n\n public shouldMigrate(): boolean {\n return this.schemaMigrations.size > 0;\n }\n\n public async migrate(listener?: JobListener): Promise<void> {\n if (!this.online || !Solid.isLoggedIn() || !this.ready) {\n throw new Error('Data cannot be migrated at the moment');\n }\n\n if (!this.shouldMigrate()) {\n return;\n }\n\n await this.asyncLock.run(async () => {\n this.status = CloudStatus.Migrating;\n this.migrationJob ??= new Migrate();\n\n const start = Date.now();\n const removeListeners: Function[] = [];\n const models = (this.migrationJob.models ??= getLocalModels());\n\n SyncQueue.clear(models);\n\n try {\n listener && removeListeners.push(this.migrationJob.listeners.add(listener));\n\n await Events.emit('cloud:migration-started', models);\n await dispatch(this.migrationJob);\n\n if (this.migrationJob.cancelled) {\n await Events.emit('cloud:migration-cancelled', models);\n\n return;\n }\n\n this.migrationJob = null;\n this.migrationDismissed = false;\n this.migrationPostponed = false;\n\n await after({ milliseconds: Math.max(0, 1000 - (Date.now() - start)) });\n await Events.emit('cloud:migration-completed', models);\n } catch (error) {\n await Errors.report(error, translateWithDefault('cloud.migrationFailed', 'Migration failed'));\n } finally {\n this.status = CloudStatus.Online;\n\n removeListeners.forEach((removeListener) => removeListener?.());\n }\n });\n }\n\n public async register(modelClass: SolidModelConstructor, options: RegisterOptions = {}): Promise<void> {\n if (this.registeredModels.find((registered) => modelClass === registered.modelClass)) {\n return;\n }\n\n const engine = this.engine;\n\n if (engine) {\n getRelatedClasses(modelClass).forEach((relatedClass) => getRemoteClass(relatedClass).setEngine(engine));\n }\n\n this.whenReady(() => {\n if (!isContainerClass(modelClass)) {\n return;\n }\n\n modelClass.collection = getRemoteContainersCollection(options.path);\n });\n\n await trackModels(modelClass, {\n created: (model) => createRemoteModel(model),\n updated: (model) => updateRemoteModel(model),\n deleted: (model) => clearLocalModelUpdates([model]),\n });\n\n if (isContainerClass(modelClass)) {\n getContainerRelations(modelClass).forEach((relation) => {\n const relatedClass = modelClass\n .instance()\n .requireRelation<SolidContainsRelation>(relation).relatedClass;\n\n relatedClass.on('created', (model) => createRemoteModel(model));\n relatedClass.on('updated', (model) => updateRemoteModel(model));\n relatedClass.on('deleted', (model) => clearLocalModelUpdates([model]));\n });\n }\n\n this.registeredModels.push({ modelClass, path: options.path });\n\n for (const collection of this.modelCollections[modelClass.modelName] ?? []) {\n await trackModelsCollection(modelClass, collection);\n }\n }\n\n public registerSchemaMigration(\n modelClass: SolidModelConstructor,\n schema: SolidModelConstructor | SolidSchemaDefinition,\n ): void {\n this.schemaMigrations.set(modelClass, schema);\n }\n\n public requireRemoteCollection(modelClass: SolidModelConstructor): string {\n for (const registration of this.registeredModels) {\n if (modelClass !== registration.modelClass) {\n continue;\n }\n\n return getRemoteContainersCollection(registration.path);\n }\n\n throw new Error(`Failed resolving remote collection for '${modelClass.modelName}' model`);\n }\n\n protected override async boot(): Promise<void> {\n await Solid.booted;\n\n Solid.isLoggedIn() && this.login(Solid.authenticator);\n\n Events.on('auth:login', ({ authenticator }) => this.login(authenticator));\n Events.on('auth:logout', () => this.logout());\n Events.once('application-ready', () => this.onApplicationReady());\n Events.once('application-mounted', () => this.onApplicationMounted());\n\n watchEffect(() => {\n this.pollingInterval && clearInterval(this.pollingInterval);\n\n if (!this.pollingEnabled || this.migrationJob) {\n this.pollingInterval = null;\n\n return;\n }\n\n this.pollingInterval = setInterval(() => this.sync(), this.pollingMinutes * 60 * 1000);\n });\n }\n\n protected getDirtyLocalModels(): SolidModel[] {\n const urls = Object.keys(this.localModelUpdates);\n const dirtyLocalModels = [];\n\n for (const { modelClass } of this.registeredModels) {\n for (const model of getTrackedModels(modelClass)) {\n dirtyLocalModels.push(...this.getModelsIn(urls, model));\n }\n }\n\n return dirtyLocalModels;\n }\n\n protected getModelsIn(urls: string[], model: SolidModel): SolidModel[] {\n const models = [];\n\n if (urls.includes(model.url)) {\n models.push(model);\n }\n\n if (isContainer(model)) {\n models.push(\n ...getContainedModels(model)\n .map((containedModel) => this.getModelsIn(urls, containedModel))\n .flat(),\n );\n }\n\n return models;\n }\n\n protected requireEngine(): Engine {\n return this.engine ?? fail('Could not get required Engine');\n }\n\n protected async setReady(ready: boolean): Promise<void> {\n if (this.ready || !ready) {\n return;\n }\n\n await Events.emit('cloud:ready');\n\n this.ready = true;\n }\n\n protected async backup(modelUrlMappings?: WeakMap<SolidModelConstructor, Record<string, string>>): Promise<void> {\n await Events.emit('cloud:backup-started');\n\n modelUrlMappings ??= new WeakMap();\n\n const job = new Backup();\n\n for (const { modelClass, path } of this.registeredModels) {\n if (!isContainerClass(modelClass)) {\n continue;\n }\n\n for (const [local, remote] of Object.entries(modelUrlMappings.get(modelClass) ?? {})) {\n job.migrateUrl(modelClass, local, remote);\n }\n\n const localCollection = modelClass.collection;\n const remoteCollection = getRemoteContainersCollection(path);\n\n modelClass.collection = remoteCollection;\n\n job.migrateCollection(modelClass, localCollection, remoteCollection);\n }\n\n await dispatch(job);\n await Events.emit('cloud:backup-completed');\n }\n\n protected async onApplicationReady(): Promise<void> {\n if (this.ready || !Solid.isLoggedIn()) {\n return;\n }\n\n await this.setReady(!getLocalModels().some((model) => model.url.startsWith('solid://')));\n }\n\n protected async onApplicationMounted(): Promise<void> {\n if (!this.syncOnStartup()) {\n return;\n }\n\n await this.sync();\n }\n\n protected login(authenticator: Authenticator): void {\n const relatedClasses = [...this.registeredModels]\n .map(({ modelClass }) => getRelatedClasses(modelClass))\n .flat()\n .concat([Tombstone]);\n\n this.status = CloudStatus.Online;\n this.engine = authenticator.engine;\n\n for (const relatedClass of relatedClasses) {\n getRemoteClass(relatedClass).setEngine(this.engine);\n }\n }\n\n protected logout(): void {\n this.setState({\n localModelUpdates: {},\n migrationDismissed: false,\n migrationJob: null,\n migrationPostponed: false,\n modelCollections: {},\n pollingEnabled: true,\n pollingMinutes: 10,\n ready: false,\n setupDismissed: false,\n setupOngoing: false,\n startupSync: true,\n status: CloudStatus.Disconnected,\n });\n }\n\n private syncOnStartup(): boolean {\n if (hasLocationQueryParameter('startupSync')) {\n return parseBoolean(getLocationQueryParameter('startupSync'));\n }\n\n if (this.migrationJob) {\n return false;\n }\n\n return this.startupSync;\n }\n\n}\n\nexport default facade(CloudService);\n\ndeclare module '@aerogel/core' {\n export interface EventsPayload {\n 'cloud:ready': void;\n 'cloud:backup-started': void;\n 'cloud:backup-completed': void;\n 'cloud:migration-started': SolidModel[];\n 'cloud:migration-cancelled': SolidModel[];\n 'cloud:migration-completed': SolidModel[];\n 'cloud:sync-started': SolidModel[] | undefined;\n 'cloud:sync-completed': SolidModel[] | undefined;\n }\n}\n","import { bootServices } from '@aerogel/core';\nimport type { Plugin } from '@aerogel/core';\n\nimport Cloud from '@aerogel/plugin-local-first/services/Cloud';\nimport DocumentsCache from '@aerogel/plugin-local-first/services/DocumentsCache';\n\nconst services = { $cloud: Cloud };\n\nexport { Cloud };\nexport * from './components';\nexport * from './services/Cloud';\n\nexport type LocalFirstServices = typeof services;\n\nexport default function localFirst(): Plugin {\n return {\n name: '@aerogel/local-first',\n async install(app) {\n await bootServices(app, {\n ...services,\n $_documentsCache: DocumentsCache,\n });\n },\n };\n}\n\ndeclare module '@aerogel/core' {\n interface Services extends LocalFirstServices {}\n}\n"],"names":["containerRelations","getContainerRegisteredClasses","modelClass","arrayFilter","getContainerRelations","relation","relatedClass","isContainerClass","SolidModel","SolidContainsRelation","getContainedModels","model","models","getRelatedClasses","relatedClasses","instance","getRelatedAppModels","related","isInstanceOf","SolidACLAuthorization","SolidDocument","Metadata","Operation","SolidContainer","isDirtyOrHasDirtyChildren","relationHasDirtyModels","_a","relatedModel","Cloud","required","App","SyncQueue","__publicField","after","operationOrPromise","promise","arrayRemove","children","isContainer","child","SyncQueue$1","facade","remoteClasses","localClasses","cleanRemoteModelClone","remoteModel","relatedModels","fixRemoteModelClone","operations","operation","PropertyOperation","createRemoteModel","localModel","isRegisteredModelClass","trackModelsCollection","requireUrlParentDirectory","collection","trackSoukaiModelsCollection","updateRemoteModel","ignoreModelUpdates","modelUpdates","objectWithout","clearLocalModelUpdates","malformedDocuments","syncedModelUrls","toString","localModelUpdates","url","count","documentUrl","urlRoute","modelUrl","cloneLocalModel","options","localModelClasses","constructors","localClass","getRemoteClass","tap","cloneRemoteModel","remoteModelClasses","remoteClass","getLocalClass","completeRemoteModels","localModels","remoteModels","RemoteTombstone","Tombstone","remoteModelUrls","missingModelDocumentUrls","tombstones","updatedAt","getLocalModel","getLocalModels","getTrackedModels","getSchemaMigrations","clearSchemaMigrations","getSchemaMigration","makeRemoteClass","getRemoteContainersCollection","path","rootStorage","Solid","urlResolveDirectory","getRemoteModel","isRegisteredModel","registeredModel","isRemoteModel","isLocalModel","registeredModelClass","LocalClass","withLocalHistoryConfig","RemoteClass","attributes","exists","schema","bootModels","fail","Backup","Job","local","remote","engine","requireEngine","collections","documents","id","document","ignoreModelsCollection","key","value","DocumentsCacheService","Service","IndexedDBMap","modifiedAt","meta","modifiedAtTime","Events","DocumentsCache","lazy","getter","result","LoadsChildren","relationModels","arrayFrom","map","documentUrlChunks","arrayChunk","statusChildren","statusChildrenMap","documentUrls","documentChildren","documentTombstones","documentModels","childrenArray","onMalformedDocument","relationInstance","relatedLocalModels","_b","relatedLocalModel","readDocument","error","DocumentNotFound","MalformedSolidDocumentError","typeIndexes","LoadsTypeIndex","user","TracksLocalModels","BaseJob","Migrate","mixed","status","job","childrenStatus","objectMap","modelStatuses","typeIndex","modelStatus","registeredClasses","registration","instanceContainer","migratedModel","migratedOperation","childStatus","isRootStatus","Sync","updateDocumentDate","headers","date","clearListener","round","remoteModelsArray","index","pullStatus","processedContainerUrls","registeredModels","registeredChildren","childrenClass","registrations","rdfsClasses","rdfsClass","match","container","childrenStatuses","synchronizedModelUrls","deletedModels","dirtyRemoteModels","processedModels","remoteRelatedModels","localRelatedModel","localRelation","remoteRelation","newLocalModelUrls","newRemoteModelUrls","CloudStatus","defineServiceState","state","replaceExisting","migrationJob","total","ready","translateWithDefault","CloudService","Semaphore","callback","resolve","onReady","modelUrlMappings","config","isArray","start","dispatch","isTesting","Errors","listener","removeListeners","removeListener","registered","trackModels","authenticator","watchEffect","urls","dirtyLocalModels","containedModel","localCollection","remoteCollection","hasLocationQueryParameter","parseBoolean","getLocationQueryParameter","services","localFirst","app","bootServices"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@aerogel/plugin-local-first",
3
+ "version": "0.0.0-next.0d1cf82f9dfbe1d3e7ec5644f85f97a43c8c2334",
4
+ "type": "module",
5
+ "sideEffects": false,
6
+ "exports": {
7
+ "types": "./dist/aerogel-plugin-local-first.d.ts",
8
+ "default": "./dist/aerogel-plugin-local-first.js"
9
+ },
10
+ "files": [
11
+ "src",
12
+ "dist"
13
+ ],
14
+ "license": "MIT",
15
+ "author": "Noel De Martin",
16
+ "repository": "github:NoelDeMartin/aerogel",
17
+ "scripts": {
18
+ "build": "vite build",
19
+ "lint": "noeldemartin-lint src",
20
+ "test": "vitest --run",
21
+ "test:ci": "vitest --run --reporter verbose",
22
+ "verify": "noeldemartin-verify"
23
+ },
24
+ "peerDependencies": {
25
+ "@aerogel/core": "*",
26
+ "@aerogel/plugin-solid": "*",
27
+ "@aerogel/plugin-soukai": "*",
28
+ "soukai": "*",
29
+ "soukai-solid": "*"
30
+ },
31
+ "dependencies": {
32
+ "@noeldemartin/solid-utils": "0.6.0-next.508449b33de64b0bcade86b642c9793381434231",
33
+ "@noeldemartin/utils": "0.7.0-next.26f0bbb6596310f174e1ea368f158997a01c3081",
34
+ "idb": "^8.0.2",
35
+ "vue": "^3.3.0"
36
+ },
37
+ "devDependencies": {
38
+ "@aerogel/core": "*",
39
+ "@aerogel/plugin-solid": "*",
40
+ "@aerogel/plugin-soukai": "*",
41
+ "fake-indexeddb": "^6.0.0",
42
+ "soukai": "*",
43
+ "soukai-solid": "*"
44
+ },
45
+ "eslintConfig": {
46
+ "extends": [
47
+ "@noeldemartin/eslint-config-vue"
48
+ ]
49
+ }
50
+ }
@@ -0,0 +1,31 @@
1
+ <template>
2
+ <AGSolidStatus>
3
+ <template #logged-in="{ session }: IAGSolidStatusLoggedInSlotProps">
4
+ <AGMarkdown v-if="$cloud.syncing" :text="$td('cloud.syncing', 'Syncing...')" />
5
+ <div v-else class="flex flex-col gap-3">
6
+ <AGMarkdown
7
+ :text="
8
+ $td('solid.loggedIn', 'You are logged in as [{userName}]({userWebId})', {
9
+ userName: session.user.name ?? session.user.webId,
10
+ userWebId: session.user.webId,
11
+ })
12
+ "
13
+ />
14
+ <AGButton @click="$cloud.sync(), $emit('sync')">
15
+ {{ $td('cloud.sync', 'Synchronize') }}
16
+ </AGButton>
17
+ <AGButton @click="$solid.logout()">
18
+ {{ $td('solid.logout', 'Logout') }}
19
+ </AGButton>
20
+ </div>
21
+ </template>
22
+ </AGSolidStatus>
23
+ </template>
24
+
25
+ <script setup lang="ts">
26
+ import { AGButton, AGMarkdown } from '@aerogel/core';
27
+ import { AGSolidStatus } from '@aerogel/plugin-solid';
28
+ import type { IAGSolidStatusLoggedInSlotProps } from '@aerogel/plugin-solid';
29
+
30
+ defineEmits(['sync']);
31
+ </script>
@@ -0,0 +1,3 @@
1
+ import AGCloudStatus from './AGCloudStatus.vue';
2
+
3
+ export { AGCloudStatus };
package/src/index.ts ADDED
@@ -0,0 +1,29 @@
1
+ import { bootServices } from '@aerogel/core';
2
+ import type { Plugin } from '@aerogel/core';
3
+
4
+ import Cloud from '@aerogel/plugin-local-first/services/Cloud';
5
+ import DocumentsCache from '@aerogel/plugin-local-first/services/DocumentsCache';
6
+
7
+ const services = { $cloud: Cloud };
8
+
9
+ export { Cloud };
10
+ export * from './components';
11
+ export * from './services/Cloud';
12
+
13
+ export type LocalFirstServices = typeof services;
14
+
15
+ export default function localFirst(): Plugin {
16
+ return {
17
+ name: '@aerogel/local-first',
18
+ async install(app) {
19
+ await bootServices(app, {
20
+ ...services,
21
+ $_documentsCache: DocumentsCache,
22
+ });
23
+ },
24
+ };
25
+ }
26
+
27
+ declare module '@aerogel/core' {
28
+ interface Services extends LocalFirstServices {}
29
+ }
@@ -0,0 +1,98 @@
1
+ import { Job } from '@aerogel/core';
2
+ import { requireEngine } from 'soukai';
3
+ import { requireUrlParentDirectory } from '@noeldemartin/utils';
4
+ import { ignoreModelsCollection, trackModelsCollection } from '@aerogel/plugin-soukai';
5
+ import type { EngineDocument, IndexedDBEngine } from 'soukai';
6
+ import type { SolidModelConstructor } from 'soukai-solid';
7
+
8
+ interface Migration {
9
+ modelClass: SolidModelConstructor;
10
+ local: string;
11
+ remote: string;
12
+ }
13
+
14
+ export default class Backup extends Job {
15
+
16
+ private urlMigrations: Migration[] = [];
17
+ private collectionMigrations: Migration[] = [];
18
+
19
+ public migrateUrl(modelClass: SolidModelConstructor, local: string, remote: string): void {
20
+ this.urlMigrations.push({
21
+ modelClass,
22
+ local,
23
+ remote,
24
+ });
25
+ }
26
+
27
+ public migrateCollection(modelClass: SolidModelConstructor, local: string, remote: string): void {
28
+ this.collectionMigrations.push({
29
+ modelClass,
30
+ local,
31
+ remote,
32
+ });
33
+ }
34
+
35
+ protected async run(): Promise<void> {
36
+ const engine = requireEngine<IndexedDBEngine>();
37
+ const collections = await engine.getCollections();
38
+
39
+ for (const collection of collections) {
40
+ const documents = await engine.readMany(collection);
41
+
42
+ for (const [id, document] of Object.entries(documents)) {
43
+ const url = this.replaceUrl(id);
44
+
45
+ await engine.create(requireUrlParentDirectory(url), this.replaceDocumentUrls(document), url);
46
+ await engine.delete(collection, id);
47
+ }
48
+ }
49
+
50
+ for (const { modelClass, remote } of this.urlMigrations) {
51
+ trackModelsCollection(modelClass, requireUrlParentDirectory(remote), { refresh: false });
52
+ }
53
+
54
+ for (const { modelClass, local, remote } of this.collectionMigrations) {
55
+ ignoreModelsCollection(modelClass, local);
56
+ trackModelsCollection(modelClass, remote, { refresh: false });
57
+ }
58
+ }
59
+
60
+ protected replaceDocumentUrls(document: EngineDocument): EngineDocument {
61
+ for (const [key, value] of Object.entries(document)) {
62
+ if (key === '@id' && typeof value === 'string') {
63
+ document[key] = this.replaceUrl(value);
64
+
65
+ continue;
66
+ }
67
+
68
+ if (typeof value !== 'object' || value === null) {
69
+ continue;
70
+ }
71
+
72
+ document[key] = this.replaceDocumentUrls(value as EngineDocument);
73
+ }
74
+
75
+ return document;
76
+ }
77
+
78
+ protected replaceUrl(url: string): string {
79
+ for (const { local, remote } of this.urlMigrations) {
80
+ if (!url.startsWith(local)) {
81
+ continue;
82
+ }
83
+
84
+ return url.replace(local, remote);
85
+ }
86
+
87
+ for (const { local, remote } of this.collectionMigrations) {
88
+ if (!url.startsWith(local)) {
89
+ continue;
90
+ }
91
+
92
+ return url.replace(local, remote);
93
+ }
94
+
95
+ return url;
96
+ }
97
+
98
+ }