@statewalker/webrun-files 0.3.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +188 -6
  2. package/dist/cjs/index.cjs +599 -0
  3. package/dist/esm/index.js +584 -0
  4. package/dist/files-api.d.ts +44 -0
  5. package/dist/files-api.d.ts.map +1 -0
  6. package/dist/impl/index.d.ts +6 -0
  7. package/dist/impl/index.d.ts.map +1 -0
  8. package/dist/impl/mem-files-api.d.ts +13 -0
  9. package/dist/impl/mem-files-api.d.ts.map +1 -0
  10. package/dist/impl/node-files-api.d.ts +24 -0
  11. package/dist/impl/node-files-api.d.ts.map +1 -0
  12. package/dist/index.d.ts +12 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/types.d.ts +67 -0
  15. package/dist/types.d.ts.map +1 -0
  16. package/dist/utils/collect-stream.d.ts +16 -0
  17. package/dist/utils/collect-stream.d.ts.map +1 -0
  18. package/dist/utils/file-info-utils.d.ts +10 -0
  19. package/dist/utils/file-info-utils.d.ts.map +1 -0
  20. package/dist/utils/index.d.ts +8 -0
  21. package/dist/utils/index.d.ts.map +1 -0
  22. package/dist/utils/normalize-path.d.ts +21 -0
  23. package/dist/utils/normalize-path.d.ts.map +1 -0
  24. package/dist/utils/path-utils.d.ts +20 -0
  25. package/dist/utils/path-utils.d.ts.map +1 -0
  26. package/package.json +30 -31
  27. package/src/files-api.ts +168 -0
  28. package/src/impl/index.ts +6 -0
  29. package/src/impl/mem-files-api.ts +323 -0
  30. package/src/impl/node-files-api.ts +271 -0
  31. package/src/index.ts +36 -0
  32. package/src/types.ts +79 -0
  33. package/src/utils/collect-stream.ts +35 -0
  34. package/src/utils/file-info-utils.ts +15 -0
  35. package/src/utils/index.ts +8 -0
  36. package/src/utils/normalize-path.ts +34 -0
  37. package/src/utils/path-utils.ts +46 -0
  38. package/CHANGELOG.md +0 -2
  39. package/dist/index-umd.js +0 -1054
  40. package/dist/index-umd.min.js +0 -2
  41. package/dist/index.js +0 -1033
  42. package/dist/index.min.js +0 -2
  43. package/index.js +0 -1
  44. package/src/BrowserFilesApi.js +0 -335
  45. package/src/FilesApi.js +0 -133
  46. package/src/MemFilesApi.js +0 -129
  47. package/src/NodeFilesApi.js +0 -222
  48. package/src/addFilesApiLogger.js +0 -25
  49. package/src/getMimeType.js +0 -19
  50. package/src/index.js +0 -10
  51. package/src/mimeTypes.js +0 -96
  52. package/src/normalizePath.js +0 -8
  53. package/src/notImplemented.js +0 -3
  54. package/src/openBrowserFilesApi.js +0 -67
