All files / app/util zip.ts

10.34% Statements 3/29
0% Branches 0/12
0% Functions 0/15
11.53% Lines 3/26

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 75126x   126x 126x                                                                                                                                              
import JSZip from 'jszip';
import { isArray } from 'lodash-es';
import { Ext, mapExt } from '../model/ext';
import { mapRef, Ref } from '../model/ref';
import { Cursor } from '../model/tag';
 
export function unzip(file: File) {
  return JSZip.loadAsync(file).catch(() => {
    throw 'Could not read ZIP file.';
  });
}
 
export function zippedFile(zip: JSZip, fileName: string) {
  return zip.file(fileName)?.async('string')?.catch(err => {
    console.error(err);
      return '';
    }) ||
    Promise.resolve(undefined);
}
 
export function getTextFile(file: File): Promise<string | undefined> {
  return new Promise((resolve, reject) => {
    const fr = new FileReader();
    fr.onload = () => {
      resolve(fr.result as string)
    };
    fr.onerror = () => reject('Could not read text file.');
    fr.readAsText(file);
  });
}
 
export function getZipOrTextFile(file: File, zipFileName: string): Promise<string | undefined> {
  if (file.name.toLowerCase().endsWith('.zip')) {
    return unzip(file).then(zip => zippedFile(zip, zipFileName));
  } else {
    return getTextFile(file);
  }
}
 
export type FilteredModels = {ref: Ref[], ext: Ext[]};
export function filterModels<T extends Cursor>(models: T[]): FilteredModels {
  return {
    ref: models.filter(m => 'url' in m).map(mapRef),
    ext: models.filter(m => 'tag' in m).map(mapExt),
  };
}
 
export function getModels<T extends Cursor>(json?: string): T[] {
  if (!json) return [];
  const models = JSON.parse(json);
  return (isArray(models) ? models : [models]).map(m => {
    m.upload = true;
    delete m.created;
    return m;
  });
}
 
export function parseModels(file: File): Promise<FilteredModels> {
  if (file.name.toLowerCase().endsWith('.zip')) {
    return unzip(file).then(zip => Promise.all([
      zippedFile(zip, 'ext.json')
        .then(json => getModels<Ext>(json))
        .then(exts => exts.map(mapExt)),
      zippedFile(zip, 'ref.json')
        .then(json => getModels<Ref>(json))
        .then(refs => refs.map(mapRef)),
    ]))
      .then(([ext, ref]) => ({ ext, ref }));
  } else {
    return getTextFile(file)
      .then(getModels)
      .then(filterModels);
  }
}