Files
spacedrive/packages/ts-client
Jamie Pineandcapy-ai-staging[bot] e4b4cb71f5 Capture time and place in listings and search, read from the image facet on both backends (#3151)
* Capture time and place in listings and search, read from the image facet on both backends

search.files sorts by CapturedAt and filters by a CapturedAt range and
has_location; files.directory_listing sorts by datetaken; the media
listing's datetaken reads the facet. The store joins facet_image into
every entry read, guarded by the row's content hash, and the arena path
reads the facet from the store ahead of its sort and filter, so both
backends hand the same File to one predicate and one order (R8 row 19,
new row 29). File.image_media_data is filled from the facet on every
path; the inspector shows the capture time and the coordinates; Date
Taken is in every explorer view's sort menu.

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* search.media judges the capture filters on its rows and leaves replicas out under them; a directory listing reads facets ahead of the sort only for a capture order

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* search.media judges a replica's rows under a capture filter as search.files does instead of dropping the partition

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

---------

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>
2026-10-09 10:30:21 +00:00
..
…
…

@spacedrive/client

Type-safe TypeScript client for the Spacedrive daemon, automatically generated from Rust core types using Specta.

Features

  • Fully Type-Safe - All types generated directly from Rust core
  • Real-time Events - Subscribe to daemon events with full type safety
  • Unix Domain Sockets - Direct communication with daemon
  • Auto-Generated - Types stay in sync with Rust core automatically
  • Rich Documentation - JSDoc comments from Rust code

Installation

npm install @spacedrive/client

Quick Start

import { SpacedriveClient } from '@spacedrive/client';

const client = new SpacedriveClient();

// Test connection
await client.ping();

// Get libraries (fully typed)
const libraries = await client.getLibraries();
console.log('Libraries:', libraries);

// Get jobs with status filtering
const jobs = await client.getJobs('running');
console.log('Running jobs:', jobs);

// Create a new library
const newLibrary = await client.createLibrary('My Photos', '/Users/me/Photos');
console.log('Created library:', newLibrary);

Event Subscription

// Subscribe to specific event types
await client.subscribe(['JobStarted', 'JobProgress', 'JobCompleted']);

// Listen for events (fully typed)
client.on('event', (event) => {
  switch (event) {
    case 'CoreStarted':
      console.log('Daemon started');
      break;
    default:
      if ('JobStarted' in event) {
        console.log(`Job started: ${event.JobStarted.job_type} (${event.JobStarted.job_id})`);
      } else if ('JobProgress' in event) {
        console.log(`Job progress: ${event.JobProgress.progress * 100}%`);
      } else if ('JobCompleted' in event) {
        console.log(`Job completed: ${event.JobCompleted.job_type}`);
        console.log('Output:', event.JobCompleted.output);
      }
      break;
  }
});

client.on('error', (error) => {
  console.error('Client error:', error);
});

client.on('disconnected', () => {
  console.log('Disconnected from daemon');
});

Type Generation

Types are automatically generated from the Rust core using Specta. To regenerate types:

npm run generate-types

API Reference

Core Methods

  • ping() - Test daemon connectivity
  • executeQuery<Q, R>(query: Q, method: string): Promise<R> - Execute a query operation
  • executeAction<A, R>(action: A, method: string): Promise<R> - Execute an action operation
  • subscribe(eventTypes?: string[]): Promise<void> - Subscribe to daemon events

Convenience Methods

  • getLibraries(includeStats?: boolean): Promise<LibraryInfo[]> - Get all libraries
  • createLibrary(name: string, path?: string): Promise<LibraryCreateOutput> - Create a new library
  • getJobs(status?: JobStatus): Promise<JobListOutput> - Get job list with optional filtering

Event Types

All event types are fully typed TypeScript unions:

  • Event - Main event union type
  • JobOutput - Job completion output (adjacently tagged)
  • JobStatus - Job status enum ("queued" | "running" | "completed" | ...)
  • FileOperation - File operation types
  • Progress - Progress information with multiple formats

Architecture

This client uses the same architecture as the Swift client:

  1. JSON API Layer - Communicates via JSON instead of bincode for external clients
  2. Unix Domain Sockets - Direct, efficient communication with daemon
  3. Type Generation - Rust types → TypeScript via Specta
  4. Event Streaming - Real-time event subscription with line-delimited JSON

Development

# Install dependencies
npm install

# Build the client
npm run build

# Run tests
npm test

# Watch mode for development
npm run dev