@@ -1,2 +0,0 @@
1
- // @statewalker/webrun-files v0.3.1 https://github.com/statewalker/webrun-files Copyright 2024 Mikhail Kotelnikov
2
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t(((e="undefined"!=typeof globalThis?globalThis:e||self).statewalker=e.statewalker||{},e.statewalker["webrun-files"]=e.statewalker["webrun-files"]||{}))}(this,(function(e){"use strict";function t(e){const t=e.split("/").filter((e=>!!e&&"."!==e));return 0===t.length&&t.push(""),t.unshift(""),t.join("/")}function i(){throw new Error("Not implemented.")}class n{constructor(e){this.options=e||{}}async*list(e,t={}){yield i()}async stats(e){return i()}async remove(e){return i()}async write(e,t){return i()}async*read(e,t){yield i()}async copy(e,t,i={}){const n=async(e,t,i)=>{t=`${t}${i.path.substring(e.length)}`;const n=this.read(i);return await this.write(t,n)},s=void 0===i.recursive||!!i.recursive,o=await this.stats(e);if("directory"===o.kind)for await(const o of this.list(e,{...i,recursive:s}))"directory"!==o.kind&&await n(e,t,o);else await n(e,t,o);return!0}async move(e,t,i={}){return!!await this.copy(e,t,i)&&(await this.remove(e),!0)}normalizePath(e){return t("object"==typeof e?e.path:e+"")}}const s=[{extensions:["aac"],mime:"audio/aac",description:"AAC audio"},{extensions:["abw"],mime:"application/x-abiword",description:"AbiWord document"},{extensions:["arc"],mime:"application/x-freearc",description:"Archive document (multiple files embedded)"},{extensions:["avi"],mime:"video/x-msvideo",description:"AVI: Audio Video Interleave"},{extensions:["azw"],mime:"application/vnd.amazon.ebook",description:"Amazon Kindle eBook format"},{extensions:["bin"],mime:"application/octet-stream",description:"Any kind of binary data"},{extensions:["bmp"],mime:"image/bmp",description:"Windows OS/2 Bitmap Graphics"},{extensions:["bz"],mime:"application/x-bzip",description:"BZip archive"},{extensions:["bz2"],mime:"application/x-bzip2",description:"BZip2 archive"},{extensions:["csh"],mime:"application/x-csh",description:"C-Shell script"},{extensions:["css"],mime:"text/css",description:"Cascading Style Sheets (CSS)"},{extensions:["csv"],mime:"text/csv",description:"Comma-separated values (CSV)"},{extensions:["doc"],mime:"application/msword",description:"Microsoft Word"},{extensions:["docx"],mime:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",description:"Microsoft Word (OpenXML)"},{extensions:["eot"],mime:"application/vnd.ms-fontobject",description:"MS Embedded OpenType fonts"},{extensions:["epub"],mime:"application/epub+zip",description:"Electronic publication (EPUB)"},{extensions:["gz"],mime:"application/gzip",description:"GZip Compressed Archive"},{extensions:["gif"],mime:"image/gif",description:"Graphics Interchange Format (GIF)"},{extensions:["htm","html"],mime:"text/html",description:"HyperText Markup Language (HTML)"},{extensions:["ico"],mime:"image/vnd.microsoft.icon",description:"Icon format"},{extensions:["ics"],mime:"text/calendar",description:"iCalendar format"},{extensions:["jar"],mime:"application/java-archive",description:"Java Archive (JAR)"},{extensions:["jpg","jpeg"],mime:"image/jpeg",description:"JPEG images"},{extensions:["js"],mime:"text/javascript",description:"JavaScript per the following specifications: https://html.spec.whatwg.org/multipage/#scriptingLanguages, https://html.spec.whatwg.org/multipage/#dependencies:willful-violation, https://datatracker.ietf.org/doc/draft-ietf-dispatch-javascript-mjs/"},{extensions:["json"],mime:"application/json",description:"JSON format"},{extensions:["jsonld"],mime:"application/ld+json",description:"JSON-LD format"},{extensions:["mid","midi"],mime:"application/ld+json",description:"Musical Instrument Digital Interface (MIDI)\taudio/midi audio/x-midi"},{extensions:["mjs"],mime:"text/javascript",description:"JavaScript module"},{extensions:["mp3"],mime:"audio/mpeg",description:"MP3 audio"},{extensions:["md"],mime:"text/markdown",description:"Markdown"},{extensions:["mpeg"],mime:"video/mpeg",description:"MPEG Video"},{extensions:["mpkg"],mime:"application/vnd.apple.installer+xml",description:"Apple Installer Package"},{extensions:["odp"],mime:"application/vnd.oasis.opendocument.presentation",description:"OpenDocument presentation document"},{extensions:["ods"],mime:"application/vnd.oasis.opendocument.spreadsheet",description:"OpenDocument spreadsheet document"},{extensions:["odt"],mime:"application/vnd.oasis.opendocument.text",description:"OpenDocument text document"},{extensions:["oga"],mime:"audio/ogg",description:"OGG audio"},{extensions:["ogv"],mime:"video/ogg",description:"OGG video"},{extensions:["ogx"],mime:"application/ogg",description:"OGG"},{extensions:["opus"],mime:"audio/opus",description:"Opus audio"},{extensions:["otf"],mime:"font/otf",description:"OpenType font"},{extensions:["png"],mime:"image/png",description:"Portable Network Graphics"},{extensions:["pdf"],mime:"application/pdf",description:"Adobe Portable Document Format (PDF)"},{extensions:["php"],mime:"application/x-httpd-php",description:"Hypertext Preprocessor (Personal Home Page)"},{extensions:["ppt"],mime:"application/vnd.ms-powerpoint",description:"Microsoft PowerPoint"},{extensions:["pptx"],mime:"application/vnd.openxmlformats-officedocument.presentationml.presentation",description:"Microsoft PowerPoint (OpenXML)"},{extensions:["rar"],mime:"application/vnd.rar",description:"RAR archive"},{extensions:["rtf"],mime:"application/rtf",description:"Rich Text Format (RTF)"},{extensions:["sh"],mime:"application/x-sh",description:"Bourne shell script"},{extensions:["svg"],mime:"image/svg+xml",description:"Scalable Vector Graphics (SVG)"},{extensions:["swf"],mime:"application/x-shockwave-flash",description:"Small web format (SWF) or Adobe Flash document"},{extensions:["tar"],mime:"application/x-tar",description:"Tape Archive (TAR)"},{extensions:["tif","tiff"],mime:"image/tiff",description:"Tagged Image File Format (TIFF)"},{extensions:["ttf"],mime:"font/ttf",description:"TrueType Font"},{extensions:["txt"],mime:"text/plain",description:"Text, (generally ASCII or ISO 8859-n)"},{extensions:["vsd"],mime:"application/vnd.visio",description:"Microsoft Visio"},{extensions:["wav"],mime:"audio/wav",description:"Waveform Audio Format"},{extensions:["weba"],mime:"audio/webm",description:"WEBM audio"},{extensions:["webm"],mime:"video/webm",description:"WEBM video"},{extensions:["webp"],mime:"image/webp",description:"WEBP image"},{extensions:["woff"],mime:"font/woff",description:"Web Open Font Format (WOFF)"},{extensions:["woff2"],mime:"font/woff2",description:"Web Open Font Format (WOFF)"},{extensions:["xhtml"],mime:"application/xhtml+xml",description:"XHTML"},{extensions:["xls"],mime:"application/vnd.ms-excel",description:"Microsoft Excel"},{extensions:["xlsx"],mime:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",description:"Microsoft Excel (OpenXML)"},{extensions:["xml"],mime:"application/xml",description:"XML; application/xml - if not readable from casual users (RFC 3023, section 3); text/xml - if readable from casual users (RFC 3023, section 3)"},{extensions:["xul"],mime:"application/vnd.mozilla.xul+xml",description:"XUL"},{extensions:["zip"],mime:"application/zip",description:"ZIP archive"},{extensions:["3gp"],mime:"video/3gpp",description:"3GPP audio/video container"},{extensions:["3g2"],mime:"video/3gpp2",description:"3GPP2 audio/video container; audio/3gpp if it doesn't contain video; audio/3gpp2 if it doesn't contain video"},{extensions:["7z"],mime:"application/x-7z-compressed",description:"7-zip archive"},{extensions:["jsx"],mime:"text/jsx",description:"JavaScript Syntax Extension / JavaScript XML format"},{extensions:["ts"],mime:"text/ts",description:"TypeScript format"},{extensions:["tsx"],mime:"text/tsx",description:"TypeScript Syntax Extension / TypeScript XML format"}],o=s.reduce(((e,t)=>(e[t.mime]=t.description,e)),{}),a=s.reduce(((e,t)=>{for(const i of t.extensions)e[i]=t.mime;return e}),{}),r=s.reduce(((e,t)=>(e[t.mime]=t.extensions,e)),{});function c(e){const t=e=e||"",i=(e=(e=e.split("?").shift()).split("/").pop()).split(".").pop();let n=a[i];return n||(n=t.match(/api\.observablehq\.com/)||t.match(/\.ojs$/)?"application/javascript-observable":"application/binary"),n}function p(e){const t=e.split("/");return t.pop(),t.join("/")}function d(...e){let t=e.map((e=>e.split("/"))).reduce(((e,t)=>(e.push(...t),e)),[]);const i=t.shift();return t=t.filter((e=>!!e&&"."!==e)),t.unshift(i),t.join("/")}async function l(e,t){try{const i=await e.stat(t);if(i&&i.isDirectory())return!0}catch(e){}const i=p(t);return t!==i&&(await l(e,i),await e.mkdir(t,{recursive:!0}),!0)}async function m(e,t){try{if((await e.stat(t)).isDirectory()){for await(let i of h(e,t,!1))await m(e,i.path);await e.rmdir(t)}else await e.unlink(t)}catch(e){if("ENOENT"!==e.code)throw e}}async function*h(e,t,i){try{if((await e.stat(t)).isDirectory()){const n=await e.readdir(t);for(const s of n.sort()){const n=d(t,s);let o=await e.stat(n);yield{path:n,stat:o},i&&o.isDirectory()&&(yield*h(e,n,!0))}}}catch(e){if("ENOENT"!==e.code)throw e}}class f{static canApply(e){return(e?.isDirectory||e?.isFile)&&"string"==typeof e?.name}async*listDirectoryChildren(e){let t=e.createReader();for(;;){const e=await new Promise(((e,i)=>t.readEntries(e,i)));if(!e.length)break;yield*e}}isDirectoryHandle(e){return e?.isDirectory}isFileHandle(e){return e?.isFile}async getSubdirectoryHandle(e,t,i){return new Promise(((n,s)=>e.getDirectory(t,{create:i},n,s)))}async getFileHandle(e,t,i=!0){return new Promise(((n,s)=>e.getFile(t,{create:i},n,s)))}async removeDirectoryEntry(e,t){return new Promise(((e,i)=>t.remove(e,i)))}async getFile(e){return await new Promise(((t,i)=>e.file(t,i)))}async getFileWriteStream(e){throw new Error("Not implemented")}}class u{static canApply(e){return"file"===e?.kind||"directory"===e?.kind}async*listDirectoryChildren(e){yield*e.values()}isDirectoryHandle(e){return"directory"===e?.kind}isFileHandle(e){return"file"===e?.kind}async getSubdirectoryHandle(e,t,i){return await e.getDirectoryHandle(t,{create:i})}async getFileHandle(e,t,i=!0){return await e.getFileHandle(t,{create:i})}async removeDirectoryEntry(e,t){return await e.removeEntry(t.name,{recursive:!0})}async getFile(e){return await e.getFile()}async getFileWriteStream(e){return await e.createWritable()}}class y extends n{constructor(e){if(super(e),!this.rootHandle)throw new Error("Root directory handle is not defined");if(!this.adapter)throw new Error("Can not define a browser adapter for the specified root handle")}get rootHandle(){return this.options.rootHandle||this.options.rootHandler}get adapter(){if(!this._adapter){const e=this.rootHandle;let t=f.canApply(e)?new f:u.canApply(e)?new u:null;this._adapter=t}return this._adapter}async*list(e,{recursive:t=!1}={}){const i=this._getPathSegments(e),n=await this._getHandle(i);if(!n)return;const s=this;this.adapter.isDirectoryHandle(n)&&(yield*async function*e(t,i,n){for await(const o of s._listDirectoryContent(i))yield await s._getFileInfo([...t,o.name],o),n&&s.adapter.isDirectoryHandle(o)&&(yield*e([...t,o.name],o,n))}(i,n,t))}async stats(e){const t=this._getPathSegments(e),i=await this._getHandle(t);return i?await this._getFileInfo(t,i):null}async remove(e){const t=async(e,i)=>{let n=!0;if(this.adapter.isDirectoryHandle(i)){const e=[];for await(let t of this.adapter.listDirectoryChildren(i))e.push(t);for(let s of e)n=n&&await t(i,s)}return e&&(n&=await this.adapter.removeDirectoryEntry(e,i)),n},i=this._getPathSegments(e),n=await this._getHandle(i);i.pop();const s=await this._getHandle(i);return t(s!==n?s:null,n)}async write(e,t){const i=this._getPathSegments(e),n=i.pop(),s=await this._getDirectoryHandle(i,!0),o=await this.adapter.getFileHandle(s,n,!0),a=await this.adapter.getFileWriteStream(o);try{"function"==typeof t&&(t=t());for await(let e of t)await a.write(e.buffer?e.buffer:e)}finally{await a.close()}}async*read(e){const t=this._getPathSegments(e),i=t.pop(),n=await this._getDirectoryHandle(t,!1),s=await this.adapter.getFileHandle(n,i,!1);if(!s)return;const o=(await this.adapter.getFile(s)).stream().getReader();try{let e;for(;(e=await o.read())&&!e.done;)yield await e.value}finally{await o.cancel&&o.cancel()}}async _getFileInfo(e,t){const i=(e=[...e])[e.length-1];e.unshift("");const n=e.join("/"),s={kind:"",path:n,name:i};if(this.adapter.isDirectoryHandle(t))s.kind="directory";else{s.kind="file";const e=await this.adapter.getFile(t);s.size=e.size,s.type=c(n),s.lastModified=e.lastModified}return s}_getPathSegments(e){return("object"==typeof e?e.path:e+"").split("/").filter((e=>!!e))}async _getHandle(e){const t=[...e],i=t.pop(),n=!1;try{const e=await this._getDirectoryHandle(t,n);try{return i?await this.adapter.getSubdirectoryHandle(e,i,n):e}catch(t){return await this.adapter.getFileHandle(e,i,n)}}catch(e){return}}async _getDirectoryHandle(e,t=!0){e=[...e];let i=this.rootHandle;for(let n of e)if(i=await this.adapter.getSubdirectoryHandle(i,n,t),!i)break;return i}async*_listDirectoryContent(e){let t=[];for await(const i of this.adapter.listDirectoryChildren(e))t.push(i);t=t.sort(((e,t)=>t.name>e.name?1:-1)),yield*t}}async function w(e){let t=!1;try{if("file"===e.kind)await e.getFile();else for await(let t of e.values())break;t=!0}catch(i){console.log(i,e),t=!1}return t}async function g(e,t){const i={};t&&(i.mode="readwrite");let n=!1;return"granted"===await e.queryPermission(i)&&(n=!0),n||"granted"!==await e.requestPermission(i)||(n=!0),n}e.BrowserFilesApi=y,e.FilesApi=n,e.MemFilesApi=class extends n{constructor(e){super(e),this.index={"/":{kind:"directory",path:"/",name:""}}}async*list(e,{recursive:t=!1}={}){await this._init();const i=this.normalizePath(e),n=this._getPaths();for(const e of n){if(0!==e.indexOf(i)||e===i)continue;const n=e.substring(i.length+1).split("/");(t||1===n.length)&&(yield this._getFileInfo(e))}}async stats(e){await this._init();const t=this.normalizePath(e);return this._getFileInfo(t)}async remove(e){await this._init();const t=await this.stats(e);if(!t)return!1;for await(const{path:e}of this.list(t,{recursive:!0}))"/"!==e&&delete this.index[e];delete this.index[t.path]}async write(e,t){await this._init(),await this._doWrite(e,t)}async*read(e){await this._init();const t=this.normalizePath(e),i=this.index[t];if(!i||"file"!==i.kind)return;const n=i.content;yield*n}async _init(){return this._initPromise=this._initPromise||Promise.resolve().then((()=>this._addEntries(this.options.files)))}async _doWrite(e,t){const i=this.normalizePath(e).split("/").filter((e=>!!e)),n=[""];let s;for(let e=0;e<i.length;e++){const t=i[e];n.push(t);const o=n.join("/");s=this.index[o]=this.index[o]||{path:o,name:t,kind:"directory"}}s.kind="file",s.content=[],s.type=c(s.path),s.size=0,s.lastModified=Date.now(),"function"==typeof t&&(t=t());for await(let e of t)e=new Uint8Array(e),s.content.push(e),s.size+=e.length}async _addEntries(e={}){for(let[t,i]of Object.entries(e))"string"==typeof i?i=[(new TextEncoder).encode(i)]:i instanceof Uint8Array&&(i=[i]),await this._doWrite(t,i)}_getPaths(){return this._getIndexPaths(this.index)}_getIndexPaths(e){return Object.keys(e).sort((function(e,t){return e>t?1:e<t?-1:0}))}_getFileInfo(e){const t=this.index[e];if(!t)return null;const i={...t};return delete i.content,i}},e.NodeFilesApi=class extends n{constructor(e){if(super(e),!this.fs)throw new Error("File System is not defined.");if(!this.rootDir)throw new Error("Root directory is not defined.")}get rootDirSegments(){return this._rootDirSegments||(this._rootDirSegments=this._toPathSegments(this.options.rootDir||"./")),this._rootDirSegments}get rootDir(){return this._rootDir||(this._rootDir=this.rootDirSegments.join("/")),this._rootDir}get fs(){return this.options.fs}async _init(){return this._initialized=this._initialized||(async()=>{const e=this.rootDir;return await l(this.fs,e)})()}async*list(e,{recursive:t=!1}={}){await this._init();const i=this._expandPath(e),n=await this._stats(i);if(n&&"directory"===n.kind)for await(let e of h(this.fs,i,t))yield this._getFileInfo(e.path,e.stat)}async stats(e){await this._init();const t=this._expandPath(e);return this._stats(t)}async remove(e){await this._init();const t=this._expandPath(e);return await m(this.fs,t)}async write(e,t){await this._init();const i=this._expandPath(e),n=p(i);let s;await this.fs.mkdir(n,{recursive:!0});try{s=await this.fs.open(i,"w"),"function"==typeof t&&(t=t()),await s.writeFile(t)}finally{s&&await s.close()}}async*read(e,{start:t=0,bufferSize:i=8192}={}){await this._init();const n=this._expandPath(e);let s;try{s=await this.fs.open(n,"r");const e=0;for(let n=t,o=0;;n+=o){const t=new Uint8ClampedArray(i),a=await s.read(t,e,i,n);if(o=a.bytesRead,0===o)break;yield o<i?a.buffer.slice(0,o):a.buffer}}finally{s&&await s.close()}}async _stats(e){try{const t=await this.fs.stat(e);return this._getFileInfo(e,t)}catch(e){if("ENOENT"!==e.code)throw e;return null}}_getFileInfo(e,t){const i=this._toPathSegments(e).slice(this.rootDirSegments.length);i.unshift("");const n=i[i.length-1];let s={path:e=i.join("/"),name:n,kind:""};return t.isFile()?(s.size=t.size||0,s.type=c(e),s.kind="file",s.lastModified=new Date(t.mtime).getTime()):s.kind="directory",s}_toPathSegments(e){return(e=this.normalizePath(e)).split("/")}_expandPath(e){const t="object"==typeof e?e.path:e+"",i=this._toPathSegments(t).filter((e=>!!e));return i.unshift(...this.rootDirSegments),i.join("/")}},e.addFilesApiLogger=function({filesApi:e,log:t=console.log,wrapper:i={}}){return["list","stats","remove","write","read","copy","move"].reduce(((i,n)=>{const s=e[n].bind(e);return i[n]=(...i)=>{let o={method:n,stage:"enter",args:i};try{return t(o),o.result=s.call(e,...i)}catch(e){o.error=e}finally{o.stage="exit",t(o)}},i}),i)},e.extensionToMimeType=a,e.getMimeType=c,e.isHandlerAccessible=w,e.mimeTypeToExtensions=r,e.mimeTypes=s,e.mimeTypesDescriptions=o,e.normalizePath=t,e.openBrowserFilesApi=async function({handlerKey:e="root-dir",readwrite:t=!0,index:i={},get:n=(async e=>i[e]),set:s=(async(e,t)=>i[e]=t),del:o=(async e=>delete i[e])}={}){let a=await n(e);if(a||(a=await window.showDirectoryPicker(),await s(e,a)),!await g(a,t))throw new Error("Access was not granted");if(!await w(a))throw await o(e),new Error("Can not access to the folder. Please try again.");return new y({rootHandler:a})},e.verifyPermission=g}));