From bf10fbd25f1dadc2093a5b8c4c70383e0ffbddd7 Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Thu, 20 Jun 2024 15:19:49 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8(service-worker)=20add=20offline=20doc?= =?UTF-8?q?s=20delete?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add offline docs delete to the service worker. We use the Network fisrt strategy, if the network is down, we will delete the doc in the indexDB. When the connection is back, we will remove the doc to the server. --- .../src/core/service-worker/ApiPlugin.ts | 71 ++++++++++++++++++- .../core/service-worker/service-worker-api.ts | 13 ++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/src/frontend/apps/impress/src/core/service-worker/ApiPlugin.ts b/src/frontend/apps/impress/src/core/service-worker/ApiPlugin.ts index f674c6f9..0502defe 100644 --- a/src/frontend/apps/impress/src/core/service-worker/ApiPlugin.ts +++ b/src/frontend/apps/impress/src/core/service-worker/ApiPlugin.ts @@ -71,7 +71,11 @@ export class ApiPlugin implements WorkboxPlugin { * A body sent get "used", and can't be read anymore. */ requestWillFetch: WorkboxPlugin['requestWillFetch'] = async ({ request }) => { - if (this.options.type === 'update' || this.options.type === 'create') { + if ( + this.options.type === 'update' || + this.options.type === 'create' || + this.options.type === 'delete' + ) { this.initialRequest = request.clone(); } @@ -91,6 +95,8 @@ export class ApiPlugin implements WorkboxPlugin { switch (this.options.type) { case 'create': return this.handlerDidErrorCreate(request); + case 'delete': + return this.handlerDidErrorDelete(request); case 'update': return this.handlerDidErrorUpdate(request); case 'list': @@ -203,6 +209,69 @@ export class ApiPlugin implements WorkboxPlugin { }); }; + private handlerDidErrorDelete = async (request: Request) => { + if (!this.initialRequest) { + return new Response('Request not found', { status: 404 }); + } + + /** + * Queue the request in the cache 'doc-mutation' to sync it later. + */ + const requestData = ( + await RequestSerializer.fromRequest(this.initialRequest) + ).toObject(); + + const serializeRequest: DBRequest = { + requestData, + key: `${Date.now()}`, + }; + + await DocsDB.cacheResponse( + serializeRequest.key, + serializeRequest, + 'doc-mutation', + ); + + /** + * Delete item in the cache + */ + const db = await DocsDB.open(); + await db.delete('doc-item', request.url); + + /** + * Delete entry from the cache list. + */ + // Get id from url + const url = new URL(request.url); + const docId = url.pathname.slice(0, -1).split('/').pop(); + + const listKeys = await db.getAllKeys('doc-list'); + for (const key of listKeys) { + const list = await db.get('doc-list', key); + + if (!list) { + continue; + } + + list.results = list.results.filter((result) => result.id !== docId); + + await DocsDB.cacheResponse(key, list, 'doc-list'); + } + + db.close(); + + /** + * All is good for our client, we return the new response. + */ + return new Response(null, { + status: 204, + statusText: 'OK', + headers: { + 'Content-Type': 'application/json', + }, + }); + }; + private handlerDidErrorUpdate = async (request: Request) => { const db = await DocsDB.open(); const storedResponse = await db.get('doc-item', request.url); diff --git a/src/frontend/apps/impress/src/core/service-worker/service-worker-api.ts b/src/frontend/apps/impress/src/core/service-worker/service-worker-api.ts index 280f76d1..f531ec08 100644 --- a/src/frontend/apps/impress/src/core/service-worker/service-worker-api.ts +++ b/src/frontend/apps/impress/src/core/service-worker/service-worker-api.ts @@ -78,3 +78,16 @@ registerRoute( }), 'POST', ); + +registerRoute( + ({ url }) => isApiUrl(url.href) && url.href.match(/.*\/documents\/.*\//), + new NetworkOnly({ + plugins: [ + new ApiPlugin({ + type: 'delete', + syncManager, + }), + ], + }), + 'DELETE', +);