web-dc-api 0.1.5 → 0.1.6
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/dist/cjs/index.js +1 -1
- package/dist/dc.min.js +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/index.d.ts +934 -878
- package/package.json +4 -8
- package/dist/cjs/helia-core-B1Xqha7a.js +0 -1
- package/dist/cjs/helia-core-D8Uv1KjQ.js +0 -1
- package/dist/cjs/polkadot-api-7PhQf3ws.js +0 -1
- package/dist/cjs/polkadot-api-CtrJVWuZ.js +0 -1
- package/dist/esm/chunks/helia-core-BxMqyK2Y.js +0 -1
- package/dist/esm/chunks/helia-core-DMXRpcO-.js +0 -1
- package/dist/esm/chunks/polkadot-api-5Y9Bw8VT.js +0 -1
- package/dist/esm/chunks/polkadot-api-D69Ioun_.js +0 -1
- package/lib/common/blowfish/block.ts +0 -259
- package/lib/common/blowfish/cipher.ts +0 -144
- package/lib/common/blowfish/const.ts +0 -195
- package/lib/common/chain.ts +0 -469
- package/lib/common/commonclient.ts +0 -202
- package/lib/common/constants.ts +0 -55
- package/lib/common/dc-key/ed25519.ts +0 -343
- package/lib/common/dc-key/keyManager.ts +0 -424
- package/lib/common/dcapi.ts +0 -98
- package/lib/common/dcutil.ts +0 -627
- package/lib/common/define.ts +0 -70
- package/lib/common/error.ts +0 -67
- package/lib/common/grpc-dc.ts +0 -104
- package/lib/common/module-system.ts +0 -184
- package/lib/common/service-worker.ts +0 -234
- package/lib/common/types/types.ts +0 -344
- package/lib/dc.ts +0 -701
- package/lib/implements/account/client.ts +0 -185
- package/lib/implements/account/manager.ts +0 -683
- package/lib/implements/aiproxy/client.ts +0 -357
- package/lib/implements/aiproxy/manager.ts +0 -670
- package/lib/implements/cache/client.ts +0 -105
- package/lib/implements/cache/manager.ts +0 -127
- package/lib/implements/comment/client.ts +0 -982
- package/lib/implements/comment/manager.ts +0 -1151
- package/lib/implements/dc/client.ts +0 -51
- package/lib/implements/dc/manager.ts +0 -33
- package/lib/implements/file/client.ts +0 -253
- package/lib/implements/file/file-cache-manager.ts +0 -142
- package/lib/implements/file/manager.ts +0 -1240
- package/lib/implements/file/seekableFileStream.ts +0 -344
- package/lib/implements/file/streamwriter.ts +0 -322
- package/lib/implements/keyvalue/client.ts +0 -376
- package/lib/implements/keyvalue/manager.ts +0 -759
- package/lib/implements/message/client.ts +0 -250
- package/lib/implements/message/manager.ts +0 -215
- package/lib/implements/threaddb/cbor/coding.ts +0 -62
- package/lib/implements/threaddb/cbor/event.ts +0 -336
- package/lib/implements/threaddb/cbor/node.ts +0 -542
- package/lib/implements/threaddb/cbor/record.ts +0 -398
- package/lib/implements/threaddb/common/AsyncMutex.ts +0 -24
- package/lib/implements/threaddb/common/addrinfo.ts +0 -135
- package/lib/implements/threaddb/common/dispatcher.ts +0 -81
- package/lib/implements/threaddb/common/idbstore-adapter.ts +0 -260
- package/lib/implements/threaddb/common/json-patcher.ts +0 -204
- package/lib/implements/threaddb/common/key.ts +0 -290
- package/lib/implements/threaddb/common/level-adapter.ts +0 -235
- package/lib/implements/threaddb/common/lineReader.ts +0 -79
- package/lib/implements/threaddb/common/logstore.ts +0 -215
- package/lib/implements/threaddb/common/transformed-datastore.ts +0 -308
- package/lib/implements/threaddb/core/app.ts +0 -206
- package/lib/implements/threaddb/core/core.ts +0 -230
- package/lib/implements/threaddb/core/db.ts +0 -249
- package/lib/implements/threaddb/core/event.ts +0 -54
- package/lib/implements/threaddb/core/head.ts +0 -89
- package/lib/implements/threaddb/core/identity.ts +0 -171
- package/lib/implements/threaddb/core/logstore.ts +0 -137
- package/lib/implements/threaddb/core/options.ts +0 -14
- package/lib/implements/threaddb/core/record.ts +0 -54
- package/lib/implements/threaddb/db/collection.ts +0 -1910
- package/lib/implements/threaddb/db/db.ts +0 -698
- package/lib/implements/threaddb/db/json2Query.ts +0 -192
- package/lib/implements/threaddb/db/query.ts +0 -524
- package/lib/implements/threaddb/dbclient.ts +0 -543
- package/lib/implements/threaddb/dbmanager.ts +0 -1906
- package/lib/implements/threaddb/lsstoreds/addr_book.ts +0 -549
- package/lib/implements/threaddb/lsstoreds/cache.ts +0 -36
- package/lib/implements/threaddb/lsstoreds/cyclic_batch.ts +0 -87
- package/lib/implements/threaddb/lsstoreds/global.ts +0 -151
- package/lib/implements/threaddb/lsstoreds/headbook.ts +0 -373
- package/lib/implements/threaddb/lsstoreds/keybook.ts +0 -297
- package/lib/implements/threaddb/lsstoreds/logstore.ts +0 -29
- package/lib/implements/threaddb/lsstoreds/metadata.ts +0 -223
- package/lib/implements/threaddb/net/define.ts +0 -149
- package/lib/implements/threaddb/net/grpcClient.ts +0 -589
- package/lib/implements/threaddb/net/grpcserver.ts +0 -146
- package/lib/implements/threaddb/net/net.ts +0 -2047
- package/lib/implements/threaddb/pb/lstore.proto +0 -38
- package/lib/implements/threaddb/pb/lstore.ts +0 -393
- package/lib/implements/threaddb/pb/lstore_pb.d.ts +0 -433
- package/lib/implements/threaddb/pb/lstore_pb.js +0 -1085
- package/lib/implements/threaddb/pb/net.proto +0 -194
- package/lib/implements/threaddb/pb/net_pb.d.ts +0 -2349
- package/lib/implements/threaddb/pb/net_pb.js +0 -5525
- package/lib/implements/threaddb/pb/proto-custom-types.ts +0 -212
- package/lib/implements/util/client.ts +0 -72
- package/lib/implements/util/manager.ts +0 -146
- package/lib/implements/wallet/manager.ts +0 -671
- package/lib/index.ts +0 -57
- package/lib/interfaces/DCContext.ts +0 -51
- package/lib/interfaces/aiproxy-interface.ts +0 -145
- package/lib/interfaces/auth-interface.ts +0 -118
- package/lib/interfaces/cache-interface.ts +0 -22
- package/lib/interfaces/client-interface.ts +0 -11
- package/lib/interfaces/comment-interface.ts +0 -167
- package/lib/interfaces/components/news-component.ts +0 -0
- package/lib/interfaces/database-interface.ts +0 -169
- package/lib/interfaces/file-interface.ts +0 -120
- package/lib/interfaces/index.ts +0 -10
- package/lib/interfaces/keyvalue-interface.ts +0 -156
- package/lib/interfaces/message-interface.ts +0 -22
- package/lib/interfaces/util-interface.ts +0 -31
- package/lib/modules/aiproxy-module.ts +0 -246
- package/lib/modules/auth-module.ts +0 -753
- package/lib/modules/cache-module.ts +0 -99
- package/lib/modules/client-module.ts +0 -71
- package/lib/modules/comment-module.ts +0 -429
- package/lib/modules/components/news-components.ts +0 -390
- package/lib/modules/database-module.ts +0 -598
- package/lib/modules/file-module.ts +0 -291
- package/lib/modules/index.ts +0 -13
- package/lib/modules/keyvalue-module.ts +0 -379
- package/lib/modules/message-module.ts +0 -107
- package/lib/modules/util-module.ts +0 -148
- package/lib/polyfills/process-env-browser.ts +0 -1
- package/lib/proto/datasource.ts +0 -93
- package/lib/proto/dcnet.proto +0 -1601
- package/lib/proto/dcnet_proto.d.ts +0 -22857
- package/lib/proto/dcnet_proto.js +0 -55204
- package/lib/proto/dcnet_proto_sparse.js +0 -55166
- package/lib/proto/oidfetch.proto +0 -25
- package/lib/proto/oidfetch_proto.d.ts +0 -585
- package/lib/proto/oidfetch_proto.js +0 -1247
- package/lib/serverless/babel-browser.ts +0 -39
- package/lib/serverless/base_entity.ts +0 -78
- package/lib/serverless/base_repository.ts +0 -414
- package/lib/serverless/browser_schema_extractor.ts +0 -283
- package/lib/serverless/decorator_factory.ts +0 -322
- package/lib/util/BrowserLineReader.ts +0 -73
- package/lib/util/base64.ts +0 -105
- package/lib/util/bcrypt.ts +0 -206
- package/lib/util/curve25519Encryption.ts +0 -418
- package/lib/util/dccrypt.ts +0 -73
- package/lib/util/logger.ts +0 -104
- package/lib/util/utils.ts +0 -289
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
import { Key, Query, Batch, Pair, KeyQuery } from 'interface-datastore'
|
|
2
|
-
import { IDBDatastore } from "datastore-idb";
|
|
3
|
-
import { QueryExt, QueryResult, Transaction,TxnDatastoreExtended } from '../core/db'
|
|
4
|
-
import { AbortOptions } from '@libp2p/interface';
|
|
5
|
-
type AwaitIterable<T> = AsyncIterable<T> | Iterable<T>;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class IDBDatastoreAdapter implements TxnDatastoreExtended {
|
|
9
|
-
private store: IDBDatastore;
|
|
10
|
-
private txn: any;
|
|
11
|
-
|
|
12
|
-
constructor(store: IDBDatastore) {
|
|
13
|
-
this.store = store;
|
|
14
|
-
this.txn = null;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// 修改 queryKeys 的实现
|
|
18
|
-
async *queryKeys(
|
|
19
|
-
query: KeyQuery,
|
|
20
|
-
options?: AbortOptions
|
|
21
|
-
): AsyncIterable<Key> {
|
|
22
|
-
const { filters = [], prefix } = query;
|
|
23
|
-
const q = { prefix } as Query;
|
|
24
|
-
for await (const { key } of this.store.query(q)) {
|
|
25
|
-
let match = true;
|
|
26
|
-
|
|
27
|
-
// 应用所有过滤器
|
|
28
|
-
for (const filter of filters) {
|
|
29
|
-
if (!filter(key)) {
|
|
30
|
-
match = false;
|
|
31
|
-
break;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (match) {
|
|
36
|
-
yield key;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async *query(
|
|
42
|
-
query: Query,
|
|
43
|
-
options?: AbortOptions
|
|
44
|
-
): AsyncIterable<Pair> {
|
|
45
|
-
try {
|
|
46
|
-
|
|
47
|
-
// 获取迭代器
|
|
48
|
-
const storeQuery = this.store.query(query);
|
|
49
|
-
|
|
50
|
-
// 检查异步迭代器协议
|
|
51
|
-
if (!storeQuery || typeof storeQuery[Symbol.asyncIterator] !== 'function') {
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
let count = 0;
|
|
56
|
-
// 手动迭代,而不是使用 yield*
|
|
57
|
-
for await (const entry of storeQuery) {
|
|
58
|
-
count++;
|
|
59
|
-
|
|
60
|
-
// 验证返回值格式
|
|
61
|
-
if (!entry || !entry.key) {
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
yield entry;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
} catch (err) {
|
|
70
|
-
throw err; // 重新抛出以便上层处理
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// 扩展查询方法
|
|
75
|
-
|
|
76
|
-
// 修改 queryExtended 的实现
|
|
77
|
-
async *queryExtended(
|
|
78
|
-
q: QueryExt
|
|
79
|
-
): AsyncIterable<QueryResult> {
|
|
80
|
-
const { prefix, filters = [] } = q;
|
|
81
|
-
|
|
82
|
-
const queryOptions: Query = {};
|
|
83
|
-
if (prefix !== undefined) {
|
|
84
|
-
queryOptions.prefix = prefix;
|
|
85
|
-
}
|
|
86
|
-
for await (const entry of this.store.query(queryOptions)) {
|
|
87
|
-
let match = true;
|
|
88
|
-
|
|
89
|
-
// 应用所有过滤器
|
|
90
|
-
for (const filter of filters) {
|
|
91
|
-
if (!filter(entry)) {
|
|
92
|
-
match = false;
|
|
93
|
-
break;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (match) {
|
|
98
|
-
yield {
|
|
99
|
-
key: entry.key.toString(),
|
|
100
|
-
value: entry.value,
|
|
101
|
-
size: entry.value.length
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// 其他批量操作方法
|
|
108
|
-
async *putMany(
|
|
109
|
-
source: AwaitIterable<Pair>,
|
|
110
|
-
options?: AbortOptions
|
|
111
|
-
): AsyncIterable<Key> {
|
|
112
|
-
const batch = this.batch();
|
|
113
|
-
|
|
114
|
-
for await (const entry of source) {
|
|
115
|
-
const key = entry.key;
|
|
116
|
-
batch.put(key, entry.value);
|
|
117
|
-
yield key;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
await batch.commit();
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
async *getMany(
|
|
124
|
-
source: AwaitIterable<Key>,
|
|
125
|
-
options?: AbortOptions
|
|
126
|
-
): AsyncIterable<Pair> {
|
|
127
|
-
for await (const key of source) {
|
|
128
|
-
try {
|
|
129
|
-
const value = await this.get(key);
|
|
130
|
-
yield {
|
|
131
|
-
key: key,
|
|
132
|
-
value
|
|
133
|
-
};
|
|
134
|
-
} catch (err) {
|
|
135
|
-
console.error(`Error getting key ${key}:`, err);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
async *deleteMany(
|
|
141
|
-
source: AwaitIterable<Key>,
|
|
142
|
-
options?: AbortOptions
|
|
143
|
-
): AsyncIterable<Key> {
|
|
144
|
-
const batch = this.batch();
|
|
145
|
-
|
|
146
|
-
for await (const key of source) {
|
|
147
|
-
batch.delete(key);
|
|
148
|
-
yield key;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
await batch.commit();
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// 基本操作方法
|
|
155
|
-
async put(key: Key, value: Uint8Array): Promise<Key> {
|
|
156
|
-
return this.store.put(key, value);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
async get(key: Key): Promise<Uint8Array> {
|
|
160
|
-
return this.store.get(key);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
async has(key: Key): Promise<boolean> {
|
|
164
|
-
return this.store.has(key);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
async delete(key: Key): Promise<void> {
|
|
168
|
-
return this.store.delete(key);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
batch(): Batch {
|
|
172
|
-
return this.store.batch();
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
// 实现 TxnDatastoreExtended 接口的方法
|
|
177
|
-
async newTransactionExtended(
|
|
178
|
-
|
|
179
|
-
readOnly: boolean
|
|
180
|
-
): Promise<Transaction> {
|
|
181
|
-
// 保存当前实例的引用
|
|
182
|
-
const store = this.store;
|
|
183
|
-
// 由于 LevelDatastore 不支持原生事务,我们创建一个简单的包装器
|
|
184
|
-
const txn: Transaction = {
|
|
185
|
-
put: async ( key: Key, value: Uint8Array): Promise<Key> => {
|
|
186
|
-
if (readOnly) throw new Error('Transaction is read-only');
|
|
187
|
-
await this.store.put(key, value);
|
|
188
|
-
return key;
|
|
189
|
-
},
|
|
190
|
-
|
|
191
|
-
get: async ( key: Key): Promise<Uint8Array> => {
|
|
192
|
-
return this.store.get(key);
|
|
193
|
-
},
|
|
194
|
-
|
|
195
|
-
has: async ( key: Key): Promise<boolean> => {
|
|
196
|
-
return this.store.has(key);
|
|
197
|
-
},
|
|
198
|
-
|
|
199
|
-
delete: async ( key: Key): Promise<void> => {
|
|
200
|
-
if (readOnly) throw new Error('Transaction is read-only');
|
|
201
|
-
await this.store.delete(key);
|
|
202
|
-
return ;
|
|
203
|
-
},
|
|
204
|
-
|
|
205
|
-
query: async function*( q: Query): AsyncIterable<QueryResult> {
|
|
206
|
-
for await (const entry of store.query(q)) {
|
|
207
|
-
yield {
|
|
208
|
-
key: entry.key.toString(),
|
|
209
|
-
value: entry.value,
|
|
210
|
-
size: entry.value.length
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
}.bind(this),
|
|
214
|
-
|
|
215
|
-
queryExtended: async function*( q: QueryExt): AsyncIterable<QueryResult> {
|
|
216
|
-
const { prefix, filters = [] } = q;
|
|
217
|
-
const queryOptions: Query = {};
|
|
218
|
-
if (prefix !== undefined) {
|
|
219
|
-
queryOptions.prefix = prefix;
|
|
220
|
-
}
|
|
221
|
-
for await (const entry of store.query(queryOptions)) {
|
|
222
|
-
let match = true;
|
|
223
|
-
for (const filter of filters) {
|
|
224
|
-
if (!filter(entry)) {
|
|
225
|
-
match = false;
|
|
226
|
-
break;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
if (match) {
|
|
230
|
-
yield {
|
|
231
|
-
key: entry.key.toString(),
|
|
232
|
-
value: entry.value,
|
|
233
|
-
size: entry.value.length
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}.bind(this),
|
|
238
|
-
|
|
239
|
-
commit: async (): Promise<void> => {
|
|
240
|
-
// 由于没有实际的事务支持,这里是一个空操作
|
|
241
|
-
return Promise.resolve();
|
|
242
|
-
} ,
|
|
243
|
-
discard: async (): Promise<void> => {
|
|
244
|
-
// 由于没有实际的事务支持,这里是一个空操作
|
|
245
|
-
return Promise.resolve();
|
|
246
|
-
}
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
return txn;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// 工厂函数
|
|
254
|
-
export async function createTxnDatastore(location: string): Promise<TxnDatastoreExtended> {
|
|
255
|
-
const levelStore = new IDBDatastore(location);
|
|
256
|
-
await levelStore.open();
|
|
257
|
-
const adapter = new IDBDatastoreAdapter(levelStore);
|
|
258
|
-
return adapter;
|
|
259
|
-
|
|
260
|
-
}
|
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
// json-patcher.ts - 完整实现
|
|
2
|
-
import { name,code, encode, decode } from '@ipld/dag-cbor';
|
|
3
|
-
import { sha256 } from 'multiformats/hashes/sha2';
|
|
4
|
-
import * as Block from 'multiformats/block';
|
|
5
|
-
import { Key } from 'interface-datastore';
|
|
6
|
-
import * as dagCBOR from '@ipld/dag-cbor';
|
|
7
|
-
import * as cbornode from '../cbor/node';
|
|
8
|
-
import {
|
|
9
|
-
IndexFunc,
|
|
10
|
-
Transaction,
|
|
11
|
-
TxnDatastoreExtended
|
|
12
|
-
} from '../core/db';
|
|
13
|
-
import {
|
|
14
|
-
EventCodec,
|
|
15
|
-
Action,
|
|
16
|
-
Event,
|
|
17
|
-
ReduceAction,
|
|
18
|
-
InstanceID,
|
|
19
|
-
CoreActionType
|
|
20
|
-
} from '../core/db';
|
|
21
|
-
import { IPLDNode } from '../core/core';
|
|
22
|
-
|
|
23
|
-
// ==================== 核心数据结构 ====================
|
|
24
|
-
interface Operation { //当前命名方式,大小写与golang一致
|
|
25
|
-
type: CoreActionType;
|
|
26
|
-
instanceID: InstanceID;
|
|
27
|
-
jSONPatch: Uint8Array ;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
interface PatchEvent { //当前命名方式大小写与golang一致
|
|
31
|
-
timestamp: BigInt;
|
|
32
|
-
iD: InstanceID;
|
|
33
|
-
collectionName?: string;
|
|
34
|
-
patch: Operation;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
interface RecordEvents {
|
|
38
|
-
patches: PatchEvent[];
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// ==================== JSON PATCHER 实现 ====================
|
|
42
|
-
// 定义codec对象,确保包含name字段
|
|
43
|
-
const DAG_CBOR_CODEC = {
|
|
44
|
-
name,
|
|
45
|
-
code,
|
|
46
|
-
encode,
|
|
47
|
-
decode
|
|
48
|
-
};
|
|
49
|
-
export class JsonPatcher implements EventCodec {
|
|
50
|
-
private static readonly ENCODER_SETTINGS = {
|
|
51
|
-
codec: DAG_CBOR_CODEC,
|
|
52
|
-
hasher: sha256,
|
|
53
|
-
cidVersion: 1 as const
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
async create(actions: Action[]): Promise<[Event[], IPLDNode ]> {
|
|
57
|
-
const events = this.convertActions(actions);
|
|
58
|
-
const recordEvents = { patches: events };
|
|
59
|
-
const obj = await cbornode.wrapObject(recordEvents);
|
|
60
|
-
// const block = await Block.encode({
|
|
61
|
-
// value: objValue,
|
|
62
|
-
// ...JsonPatcher.ENCODER_SETTINGS
|
|
63
|
-
// });
|
|
64
|
-
return [this.wrapEvents(events), obj];
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
async reduce(
|
|
68
|
-
events: Event[],
|
|
69
|
-
store: TxnDatastoreExtended,
|
|
70
|
-
baseKey: Key,
|
|
71
|
-
indexFunc: IndexFunc
|
|
72
|
-
): Promise<ReduceAction[]> {
|
|
73
|
-
const txn = await store.newTransactionExtended(false);
|
|
74
|
-
try {
|
|
75
|
-
const actions: ReduceAction[] = [];
|
|
76
|
-
for (const rawEvent of this.sortEvents(events)) {
|
|
77
|
-
const event = await this.parseEvent(rawEvent);
|
|
78
|
-
await this.processEvent(event, baseKey, txn, indexFunc);
|
|
79
|
-
actions.push({
|
|
80
|
-
type: event.patch.type,
|
|
81
|
-
collection: event.collectionName|| 'default',
|
|
82
|
-
instanceID: event.iD
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
await txn.commit();
|
|
86
|
-
return actions;
|
|
87
|
-
} catch (err) {
|
|
88
|
-
txn.discard();
|
|
89
|
-
throw this.wrapError(err as Error);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
async eventsFromBytes(data: Uint8Array): Promise<Event[]> {
|
|
94
|
-
let block = await dagCBOR.decode(data);
|
|
95
|
-
if (block && typeof block === 'object' &&'patches' in block && Array.isArray(block.patches)) {
|
|
96
|
-
return this.wrapEvents(block.patches);
|
|
97
|
-
}
|
|
98
|
-
throw new Error('Invalid block format: expected RecordEvents with patches array');
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// ==================== 私有方法 ====================
|
|
102
|
-
private convertActions(actions: Action[]): PatchEvent[] {
|
|
103
|
-
const timestamp = BigInt(Date.now() * 1000000 + Math.floor(Math.random() * 1000000));
|
|
104
|
-
return actions.map(action => ({
|
|
105
|
-
timestamp: timestamp,
|
|
106
|
-
iD: action.instanceID,
|
|
107
|
-
collectionName: action.collectionName || 'default',
|
|
108
|
-
patch: action.current ?{
|
|
109
|
-
type: action.type,
|
|
110
|
-
instanceID: action.instanceID,
|
|
111
|
-
jSONPatch: action.current
|
|
112
|
-
} : {
|
|
113
|
-
type: action.type,
|
|
114
|
-
instanceID: action.instanceID,
|
|
115
|
-
jSONPatch: new Uint8Array()
|
|
116
|
-
}
|
|
117
|
-
}));
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
private wrapEvents(patches: PatchEvent[]): Event[] {
|
|
121
|
-
if (!patches || patches.length === 0) {
|
|
122
|
-
return [];
|
|
123
|
-
}
|
|
124
|
-
return patches.map(p => ({
|
|
125
|
-
collection: p.collectionName || 'default',
|
|
126
|
-
instanceID: p.iD || p.patch.instanceID,
|
|
127
|
-
timestamp: p.timestamp,
|
|
128
|
-
payload: p.patch.jSONPatch ? p.patch.jSONPatch : new Uint8Array(),
|
|
129
|
-
marshal: async () => this.marshalPatchEvent(p)
|
|
130
|
-
}));
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
private async marshalPatchEvent(event: PatchEvent): Promise<Uint8Array> {
|
|
134
|
-
|
|
135
|
-
return encode({
|
|
136
|
-
t: event.timestamp,
|
|
137
|
-
i: event.iD || event.iD,
|
|
138
|
-
c: event.collectionName,
|
|
139
|
-
op: {
|
|
140
|
-
type: event.patch.type,
|
|
141
|
-
id: event.patch.instanceID,
|
|
142
|
-
patch: event.patch.jSONPatch ? event.patch.jSONPatch : new Uint8Array()
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
private sortEvents(events: Event[]): Event[] {
|
|
148
|
-
return [...events].sort((a, b) => {
|
|
149
|
-
if (a.timestamp < b.timestamp) return -1;
|
|
150
|
-
if (a.timestamp > b.timestamp) return 1;
|
|
151
|
-
return 0;
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
private async parseEvent(event: Event): Promise<PatchEvent> {
|
|
156
|
-
const data = decode(await event.marshal()) as any;
|
|
157
|
-
return {
|
|
158
|
-
timestamp: data.t,
|
|
159
|
-
iD: data.i,
|
|
160
|
-
collectionName: data.c,
|
|
161
|
-
patch: {
|
|
162
|
-
type: data.op.type,
|
|
163
|
-
instanceID: data.op.id,
|
|
164
|
-
jSONPatch: data.op.patch ? encode(data.op.patch) : new Uint8Array()
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
private async processEvent(
|
|
170
|
-
event: PatchEvent,
|
|
171
|
-
baseKey: Key,
|
|
172
|
-
txn: Transaction,
|
|
173
|
-
indexFunc: IndexFunc
|
|
174
|
-
): Promise<void> {
|
|
175
|
-
const recordKey = baseKey.child(new Key(event.collectionName || 'default')).child(new Key(event.iD));
|
|
176
|
-
|
|
177
|
-
const oldData = await txn.get(recordKey).catch(() => undefined);
|
|
178
|
-
const newData = event.patch.type === CoreActionType.Delete
|
|
179
|
-
? undefined
|
|
180
|
-
: event.patch.jSONPatch;
|
|
181
|
-
|
|
182
|
-
await indexFunc(
|
|
183
|
-
event.collectionName|| 'default',
|
|
184
|
-
recordKey,
|
|
185
|
-
txn ,
|
|
186
|
-
oldData,
|
|
187
|
-
newData
|
|
188
|
-
);
|
|
189
|
-
|
|
190
|
-
if (event.patch.type === CoreActionType.Delete) {
|
|
191
|
-
await txn.delete(recordKey);
|
|
192
|
-
} else if (newData) {
|
|
193
|
-
const decoded = dagCBOR.decode<Uint8Array>(newData);
|
|
194
|
-
if (!decoded) {
|
|
195
|
-
throw new Error('Failed to decode JSON patch');
|
|
196
|
-
}
|
|
197
|
-
await txn.put(recordKey, decoded);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
private wrapError(err: Error): Error {
|
|
202
|
-
return new Error(`JSONPATCHER_ERROR: ${err.message}`);
|
|
203
|
-
}
|
|
204
|
-
}
|