fix(electron): export and import (#9767)

This commit is contained in:
forehalo
2025-01-20 08:48:03 +00:00
parent 2e18ae59e3
commit cb53baca89
26 changed files with 332 additions and 453 deletions
@@ -1,12 +1,19 @@
import { ValidationResult } from '@affine/native';
import { parse } from 'node:path';
import { DocStorage, ValidationResult } from '@affine/native';
import { parseUniversalId } from '@affine/nbstore';
import fs from 'fs-extra';
import { nanoid } from 'nanoid';
import { logger } from '../logger';
import { mainRPC } from '../main-rpc';
import { ensureSQLiteDB } from '../nbstore/v1';
import { getDocStoragePool } from '../nbstore';
import { storeWorkspaceMeta } from '../workspace';
import { getWorkspaceDBPath, getWorkspacesBasePath } from '../workspace/meta';
import {
getSpaceDBPath,
getWorkspaceDBPath,
getWorkspacesBasePath,
} from '../workspace/meta';
export type ErrorMessage =
| 'DB_FILE_PATH_INVALID'
@@ -69,20 +76,26 @@ function getDefaultDBFileName(name: string, id: string) {
*
* It will just copy the file to the given path
*/
export async function saveDBFileAs(id: string): Promise<SaveDBFileResult> {
export async function saveDBFileAs(
universalId: string,
name: string
): Promise<SaveDBFileResult> {
try {
// TODO(@forehalo): use `nbstore` when it is ready
// const storage = await ensureStorage(id);
const { peer, type, id } = parseUniversalId(universalId);
const dbPath = await getSpaceDBPath(peer, type, id);
// connect to the pool and make sure all changes (WAL) are written to db
const pool = getDocStoragePool();
await pool.connect(universalId, dbPath);
await pool.checkpoint(universalId); // make sure all changes (WAL) are written to db
const storage = await ensureSQLiteDB('workspace', id);
await storage.checkpoint(); // make sure all changes (WAL) are written to db
const fakedResult = getFakedResult();
const dbPath = storage.path;
if (!dbPath) {
return {
error: 'DB_FILE_PATH_INVALID',
};
}
const ret =
fakedResult ??
(await mainRPC.showSaveDialog({
@@ -96,12 +109,10 @@ export async function saveDBFileAs(id: string): Promise<SaveDBFileResult> {
name: '',
},
],
defaultPath: getDefaultDBFileName(
(await storage.getWorkspaceName()) ?? 'db',
id
),
defaultPath: getDefaultDBFileName(name, id),
message: 'Save Workspace as a SQLite Database file',
}));
const filePath = ret.filePath;
if (ret.canceled || !filePath) {
return {
@@ -159,7 +170,7 @@ export async function selectDBFileLocation(): Promise<SelectDBFileLocationResult
* - return the new workspace id
*
* eg, it will create a new folder in app-data:
* <app-data>/<app-name>/workspaces/<workspace-id>/storage.db
* <app-data>/<app-name>/<workspaces|userspaces>/<peer>/<workspace-id>/storage.db
*
* On the renderer side, after the UI got a new workspace id, it will
* update the local workspace id list and then connect to it.
@@ -195,34 +206,29 @@ export async function loadDBFile(): Promise<LoadDBFileResult> {
}
const workspaceId = nanoid(10);
return await loadV1DBFile(originalPath, workspaceId);
let storage = new DocStorage(originalPath);
// TODO(forehalo): use `nbstore` when it is ready
// let storage = new DocStorage(originalPath);
// if imported db is not a valid v2 db, we will treat it as a v1 db
if (!(await storage.validate())) {
return await cpV1DBFile(originalPath, workspaceId);
}
// // if imported db is not a valid v2 db, we will treat it as a v1 db
// if (!(await storage.validate())) {
// return loadV1DBFile(originalPath, workspaceId);
// }
// v2 import logic
const internalFilePath = await getSpaceDBPath(
'local',
'workspace',
workspaceId
);
await fs.ensureDir(parse(internalFilePath).dir);
await fs.copy(originalPath, internalFilePath);
logger.info(`loadDBFile, copy: ${originalPath} -> ${internalFilePath}`);
// // v2 import logic
// const internalFilePath = await getSpaceDBPath(
// 'local',
// 'workspace',
// workspaceId
// );
// await fs.ensureDir(await getWorkspacesBasePath());
// await fs.copy(originalPath, internalFilePath);
// logger.info(`loadDBFile, copy: ${originalPath} -> ${internalFilePath}`);
storage = new DocStorage(internalFilePath);
await storage.setSpaceId(workspaceId);
// storage = new DocStorage(internalFilePath);
// await storage.connect();
// await storage.setSpaceId(workspaceId);
// await storage.close();
// return {
// workspaceId,
// };
return {
workspaceId,
};
} catch (err) {
logger.error('loadDBFile', err);
return {
@@ -231,7 +237,7 @@ export async function loadDBFile(): Promise<LoadDBFileResult> {
}
}
async function loadV1DBFile(
async function cpV1DBFile(
originalPath: string,
workspaceId: string
): Promise<LoadDBFileResult> {
@@ -9,8 +9,8 @@ export const dialogHandlers = {
loadDBFile: async () => {
return loadDBFile();
},
saveDBFileAs: async (id: string) => {
return saveDBFileAs(id);
saveDBFileAs: async (universalId: string, name: string) => {
return saveDBFileAs(universalId, name);
},
selectDBFileLocation: async () => {
return selectDBFileLocation();