diff --git a/src/lib/components/settings/settings-import-modal.svelte b/src/lib/components/settings/settings-import-modal.svelte new file mode 100644 index 0000000..15d9c39 --- /dev/null +++ b/src/lib/components/settings/settings-import-modal.svelte @@ -0,0 +1,45 @@ + + + +
+

Select a backup file that you exported previously to restore your notes.

+

+ Warning: + This will overwrite all of your current notes. +

+ + +
+
+ + diff --git a/src/lib/components/settings/settings-modal.svelte b/src/lib/components/settings/settings-modal.svelte index 9b30079..ff4a174 100644 --- a/src/lib/components/settings/settings-modal.svelte +++ b/src/lib/components/settings/settings-modal.svelte @@ -2,8 +2,17 @@ import Modal from '../modal.svelte'; import { settings } from '$lib/stores'; import SettingsColorPicker from './settings-color-picker.svelte'; + import Button from '../button.svelte'; + import { exportDb } from '$lib/db/export-db'; + import SettingsImportModal from './settings-import-modal.svelte'; const { open, noteScale, defaultNoteColor } = settings; + let importModalOpen = false; + + function goToImport() { + open.set(false); + importModalOpen = true; + } @@ -22,4 +31,23 @@ Default Note Color +
+
+ + +
+ + + diff --git a/src/lib/db/client.ts b/src/lib/db/client.ts index cafd424..e43450f 100644 --- a/src/lib/db/client.ts +++ b/src/lib/db/client.ts @@ -1,30 +1,16 @@ -import { Kysely, Migrator } from 'kysely'; +import { Kysely } from 'kysely'; import { SQLocalKysely } from 'sqlocal/kysely'; import type { Schema } from './schema'; -import { migrations } from './migrations/'; +import { migrate } from './migrator'; const sqlocal = new SQLocalKysely('sticky-notes.db'); const kysely = new Kysely({ dialect: sqlocal.dialect }); -await sqlocal.sql`PRAGMA foreign_keys = ON`; - -const migrator = new Migrator({ - db: kysely, - provider: { - async getMigrations() { - // TODO: Dynamic import does not work in production build - // because the imported chunk imports `sql` from the same - // chunk that imports it, so circular dependency. Vite bug. - // const { migrations } = await import('./migrations/'); - return migrations; - }, - }, -}); - -const migration = await migrator.migrateToLatest(); - -if (migration.error) { - console.error(migration.error); +try { + await migrate(kysely); +} catch (err) { + console.error(err); } export const db = kysely; +export const { getDatabaseFile, overwriteDatabaseFile } = sqlocal; diff --git a/src/lib/db/export-db.ts b/src/lib/db/export-db.ts new file mode 100644 index 0000000..2535d46 --- /dev/null +++ b/src/lib/db/export-db.ts @@ -0,0 +1,17 @@ +import { getDatabaseFile } from './client'; + +export async function exportDb() { + const databaseFile = await getDatabaseFile(); + const fileUrl = URL.createObjectURL(databaseFile); + + const now = new Date(); + const timestamp = now.toISOString().split('.')[0].replace(/\:/g, '-'); + + const a = document.createElement('a'); + a.href = fileUrl; + a.download = `notes-${timestamp}.db`; + a.click(); + a.remove(); + + URL.revokeObjectURL(fileUrl); +} diff --git a/src/lib/db/import-db.ts b/src/lib/db/import-db.ts new file mode 100644 index 0000000..c93346d --- /dev/null +++ b/src/lib/db/import-db.ts @@ -0,0 +1,16 @@ +import { notes, tags } from '$lib/stores'; +import { db, overwriteDatabaseFile } from './client'; +import { migrate } from './migrator'; + +export async function importDb(dbFile: File): Promise { + try { + await overwriteDatabaseFile(dbFile); + await migrate(db); + await tags.refreshTags(); + await notes.refreshNotes(); + } catch (err) { + return false; + } + + return true; +} diff --git a/src/lib/db/migrator.ts b/src/lib/db/migrator.ts new file mode 100644 index 0000000..c8e5725 --- /dev/null +++ b/src/lib/db/migrator.ts @@ -0,0 +1,22 @@ +import { Kysely, Migrator, sql } from 'kysely'; +import { migrations } from './migrations/'; +import type { Schema } from './schema'; + +export async function migrate(db: Kysely) { + const migrator = new Migrator({ + db, + provider: { + async getMigrations() { + return migrations; + }, + }, + }); + + await sql`PRAGMA foreign_keys = ON`.execute(db); + const migration = await migrator.migrateToLatest(); + + if (migration.error) { + console.error(migration.error); + throw new Error('Migration failed'); + } +}