[WIP] Add platform-specific filesystem compatibility adapters#5
Closed
Copilot wants to merge 1 commit into
Closed
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Thanks for asking me to work on this. I will get started on it and keep this PR's description up to date as I form a plan and make progress.
Original prompt
Context
The
v4branch oftouch-grass-biblealready has a well-definedFilesinterface insrc/external/Files.tsand aCapacitorFilesAdapterinsrc/external/CapacitorFiles.ts. There is also aFilesFromLocalStorageimplementation and aVaultproxy class.The app builds for multiple platforms:
npm run build:web) — browser/PWAnpm run build:electron) — desktop (Node.jsfs)npm run build:capacitor) — Android & iOSCurrently, the Electron build has no native filesystem adapter — it would fall through to
localStorageeven though Electron's renderer has Node.jsfsavailable. There is also no Node.js-native adapter that could be used for the Electron main process or for testing.Goal
Create platform-specific filesystem compatibility adapters that implement the existing
Filesinterface fromsrc/external/Files.ts, so that each build target can be compiled with the correct adapter injected.Tasks
1.
src/external/ElectronFiles.ts— Electron (Node.jsfs) adapterCreate a new file implementing
Filesusing Node.js'sfs/promisesmodule. This will be used when the app is bundled for Electron.Requirements:
Files,FileSystemItem,Folder,File(the class) from./FilesElectronFilesAdapter implements Filesimport { readFile, writeFile, rename, rm, mkdir, access, constants } from "fs/promises"andimport { join, dirname } from "path"root: aFolderrooted at the user data path (app.getPath("userData")from Electron — accept abasePath: stringconstructor parameter instead so it stays decoupled from Electron internals)readFile(path):fs/promisesreadFile with"utf-8"encodingwriteFile(path, data): ensure parent directories exist (mkdirrecursive), then writefileExists(path): useaccesswithconstants.F_OK, returntrue/falserename(item): rename using the item'sfullPath(uses the same path — no-op, as the caller is expected to have already updated the name property; preserve the original rename contract)moveItem(item, newParent): rename from old full path to new full pathdelete(path):rmwith{ recursive: true, force: true }createFolder(path):mkdirwith{ recursive: true }rootFolder should be initialized to thebasePathprovided in the constructor; override itsfullPathso paths are resolved relative tobasePath2.
src/external/NodeFiles.ts— Pure Node.js adapter (alias / re-export)Create
src/external/NodeFiles.tsthat simply re-exportsElectronFilesAdapterasNodeFilesAdapterfor clarity when used outside of Electron context (e.g., processing scripts, tests):3.
src/external/WebFiles.ts— Web (localStorage) adapter aliasCreate
src/external/WebFiles.tsthat re-exports the existingFilesFromLocalStorageasWebFilesAdapterfor symmetry and clarity in web builds:4.
src/external/PlatformFiles.ts— Platform detection bridgeCreate
src/external/PlatformFiles.tsthat exports acreatePlatformFiles()factory function. This function detects the runtime environment and returns the correct adapter:Detection order:
window.Capacitorexists andwindow.Capacitor.isNativeis true → useCapacitorFilesAdapterwindow.requireexists and callingwindow.require("electron")succeeds (Electron renderer) → useElectronFilesAdapterwithbasePathor a sensible defaultFilesFromLocalStorageNote: the actual
import()of platform-specific adapters should be lazy/dynamic so that esbuild's tree-shaking can eliminate unused adapters per build target. Use dynamicimport()for this reason. SincecreatePlatformFilesneeds to be async in that case, make it returnPromise<Files>.Alternatively, if dynamic imports are complex to set up in the existing esbuild config, use static imports but wrap with
try/catchfor the Electronrequiredetection. Document this in the file.5. Update
esbuild.config.mjs— addplatformbuild flagModify
esbuild.config.mjsto accept a second CLI argument (process.argv[3]) for platform target:web,electron, orcapacitor. Use esbuild'sdefineoption to injectPLATFORMas a compile-time constant: