All files / src/fsa CoreFileSystemFileHandle.ts

81.08% Statements 30/37
35.71% Branches 5/14
100% Functions 5/5
82.85% Lines 29/35

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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 905x 5x 5x 5x                   5x       42x 42x     42x 42x 42x                   13x 13x 13x 13x   13x         13x     13x 13x   13x 13x                                 12x 11x 9x 2x   7x                   13x 12x 2x   10x      
import { CoreFileSystemHandle } from './CoreFileSystemHandle';
import { CoreFileSystemSyncAccessHandle } from './CoreFileSystemSyncAccessHandle';
import { assertCanWrite, basename, ctx as createCtx, newNotAllowedError, newNoModificationAllowedError } from './util';
import { CoreFileSystemWritableFileStream } from './CoreFileSystemWritableFileStream';
import type {
  CoreFsaContext,
  CreateWritableOptions,
  IFileSystemFileHandle,
  IFileSystemSyncAccessHandle,
} from './types';
import type { Superblock } from '../core/Superblock';
import { ERROR_CODE } from '../core/constants';
 
export class CoreFileSystemFileHandle extends CoreFileSystemHandle implements IFileSystemFileHandle {
  protected readonly ctx: CoreFsaContext;
 
  constructor(
    protected readonly _core: Superblock,
    public readonly __path: string,
    ctx: Partial<CoreFsaContext> = {},
  ) {
    const fullCtx = createCtx(ctx);
    super('file', basename(__path, fullCtx.separator), fullCtx);
    this.ctx = fullCtx;
  }
 
  /**
   * Returns a {@link Promise} which resolves to a {@link File} object
   * representing the state on disk of the entry represented by the handle.
   *
   * @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemFileHandle/getFile
   */
  public async getFile(): Promise<File> {
    try {
      const path = this.__path;
      const link = this._core.getResolvedLinkOrThrow(path);
      const node = link.getNode();
 
      Iif (!node.isFile()) {
        throw new Error('Not a file');
      }
 
      // Get file stats for lastModified
      const lastModified = node.mtime ? node.mtime.getTime() : Date.now();
 
      // Read file content
      const buffer = node.getBuffer();
      const data = new Uint8Array(buffer);
 
      const file = new File([data], this.name, { lastModified });
      return file;
    } catch (error) {
      Iif (error instanceof DOMException) throw error;
      Iif (error && typeof error === 'object') {
        switch (error.code) {
          case ERROR_CODE.EACCES:
            throw newNotAllowedError();
        }
      }
      throw error;
    }
  }
 
  /**
   * @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemFileHandle/createSyncAccessHandle
   */
  public get createSyncAccessHandle(): undefined | (() => Promise<IFileSystemSyncAccessHandle>) {
    if (!this.ctx.syncHandleAllowed) return undefined;
    return async () => {
      if (this.ctx.locks.isLocked(this.__path)) {
        throw newNoModificationAllowedError();
      }
      return new CoreFileSystemSyncAccessHandle(this._core, this.__path, this.ctx);
    };
  }
 
  /**
   * @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemFileHandle/createWritable
   */
  public async createWritable(
    { keepExistingData = false }: CreateWritableOptions = { keepExistingData: false },
  ): Promise<CoreFileSystemWritableFileStream> {
    assertCanWrite(this.ctx.mode);
    if (this.ctx.locks.isLocked(this.__path)) {
      throw newNoModificationAllowedError();
    }
    return new CoreFileSystemWritableFileStream(this._core, this.__path, keepExistingData, this.ctx);
  }
}