All files / src/adapters opfs.ts

100% Statements 16/16
100% Branches 9/9
100% Functions 2/2
100% Lines 16/16

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 311x 1x               1x 21x 21x             1x   1x 5x 4x 5x 5x 4x 4x 5x 5x 1x  
import { normalizePath } from '../path.js';
import { HandleAdapter } from './handle.js';
 
export interface OPFSAdapterOptions {
  /** Subfolder of the origin-private root to use as the adapter root. */
  path?: string;
  name?: string;
}
 
export function isOPFSAvailable(): boolean {
  return typeof navigator !== 'undefined' && !!navigator.storage?.getDirectory;
}
 
/**
 * Origin Private File System backend. Always available offline, never prompts,
 * and — unlike the File System Access API — its handles never lose permission,
 * which makes it the natural home for a background sync loop.
 */
export class OPFSAdapter extends HandleAdapter {
  /** Resolves the origin-private root (optionally a subfolder of it). */
  static async open(options: OPFSAdapterOptions = {}): Promise<OPFSAdapter> {
    if (!isOPFSAvailable()) throw new Error('OPFS is not available in this environment');
    let root = await navigator.storage.getDirectory();
    const path = normalizePath(options.path ?? '');
    for (const segment of path.split('/').filter(Boolean)) {
      root = await root.getDirectoryHandle(segment, { create: true });
    }
    return new OPFSAdapter(root, options.name ?? (path || 'opfs'));
  }
}