Skip to content

Commit

Permalink
Abstract syncfs
Browse files Browse the repository at this point in the history
  • Loading branch information
pulsejet committed Feb 20, 2025
1 parent 17e7b83 commit fb1062d
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 25 deletions.
22 changes: 5 additions & 17 deletions src/services/latex/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,18 @@ export async function compile(project: WorkspaceProj): Promise<Uint8Array | stri
activeProject = project.name;
}

// Fail fast if main.tex is not found
const fileList = project.fileList();
if (!fileList.some((file) => file.path === '/main.tex')) {
throw new Error('main.tex not found at root of project');
}

// TODO: show progress
for (const file of fileList) {
// Folders are automatically created by the worker
if (file.path.endsWith('/')) continue;

// Write the file to the OPFS filesystem.
// TODO: synchronize this more efficiently and generically.
// TODO: prefix the path with the workspace prefix.
let content = await project.exportFile(file.path);
if (content !== null) {
if (typeof content === 'string') {
content = new TextEncoder().encode(content);
}
await opfs.writeFileOpfsRecursive(`/${project.name}${file.path}`, content);
}
}
// Sync the project to OPFS
const root = await project.syncFS();

// Compile the project
// TODO: show progress
const res = await activeEngine.compileLaTeX(`/${project.name}`, 'main.tex');
const res = await activeEngine.compileLaTeX(root, 'main.tex');
if (res.status == EngineStatus.Error) {
throw new Error('Engine Error');
} else if (res.pdf === undefined) {
Expand Down
46 changes: 38 additions & 8 deletions src/services/opfs.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,49 @@
/**
* Write file to OPFS recursively
* @param filename Full path of the file
* @param path Full path of the file
* @param content File content
*/
export async function writeFileOpfsRecursive(filename: string, content: Uint8Array) {
let folder = await self.navigator.storage.getDirectory();
const parts = filename.split('/').filter(Boolean);
for (let i = 0; i < parts.length - 1; i++) {
folder = await folder.getDirectoryHandle(parts[i], { create: true });
}
export async function writeFile(
path: string,
content: Uint8Array,
opts?: {
create?: boolean;
root?: FileSystemDirectoryHandle;
},
) {
const parts = path.split('/').filter(Boolean);
const folder = parts.slice(0, -1).join('/');
const folderHandle = await getDirectoryHandle(folder, {
create: opts?.create,
root: opts?.root,
});

const basename = parts[parts.length - 1];
if (!basename) return;
const file = await folder.getFileHandle(basename, { create: true });
const file = await folderHandle.getFileHandle(basename, { create: opts?.create });
const writable = await file.createWritable();
await writable.write(content);
await writable.close();
}

/**
* Get directory handle from OPFS recursively
* @param path Path to the directory
* @returns Directory handle
*/
export async function getDirectoryHandle(
path: string,
opts?: {
create?: boolean;
root?: FileSystemDirectoryHandle;
},
): Promise<FileSystemDirectoryHandle> {
let folder = opts?.root ?? (await self.navigator.storage.getDirectory());
const parts = path.split('/').filter(Boolean);
for (const part of parts) {
folder = await folder.getDirectoryHandle(part, {
create: opts?.create ?? false,
});
}
return folder;
}
40 changes: 40 additions & 0 deletions src/services/workspace-proj.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as awareProto from 'y-protocols/awareness.js';

import { GlobalBus } from './event-bus';
import { SvsProvider } from './svs-provider';
import * as opfs from '@/services/opfs';
import * as utils from '@/utils';

import type { WorkspaceAPI } from './ndn';
Expand All @@ -29,6 +30,11 @@ export class WorkspaceProjManager {
listObserver();
}

/** Name of the workspace (group) */
public get group(): string {
return this.wksp.group;
}

/** Create the project manager instance */
public static async create(
wksp: WorkspaceAPI,
Expand Down Expand Up @@ -305,4 +311,38 @@ export class WorkspaceProj {

return await this.provider.getAwareness(uuid);
}

/**
* Synchronize the project to the OPFS.
*
* @returns The path to the project in the OPFS.
*/
public async syncFS(): Promise<string> {
const basedir = `${this.manager.group}/${this.name}`;
const folder = await opfs.getDirectoryHandle(basedir, { create: true });

// TODO: show progress
for (const file of this.fileList()) {
// Folders are automatically created, don't bother writing them
if (file.path.endsWith('/')) continue;

// Write the file to the OPFS filesystem.
// TODO: synchronize this more efficiently (check timestamps)
let content = await this.exportFile(file.path);
if (content !== null) {
// Only binary content is accepted
if (typeof content === 'string') {
content = new TextEncoder().encode(content);
}

// Write file to the FS recursively
await opfs.writeFile(file.path, content, {
create: true,
root: folder,
});
}
}

return basedir;
}
}

0 comments on commit fb1062d

Please sign in to comment.