zen-fs-config 0.5.19 → 0.5.21
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.
- package/README.md +89 -84
- package/README.zh-CN.md +193 -0
- package/dist/index.js +106 -118
- package/dist/index.mjs +106 -118
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -1,192 +1,197 @@
|
|
|
1
1
|
# zen-fs-config
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Distributed configuration management library built on [ZenFS](https://github.com/weijia/zen-fs), with IndexedDB as the offline-first local primary backend and user-provided remote backends as replicas that sync automatically. Supports app isolation, shared spaces, node-local config, and conflict-safe operations.
|
|
4
4
|
|
|
5
5
|
**GitHub**: https://github.com/weijia/zen-fs-config
|
|
6
6
|
**NPM**: `zen-fs-config`
|
|
7
|
-
|
|
7
|
+
**Design doc**: [DESIGN.md](./DESIGN.md)
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **Offline-first** — IndexedDB is always the primary backend; reads and writes work without network
|
|
12
|
+
- **Multi-backend sync** — Add any number of remote replicas (Gitee, GitHub, RemoteStorage, WebDAV, etc.) with automatic bi-directional sync
|
|
13
|
+
- **App isolation** — Each app gets its own namespace under `/{appId}/`
|
|
14
|
+
- **Shared spaces** — Cross-app shared config under `/shared/`
|
|
15
|
+
- **Node-local config** — Per-device settings under `/nodes/{nodeId}/` that never sync
|
|
16
|
+
- **Self-describing topology** — Backend configuration is stored as files in `.meta/backends/`, so re-opening a repo restores everything automatically
|
|
17
|
+
- **Conflict safety** — Conflicts are archived instead of silently overwritten; JSON deep-merge is available as a strategy
|
|
18
|
+
- **Version tracking** — Every config file has a version sidecar with version number and SHA-256 hash
|
|
19
|
+
- **Caching layer** — Optional ETag/TTL caching via `zen-fs-cache` to reduce remote API calls
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
10
22
|
|
|
11
23
|
```bash
|
|
12
24
|
npm install zen-fs-config @zenfs/core @zenfs/dom zen-fs-sync
|
|
13
25
|
```
|
|
14
26
|
|
|
15
|
-
> `@zenfs/dom`
|
|
27
|
+
> `@zenfs/dom` provides the IndexedDB backend (required in browser environments). `zen-fs-cache` is an optional dependency for remote request caching.
|
|
16
28
|
|
|
17
|
-
##
|
|
29
|
+
## Quick Start
|
|
18
30
|
|
|
19
|
-
### 1.
|
|
31
|
+
### 1. Initialize (zero-configuration)
|
|
20
32
|
|
|
21
33
|
```typescript
|
|
22
34
|
import { createConfigRepo } from 'zen-fs-config';
|
|
23
35
|
|
|
24
|
-
//
|
|
36
|
+
// Creates an IndexedDB primary backend automatically
|
|
25
37
|
const repo = await createConfigRepo('my-app');
|
|
26
38
|
|
|
27
|
-
//
|
|
39
|
+
// Read/write config (synchronous API, served from IndexedDB)
|
|
28
40
|
repo.setConfig('/database', { host: 'localhost', port: 5432 });
|
|
29
41
|
const db = repo.getConfig<{ host: string; port: number }>('/database');
|
|
30
42
|
```
|
|
31
43
|
|
|
32
|
-
### 2.
|
|
33
|
-
|
|
34
|
-
```typescript
|
|
35
|
-
repo.setConfig('/cache', { ttl: 3600, maxSize: '100MB' });
|
|
36
|
-
repo.setConfig('/feature-flags', { newUI: true, beta: false });
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
### 3. 增加数据后端(副本)
|
|
44
|
+
### 2. Add a remote replica backend
|
|
40
45
|
|
|
41
46
|
```typescript
|
|
42
47
|
import { registerBackend } from 'zen-fs-config';
|
|
43
48
|
import { Gitee } from 'zen-fs-gitee';
|
|
44
49
|
|
|
45
|
-
//
|
|
50
|
+
// Register the backend type first
|
|
46
51
|
registerBackend('Gitee', async (options) => {
|
|
47
52
|
return Gitee.create(options);
|
|
48
53
|
});
|
|
49
54
|
|
|
50
|
-
//
|
|
55
|
+
// Dynamically add a replica — auto-syncs bi-directionally with local IndexedDB
|
|
51
56
|
await repo.addBackend('gitee-prod', 'Gitee', {
|
|
52
57
|
token: 'your-token',
|
|
53
58
|
owner: 'your-name',
|
|
54
59
|
repo: 'config-repo',
|
|
55
60
|
branch: 'main',
|
|
56
|
-
}, '
|
|
61
|
+
}, 'Production Gitee config repo');
|
|
57
62
|
```
|
|
58
63
|
|
|
59
|
-
###
|
|
64
|
+
### 3. Automatic sync
|
|
60
65
|
|
|
61
66
|
```typescript
|
|
62
|
-
//
|
|
67
|
+
// Writing to IndexedDB triggers auto-sync to all replicas
|
|
63
68
|
repo.setConfig('/database', { host: 'new-host', port: 5432 });
|
|
64
69
|
|
|
65
|
-
//
|
|
70
|
+
// Manual flush (usually not needed — sync is automatic)
|
|
66
71
|
await repo.flush();
|
|
67
72
|
```
|
|
68
73
|
|
|
69
|
-
###
|
|
74
|
+
### 4. Re-open on next page load
|
|
70
75
|
|
|
71
76
|
```typescript
|
|
72
|
-
//
|
|
73
|
-
// IndexedDB 中的配置和后端拓扑会自动恢复
|
|
77
|
+
// Just pass the appId — IndexedDB restores everything
|
|
74
78
|
const repo = await createConfigRepo('my-app');
|
|
75
79
|
|
|
76
|
-
//
|
|
80
|
+
// Config is readable immediately (offline)
|
|
77
81
|
const db = repo.getConfig<{ host: string; port: number }>('/database');
|
|
78
82
|
|
|
79
|
-
//
|
|
83
|
+
// Registered replicas reconnect and sync automatically
|
|
80
84
|
const backends = await repo.getBackends();
|
|
81
85
|
console.log(backends?.backends.map(b => b.id)); // ['local-idb', 'gitee-prod', ...]
|
|
82
86
|
```
|
|
83
87
|
|
|
84
|
-
###
|
|
88
|
+
### Initialize with a backend from the start
|
|
85
89
|
|
|
86
90
|
```typescript
|
|
87
|
-
// 首次初始化时可以直接传入远程后端
|
|
88
91
|
const repo = await createConfigRepo('my-app', {
|
|
89
|
-
primaryBackendId: 'gitee-prod',
|
|
92
|
+
primaryBackendId: 'gitee-prod',
|
|
90
93
|
backendInfo: {
|
|
91
94
|
type: 'Gitee',
|
|
92
95
|
options: { token: 'xxx', owner: 'xxx', repo: 'xxx', branch: 'main' },
|
|
93
96
|
},
|
|
94
|
-
idbStoreName: 'my-app-config',
|
|
97
|
+
idbStoreName: 'my-app-config', // custom IndexedDB store name
|
|
95
98
|
});
|
|
96
99
|
|
|
97
|
-
//
|
|
100
|
+
// Next time you don't need to pass backend info again
|
|
98
101
|
const repo2 = await createConfigRepo('my-app');
|
|
99
102
|
```
|
|
100
103
|
|
|
101
|
-
##
|
|
104
|
+
## Directory Structure
|
|
102
105
|
|
|
103
106
|
```
|
|
104
107
|
/
|
|
105
|
-
├── {appId}/ #
|
|
106
|
-
├── shared/ #
|
|
107
|
-
├── nodes/{nodeId}/ #
|
|
108
|
+
├── {appId}/ # App-private config (auto-synced to replicas)
|
|
109
|
+
├── shared/ # Cross-app shared config (bi-directional sync)
|
|
110
|
+
├── nodes/{nodeId}/ # Node-local config (never synced)
|
|
108
111
|
└── .meta/
|
|
109
|
-
├── backends/ #
|
|
112
|
+
├── backends/ # Backend topology (one file per backend)
|
|
110
113
|
│ ├── local-idb.json
|
|
111
114
|
│ ├── gitee-prod.json
|
|
112
115
|
│ └── ...
|
|
113
|
-
├── .deleted/ #
|
|
114
|
-
└── .conflicts/ #
|
|
116
|
+
├── .deleted/ # Deletion tombstones (propagate deletes across backends)
|
|
117
|
+
└── .conflicts/ # Conflict archives (both sides preserved)
|
|
115
118
|
```
|
|
116
119
|
|
|
117
|
-
|
|
120
|
+
Each config file has a sidecar version file: `db.json` → `.db.json.version` (version number + SHA-256 hash).
|
|
121
|
+
|
|
122
|
+
## Core API
|
|
118
123
|
|
|
119
|
-
|
|
124
|
+
### ConfigRepo
|
|
120
125
|
|
|
121
|
-
|
|
|
122
|
-
|
|
123
|
-
| `createConfigRepo(appId, options?)` |
|
|
124
|
-
| `getConfig<T>(path)` |
|
|
125
|
-
| `setConfig(path, data)` |
|
|
126
|
-
| `addBackend(id, type, options, desc?)` |
|
|
127
|
-
| `removeBackend(id)` |
|
|
128
|
-
| `getBackends()` |
|
|
129
|
-
| `getNodeConfig<T>(nodeId, path)` |
|
|
130
|
-
| `setNodeConfig(nodeId, path, data)` |
|
|
131
|
-
| `publishNodeConfig(nodeId)` |
|
|
132
|
-
| `peekNodeConfig<T>(nodeId, path)` |
|
|
133
|
-
| `flush()` |
|
|
134
|
-
| `listConflicts()` |
|
|
135
|
-
| `resolveConflict(id, merged)` |
|
|
136
|
-
| `fs.promises.*` |
|
|
137
|
-
| `dispose()` |
|
|
126
|
+
| Method | Description |
|
|
127
|
+
|--------|-------------|
|
|
128
|
+
| `createConfigRepo(appId, options?)` | Create a config repo. IndexedDB is always primary; `backendInfo` becomes a replica. |
|
|
129
|
+
| `getConfig<T>(path)` | Synchronously read app config (from IndexedDB) |
|
|
130
|
+
| `setConfig(path, data)` | Synchronously write app config (async persistence + auto-sync) |
|
|
131
|
+
| `addBackend(id, type, options, desc?)` | Dynamically add a replica backend with auto bi-directional sync |
|
|
132
|
+
| `removeBackend(id)` | Remove a replica backend and stop syncing |
|
|
133
|
+
| `getBackends()` | Read backend topology (aggregated from `.meta/backends/*.json`) |
|
|
134
|
+
| `getNodeConfig<T>(nodeId, path)` | Asynchronously read node-local config |
|
|
135
|
+
| `setNodeConfig(nodeId, path, data)` | Asynchronously write node-local config (not synced) |
|
|
136
|
+
| `publishNodeConfig(nodeId)` | One-time push of node config to all backends |
|
|
137
|
+
| `peekNodeConfig<T>(nodeId, path)` | Read-only view of another node's published config |
|
|
138
|
+
| `flush()` | Manually trigger all pending syncs |
|
|
139
|
+
| `listConflicts()` | List all archived conflicts |
|
|
140
|
+
| `resolveConflict(id, merged)` | Resolve a conflict with merged content |
|
|
141
|
+
| `fs.promises.*` | Standard fs API, chrooted to `/{appId}/` |
|
|
142
|
+
| `dispose()` | Stop syncing and release resources |
|
|
138
143
|
|
|
139
|
-
|
|
144
|
+
### Backend Registration
|
|
140
145
|
|
|
141
|
-
zen-fs-config
|
|
142
|
-
- **IndexedDB** —
|
|
143
|
-
- **InMemory** —
|
|
146
|
+
zen-fs-config includes two built-in backends:
|
|
147
|
+
- **IndexedDB** — local primary backend (based on `@zenfs/dom`), no registration needed
|
|
148
|
+
- **InMemory** — in-memory backend (based on `@zenfs/core`), useful for testing
|
|
144
149
|
|
|
145
|
-
|
|
150
|
+
Register custom backends:
|
|
146
151
|
|
|
147
152
|
```typescript
|
|
148
153
|
import { registerBackend } from 'zen-fs-config';
|
|
149
154
|
|
|
150
|
-
//
|
|
155
|
+
// Register Gitee backend
|
|
151
156
|
registerBackend('Gitee', async (options) => {
|
|
152
157
|
const { Gitee } = await import('zen-fs-gitee');
|
|
153
158
|
return Gitee.create(options);
|
|
154
159
|
});
|
|
155
160
|
|
|
156
|
-
//
|
|
157
|
-
registerBackend('
|
|
158
|
-
const {
|
|
159
|
-
return
|
|
161
|
+
// Register RemoteStorage backend
|
|
162
|
+
registerBackend('RemoteStorage', async (options) => {
|
|
163
|
+
const { createRemoteStorageFileSystem } = await import('zen-fs-remotestoragejs');
|
|
164
|
+
return createRemoteStorageFileSystem(options);
|
|
160
165
|
});
|
|
161
166
|
```
|
|
162
167
|
|
|
163
|
-
##
|
|
168
|
+
## Architecture
|
|
164
169
|
|
|
165
170
|
```
|
|
166
171
|
Application code
|
|
167
172
|
↓ (reads/writes via standard fs API)
|
|
168
|
-
ConfigRepo
|
|
173
|
+
ConfigRepo
|
|
169
174
|
├─ IndexedDB (local primary, always)
|
|
170
175
|
│ └─ All config operations target IndexedDB first
|
|
171
176
|
└─ zen-fs-sync → Bi-directional sync
|
|
172
|
-
├─ Replica
|
|
173
|
-
├─ Replica
|
|
174
|
-
└─ Replica
|
|
177
|
+
├─ Replica 1 (e.g. Gitee)
|
|
178
|
+
├─ Replica 2 (e.g. RemoteStorage)
|
|
179
|
+
└─ Replica 3 (e.g. GitHub)
|
|
175
180
|
```
|
|
176
181
|
|
|
177
|
-
- **IndexedDB
|
|
178
|
-
-
|
|
179
|
-
-
|
|
180
|
-
-
|
|
182
|
+
- **IndexedDB is the only primary backend** — all reads and writes go directly to IndexedDB, guaranteeing offline availability
|
|
183
|
+
- **Remote backends are replicas** — added via `addBackend()` or `createConfigRepo({ backendInfo })`
|
|
184
|
+
- **Auto-sync** — changes to IndexedDB automatically propagate to all replicas
|
|
185
|
+
- **Self-describing topology** — backend configuration lives in `.meta/backends/`, one JSON file per backend
|
|
181
186
|
|
|
182
|
-
##
|
|
187
|
+
## Dependencies
|
|
183
188
|
|
|
184
|
-
|
|
|
185
|
-
|
|
186
|
-
| `@zenfs/core >=2.3.0` | ZenFS
|
|
187
|
-
| `@zenfs/dom >=1.0.0` | IndexedDB
|
|
188
|
-
| `zen-fs-sync >=0.
|
|
189
|
-
| `zen-fs-cache >=1.0.0` | ETag/TTL
|
|
189
|
+
| Package | Description | Required |
|
|
190
|
+
|---------|-------------|----------|
|
|
191
|
+
| `@zenfs/core >=2.3.0` | ZenFS virtual file system | Yes |
|
|
192
|
+
| `@zenfs/dom >=1.0.0` | IndexedDB backend (browser) | Yes (browser) |
|
|
193
|
+
| `zen-fs-sync >=0.4.7` | Cross-backend sync engine | Yes |
|
|
194
|
+
| `zen-fs-cache >=1.0.0` | ETag/TTL caching layer | No (optional) |
|
|
190
195
|
|
|
191
196
|
## License
|
|
192
197
|
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# zen-fs-config
|
|
2
|
+
|
|
3
|
+
基于 ZenFS 的分布式配置管理库。以 IndexedDB 为本地主后端(offline-first),用户提供的远程后端作为副本自动同步。支持应用隔离、共享空间、节点本地配置和冲突安全。
|
|
4
|
+
|
|
5
|
+
**GitHub**: https://github.com/weijia/zen-fs-config
|
|
6
|
+
**NPM**: `zen-fs-config`
|
|
7
|
+
**设计文档**: [DESIGN.md](./DESIGN.md)
|
|
8
|
+
|
|
9
|
+
## 安装
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install zen-fs-config @zenfs/core @zenfs/dom zen-fs-sync
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
> `@zenfs/dom` 提供 IndexedDB 后端(浏览器环境必需)。`zen-fs-cache` 为可选依赖。
|
|
16
|
+
|
|
17
|
+
## 快速开始
|
|
18
|
+
|
|
19
|
+
### 1. 初始化(零参数)
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { createConfigRepo } from 'zen-fs-config';
|
|
23
|
+
|
|
24
|
+
// 不传任何后端参数,自动创建 IndexedDB 本地主后端
|
|
25
|
+
const repo = await createConfigRepo('my-app');
|
|
26
|
+
|
|
27
|
+
// 读写配置(同步 API,从 IndexedDB 读取)
|
|
28
|
+
repo.setConfig('/database', { host: 'localhost', port: 5432 });
|
|
29
|
+
const db = repo.getConfig<{ host: string; port: number }>('/database');
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 2. 设置新的配置
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
repo.setConfig('/cache', { ttl: 3600, maxSize: '100MB' });
|
|
36
|
+
repo.setConfig('/feature-flags', { newUI: true, beta: false });
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 3. 增加数据后端(副本)
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { registerBackend } from 'zen-fs-config';
|
|
43
|
+
import { Gitee } from 'zen-fs-gitee';
|
|
44
|
+
|
|
45
|
+
// 注册后端类型
|
|
46
|
+
registerBackend('Gitee', async (options) => {
|
|
47
|
+
return Gitee.create(options);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// 动态添加副本后端,自动与本地 IndexedDB 双向同步
|
|
51
|
+
await repo.addBackend('gitee-prod', 'Gitee', {
|
|
52
|
+
token: 'your-token',
|
|
53
|
+
owner: 'your-name',
|
|
54
|
+
repo: 'config-repo',
|
|
55
|
+
branch: 'main',
|
|
56
|
+
}, '生产环境 Gitee 配置仓库');
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 4. 自动同步
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
// setConfig 写入 IndexedDB 后,自动同步到所有副本后端
|
|
63
|
+
repo.setConfig('/database', { host: 'new-host', port: 5432 });
|
|
64
|
+
|
|
65
|
+
// 手动触发同步(通常不需要,同步是自动的)
|
|
66
|
+
await repo.flush();
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 5. 再次打开时初始化
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
// 重新打开页面时,只需传入 appId
|
|
73
|
+
// IndexedDB 中的配置和后端拓扑会自动恢复
|
|
74
|
+
const repo = await createConfigRepo('my-app');
|
|
75
|
+
|
|
76
|
+
// 配置直接从 IndexedDB 读取(离线可用)
|
|
77
|
+
const db = repo.getConfig<{ host: string; port: number }>('/database');
|
|
78
|
+
|
|
79
|
+
// 已注册的副本后端会自动重新连接并同步
|
|
80
|
+
const backends = await repo.getBackends();
|
|
81
|
+
console.log(backends?.backends.map(b => b.id)); // ['local-idb', 'gitee-prod', ...]
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 带初始后端初始化
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
// 首次初始化时可以直接传入远程后端
|
|
88
|
+
const repo = await createConfigRepo('my-app', {
|
|
89
|
+
primaryBackendId: 'gitee-prod', // 副本后端 ID
|
|
90
|
+
backendInfo: {
|
|
91
|
+
type: 'Gitee',
|
|
92
|
+
options: { token: 'xxx', owner: 'xxx', repo: 'xxx', branch: 'main' },
|
|
93
|
+
},
|
|
94
|
+
idbStoreName: 'my-app-config', // 自定义 IndexedDB store 名称
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// 之后重新打开时不需要再传后端参数
|
|
98
|
+
const repo2 = await createConfigRepo('my-app');
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## 目录结构
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
/
|
|
105
|
+
├── {appId}/ # 应用私有配置(自动同步到副本)
|
|
106
|
+
├── shared/ # 跨应用共享配置(双向同步)
|
|
107
|
+
├── nodes/{nodeId}/ # 节点本地配置(不同步)
|
|
108
|
+
└── .meta/
|
|
109
|
+
├── backends/ # 后端拓扑(每个后端一个文件)
|
|
110
|
+
│ ├── local-idb.json
|
|
111
|
+
│ ├── gitee-prod.json
|
|
112
|
+
│ └── ...
|
|
113
|
+
├── .deleted/ # 删除墓碑(跨后端删除传播)
|
|
114
|
+
└── .conflicts/ # 冲突归档(双方内容都保存)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
每个配置文件有 sidecar 版本文件:`db.json` → `.db.json.version`(版本号 + SHA-256 哈希)。
|
|
118
|
+
|
|
119
|
+
## 核心 API
|
|
120
|
+
|
|
121
|
+
| 方法 | 说明 |
|
|
122
|
+
|---|---|
|
|
123
|
+
| `createConfigRepo(appId, options?)` | 创建配置仓库。IndexedDB 始终为主后端,`backendInfo` 作为副本 |
|
|
124
|
+
| `getConfig<T>(path)` | 同步读取应用配置(从 IndexedDB) |
|
|
125
|
+
| `setConfig(path, data)` | 同步写入应用配置(异步持久化 + 自动同步) |
|
|
126
|
+
| `addBackend(id, type, options, desc?)` | 动态添加副本后端,自动建立双向同步 |
|
|
127
|
+
| `removeBackend(id)` | 移除副本后端,停止同步 |
|
|
128
|
+
| `getBackends()` | 读取所有后端拓扑(从 `.meta/backends/*.json` 聚合) |
|
|
129
|
+
| `getNodeConfig<T>(nodeId, path)` | 异步读取节点本地配置 |
|
|
130
|
+
| `setNodeConfig(nodeId, path, data)` | 异步写入节点本地配置(不同步) |
|
|
131
|
+
| `publishNodeConfig(nodeId)` | 将节点配置一次性同步到所有后端 |
|
|
132
|
+
| `peekNodeConfig<T>(nodeId, path)` | 只读查看其他节点的已发布配置 |
|
|
133
|
+
| `flush()` | 手动触发所有同步 |
|
|
134
|
+
| `listConflicts()` | 列出所有冲突归档 |
|
|
135
|
+
| `resolveConflict(id, merged)` | 用合并内容解决冲突 |
|
|
136
|
+
| `fs.promises.*` | 标准 fs API,chroot 隔离到 `/{appId}/` |
|
|
137
|
+
| `dispose()` | 停止同步、释放资源 |
|
|
138
|
+
|
|
139
|
+
## 后端注册
|
|
140
|
+
|
|
141
|
+
zen-fs-config 内置两个后端:
|
|
142
|
+
- **IndexedDB** — 本地主后端(基于 `@zenfs/dom`),无需注册
|
|
143
|
+
- **InMemory** — 内存后端(基于 `@zenfs/core`),用于测试
|
|
144
|
+
|
|
145
|
+
注册自定义后端:
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
import { registerBackend } from 'zen-fs-config';
|
|
149
|
+
|
|
150
|
+
// 注册 Gitee 后端
|
|
151
|
+
registerBackend('Gitee', async (options) => {
|
|
152
|
+
const { Gitee } = await import('zen-fs-gitee');
|
|
153
|
+
return Gitee.create(options);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// 注册 S3 后端
|
|
157
|
+
registerBackend('S3Bucket', async (options) => {
|
|
158
|
+
const { S3Bucket } = await import('@zenfs/core');
|
|
159
|
+
return S3Bucket.create(options);
|
|
160
|
+
});
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## 架构概览
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
Application code
|
|
167
|
+
↓ (reads/writes via standard fs API)
|
|
168
|
+
ConfigRepo (this library)
|
|
169
|
+
├─ IndexedDB (local primary, always)
|
|
170
|
+
│ └─ All config operations target IndexedDB first
|
|
171
|
+
└─ zen-fs-sync → Bi-directional sync
|
|
172
|
+
├─ Replica X (e.g., Gitee)
|
|
173
|
+
├─ Replica Y (e.g., S3)
|
|
174
|
+
└─ Replica Z (e.g., RemoteStorage)
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
- **IndexedDB 是唯一的主后端**:所有读写操作直接操作 IndexedDB,保证离线可用
|
|
178
|
+
- **远程后端是副本**:通过 `addBackend()` 或 `createConfigRepo({ backendInfo })` 添加
|
|
179
|
+
- **自动同步**:对 IndexedDB 的修改会自动同步到所有副本后端
|
|
180
|
+
- **自描述拓扑**:后端配置存储在 `.meta/backends/` 目录中,每个后端一个 JSON 文件
|
|
181
|
+
|
|
182
|
+
## 依赖
|
|
183
|
+
|
|
184
|
+
| 包 | 说明 | 必需 |
|
|
185
|
+
|---|---|---|
|
|
186
|
+
| `@zenfs/core >=2.3.0` | ZenFS 虚拟文件系统 | 是 |
|
|
187
|
+
| `@zenfs/dom >=1.0.0` | IndexedDB 后端(浏览器) | 是(浏览器) |
|
|
188
|
+
| `zen-fs-sync >=0.1.0` | 跨后端同步引擎 | 是 |
|
|
189
|
+
| `zen-fs-cache >=1.0.0` | ETag/TTL 缓存层 | 否(可选) |
|
|
190
|
+
|
|
191
|
+
## License
|
|
192
|
+
|
|
193
|
+
MIT
|