UNPKG

bakana

Version:

Backend for kana's single-cell analyses. This supports single or multiple samples, execution in Node.js or the browser, in-memory caching of results for iterative analyses, and serialization to/from file for redistribution.

98 lines (90 loc) 3.14 kB
import * as fs from "fs"; import * as path from "path"; /** * Simple wrapper to represent a file in both Node.js and the browser. * This enables downstream code to operate independently of the source of the file. */ export class SimpleFile { #mode; #path; #buffer; #name; /** * @param {Uint8Array|string|File} x - Contents of a file or a pointer to it. * For browsers, this may be a File object; * for Node.js, this may be a string containing a file path. * @param {object} [options={}] - Optional parameters. * @param {?string} [options.name=null] - Name of the file. * If `null`, it is determined automatically from `x` where possible (i.e., basename of the file path or extracted from the File object). * If `x` is a Uint8Array, an explicit name is required. */ constructor(x, { name = null } = {}) { if (typeof x == "string") { this.#mode = "path"; this.#path = x; if (name === null) { name = path.basename(x); } this.#name = name; } else { this.#mode = "buffer"; this.#buffer = x; if (name === null) { throw new Error("'name' must be provided for Uint8Array inputs in SimpleFile constructor"); } this.#name = name; } } #get_buffer(copy) { if (copy) { return this.#buffer.slice(); } else { return this.#buffer; } } /** * @param {object} [options={}] - Optional parameters. * @param {boolean} [options.copy=false] - Whether to create a new copy of the buffer. * Callers should set this to `true` for non-read-only applications. * @return {Uint8Array} Contents of the file as an array. */ buffer({ copy = false } = {}) { if (this.#mode == "path") { let f = fs.readFileSync(this.#path); let b = f.buffer.slice(f.byteOffset, f.byteOffset + f.byteLength); return new Uint8Array(b); } else { return this.#get_buffer(copy); } } /** * @return {string} Name of the file, for disambiguation purposes. */ name() { return this.#name; } /** * @return {number} Size of the file, in bytes. */ size() { if (this.#mode == "path") { return fs.statSync(this.#path).size; } else { return this.#buffer.length; } } /** * @param {object} [options={}] - Optional parameters. * @param {boolean} [options.copy=false] - Whether to create a new copy of the buffer. * Callers should set this to `true` for non-read-only applications. * @return {Uint8Array|string} Contents of the file, as in {@linkcode SimpleFile#buffer SimpleFile.buffer}. * For Node.js, a string may also be returned containing the path to the original file. */ content({ copy = false } = {}) { if (this.#mode == "path") { return this.#path; } else { return this.#get_buffer(copy); } } };