Lynx/Modules/File System/Usage
@sigx/lynx-file-system · Stable

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.

TSX
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.

TSX
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.

TSX
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.

TSX
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.

TSX
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.