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.
Files changed (148) hide show
  1. package/dist/cjs/index.js +1 -1
  2. package/dist/dc.min.js +1 -1
  3. package/dist/esm/index.js +1 -1
  4. package/dist/index.d.ts +934 -878
  5. package/package.json +4 -8
  6. package/dist/cjs/helia-core-B1Xqha7a.js +0 -1
  7. package/dist/cjs/helia-core-D8Uv1KjQ.js +0 -1
  8. package/dist/cjs/polkadot-api-7PhQf3ws.js +0 -1
  9. package/dist/cjs/polkadot-api-CtrJVWuZ.js +0 -1
  10. package/dist/esm/chunks/helia-core-BxMqyK2Y.js +0 -1
  11. package/dist/esm/chunks/helia-core-DMXRpcO-.js +0 -1
  12. package/dist/esm/chunks/polkadot-api-5Y9Bw8VT.js +0 -1
  13. package/dist/esm/chunks/polkadot-api-D69Ioun_.js +0 -1
  14. package/lib/common/blowfish/block.ts +0 -259
  15. package/lib/common/blowfish/cipher.ts +0 -144
  16. package/lib/common/blowfish/const.ts +0 -195
  17. package/lib/common/chain.ts +0 -469
  18. package/lib/common/commonclient.ts +0 -202
  19. package/lib/common/constants.ts +0 -55
  20. package/lib/common/dc-key/ed25519.ts +0 -343
  21. package/lib/common/dc-key/keyManager.ts +0 -424
  22. package/lib/common/dcapi.ts +0 -98
  23. package/lib/common/dcutil.ts +0 -627
  24. package/lib/common/define.ts +0 -70
  25. package/lib/common/error.ts +0 -67
  26. package/lib/common/grpc-dc.ts +0 -104
  27. package/lib/common/module-system.ts +0 -184
  28. package/lib/common/service-worker.ts +0 -234
  29. package/lib/common/types/types.ts +0 -344
  30. package/lib/dc.ts +0 -701
  31. package/lib/implements/account/client.ts +0 -185
  32. package/lib/implements/account/manager.ts +0 -683
  33. package/lib/implements/aiproxy/client.ts +0 -357
  34. package/lib/implements/aiproxy/manager.ts +0 -670
  35. package/lib/implements/cache/client.ts +0 -105
  36. package/lib/implements/cache/manager.ts +0 -127
  37. package/lib/implements/comment/client.ts +0 -982
  38. package/lib/implements/comment/manager.ts +0 -1151
  39. package/lib/implements/dc/client.ts +0 -51
  40. package/lib/implements/dc/manager.ts +0 -33
  41. package/lib/implements/file/client.ts +0 -253
  42. package/lib/implements/file/file-cache-manager.ts +0 -142
  43. package/lib/implements/file/manager.ts +0 -1240
  44. package/lib/implements/file/seekableFileStream.ts +0 -344
  45. package/lib/implements/file/streamwriter.ts +0 -322
  46. package/lib/implements/keyvalue/client.ts +0 -376
  47. package/lib/implements/keyvalue/manager.ts +0 -759
  48. package/lib/implements/message/client.ts +0 -250
  49. package/lib/implements/message/manager.ts +0 -215
  50. package/lib/implements/threaddb/cbor/coding.ts +0 -62
  51. package/lib/implements/threaddb/cbor/event.ts +0 -336
  52. package/lib/implements/threaddb/cbor/node.ts +0 -542
  53. package/lib/implements/threaddb/cbor/record.ts +0 -398
  54. package/lib/implements/threaddb/common/AsyncMutex.ts +0 -24
  55. package/lib/implements/threaddb/common/addrinfo.ts +0 -135
  56. package/lib/implements/threaddb/common/dispatcher.ts +0 -81
  57. package/lib/implements/threaddb/common/idbstore-adapter.ts +0 -260
  58. package/lib/implements/threaddb/common/json-patcher.ts +0 -204
  59. package/lib/implements/threaddb/common/key.ts +0 -290
  60. package/lib/implements/threaddb/common/level-adapter.ts +0 -235
  61. package/lib/implements/threaddb/common/lineReader.ts +0 -79
  62. package/lib/implements/threaddb/common/logstore.ts +0 -215
  63. package/lib/implements/threaddb/common/transformed-datastore.ts +0 -308
  64. package/lib/implements/threaddb/core/app.ts +0 -206
  65. package/lib/implements/threaddb/core/core.ts +0 -230
  66. package/lib/implements/threaddb/core/db.ts +0 -249
  67. package/lib/implements/threaddb/core/event.ts +0 -54
  68. package/lib/implements/threaddb/core/head.ts +0 -89
  69. package/lib/implements/threaddb/core/identity.ts +0 -171
  70. package/lib/implements/threaddb/core/logstore.ts +0 -137
  71. package/lib/implements/threaddb/core/options.ts +0 -14
  72. package/lib/implements/threaddb/core/record.ts +0 -54
  73. package/lib/implements/threaddb/db/collection.ts +0 -1910
  74. package/lib/implements/threaddb/db/db.ts +0 -698
  75. package/lib/implements/threaddb/db/json2Query.ts +0 -192
  76. package/lib/implements/threaddb/db/query.ts +0 -524
  77. package/lib/implements/threaddb/dbclient.ts +0 -543
  78. package/lib/implements/threaddb/dbmanager.ts +0 -1906
  79. package/lib/implements/threaddb/lsstoreds/addr_book.ts +0 -549
  80. package/lib/implements/threaddb/lsstoreds/cache.ts +0 -36
  81. package/lib/implements/threaddb/lsstoreds/cyclic_batch.ts +0 -87
  82. package/lib/implements/threaddb/lsstoreds/global.ts +0 -151
  83. package/lib/implements/threaddb/lsstoreds/headbook.ts +0 -373
  84. package/lib/implements/threaddb/lsstoreds/keybook.ts +0 -297
  85. package/lib/implements/threaddb/lsstoreds/logstore.ts +0 -29
  86. package/lib/implements/threaddb/lsstoreds/metadata.ts +0 -223
  87. package/lib/implements/threaddb/net/define.ts +0 -149
  88. package/lib/implements/threaddb/net/grpcClient.ts +0 -589
  89. package/lib/implements/threaddb/net/grpcserver.ts +0 -146
  90. package/lib/implements/threaddb/net/net.ts +0 -2047
  91. package/lib/implements/threaddb/pb/lstore.proto +0 -38
  92. package/lib/implements/threaddb/pb/lstore.ts +0 -393
  93. package/lib/implements/threaddb/pb/lstore_pb.d.ts +0 -433
  94. package/lib/implements/threaddb/pb/lstore_pb.js +0 -1085
  95. package/lib/implements/threaddb/pb/net.proto +0 -194
  96. package/lib/implements/threaddb/pb/net_pb.d.ts +0 -2349
  97. package/lib/implements/threaddb/pb/net_pb.js +0 -5525
  98. package/lib/implements/threaddb/pb/proto-custom-types.ts +0 -212
  99. package/lib/implements/util/client.ts +0 -72
  100. package/lib/implements/util/manager.ts +0 -146
  101. package/lib/implements/wallet/manager.ts +0 -671
  102. package/lib/index.ts +0 -57
  103. package/lib/interfaces/DCContext.ts +0 -51
  104. package/lib/interfaces/aiproxy-interface.ts +0 -145
  105. package/lib/interfaces/auth-interface.ts +0 -118
  106. package/lib/interfaces/cache-interface.ts +0 -22
  107. package/lib/interfaces/client-interface.ts +0 -11
  108. package/lib/interfaces/comment-interface.ts +0 -167
  109. package/lib/interfaces/components/news-component.ts +0 -0
  110. package/lib/interfaces/database-interface.ts +0 -169
  111. package/lib/interfaces/file-interface.ts +0 -120
  112. package/lib/interfaces/index.ts +0 -10
  113. package/lib/interfaces/keyvalue-interface.ts +0 -156
  114. package/lib/interfaces/message-interface.ts +0 -22
  115. package/lib/interfaces/util-interface.ts +0 -31
  116. package/lib/modules/aiproxy-module.ts +0 -246
  117. package/lib/modules/auth-module.ts +0 -753
  118. package/lib/modules/cache-module.ts +0 -99
  119. package/lib/modules/client-module.ts +0 -71
  120. package/lib/modules/comment-module.ts +0 -429
  121. package/lib/modules/components/news-components.ts +0 -390
  122. package/lib/modules/database-module.ts +0 -598
  123. package/lib/modules/file-module.ts +0 -291
  124. package/lib/modules/index.ts +0 -13
  125. package/lib/modules/keyvalue-module.ts +0 -379
  126. package/lib/modules/message-module.ts +0 -107
  127. package/lib/modules/util-module.ts +0 -148
  128. package/lib/polyfills/process-env-browser.ts +0 -1
  129. package/lib/proto/datasource.ts +0 -93
  130. package/lib/proto/dcnet.proto +0 -1601
  131. package/lib/proto/dcnet_proto.d.ts +0 -22857
  132. package/lib/proto/dcnet_proto.js +0 -55204
  133. package/lib/proto/dcnet_proto_sparse.js +0 -55166
  134. package/lib/proto/oidfetch.proto +0 -25
  135. package/lib/proto/oidfetch_proto.d.ts +0 -585
  136. package/lib/proto/oidfetch_proto.js +0 -1247
  137. package/lib/serverless/babel-browser.ts +0 -39
  138. package/lib/serverless/base_entity.ts +0 -78
  139. package/lib/serverless/base_repository.ts +0 -414
  140. package/lib/serverless/browser_schema_extractor.ts +0 -283
  141. package/lib/serverless/decorator_factory.ts +0 -322
  142. package/lib/util/BrowserLineReader.ts +0 -73
  143. package/lib/util/base64.ts +0 -105
  144. package/lib/util/bcrypt.ts +0 -206
  145. package/lib/util/curve25519Encryption.ts +0 -418
  146. package/lib/util/dccrypt.ts +0 -73
  147. package/lib/util/logger.ts +0 -104
  148. package/lib/util/utils.ts +0 -289
