UNPKG

sc4

Version:

A command line utility for automating SimCity 4 modding tasks & modifying savegames

88 lines (87 loc) 2.62 kB
// # glob.browser.ts // This module contains an implementation of the Node.js glob module, but then // based on the Browser's file system api instead of using Node's fs module - // which isn't available in the browser obviously. import { Minimatch } from 'minimatch'; // # Glob export class Glob { pattern; cwd; constructor(pattern, opts) { const patterns = Array.isArray(pattern) ? [...pattern] : [pattern]; this.cwd = opts.cwd; const mmOptions = { nocase: opts.nocase, }; this.pattern = patterns.map((pattern) => { return new Minimatch(pattern, mmOptions); }); } // ## *[Symbol.asyncIterator]() async *[Symbol.asyncIterator]() { yield* this.stream(); } // ## stream() // Loops over all the files as a stream. This is the base for all of our // async functions. stream() { const glob = this; const info = new FileInfo(this.cwd, '/'); return new ReadableStream({ async start(controller) { const tasks = []; await readdir(info, (info) => { if (!glob.match(info.path)) return; const { handle, kind } = info; if (kind === 'file') { const task = handle .getFile() .then((src) => { controller.enqueue(new File([src], info.path)); }); tasks.push(task); } }); await Promise.all(tasks); controller.close(); }, }); } // ## async walk() async walk() { const files = []; for await (let file of this) { files.push(file); } return files; } // ## match() match(path) { return this.pattern.some((mm) => mm.match(path)); } } // # readdir() async function readdir(info, cb) { let tasks = []; for await (let handle of info.handle.values()) { let { name, kind } = handle; let path = `${info.path}${name}${kind === 'directory' ? '/' : ''}`; let child = new FileInfo(handle, path); if (kind === 'directory') { tasks.push(readdir(child, cb)); } cb(child); } await Promise.all(tasks); } class FileInfo { handle; kind; path; constructor(handle, path) { this.handle = handle; this.kind = handle.kind; this.path = path; } }