All files / src/node-to-fsa NodeFileSystemFileHandle.ts

78.78% Statements 26/33
25% Branches 3/12
100% Functions 5/5
83.87% Lines 26/31

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 797x 7x 7x 7x       7x       123x 123x     123x 123x 123x                   32x 32x 32x 32x   32x 32x 32x                                   24x 24x 24x 2x   22x                   53x 52x 3x   49x              
import { NodeFileSystemHandle } from './NodeFileSystemHandle';
import { NodeFileSystemSyncAccessHandle } from './NodeFileSystemSyncAccessHandle';
import { assertCanWrite, basename, ctx as createCtx, newNotAllowedError, newNoModificationAllowedError } from './util';
import { NodeFileSystemWritableFileStream } from './NodeFileSystemWritableFileStream';
import type { NodeFsaContext, NodeFsaFs } from './types';
import type { IFileSystemFileHandle, IFileSystemSyncAccessHandle } from '../fsa/types';
 
export class NodeFileSystemFileHandle extends NodeFileSystemHandle implements IFileSystemFileHandle {
  protected readonly ctx: NodeFsaContext;
 
  constructor(
    protected readonly fs: NodeFsaFs,
    public readonly __path: string,
    ctx: Partial<NodeFsaContext> = {},
  ) {
    ctx = createCtx(ctx);
    super('file', basename(__path, ctx.separator!));
    this.ctx = ctx as NodeFsaContext;
  }
 
  /**
   * 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 promises = this.fs.promises;
      const stats = await promises.stat(path);
      // TODO: Once implemented, use promises.readAsBlob() instead of promises.readFile().
      const data = await promises.readFile(path);
      const file = new File([data as BlobPart], this.name, { lastModified: stats.mtime.getTime() });
      return file;
    } catch (error) {
      Iif (error instanceof DOMException) throw error;
      Iif (error && typeof error === 'object') {
        switch (error.code) {
          case 'EPERM':
          case 'EACCES':
            throw newNotAllowedError();
        }
      }
      throw error;
    }
  }
 
  /**
   * @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemFileHandle/createSyncAccessHandle
   */
  public get createSyncAccessHandle(): undefined | (() => Promise<IFileSystemSyncAccessHandle>) {
    Iif (!this.ctx.syncHandleAllowed) return undefined;
    return async () => {
      if (this.ctx.locks.isLocked(this.__path)) {
        throw newNoModificationAllowedError();
      }
      return new NodeFileSystemSyncAccessHandle(this.fs, 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<NodeFileSystemWritableFileStream> {
    assertCanWrite(this.ctx.mode);
    if (this.ctx.locks.isLocked(this.__path)) {
      throw newNoModificationAllowedError();
    }
    return new NodeFileSystemWritableFileStream(this.fs, this.__path, keepExistingData, this.ctx);
  }
}
 
export interface CreateWritableOptions {
  keepExistingData?: boolean;
}