@@ -1,698 +0,0 @@
1
- // db.ts - Complete TypeScript Implementation (Simplified Core)
2
- import { EventEmitter } from "events";
3
- import {} from "../common/transformed-datastore";
4
- import { Key, Query } from "interface-datastore";
5
- import { Key as ThreadKey } from "../common/key";
6
- import { Connector } from "../core/app";
7
- import {
8
- Context,
9
- IDBInfo,
10
- ManagedOptions,
11
- ThreadInfo,
12
- ThreadMuliaddr,
13
- } from "../core/core";
14
- import {
15
- EventCodec,
16
- Errors,
17
- pullThreadBackgroundTimeout,
18
- PullTimeout,
19
- } from "../core/db";
20
- import { IThreadRecord } from "../core/record";
21
- import { Ed25519PubKey } from "../../../common/dc-key/ed25519";
22
- import { JSONSchemaType } from "ajv";
23
- import { IThreadEvent } from "../core/event";
24
- import { Collection, Txn } from "./collection";
25
- import { ThreadToken } from "../core/identity";
26
- import { NewOptions, Index, ICollectionConfig } from "../core/core";
27
- import {
28
- Event,
29
- InstanceID,
30
- ReduceAction,
31
- Action,
32
- CoreActionType,
33
- TxnDatastoreExtended,
34
- Transaction,
35
- IndexFunc,
36
- DBPrefix,
37
- IDB,
38
- ITxn,
39
- } from "../core/db";
40
-
41
- import { ulid } from "ulid";
42
- import { JsonPatcher } from "../common/json-patcher";
43
- import { multiaddr, Multiaddr } from "@multiformats/multiaddr";
44
- import { ThreadID } from "@textile/threads-id";
45
- import { PeerId } from "@libp2p/interface";
46
- import { Net } from "../core/app";
47
- import { Dispatcher } from "../common/dispatcher";
48
- import { LocalEventsBus, App } from "../core/app";
49
- import * as dagPB from "@ipld/dag-pb";
50
- import * as threadEvent from "../cbor/event";
51
- import { IRecord } from "../core/record";
52
- import { IPLDNode } from "../core/core";
53
- import { jsonStringify } from "../../../util/utils";
54
-
55
- const baseKey = DBPrefix.dsPrefix.child(new Key("collection"));
56
- const getBlockInitialTimeout = 500;
57
- const getBlockRetries = 3;
58
-
59
- export class CollectionEvent<T = any> implements Event<T> {
60
- readonly timestamp: BigInt;
61
-
62
- constructor(
63
- readonly instanceID: InstanceID,
64
- readonly collection: string,
65
- readonly payload: T
66
- ) {
67
- this.timestamp = BigInt(
68
- Date.now() * 1000000 + Math.floor(Math.random() * 1000000)
69
- );
70
- }
71
-
72
- async marshal(): Promise<Uint8Array> {
73
- return new TextEncoder().encode(
74
- jsonStringify({
75
- t: this.timestamp,
76
- i: this.instanceID,
77
- c: this.collection,
78
- p: this.payload,
79
- })
80
- );
81
- }
82
- }
83
-
84
- class CollectionExistsError extends Error {
85
- name: string;
86
- constructor(name: string) {
87
- super(`Collection ${name} already exists`);
88
- this.name = "CollectionExistsError";
89
- }
90
- }
91
-
92
- export class DB implements App, IDB {
93
- private name: string;
94
- public connector: Connector | null = null; //
95
- public datastore: TxnDatastoreExtended;
96
- public dispatcher: Dispatcher | null = null;
97
- public eventcodec: EventCodec;
98
- public collections: Map<string, Collection> = new Map();
99
- public localEventsBus: LocalEventsBus | null = null;
100
- private webLock: string;
101
-
102
- constructor(
103
- datastore: TxnDatastoreExtended,
104
- net: Net,
105
- id: string,
106
- opts: NewOptions
107
- ) {
108
- this.datastore = datastore;
109
- this.name = opts.name || "unnamed";
110
- this.eventcodec = opts.eventCodec || new JsonPatcher();
111
- this.webLock = "webLock_db_" + id;
112
- }
113
-
114
- // 新建 DB 实例
115
- static async newDB(
116
- store: TxnDatastoreExtended,
117
- n: Net,
118
- id: ThreadID,
119
- opts?: NewOptions
120
- ): Promise<DB> {
121
- const args = opts || new NewOptions();
122
- if (!args.eventCodec) {
123
- args.eventCodec = new JsonPatcher(); //DefaultEventCodec()
124
- }
125
-
126
- const dbInstance = new DB(store, n, id.toString(), args);
127
- dbInstance.name = "";
128
- dbInstance.dispatcher = new Dispatcher(store);
129
- dbInstance.localEventsBus = new LocalEventsBus();
130
-
131
- try {
132
- await dbInstance.loadName();
133
- } catch (error) {
134
- throw new Error("Failed to load DB name");
135
- }
136
-
137
- const prevName = dbInstance.name;
138
- if (args.name) {
139
- dbInstance.name = args.name;
140
- } else if (prevName === "") {
141
- dbInstance.name = "unnamed";
142
- }
143
- await dbInstance.saveName(prevName);
144
- await dbInstance.reCreateCollections();
145
- dbInstance.dispatcher.register(dbInstance);
146
-
147
- try {
148
- const connector = await n.connectApp(dbInstance, id);
149
- dbInstance.connector = connector;
150
- } catch (err) {
151
- throw new Error(
152
- `Failed to connect app: ${
153
- err instanceof Error ? err.message : String(err)
154
- }`
155
- );
156
- }
157
-
158
- // 处理集合配置
159
- if (args.collections && args.collections.length > 0) {
160
- for (const collectionConfig of args.collections) {
161
- try {
162
- await dbInstance.newCollection(collectionConfig);
163
- } catch (err) {
164
- throw new Error(
165
- `Failed to create collection: ${
166
- err instanceof Error ? err.message : String(err)
167
- }`
168
- );
169
- }
170
- }
171
- }
172
- return dbInstance;
173
- }
174
-
175
- /**
176
- * GetDBInfo returns the addresses and key that can be used to join the DB thread.
177
- * @param options Optional settings for the operation
178
- * @returns Promise resolving to thread info
179
- */
180
- async getDBInfo(options?: ManagedOptions): Promise<IDBInfo> {
181
- console.debug(`getting db info in ${this.name}`);
182
-
183
- try {
184
- const threadInfo = await this.connector?.net.getThread(
185
- this.connector?.threadId,
186
- { token: options?.token }
187
- );
188
- const dbInfo: IDBInfo = {
189
- id: this.connector ? this.connector.threadId.toString() : "",
190
- name: this.name,
191
- addrs: threadInfo
192
- ? threadInfo.addrs.map((addr: ThreadMuliaddr) => addr.toString())
193
- : [],
194
- key: threadInfo ? threadInfo.key?.toString() : "",
195
- };
196
- return dbInfo;
197
- } catch (err) {
198
- throw new Error(
199
- `Failed to get DB info: ${
200
- err instanceof Error ? err.message : String(err)
201
- }`
202
- );
203
- }
204
- }
205
-
206
- async saveName(prevName: string): Promise<void> {
207
- if (this.name === prevName) return;
208
- if (!this.name.match(/^[a-zA-Z0-9_-]+$/)) {
209
- // 根据需求定义规则
210
- throw new Error("Invalid name");
211
- }
212
- await this.datastore.put(
213
- DBPrefix.dsName,
214
- new TextEncoder().encode(this.name)
215
- );
216
- }
217
-
218
- async loadName(): Promise<void> {
219
- try {
220
- const nameBuffer = await this.datastore.get(DBPrefix.dsName);
221
- if (nameBuffer) {
222
- this.name = new TextDecoder().decode(nameBuffer);
223
- }
224
- } catch (error) {}
225
- }
226
-
227
- async saveVerno(verno: number): Promise<void> {
228
- await this.datastore.put(
229
- DBPrefix.dsVerno,
230
- new TextEncoder().encode(verno.toString())
231
- );
232
- }
233
-
234
- async loadVerno(): Promise<number> {
235
- try {
236
- const vernoBuffer = await this.datastore.get(DBPrefix.dsVerno);
237
- if (vernoBuffer) {
238
- return parseInt(new TextDecoder().decode(vernoBuffer));
239
- }
240
- } catch (error) {}
241
- return 0;
242
- }
243
-
244
-
245
- private async initCollections(configs: ICollectionConfig[]): Promise<void> {
246
- for (const config of configs) {
247
- await this.newCollection(config);
248
- }
249
- }
250
-
251
- async upgradeCollections(configs: ICollectionConfig[]): Promise<void> {
252
- for (const config of configs) {
253
- await this.newCollection(config,true);
254
- }
255
- }
256
-
257
- async newCollection(config: ICollectionConfig,forceUpdate:boolean=false): Promise<Collection> {
258
- if (this.collections.has(config.name) && !forceUpdate) {
259
- throw new CollectionExistsError(config.name);
260
- }
261
- const collection = new Collection(config.name, config.schema, this);
262
-
263
- // Add default _id index
264
- await collection.addIndex({ path: "_id", unique: true });
265
-
266
- // Add custom indexes
267
- for (const index of config.indexes || []) {
268
- await collection.addIndex(index);
269
- }
270
- //保存集合配置到数据存储
271
- this.saveCollection(collection);
272
- return collection;
273
- }
274
-
275
- async saveCollection(c: Collection): Promise<void> {
276
- console.debug(`saving collection ${c.name} in ${this.name}`);
277
-
278
- try {
279
- // Save schema
280
- await this.datastore.put(
281
- DBPrefix.dsSchemas.child(new Key(c.name)),
282
- c.getSchema()
283
- );
284
-
285
- // Save write validator if exists
286
- if (c.rawWriteValidator) {
287
- await this.datastore.put(
288
- DBPrefix.dsValidators.child(new Key(c.name)),
289
- new TextEncoder().encode(c.rawWriteValidator)
290
- );
291
- }
292
-
293
- // Save read filter if exists
294
- if (c.rawReadFilter) {
295
- await this.datastore.put(
296
- DBPrefix.dsFilters.child(new Key(c.name)),
297
- new TextEncoder().encode(c.rawReadFilter)
298
- );
299
- }
300
- // Add collection to local map
301
- this.collections.set(c.name, c);
302
- } catch (err) {
303
- throw new Error(
304
- `Failed to save collection ${c.name}: ${
305
- err instanceof Error ? err.message : String(err)
306
- }`
307
- );
308
- }
309
- }
310
-
311
- async reCreateCollections(): Promise<void> {
312
- try {
313
- const results = this.datastore.query({
314
- prefix: DBPrefix.dsSchemas.toString(),
315
- }) as AsyncIterable<{ key: Key; value: Uint8Array }>;
316
-
317
- try {
318
- for await (const res of results) {
319
- const name = res.key.name();
320
- const schema = JSON.parse(new TextDecoder().decode(res.value));
321
-
322
- let wv: string | undefined;
323
- try {
324
- const wvBuffer = await this.datastore.get(
325
- DBPrefix.dsValidators.child(new Key(name))
326
- );
327
- wv = new TextDecoder().decode(wvBuffer);
328
- } catch (err: any) {
329
- if (err.code !== "ERR_NOT_FOUND") throw err;
330
- }
331
-
332
- let rf: string | undefined;
333
- try {
334
- const rfBuffer = await this.datastore.get(
335
- DBPrefix.dsFilters.child(new Key(name))
336
- );
337
- rf = new TextDecoder().decode(rfBuffer);
338
- } catch (err: any) {
339
- if (err.code !== "ERR_NOT_FOUND") throw err;
340
- }
341
-
342
- const c = new Collection(name, schema, this);
343
-
344
- // 修复索引对象
345
- try {
346
- const indexBuffer = await this.datastore.get(
347
- DBPrefix.dsIndexes.child(new Key(name))
348
- );
349
- const indexData = JSON.parse(new TextDecoder().decode(indexBuffer));
350
-
351
- // 修复索引映射 - 使用 Map 而不是对象
352
- for (const [path, index] of Object.entries(indexData)) {
353
- if (path) {
354
- c.indexes.set(path, index as Index);
355
- }
356
- }
357
- } catch (err: any) {
358
- if (err.code !== "ERR_NOT_FOUND") throw err;
359
- }
360
-
361
- // 添加到集合映射
362
- this.collections.set(c.name, c);
363
- }
364
- } catch (err) {
365
- throw new Error(
366
- `Error re-creating collections: ${
367
- err instanceof Error ? err.message : String(err)
368
- }`
369
- );
370
- }
371
- } catch (err) {
372
- throw new Error(
373
- `Error re-creating collections: ${
374
- err instanceof Error ? err.message : String(err)
375
- }`
376
- );
377
- }
378
- }
379
-
380
- getCollection(name: string): Collection {
381
- const collection = this.collections.get(name);
382
- if (!collection) throw new Error(`Collection ${name} not found`);
383
- return collection;
384
- }
385
-
386
- async close(): Promise<void> {}
387
-
388
- async reduce(events: Event[]): Promise<void> {
389
- try {
390
- // 调用事件编解码器的 reduce 方法获取处理结果
391
- const codecActions = await this.eventcodec.reduce(
392
- events,
393
- this.datastore,
394
- baseKey,
395
- this.defaultIndexFunc()
396
- );
397
-
398
-
399
- // 创建 actions 数组并映射处理结果
400
- const actions: Action[] = codecActions.map((ca) => {
401
- // 返回转换后的 Action 对象
402
- return {
403
- collectionName: ca.collection,
404
- type: ca.type,
405
- instanceID: ca.instanceID,
406
- };
407
- });
408
-
409
- // 通知状态变更
410
- this.notifyStateChanged(actions);
411
- } catch (err) {
412
- throw new Error(
413
- `Error reducing events: ${
414
- err instanceof Error ? err.message : String(err)
415
- }`
416
- );
417
- }
418
- }
419
-
420
- /**
421
- * 默认索引函数
422
- * 创建一个处理集合索引更新的函数
423
- */
424
- defaultIndexFunc(): (
425
- collection: string,
426
- key: Key,
427
- txn: any,
428
- oldData?: Uint8Array,
429
- newData?: Uint8Array
430
- ) => Promise<void> {
431
- return async (
432
- collection: string,
433
- key: Key,
434
- txn: any,
435
- oldData?: Uint8Array,
436
- newData?: Uint8Array
437
- ): Promise<void> => {
438
- const c = this.collections.get(collection);
439
- if (!c) {
440
- throw new Error(`collection (${collection}) not found`);
441
- }
442
- if (oldData) {
443
- await c.indexDelete(txn, key, oldData);
444
- }
445
- if (!newData) {
446
- return;
447
- }
448
- await c.indexAdd(txn, key, newData);
449
- };
450
- }
451
-
452
- // 添加通知状态变更的方法
453
- private notifyStateChanged(actions: Action[]): void {
454
- // 发送状态变更事件
455
- if (this.localEventsBus) {
456
- //浏览器侧暂不实现
457
- }
458
- }
459
- /**
460
- * 通知事务事件
461
- * 将事务相关的节点和令牌发送到本地事件总线
462
- */
463
- async notifyTxnEvents(node: IPLDNode, token: ThreadToken): Promise<void> {
464
- try {
465
- await this.localEventsBus?.send({
466
- node: node,
467
- token: token,
468
- });
469
- } catch (err) {
470
- throw new Error(
471
- `Failed to notify transaction events: ${
472
- err instanceof Error ? err.message : String(err)
473
- }`
474
- );
475
- }
476
- }
477
-
478
- async dispatch(events: Event[]): Promise<void> {
479
- // 实现事件分发逻辑
480
- for (const event of events) {
481
- await this.reduce([event]);
482
- }
483
- }
484
-
485
- async validateNetRecordBody(
486
- body: IPLDNode,
487
- identity: Ed25519PubKey
488
- ): Promise<Error | undefined> {
489
- try {
490
- const events: Event[] = await this.eventcodec.eventsFromBytes(
491
- body.data()
492
- );
493
- if (events.length === 0) {
494
- return;
495
- }
496
-
497
- for (const e of events) {
498
- const collection = this.collections.get(e.collection);
499
- if (!collection) {
500
- return Errors.ErrCollectionNotFound;
501
- }
502
- }
503
- return;
504
- } catch (error) {
505
- return error as Error;
506
- }
507
- }
508
-
509
- async handleNetRecord(
510
- rec: IThreadRecord,
511
- key: ThreadKey
512
- ): Promise<Error | undefined> {
513
- let event: any;
514
- try {
515
- if (!this.connector) {
516
- return new Error("no connector");
517
- }
518
- // 从记录中解码事件
519
- event = await threadEvent.EventFromRecord(
520
- this.connector?.net.bstore,
521
- rec.value()
522
- );
523
- } catch (err) {
524
- // 如果解码失败,尝试从块中获取事件
525
- try {
526
- const block = await this.getBlockWithRetry(rec.value());
527
- event = await threadEvent.EventFromNode(block);
528
- } catch (blockErr) {
529
- return blockErr as Error;
530
- }
531
- }
532
- try {
533
- // 获取事件的主体
534
- const body = await event.getBody(this.connector?.net, key.read());
535
-
536
- // 从字节数据中解码事件
537
- const events = await this.eventcodec.eventsFromBytes(body.rawData());
538
-
539
- // 分发事件
540
- await this.dispatch(events);
541
- } catch (err) {
542
- return new Error(
543
- `error when processing event: ${
544
- err instanceof Error ? err.message : String(err)
545
- }`
546
- );
547
- }
548
- return;
549
- }
550
-
551
- async getNetRecordCreateTime(
552
- rec: IThreadRecord,
553
- key: ThreadKey
554
- ): Promise<BigInt> {
555
- let event: IThreadEvent;
556
- if (!this.connector) {
557
- throw new Error("no connector");
558
- }
559
- try {
560
- // 从记录中解码事件
561
- event = await threadEvent.EventFromRecord(
562
- this.connector?.net.bstore,
563
- rec.value()
564
- );
565
- } catch (err) {
566
- // 如果解码失败,尝试从块中获取事件
567
- try {
568
- const block = await this.getBlockWithRetry(rec.value());
569
- event = await threadEvent.EventFromNode(block);
570
- } catch (decodeErr) {
571
- throw new Error(
572
- `Error when decoding block to event: ${
573
- decodeErr instanceof Error ? decodeErr.message : String(decodeErr)
574
- }`
575
- );
576
- }
577
- }
578
-
579
- let body: IPLDNode;
580
- try {
581
- // 获取事件的主体
582
- body = await event.getBody(this.connector?.net.bstore, key.read());
583
- } catch (err) {
584
- throw new Error(
585
- `Error when getting body of event on thread ${
586
- this.connector?.threadId
587
- }/${rec.logID()}: ${err instanceof Error ? err.message : String(err)}`
588
- );
589
- }
590
-
591
- let events: Event<any>[];
592
- try {
593
- // 从字节数据中解码事件
594
- events = await this.eventcodec.eventsFromBytes(body.data());
595
- } catch (err) {
596
- throw new Error(
597
- `Error when unmarshaling event from bytes: ${
598
- err instanceof Error ? err.message : String(err)
599
- }`
600
- );
601
- }
602
-
603
- if (events.length === 0) {
604
- throw new Error("No events found in record");
605
- }
606
- return events[0]!.timestamp;
607
- }
608
-
609
- private async getBlockWithRetry(rec: IRecord): Promise<any> {
610
- let backoff = getBlockInitialTimeout;
611
- let lastError: Error | null = null;
612
- if (!this.connector) {
613
- throw new Error("no connector");
614
- }
615
- // 重试循环
616
- for (let i = 1; i <= getBlockRetries; i++) {
617
- try {
618
- // 尝试获取块
619
- const block = await rec.getBlock(this.connector?.net.bstore);
620
- return block; // 成功则立即返回
621
- } catch (err) {
622
- lastError = err as Error;
623
- console.warn(`错误: 在第 ${i} 次重试中获取块 ${rec.cid()} 失败`);
624
- await new Promise((resolve) => setTimeout(resolve, backoff));
625
- backoff *= 2;
626
- }
627
- }
628
- }
629
-
630
- async readTxn(
631
- collection: Collection,
632
- fn: (txn: ITxn) => Promise<void>,
633
- token?: ThreadToken
634
- ): Promise<void> {
635
- // 创建事务选项
636
- const args = { token: undefined } as any;
637
-
638
- // 创建只读事务
639
- const txn = new Txn(collection, token, true);
640
-
641
- try {
642
- // 执行事务函数
643
- await fn(txn);
644
- } finally {
645
- // 确保事务被丢弃
646
- txn.discard();
647
- }
648
- }
649
-
650
- // 使用队列确保写入操作按顺序执行
651
- private writeQueue = Promise.resolve();
652
-
653
- async writeTxn(
654
- collection: Collection,
655
- fn: (txn: ITxn) => Promise<void>,
656
- token?: ThreadToken
657
- ): Promise<void> {
658
- // Save the current promise chain
659
- const previousOperation = this.writeQueue;
660
-
661
- // Create a new promise for this operation
662
- const currentOperation = new Promise<void>((resolve, reject) => {
663
- // Wait for previous operations to complete (or fail)
664
- previousOperation
665
- .catch(() => {
666
- // Ignore previous errors - just ensure we wait for previous operations
667
- })
668
- .finally(async () => {
669
- // After previous operations are done (success or failure), run this operation
670
- const txn = new Txn(collection, token, false);
671
- try {
672
- // Execute transaction function
673
- await fn(txn);
674
-
675
- // Commit transaction
676
- await txn.commit();
677
- resolve();
678
- } catch (err) {
679
- // Properly propagate the error
680
- reject(err);
681
- } finally {
682
- // Always discard the transaction
683
- txn.discard();
684
- }
685
- });
686
- });
687
-
688
- // Update the queue with our operation
689
- this.writeQueue = currentOperation.catch(() => {
690
- // Swallow errors in the queue chain but log them
691
- // This ensures future operations will still execute
692
- return Promise.resolve();
693
- });
694
-
695
- // Return the current operation, allowing errors to propagate to the caller
696
- return currentOperation;
697
- }
698
- }