ZenFS
ZenFS 是一个跨平台库,用于模拟 Node.js 文件系统 API。 它通过一套后端系统工作,ZenFS 使用这些后端来存储和检索数据。 ZenFS 还可以与其他工具集成。
后端
ZenFS 是模块化的,易于扩展。核心包含一些内置后端:
InMemory: 在内存中存储文件。当运行时结束时(例如用户离开网页或 Node 进程退出)会被清除CopyOnWrite: 使用可读和可写文件系统,并采用 写时复制。Fetch: 通过fetchAPI 使用 HTTP 下载文件Port: 通过类似MessagePort的接口与远程交互(例如 worker)Passthrough: 使用现有的node:fs接口与 ZenFS 配合SingleBuffer: 包含在单个缓冲区中的后端。可以使用SharedArrayBuffer进行同步多线程操作
ZenFS 支持许多其他后端。
许多作为单独的软件包在 @zenfs 下提供。
可以通过扩展 FileSystem 类并提供一个 Backend 对象,由单独的库定义更多后端。
你可以在 NPM 上找到所有可用的软件包。以下是其中一些软件包包含的后端列表:
- @zenfs/archives:
Zip,Iso - @zenfs/cloud:
Dropbox,GoogleDrive,S3Bucket - @zenfs/dom:
WebAccess(Web 文件系统访问 API/OPFS),IndexedDB,WebStorage(localStorage/sessionStorage),XML(DOM 元素) - @zenfs/emscripten:
Emscripten以及 Emscripten 文件系统 API 的插件
作为额外的好处,所有 ZenFS 后端都支持同步操作。 此外,核心中包含的所有后端都是跨平台的。
有关更多信息,请参阅 docs。
安装
npm install @zenfs/core
如果你正在使用 ZenFS,尤其是用于大型项目,请考虑支持该项目。 数千小时已投入其开发。 你的财务支持将极大地推动 ZenFS 及其社区的改进。
用法
import { fs } from '@zenfs/core'; // You can also use the default export
fs.writeFileSync('/test.txt', 'You can do this anywhere, including browsers!');
const contents = fs.readFileSync('/test.txt', 'utf-8');
console.log(contents);
使用不同和/或多个后端
默认情况下,会创建一个 InMemory 后端,并挂载到 /。
您可以配置 ZenFS 使用不同的后端并挂载多个后端。强烈建议使用 configure 函数来实现。
您可以通过向 configure 传递一个对象来使用多个后端,该对象将路径映射到文件系统。
以下示例将 zip 文件挂载到 /zip,将内存存储挂载到 /tmp,将 IndexedDB 挂载到 /home。请注意,/ 具有默认的内存后端。
import { configure, InMemory } from '@zenfs/core';
import { IndexedDB } from '@zenfs/dom';
import { Zip } from '@zenfs/archives';
const res = await fetch('mydata.zip');
await configure({
mounts: {
'/mnt/zip': { backend: Zip, data: await res.arrayBuffer() },
'/tmp': InMemory,
'/home': IndexedDB,
},
});
请注意,虽然您不必使用 mounts 的键的绝对路径,但这样做是一个好习惯。
[!TIP] 在配置挂载点时,您可以传入
- 一个
Backend对象,如果后端没有必需的选项- 一个包含后端接受的选项和一个
backend属性的对象,该属性是一个Backend对象- 一个
FileSystem实例
以下是一个将 @zenfs/dom 的 WebStorage 后端挂载到 / 的示例:
import { configureSingle, fs } from '@zenfs/core';
import { WebStorage } from '@zenfs/dom';
await configureSingle({ backend: WebStorage });
if (!fs.existsSync('/test.txt')) {
fs.writeFileSync('/test.txt', 'This will persist across reloads!');
}
const contents = fs.readFileSync('/test.txt', 'utf-8');
console.log(contents);
FS Promises
FS promises API 以 promises 的形式暴露。
import { configureSingle } from '@zenfs/core';
import { exists, writeFile } from '@zenfs/core/promises';
import { IndexedDB } from '@zenfs/dom';
await configureSingle({ backend: IndexedDB });
const exists = await exists('/myfile.txt');
if (!exists) {
await writeFile('/myfile.txt', 'Lots of persistent data');
}
[!NOTE] 你可以使用以下方式导入 promises API:
- 来自
@zenfs/core/promises的导出- 来自
@zenfs/core的promises导出- 来自
@zenfs/core的已导出fs上的fs.promises。
挂载与卸载,创建后端
如果你希望在不使用 configure 的情况下创建后端(例如在运行时执行某些动态操作),你可以通过导入后端并调用 resolveMountConfig 来实现。
然后,你可以使用 mount 和 umount 来挂载和卸载后端实例。
import { configure, resolveMountConfig, InMemory } from '@zenfs/core';
import { IndexedDB } from '@zenfs/dom';
import { Zip } from '@zenfs/archives';
await configure({
mounts: {
'/tmp': InMemory,
'/home': IndexedDB,
},
});
fs.mkdirSync('/mnt/zip', { recursive: true });
const res = await fetch('mydata.zip');
const zipfs = await resolveMountConfig({ backend: Zip, data: await res.arrayBuffer() });
fs.mount('/mnt/zip', zipfs);
// do stuff with the mounted zip
fs.umount('/mnt/zip'); // finished using the zip
[!CAUTION] 后端实例遵循 内部 API。除非您正在扩展后端,否则不应使用后端的方法。
设备与设备文件
ZenFS 包含对设备文件的支持。这些设计旨在遵循 Linux 的设备文件行为,以保持一致性和易用性。请参阅 Devices and Device Drivers 文档以获取更多信息。
node:* 仿真
ZenFS 还包含对其他一些 node: 模块的仿真,出于各种原因,可从 @zenfs/core/<name> 导入:
node:pathnode:readline
例如:
import * as path from '@zenfs/core/path';
打包
ZenFS 导出了 Node 的 fs 模块的替代方案,因此您可以使用默认导出将其用于您选择的打包器。
[!IMPORTANT] 参见 COPYING.md
赞助商
衷心感谢 deco.cx 赞助 ZenFS 并帮助实现这一切。
联系与支持
您可以通过 Discord 或发送邮件至 jp@zenfs.dev 与我们联系