{
  "version": 3,
  "sources": ["../index.ts"],
  "sourcesContent": ["/**\n * @module @xmcl/unzip\n */\nimport { Readable } from 'stream'\nimport { Entry, fromBuffer, fromFd, open as yopen, ZipFile, ZipFileOptions, Options } from 'yauzl'\n\nexport type OpenTarget = string | Buffer | number\n\n/**\n * Open a yauzl zip\n * @param target The zip path or buffer or file descriptor\n * @param options The option to open\n */\nexport async function open(target: OpenTarget, options: Options = { lazyEntries: true, autoClose: false }) {\n  return new Promise<ZipFile>((resolve, reject) => {\n    function handleZip(err: Error | null, zipfile: ZipFile | null) {\n      if (err || !zipfile) {\n        reject(err ?? new Error('Cannot open zip!'))\n      } else {\n        resolve(zipfile)\n      }\n    }\n    if (typeof target === 'string') {\n      yopen(target, options, handleZip)\n    } else if (target instanceof Buffer) {\n      fromBuffer(target, options, handleZip)\n    } else {\n      fromFd(target, options, handleZip)\n    }\n  })\n}\n\n/**\n * Open the entry readstream for the zip file\n * @param zip The zip file object\n * @param entry The entry to open\n * @param options The options to open stream\n */\nexport function openEntryReadStream(zip: ZipFile, entry: Entry, options?: ZipFileOptions) {\n  return new Promise<Readable>((resolve, reject) => {\n    function handleStream(err: Error | null, stream: Readable | null) {\n      if (err || !stream) { reject(err) } else { resolve(stream) }\n    }\n    if (options) { zip.openReadStream(entry, options, handleStream) } else { zip.openReadStream(entry, handleStream) }\n  })\n}\n\n/**\n * Read the entry to buffer\n * @param zip The zip file object\n * @param entry The entry to open\n * @param options The options to open stream\n */\nexport async function readEntry(zip: ZipFile, entry: Entry, options?: ZipFileOptions) {\n  const stream = await openEntryReadStream(zip, entry, options)\n  const buffers: Buffer[] = []\n  await new Promise((resolve, reject) => {\n    stream.on('data', (chunk) => { buffers.push(chunk) })\n    stream.on('end', resolve)\n    stream.on('error', reject)\n  })\n  return Buffer.concat(buffers)\n}\n\n/**\n * Get the async entry generator for the zip file\n * @param zip The zip file\n */\nexport async function * walkEntriesGenerator(zip: ZipFile): AsyncGenerator<Entry, void, boolean | undefined> {\n  let ended = false\n  let error: any\n  let resume: (v?: any) => void = () => { }\n  let wait = new Promise<void>((resolve) => {\n    resume = resolve\n  })\n  const entries: Entry[] = []\n  const onEntry = (e: Entry) => {\n    entries.push(e)\n    resume()\n  }\n  const onEnd = () => {\n    ended = true\n    resume()\n  }\n  const onError = (e: any) => {\n    error = e\n    resume()\n  }\n\n  zip.addListener('entry', onEntry)\n    .addListener('end', onEnd)\n    .addListener('error', onError)\n\n  try {\n    while (!ended) {\n      if (zip.lazyEntries) {\n        zip.readEntry()\n      }\n      await wait\n      // if error, throw error\n      if (error) {\n        throw error\n      }\n      // if entries read, yield entries\n      while (entries.length > 0 && !ended) {\n        ended = !!(yield entries.pop()!)\n      }\n      // reset wait\n      wait = new Promise<void>((resolve) => {\n        resume = resolve\n      })\n    }\n  } finally {\n    zip.removeListener('entry', onEntry)\n      .removeListener('end', onEnd)\n      .removeListener('error', onError)\n  }\n}\n\n/**\n * Walk all the entries of the zip and once provided entries are all found, then terminate the walk process\n * @param zip The zip file\n * @param entries The entry to read\n */\nexport async function filterEntries(zip: ZipFile, entries: Array<string | ((entry: Entry) => boolean)>): Promise<(Entry | undefined)[]> {\n  const bags = entries.map(e => [e, undefined as undefined | Entry] as const)\n  let remaining = entries.length\n  for await (const entry of walkEntriesGenerator(zip)) {\n    for (const bag of bags) {\n      if (typeof bag[0] === 'string') {\n        if (bag[0] === entry.fileName) {\n          // @ts-ignore\n          bag[1] = entry\n          remaining -= 1\n        }\n      } else {\n        if (bag[0](entry)) {\n          // @ts-ignore\n          bag[1] = entry\n          remaining -= 1\n        }\n      }\n      if (remaining === 0) break\n    }\n  }\n  return bags.map(b => b[1])\n}\n\n/**\n * Walk all the entries of a unread zip file\n * @param zip The unread zip file\n * @param entryHandler The handler to recieve entries. Return true or Promise<true> to stop the walk\n */\nexport async function walkEntries(zip: ZipFile, entryHandler: (entry: Entry) => Promise<boolean> | boolean | void) {\n  const itr = walkEntriesGenerator(zip)\n  for await (const entry of itr) {\n    const result = await entryHandler(entry)\n    if (result) {\n      break\n    }\n  }\n}\n\nexport function getEntriesRecord(entries: Entry[]): Record<string, Entry> {\n  const record: Record<string, Entry> = {}\n  for (const entry of entries) {\n    record[entry.fileName] = entry\n  }\n  return record\n}\n\n/**\n * Walk all entries of the zip file\n * @param zipFile The zip file object\n */\nexport async function readAllEntries(zipFile: ZipFile) {\n  const entries: Entry[] = []\n  for await (const entry of walkEntriesGenerator(zipFile)) {\n    entries.push(entry)\n  }\n  return entries\n}\n"],
  "mappings": "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",
  "names": []
}
