UNPKG

@gmod/nclist

Version:

Read features from JBrowse 1 format nested containment list JSON

78 lines 3.24 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); //@ts-nocheck const abortable_promise_cache_1 = __importDefault(require("@gmod/abortable-promise-cache")); const quick_lru_1 = __importDefault(require("@jbrowse/quick-lru")); const util_ts_1 = require("./util.js"); /** * For a JSON array that gets too large to load in one go, this class * helps break it up into chunks and provides an * async API for using the information in the array. */ class LazyArray { constructor({ urlTemplate, chunkSize, length, cacheSize = 100, readFile }, baseUrl) { this.urlTemplate = urlTemplate; this.chunkSize = chunkSize; this.length = length; this.baseUrl = baseUrl === undefined ? '' : baseUrl; this.readFile = readFile; if (!readFile) { throw new Error('must provide readFile callback'); } this.chunkCache = new abortable_promise_cache_1.default({ cache: new quick_lru_1.default({ maxSize: cacheSize }), fill: this.getChunk.bind(this), }); } /** * call the callback on one element of the array * @param i index * @param callback callback, gets called with (i, value, param) * @param param (optional) callback will get this as its last parameter */ index(i, callback, param) { this.range(i, i, callback, undefined, param); } /** * async generator for the elements in the range [start,end] * * @param start index of first element to call the callback on * @param end index of last element to call the callback on */ async *range(start, end) { start = Math.max(0, start); end = Math.min(end, this.length - 1); const firstChunk = Math.floor(start / this.chunkSize); const lastChunk = Math.floor(end / this.chunkSize); const chunkreadFiles = []; for (let chunk = firstChunk; chunk <= lastChunk; chunk += 1) { chunkreadFiles.push(this.chunkCache.get(chunk, chunk)); } for (const elt of chunkreadFiles) { const [chunkNumber, chunkData] = await elt; yield* this.filterChunkData(start, end, chunkNumber, chunkData); } } async getChunk(chunkNumber) { let url = this.urlTemplate.replaceAll(/\{Chunk\}/gi, chunkNumber); if (this.baseUrl) { url = (0, util_ts_1.newURL)(url, this.baseUrl); } const data = await (0, util_ts_1.readJSON)(url, this.readFile); return [chunkNumber, data]; } *filterChunkData(queryStart, queryEnd, chunkNumber, chunkData) { // index (in the overall lazy array) of the first position in this chunk const firstIndex = chunkNumber * this.chunkSize; const chunkStart = Math.max(0, queryStart - firstIndex); const chunkEnd = Math.min(queryEnd - firstIndex, this.chunkSize - 1); for (let i = chunkStart; i <= chunkEnd; i += 1) { yield [i + firstIndex, chunkData[i]]; } } } exports.default = LazyArray; //# sourceMappingURL=lazy_array.js.map