Files
chatwoot/app/javascript/dashboard/helper/CacheHelper/DataManager.js
Shivam Mishra 00ee0478eb feat: IndexedDB based caching for labels, inboxes and teams [CW-50] (#6710)
* feat: allow caching of labels in the account scope

* feat: send cache keys in account json response

* feat: kickstart web worker

* feat: setup basic architecture for workers

* feat: install idb

* feat: add datamanger

* fix: typos

* refactor: rename method

* feat: make init db a manual step

* refactor: separate accountIdFromRoute

* feat: cache enabled API client

* feat: enable caching for inboxes and labels

* feat: enable cache for team

* feat: manage exceptions for team

* feat: add team to data manager

* feat: add a generic listener

* refactor: send only cache keys

* refactor: separate validate method

* feat: add listeners

* feat: add event for revalidate

* feat: add cache keys endpoint

* refactor: fetch cache keys instead of full account data

* fix: key pattern

* feat: don't fetch account for cache_keys

* fix: cache key base class

* refactor: cache keys helper

* feat: add helper

* fix: cache-key update logic

* feat: delete indexeddb on logout

* feat: remove worker.js

* refactor: move data-manager

* refactor: name of file

* feat: add test for DataManager

* refactor: add fake idb to jest setup

* test: cache keys helper

* test: cache keys helper

* test: cache_keys in accounts controller

* refactor: remove cache_keys context

* feat: add policy for cache-keys
2023-03-27 12:16:25 +05:30

71 lines
1.7 KiB
JavaScript

import { openDB } from 'idb';
import { DATA_VERSION } from './version';
export class DataManager {
constructor(accountId) {
this.modelsToSync = ['inbox', 'label', 'team'];
this.accountId = accountId;
this.db = null;
}
async initDb() {
if (this.db) return this.db;
this.db = await openDB(`cw-store-${this.accountId}`, DATA_VERSION, {
upgrade(db) {
db.createObjectStore('cache-keys');
db.createObjectStore('inbox', { keyPath: 'id' });
db.createObjectStore('label', { keyPath: 'id' });
db.createObjectStore('team', { keyPath: 'id' });
},
});
return this.db;
}
validateModel(name) {
if (!name) throw new Error('Model name is not defined');
if (!this.modelsToSync.includes(name)) {
throw new Error(`Model ${name} is not defined`);
}
return true;
}
async replace({ modelName, data }) {
this.validateModel(modelName);
this.db.clear(modelName);
return this.push({ modelName, data });
}
async push({ modelName, data }) {
this.validateModel(modelName);
if (Array.isArray(data)) {
const tx = this.db.transaction(modelName, 'readwrite');
data.forEach(item => {
tx.store.add(item);
});
await tx.done;
} else {
await this.db.add(modelName, data);
}
}
async get({ modelName }) {
this.validateModel(modelName);
return this.db.getAll(modelName);
}
async setCacheKeys(cacheKeys) {
Object.keys(cacheKeys).forEach(async modelName => {
this.db.put('cache-keys', cacheKeys[modelName], modelName);
});
}
async getCacheKey(modelName) {
this.validateModel(modelName);
return this.db.get('cache-keys', modelName);
}
}