Using File System
Read, write, and delete files inside your app's sandbox — no storage permissions required.
Basic usage
Every operation lives on the FileSystem namespace. Resolve a directory first, then build paths under it — always prefix paths with getDocumentDirectory() or getCacheDirectory() so they resolve consistently on both platforms.
import { FileSystem } from '@sigx/lynx-file-system';
const docs = FileSystem.getDocumentDirectory();
const path = `${docs}/data.json`;
await FileSystem.writeFile(path, JSON.stringify({ key: 'value' }));
const content = await FileSystem.readFile(path);
const data = JSON.parse(content);
No native setup is needed. The module is scoped to the per-app sandbox, so there are no Info.plist or AndroidManifest entries and no runtime grants — sigx prebuild discovers and links it automatically.
getDocumentDirectory() and getCacheDirectory() are synchronous and return a path immediately. Every other operation returns a Promise.
Persisting JSON data
The document directory survives app updates and is included in iCloud / Android backups — use it for data that must outlive the session. Check for a file with getInfo before reading so a missing file does not throw: a missing path resolves a FileInfo with exists: false and every other field zeroed.
import { FileSystem } from '@sigx/lynx-file-system';
const path = `${FileSystem.getDocumentDirectory()}/settings.json`;
async function loadSettings() {
const info = await FileSystem.getInfo(path);
if (!info.exists) return null;
const text = await FileSystem.readFile(path);
return JSON.parse(text);
}
async function saveSettings(settings: Record<string, unknown>) {
await FileSystem.writeFile(path, JSON.stringify(settings));
}
writeFile creates parent directories as needed (and writes atomically on iOS). It is UTF-8 text only — there is no binary write API.
Caching downloaded text
Use the cache directory for data you can regenerate. The OS may purge it under disk pressure, so never store anything there you cannot rebuild.
import { FileSystem } from '@sigx/lynx-file-system';
const cachePath = `${FileSystem.getCacheDirectory()}/feed.json`;
async function readCachedFeed() {
const info = await FileSystem.getInfo(cachePath);
if (!info.exists) return null;
return FileSystem.readFile(cachePath);
}
async function writeCachedFeed(json: string) {
await FileSystem.writeFile(cachePath, json);
}
Reading binary files
To read non-text files, use readFileBase64 (base64 string) or readFileAsArrayBuffer (decoded bytes). On Android, readFileBase64 also accepts content:// URIs returned by pickers. Both materialize the whole file in memory — and base64 is about 33% larger crossing the bridge — so they are fine for small and medium files only.
import { FileSystem } from '@sigx/lynx-file-system';
const path = `${FileSystem.getDocumentDirectory()}/thumbnail.png`;
const base64 = await FileSystem.readFileBase64(path);
const buffer = await FileSystem.readFileAsArrayBuffer(path);
For large media or uploads, do not read the bytes into JS. Pass the file URI from a picker directly to the network layer, or stream it from disk — see the Camera and Image Picker modules for picker URIs.
Deleting files and handling errors
deleteFile removes a file the app owns. Deleting something that isn't there is a no-op on both platforms; a real failure — a read-only path, or a non-empty directory on Android (iOS removes those recursively) — rejects. A picker's content:// URI is not a path the app owns, so deleting one rejects on Android rather than reporting a success that deleted nothing; file:// URIs are fine. Wrap calls that touch user files in try / catch.
import { FileSystem } from '@sigx/lynx-file-system';
const path = `${FileSystem.getDocumentDirectory()}/draft.txt`;
try {
await FileSystem.deleteFile(path);
} catch (err) {
console.error('Could not delete draft:', err);
}
Every async method throws on failure — a missing file for readFile, an unwritable path or a full volume for writeFile, a stat that fails for getInfo. The rejection is a SigxError with code: 'native_error', a message prefixed [@sigx/lynx-file-system] and the raw native payload on cause; a build without the native module throws 'module_unavailable' instead. See Handling errors.
Notes
- Guard against missing modules in a build with
FileSystem.isAvailable()before calling. - All operations run synchronously on the bridge thread, so keep reads and writes small to avoid blocking.
- Continue to the API reference for the full typed surface.
