import { FileSystem } from "./system" ; import JSZip from "jszip" ; class JSZipFS extends FileSystem { sep : string = "/" ; type : "zip" | "path" = "zip" ; writeable : boolean = true ; root : string = "" ; protected normalizePath ( path ) { if ( path . startsWith ( "/" ) ) { path = path . substring ( 1 ) ; } if ( this . root !== "" ) { path = [ this . root , path ] . join ( "/" ) ; } return path ; } join ( ... paths ) { return paths . join ( "/" ) ; } isDirectory ( name ) { name = this . normalizePath ( name ) ; name = name . endsWith ( "/" ) ? name : name + "/" ; return Promise . resolve ( Object . keys ( this . zip . files ) . some ( ( e ) => e . startsWith ( name ) ) ) ; } async writeFile ( name , data ) { name = this . normalizePath ( name ) ; this . zip . file ( name , data ) ; } existsFile ( name ) { name = this . normalizePath ( name ) ; if ( this . zip . files [ name ] !== undefined ) { return Promise . resolve ( true ) ; } return this . isDirectory ( name ) ; } readFile ( name , encoding ? ) { name = this . normalizePath ( name ) ; if ( ! encoding ) { return this . zip . files [ name ] . async ( "uint8array" ) ; } if ( encoding === "utf-8" ) { return this . zip . files [ name ] . async ( "text" ) ; } if ( encoding === "base64" ) { return this . zip . files [ name ] . async ( "base64" ) ; } throw new TypeError ( `Expect encoding to be utf-8/base64 or empty. Got ${ encoding }.` ) ; } async listFiles ( name ) { if ( ! await this . isDirectory ( name ) ) { return Promise . reject ( "Require a directory!" ) ; } name = this . normalizePath ( name ) ; return Promise . resolve ( Object . keys ( this . zip . files ) . filter ( ( e ) => e . startsWith ( name ) ) . map ( ( e ) => e . substring ( name . length ) ) . map ( ( e ) => e . startsWith ( "/" ) ? e . substring ( 1 ) : e ) . map ( ( e ) => e . split ( "/" ) [ 0 ] ) ) ; } cd ( name ) { if ( name . startsWith ( "/" ) ) { this . root = name . substring ( 1 ) ; return ; } let paths = name . split ( "/" ) ; for ( let path of paths ) { if ( path === "." ) { continue ; } else if ( path === ".." ) { let sub = this . root . split ( "/" ) ; if ( sub . length > 0 ) { sub . pop ( ) ; this . root = sub . join ( "/" ) ; } } else { if ( this . root === "" ) { this . root = path ; } else { this . root += `/${ path }` ; } } } } constructor ( private zip ) { super ( ) ; } } export async function openFileSystem ( basePath ) { if ( typeof basePath === "string" ) { throw new Error ( "Unsupported" ) ; } return new JSZipFS ( await JSZip . loadAsync ( basePath ) ) ; } export function resolveFileSystem ( base ) { if ( typeof base === "string" || base instanceof Uint8Array ) { return openFileSystem ( base ) ; } else { return Promise . resolve ( base ) ; } } export * from "./system" ;