npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@livestore-filesync/expo

v0.6.1

Published

Expo filesystem and image processing adapters for livestore-filesync

Downloads

824

Readme

@livestore-filesync/expo

Expo/React Native adapters for livestore-filesync. Provides filesystem and image processing implementations for mobile apps.

Features

  • Effect Platform FileSystem - Full @effect/platform FileSystem implementation using expo-file-system
  • Image Processor - URI-based image processor using expo-image-manipulator for thumbnails and resizing
  • ExpoFile Wrapper - File-like wrapper that bridges URI-based files with the Web File API

Installation

pnpm add @livestore-filesync/expo @livestore-filesync/core

Peer Dependencies

This package requires the following Expo packages to be installed in your app:

npx expo install expo-file-system expo-image-manipulator

Usage

FileSystem Adapter

The Expo FileSystem adapter implements the @effect/platform FileSystem interface, allowing livestore-filesync to work seamlessly on mobile:

import { initFileSync } from '@livestore-filesync/core'
import { layer as expoFileSystemLayer } from '@livestore-filesync/expo'

// Initialize with Expo filesystem (uses Documents directory by default)
const dispose = initFileSync(store, {
  fileSystem: expoFileSystemLayer(),
  remote: { signerBaseUrl: 'https://api.example.com' }
})

Custom Base Directory

By default, files are stored in Paths.document (persistent storage). You can customize this:

import { layer as expoFileSystemLayer } from '@livestore-filesync/expo'
import { Paths } from 'expo-file-system'

// Use cache directory instead (can be cleared by OS)
const dispose = initFileSync(store, {
  fileSystem: expoFileSystemLayer({ baseDirectory: Paths.cache }),
  remote: { signerBaseUrl: 'https://api.example.com' }
})

Image Processor

The Expo image processor uses expo-image-manipulator for native image processing:

import { createExpoImageProcessor } from '@livestore-filesync/expo'

const processor = createExpoImageProcessor()
await processor.init()

// Process a single image
const result = await processor.process('file:///path/to/image.jpg', {
  maxDimension: 1500,
  format: 'jpeg',
  quality: 85
})

console.log(result.uri)    // file:///path/to/processed.jpg
console.log(result.width)  // 1500
console.log(result.height) // 1000
console.log(result.mimeType) // image/jpeg

// Process multiple sizes at once
const thumbnails = await processor.processMultiple(
  'file:///path/to/image.jpg',
  { small: 200, medium: 800, large: 1500 },
  { format: 'jpeg', quality: 80 }
)

Format Support

| Format | iOS | Android | |--------|-----|---------| | JPEG | Yes | Yes | | PNG | Yes | Yes | | WebP | No* | Yes |

*WebP encoding is only supported on Android. On iOS, requesting WebP will automatically fall back to JPEG.

ExpoFile Wrapper

The ExpoFile class provides a Web File-like interface for URI-based files, enabling compatibility with FilePreprocessor and other APIs that expect the standard File API:

import { ExpoFile } from '@livestore-filesync/expo'

// Create from a file URI
const file = ExpoFile.fromUri('file:///path/to/image.jpg', {
  type: 'image/jpeg'  // Optional, inferred from extension if not provided
})

// Use with any API expecting a File
const buffer = await file.arrayBuffer()
const text = await file.text()
const bytes = await file.bytes()

// Create from bytes (writes to cache directory)
const newFile = await ExpoFile.fromBytes(
  uint8Array,
  'output.jpg',
  'image/jpeg'
)
console.log(newFile.uri) // file:///path/to/cache/output.jpg

File Properties

file.uri          // The file:// URI
file.name         // Filename
file.type         // MIME type
file.size         // File size in bytes (0 if unknown, use getSize() for accurate size)
file.lastModified // Last modified timestamp

API Reference

FileSystem Layer

// Default layer (uses Paths.document)
export const layerDefault: Layer.Layer<FileSystem>

// Configurable layer
export function layer(options?: ExpoFileSystemOptions): Layer.Layer<FileSystem>

interface ExpoFileSystemOptions {
  baseDirectory?: string  // Base directory for all operations
}

Image Processor

export function createExpoImageProcessor(
  options?: ExpoImageProcessorOptions
): UriImageProcessor

interface ExpoImageProcessorOptions {
  defaultQuality?: number  // Default quality 0-100 (default: 90)
}

interface UriImageProcessor {
  readonly type: 'uri'
  readonly capabilities: ImageProcessorCapabilities
  init(): Promise<void>
  isInitialized(): boolean
  process(inputUri: string, options: ProcessImageOptions): Promise<ProcessedImageUri>
  processMultiple(
    inputUri: string,
    sizes: Record<string, number>,
    options: Omit<ProcessImageOptions, 'maxDimension'>
  ): Promise<Record<string, ProcessedImageUri>>
}

interface ProcessImageOptions {
  maxDimension: number
  format: 'jpeg' | 'webp' | 'png'
  quality?: number  // 0-100
}

interface ProcessedImageUri {
  uri: string
  width: number
  height: number
  mimeType: string
}

ExpoFile

export class ExpoFile implements Blob {
  readonly uri: string
  readonly name: string
  readonly type: string
  readonly size: number
  readonly lastModified: number

  constructor(uri: string, name: string, type: string, options?: {
    lastModified?: number
    size?: number
  })

  // Async methods
  arrayBuffer(): Promise<ArrayBuffer>
  bytes(): Promise<Uint8Array>
  text(): Promise<string>
  getSize(): Promise<number>  // Accurate size (reads from filesystem if needed)
  stream(): ReadableStream<Uint8Array>

  // Static factories
  static fromUri(uri: string, options?: {
    name?: string
    type?: string
    lastModified?: number
    size?: number
  }): ExpoFile

  static fromBytes(
    bytes: Uint8Array,
    name: string,
    type: string,
    options?: { cacheDir?: string }
  ): Promise<ExpoFile>
}

Supported FileSystem Operations

| Operation | Supported | Notes | |-----------|-----------|-------| | readFile / writeFile | Yes | | | readFileString / writeFileString | Yes | | | exists | Yes | | | makeDirectory | Yes | Recursive by default | | readDirectory | Yes | Supports recursive option | | remove | Yes | Supports recursive and force options | | copy / copyFile | Yes | | | rename | Yes | Uses move internally | | stat | Yes | Returns size, type, mtime, birthtime | | makeTempFile / makeTempDirectory | Yes | Uses cache directory | | chmod / chown | No-op | Not supported on mobile | | link / symlink / readLink | Error | Not supported on mobile | | watch | Error | Not supported by expo-file-system | | open (file handles) | Error | Use readFile/writeFile instead |

Limitations

  1. No file watching - expo-file-system doesn't support filesystem watching
  2. No symlinks/hardlinks - Not available on mobile platforms
  3. No permissions - chmod/chown are no-ops
  4. WebP on iOS - WebP encoding falls back to JPEG on iOS
  5. File handles - The open() method is not implemented; use readFile/writeFile instead

License

MIT