From e24df950942000c3ac91b485f83ba79dcf2e4383 Mon Sep 17 00:00:00 2001 From: Burak Date: Sat, 23 Nov 2024 00:53:35 +0300 Subject: [PATCH] update paths and backup api - see changelog for detailed explanation --- CHANGES.md | 15 ++++ package.json | 2 +- packages/app-desktop/package.json | 2 +- .../app-desktop/src/electron/api/backup.ts | 81 +++++++++++-------- .../app-desktop/src/electron/lib/paths.ts | 14 +++- packages/common/package.json | 2 +- 6 files changed, 76 insertions(+), 40 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index fff6c9b..da8b995 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,18 @@ +# 0.2.0-alpha.1 + +## ⚠️ Breaking changes + +- Directories in which application data is stored has changed. App data will be stored in a subdirectory named `darkwrite-data` when running production builds, and `darkwrite-data-nightly` when running development builds. If you are upgrading from 0.1.0-alpha.x, navigate to Darkwrite's data directory (you can use the application menu for this), move `data.db`, `settings.json` and `notes/` into `darkwrite-data/`. +- Alternatively, create a backup before upgrading and restore from the backup after upgrading. + +## ✨ Improvements and fixes + +- New backups now include a date in their file names by default. + +## 🛠️ Technical changes + +- App data is now stored in an isolated folder, which opens the door to safe development sessions without risking data and simplifies the code responsible from backups. + # 0.1.0-alpha.2 ## Features diff --git a/package.json b/package.json index c74c28c..8b44b3e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "darkwrite", - "version": "0.1.0-alpha.1", + "version": "0.2.0-alpha.1", "description": "", "scripts": { "test:all": "yarn workspaces foreach -A run test", diff --git a/packages/app-desktop/package.json b/packages/app-desktop/package.json index 87f2845..39fe4f6 100644 --- a/packages/app-desktop/package.json +++ b/packages/app-desktop/package.json @@ -7,7 +7,7 @@ "description": "The eye candy note-taking app for all desktops.", "productName": "Darkwrite", "private": true, - "version": "0.1.0-alpha.2", + "version": "0.2.0-alpha.1", "type": "module", "license": "AGPL-3.0-or-later", "main": "dist-electron/main.js", diff --git a/packages/app-desktop/src/electron/api/backup.ts b/packages/app-desktop/src/electron/api/backup.ts index c3dc75f..c5728f5 100644 --- a/packages/app-desktop/src/electron/api/backup.ts +++ b/packages/app-desktop/src/electron/api/backup.ts @@ -3,17 +3,16 @@ import log from "electron-log"; import extract from "extract-zip"; import fse from "fs-extra"; import { join } from "node:path"; +import os from "os"; import { zip } from "zip-a-folder"; import { DB } from "../db"; import { rmIfExists } from "../lib/fs"; import { BACKUP_CACHE_DIR, DATA_DIR, - DB_PATH, + DATA_SNAPSHOT_DIR, EXPORTER_CACHE_DIR, - NOTE_CONTENTS_DIR, RESTORE_CACHE_DIR, - SETTINGS_PATH, } from "../lib/paths"; import { saveFile } from "./dialog"; @@ -70,17 +69,18 @@ export const BackupAPI = { await fse.ensureDir(BACKUP_CACHE_DIR); // copy user data - await fse.copy(DB_PATH, join(BACKUP_CACHE_DIR, "data.db")); - await fse.copy(NOTE_CONTENTS_DIR, join(BACKUP_CACHE_DIR, "notes/")); - await fse.copy( - SETTINGS_PATH, - join(BACKUP_CACHE_DIR, "settings.json"), - ); + await fse.copy(DATA_DIR, BACKUP_CACHE_DIR); + // await fse.copy(DB_PATH, join(BACKUP_CACHE_DIR, "data.db")); + // await fse.copy(NOTE_CONTENTS_DIR, join(BACKUP_CACHE_DIR, "notes/")); + // await fse.copy( + // SETTINGS_PATH, + // join(BACKUP_CACHE_DIR, "settings.json"), + // ); const saveResult = await saveFile({ buttonLabel: "Export", title: "Backup your data", - defaultPath: "darkwrite-backup.zip", + defaultPath: `darkwrite-backup-${new Date().toDateString()}.zip`, }); if (saveResult.canceled || !saveResult.path) return; await zip(BACKUP_CACHE_DIR, saveResult.path); @@ -90,9 +90,9 @@ export const BackupAPI = { } }, async restore(archivePath: string) { - const dbBackupPath = join(DATA_DIR, "data.db.old"); - const notesBackupPath = join(DATA_DIR, "notes_old"); - const settingsBackupPath = join(DATA_DIR, "settings.json.old"); + // const dbBackupPath = join(DATA_DIR, "data.db.old"); + // const notesBackupPath = join(DATA_DIR, "notes_old"); + // const settingsBackupPath = join(DATA_DIR, "settings.json.old"); let didRename = false; await DB.disconnect(); try { @@ -107,33 +107,41 @@ export const BackupAPI = { "This does not seem to be a Darkwrite backup archive.", ); - // before we do anything else, we will rename the old files so we can rollback if something goes wrong. + // before we do anything else, we will rename the old directory so we can rollback if something goes wrong. try { - await fse.rename(DB_PATH, dbBackupPath); - await fse.rename(NOTE_CONTENTS_DIR, notesBackupPath); - await fse.rename(SETTINGS_PATH, settingsBackupPath); + await fse.move(DATA_DIR, DATA_SNAPSHOT_DIR, { + overwrite: true, + }); + // await fse.rename(DB_PATH, dbBackupPath); + // await fse.rename(NOTE_CONTENTS_DIR, notesBackupPath); + // await fse.rename(SETTINGS_PATH, settingsBackupPath); } catch (error) { - /*empty */ + /*empty*/ } didRename = true; - await fse.copy(join(RESTORE_CACHE_DIR, "data.db"), DB_PATH, { - overwrite: true, - }); - await fse.copy( - join(RESTORE_CACHE_DIR, "settings.json"), - SETTINGS_PATH, - { overwrite: true }, - ); - await fse.copy( - join(RESTORE_CACHE_DIR, "notes"), - NOTE_CONTENTS_DIR, - { overwrite: true }, - ); + await fse.ensureDir(DATA_DIR); + await fse.copy(RESTORE_CACHE_DIR, DATA_DIR, { overwrite: true }); + + // await fse.copy(join(RESTORE_CACHE_DIR, "data.db"), DB_PATH, { + // overwrite: true, + // }); + // await fse.copy( + // join(RESTORE_CACHE_DIR, "settings.json"), + // SETTINGS_PATH, + // { overwrite: true }, + // ); + // await fse.copy( + // join(RESTORE_CACHE_DIR, "notes"), + // NOTE_CONTENTS_DIR, + // { overwrite: true }, + // ); dialog.showMessageBoxSync({ message: - "We restored your backup, we will relaunch Darkwrite for the changes to take effect.", + os.type() === "Linux" + ? "We restored your backup. Darkwrite needs to relaunch for the changes to take effect." + : "We restored your backup, we will relaunch Darkwrite for the changes to take effect.", }); app.relaunch(); app.exit(); @@ -141,9 +149,12 @@ export const BackupAPI = { log.error("!!! Restore failed. Rolling back..."); if (error instanceof Error) log.error(error.message); if (didRename) { - await fse.rename(dbBackupPath, DB_PATH); - await fse.rename(notesBackupPath, NOTE_CONTENTS_DIR); - await fse.rename(settingsBackupPath, SETTINGS_PATH); + await fse.move(DATA_SNAPSHOT_DIR, DATA_DIR, { + overwrite: true, + }); + // await fse.rename(dbBackupPath, DB_PATH); + // await fse.rename(notesBackupPath, NOTE_CONTENTS_DIR); + // await fse.rename(settingsBackupPath, SETTINGS_PATH); } await DB.init(); dialog.showMessageBoxSync({ diff --git a/packages/app-desktop/src/electron/lib/paths.ts b/packages/app-desktop/src/electron/lib/paths.ts index 112b54b..845ad0c 100644 --- a/packages/app-desktop/src/electron/lib/paths.ts +++ b/packages/app-desktop/src/electron/lib/paths.ts @@ -1,8 +1,18 @@ +import { is } from "@electron-toolkit/utils"; import { app } from "electron"; import { join } from "node:path"; -/** The user data directory, as defined by Electron. */ -export const DATA_DIR = app.getPath("userData"); +/** The folder to store Darkwrite's user data. + * It will point to `darkwrite-data/` on production and `darkwrite-data-nightly/` on development. */ +export const DATA_DIR = join( + app.getPath("userData"), + is.dev ? "darkwrite-data-nightly/" : "darkwrite-data/", +); +/** The folder to rollback from if a restore operation fails. */ +export const DATA_SNAPSHOT_DIR = join( + app.getPath("userData"), + "darkwrite-data-old", +); /** The directory in which note contents are stored. */ export const NOTE_CONTENTS_DIR = join(DATA_DIR, "notes/"); /** Path to the SQLite database which holds the note entries. */ diff --git a/packages/common/package.json b/packages/common/package.json index 4e1786d..fa80273 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -1,6 +1,6 @@ { "name": "@darkwrite/common", - "version": "0.1.0-alpha.2", + "version": "0.2.0-alpha.1", "types": "./dist/index.d.ts", "main": "./dist/index.js", "scripts": {