From 96b234f652d53fc325e25eaf004a380cf2cadd14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laureline=20Val=C3=A9rie=20David?= Date: Fri, 18 Oct 2024 11:10:27 +0200 Subject: [PATCH] Use Dexie.js for IndexedDB access. --- composables/viewer/useBuildLibrary.ts | 104 +++++++++++--------------- composables/viewer/useDexie.ts | 24 ++++++ composables/viewer/useIndexedDB.ts | 9 --- package.json | 1 + plugins/dexie.client.ts | 6 ++ plugins/indexed-db.client.ts | 10 --- yarn.lock | 8 ++ 7 files changed, 82 insertions(+), 80 deletions(-) create mode 100644 composables/viewer/useDexie.ts delete mode 100644 composables/viewer/useIndexedDB.ts create mode 100644 plugins/dexie.client.ts delete mode 100644 plugins/indexed-db.client.ts diff --git a/composables/viewer/useBuildLibrary.ts b/composables/viewer/useBuildLibrary.ts index e3ce98e..8bfbbb3 100644 --- a/composables/viewer/useBuildLibrary.ts +++ b/composables/viewer/useBuildLibrary.ts @@ -14,7 +14,7 @@ import { useProjectRefs, useProjectStore, } from '~/composables/store/project'; -import { useIndexedDB } from '~/composables/viewer/useIndexedDB'; +import { useDexie } from '~/composables/viewer/useDexie'; type UpdateBuildOptions = Partial> & { $choices?: boolean; @@ -22,44 +22,33 @@ type UpdateBuildOptions = Partial> & { }; export function useBuildLibrary() { - const db = useIndexedDB()!; + const db = useDexie()!; const { setSelected } = useProjectStore(); const $store = useProjectRefs(); const loadBuilds = async (): Promise => { - return db.transaction('builds', 'readonly', async (tx) => { - const store = tx.objectStore('builds'); - return store.getAll(); - }); + return db.builds.toArray(); }; const saveBuild = async (buildName: string): Promise => { - return db.transaction('builds', 'readwrite', async (tx) => { - const table = tx.objectStore('builds'); - const today = new Date(); - const entry: Omit = { - name: buildName, - createdAt: today, - updatedAt: today, - project: getProjectInfo($store.store.value), - groups: getSelectedItems( - $store.selected.value, - $store.backpack.value, - $store.getObject.value, - $store.getObjectRow.value, - $store.getRow.value, - ), - notes: clone($store.buildNotes.value), - }; - const entryId = await table.add(entry); - const savedEntry: SavedBuildData = { - ...entry, - id: entryId, - }; - - return savedEntry; - }); + const today = new Date(); + const entry: Omit = { + name: buildName, + createdAt: today, + updatedAt: today, + project: getProjectInfo($store.store.value), + groups: getSelectedItems( + $store.selected.value, + $store.backpack.value, + $store.getObject.value, + $store.getObjectRow.value, + $store.getRow.value, + ), + notes: clone($store.buildNotes.value), + }; + const entryId = await db.builds.add(entry); + return R.assoc('id', entryId, entry); }; const updateBuild = async ( @@ -71,41 +60,34 @@ export function useBuildLibrary() { return build; } - return db.transaction('builds', 'readwrite', async (tx) => { - const table = tx.objectStore('builds'); - - const entry: SavedBuildData = clone(build); - entry.updatedAt = new Date(); + const entry: SavedBuildData = clone(build); + entry.updatedAt = new Date(); - console.log('props', rest); - if (isNotEmpty(rest)) { - // Copy the updated properties into the object - Object.assign(entry, rest); - } - if ($notes) { - entry.notes = clone($store.buildNotes.value); - } - if ($choices) { - entry.project = getProjectInfo($store.store.value); - entry.groups = getSelectedItems( - $store.selected.value, - $store.backpack.value, - $store.getObject.value, - $store.getObjectRow.value, - $store.getRow.value, - ); - } - await table.put(entry); + console.log('props', rest); + if (isNotEmpty(rest)) { + // Copy the updated properties into the object + Object.assign(entry, rest); + } + if ($notes) { + entry.notes = clone($store.buildNotes.value); + } + if ($choices) { + entry.project = getProjectInfo($store.store.value); + entry.groups = getSelectedItems( + $store.selected.value, + $store.backpack.value, + $store.getObject.value, + $store.getObjectRow.value, + $store.getRow.value, + ); + } + await db.builds.put(entry); - return entry; - }); + return entry; }; const deleteBuild = async (build: SavedBuildData) => { - await db.transaction('builds', 'readwrite', async (tx) => { - const store = tx.objectStore('builds'); - await store.delete(build.id); - }); + await db.builds.delete(build.id); }; const loadBuild = (build: SavedBuildData) => { diff --git a/composables/viewer/useDexie.ts b/composables/viewer/useDexie.ts new file mode 100644 index 0000000..c02a450 --- /dev/null +++ b/composables/viewer/useDexie.ts @@ -0,0 +1,24 @@ +import Dexie, { type EntityTable } from 'dexie'; + +import type { SavedBuildData } from '~/components/viewer/utils/types'; + +export const DexieProvider = Symbol('DexieProvider') as InjectionKey; + +export class AppDb extends Dexie { + builds!: EntityTable; + + constructor() { + super('cyoa-editor'); + this.version(1).stores({ + builds: '++id', + }); + } +} + +export function createDexie(): AppDb { + return new AppDb(); +} + +export function useDexie(): AppDb { + return inject(DexieProvider)!; +} diff --git a/composables/viewer/useIndexedDB.ts b/composables/viewer/useIndexedDB.ts deleted file mode 100644 index f37bfee..0000000 --- a/composables/viewer/useIndexedDB.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { IndexedDB } from '~/composables/utils/idb'; - -export const indexedDBProvider = Symbol( - 'indexedDBProvider', -) as InjectionKey; - -export function useIndexedDB(): IndexedDB | undefined { - return inject(indexedDBProvider); -} diff --git a/package.json b/package.json index b80de00..6415df0 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "@vueuse/nuxt": "^11.0.3", "bootstrap": "5.3.*", "canvas-size": "^2.0.0", + "dexie": "^4.0.8", "dom-to-svg": "^0.12.2", "handlebars": "^4.7.8", "perfect-debounce": "^1.0.0", diff --git a/plugins/dexie.client.ts b/plugins/dexie.client.ts new file mode 100644 index 0000000..8f84db4 --- /dev/null +++ b/plugins/dexie.client.ts @@ -0,0 +1,6 @@ +import { defineNuxtPlugin } from '#app/nuxt'; +import { DexieProvider, createDexie } from '~/composables/viewer/useDexie'; + +export default defineNuxtPlugin(async (nuxtApp) => { + nuxtApp.vueApp.provide(DexieProvider, createDexie()); +}); diff --git a/plugins/indexed-db.client.ts b/plugins/indexed-db.client.ts deleted file mode 100644 index eda703d..0000000 --- a/plugins/indexed-db.client.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { defineNuxtPlugin } from '#app/nuxt'; -import { IndexedDB } from '~/composables/utils/idb'; -import { indexedDBProvider } from '~/composables/viewer/useIndexedDB'; - -export default defineNuxtPlugin(async (nuxtApp) => { - const db = await IndexedDB.open('cyoa-editor', 1, (db) => { - db.createObjectStore('builds', { keyPath: 'id', autoIncrement: true }); - }); - nuxtApp.vueApp.provide(indexedDBProvider, db); -}); diff --git a/yarn.lock b/yarn.lock index cba290a..240f812 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5137,6 +5137,13 @@ __metadata: languageName: node linkType: hard +"dexie@npm:^4.0.8": + version: 4.0.8 + resolution: "dexie@npm:4.0.8" + checksum: 156e0809d5102ec0522cdee473c842e2d8c5a9b91d92792c8a17829953317f11370b34bc2418a66c5c4dec7f99306a6ae8a53d02f530af85f98d8803965bc6bb + languageName: node + linkType: hard + "diff@npm:^5.2.0": version: 5.2.0 resolution: "diff@npm:5.2.0" @@ -8920,6 +8927,7 @@ __metadata: "@vueuse/nuxt": ^11.0.3 bootstrap: 5.3.* canvas-size: ^2.0.0 + dexie: ^4.0.8 dom-to-svg: ^0.12.2 eslint: ^8.57.0 eslint-config-prettier: ^8.10.0