web-dc-api 0.0.87 → 0.0.89
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 -0
- package/dist/cjs/protobuf-BVBdi7Hh.js +1 -0
- package/dist/dc.min.js +1 -19
- package/dist/esm/chunks/protobuf-CbxDm-Gy.js +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/index.d.ts +947 -886
- package/package.json +14 -17
- package/dist/index.cjs.js +0 -19
- package/dist/index.esm.js +0 -19
- 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 -595
- package/lib/common/define.ts +0 -66
- 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 -694
- 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 -202
- 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 -443
- package/lib/implements/threaddb/dbmanager.ts +0 -1901
- package/lib/implements/threaddb/lsstoreds/addr_book.ts +0 -452
- 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 -280
- 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 -138
- package/lib/implements/threaddb/net/grpcClient.ts +0 -582
- package/lib/implements/threaddb/net/grpcserver.ts +0 -146
- package/lib/implements/threaddb/net/net.ts +0 -2006
- 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 -664
- 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/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/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,542 +0,0 @@
|
|
|
1
|
-
import { CID } from 'multiformats/cid';
|
|
2
|
-
import * as dagCBOR from '@ipld/dag-cbor';
|
|
3
|
-
|
|
4
|
-
import { dagCbor } from '@helia/dag-cbor'
|
|
5
|
-
import { sha256 } from 'multiformats/hashes/sha2';
|
|
6
|
-
import CID_IPLD from 'cids';
|
|
7
|
-
import { Link } from 'multiformats/link'
|
|
8
|
-
import { IBlock } from '../core/core';
|
|
9
|
-
// 常量定义 - CBOR Tag for links
|
|
10
|
-
const CBORTagLink = 42;
|
|
11
|
-
|
|
12
|
-
// 错误定义
|
|
13
|
-
const Errors = {
|
|
14
|
-
ErrNoSuchLink: new Error('no such link found'),
|
|
15
|
-
ErrNonLink: new Error('non-link found at given path'),
|
|
16
|
-
ErrInvalidLink: new Error('link value should have been bytes'),
|
|
17
|
-
ErrInvalidKeys: new Error('map keys must be strings'),
|
|
18
|
-
ErrArrayOutOfRange: new Error('array index out of range'),
|
|
19
|
-
ErrNoLinks: new Error('tried to resolve through object that had no links'),
|
|
20
|
-
ErrEmptyLink: new Error('link value was empty'),
|
|
21
|
-
ErrInvalidMultibase: new Error('invalid multibase on IPLD link'),
|
|
22
|
-
ErrNonStringLink: new Error('link should have been a string')
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
export class Block {
|
|
28
|
-
_data: Uint8Array;
|
|
29
|
-
_cid: CID;
|
|
30
|
-
|
|
31
|
-
constructor(data: Uint8Array, cid: CID) {
|
|
32
|
-
this._data = data;
|
|
33
|
-
this._cid = cid;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
data(): Uint8Array {
|
|
37
|
-
return this._data;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
cid(): CID {
|
|
41
|
-
return this._cid;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
// // Link 接口定义
|
|
45
|
-
// export interface Link {
|
|
46
|
-
// name?: string;
|
|
47
|
-
// size?: number;
|
|
48
|
-
// cid: CID;
|
|
49
|
-
// }
|
|
50
|
-
|
|
51
|
-
// NodeStat 接口定义
|
|
52
|
-
interface NodeStat {
|
|
53
|
-
cumulativeSize?: number;
|
|
54
|
-
blocks?: number;
|
|
55
|
-
size?: number;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Node 类
|
|
59
|
-
export class Node {
|
|
60
|
-
private _obj: any;
|
|
61
|
-
private _tree: string[];
|
|
62
|
-
private _links: Link[];
|
|
63
|
-
private _raw: Uint8Array;
|
|
64
|
-
private _cid: CID;
|
|
65
|
-
|
|
66
|
-
constructor(obj: any, tree: string[], links: Link[], raw: Uint8Array, cid: CID) {
|
|
67
|
-
this._obj = obj;
|
|
68
|
-
this._tree = tree;
|
|
69
|
-
this._links = links;
|
|
70
|
-
this._raw = raw;
|
|
71
|
-
this._cid = cid;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// 解析路径并返回找到的对象
|
|
75
|
-
resolve(path: string[]): [any, string[] | null, Error | null] {
|
|
76
|
-
let cur: any = this._obj;
|
|
77
|
-
|
|
78
|
-
for (let i = 0; i < path.length; i++) {
|
|
79
|
-
const val = path[i]!;
|
|
80
|
-
|
|
81
|
-
if (typeof cur === 'object' && cur !== null) {
|
|
82
|
-
if (Array.isArray(cur)) {
|
|
83
|
-
const n = parseInt(val);
|
|
84
|
-
if (isNaN(n)) {
|
|
85
|
-
return [null, null, new Error('array index was not a number')];
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (n < 0 || n >= cur.length) {
|
|
89
|
-
return [null, null, Errors.ErrArrayOutOfRange];
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
cur = cur[n];
|
|
93
|
-
} else if (isCID(cur)) {
|
|
94
|
-
return [{ cid: cur }, path.slice(i), null];
|
|
95
|
-
} else {
|
|
96
|
-
const next = cur[val];
|
|
97
|
-
if (next === undefined) {
|
|
98
|
-
return [null, null, Errors.ErrNoSuchLink];
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
cur = next;
|
|
102
|
-
}
|
|
103
|
-
} else {
|
|
104
|
-
return [null, null, Errors.ErrNoLinks];
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
if (isCID(cur)) {
|
|
109
|
-
return [{ cid: cur }, null, null];
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
try {
|
|
113
|
-
const jsonish = this.convertToJSONIsh(cur);
|
|
114
|
-
return [jsonish, null, null];
|
|
115
|
-
} catch (err) {
|
|
116
|
-
return [null, null, err as Error];
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// 解析路径并返回链接
|
|
121
|
-
resolveLink(path: string[]): [Link | null, string[] | null, Error | null] {
|
|
122
|
-
try {
|
|
123
|
-
const [obj, rest, err] = this.resolve(path);
|
|
124
|
-
if (err) {
|
|
125
|
-
return [null, null, err];
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (!obj || !obj.cid || !isCID(obj.cid)) {
|
|
129
|
-
return [null, rest, Errors.ErrNonLink];
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return [obj as Link, rest, null];
|
|
133
|
-
} catch (err) {
|
|
134
|
-
return [null, null, err as Error];
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// 返回指定路径和深度的树
|
|
139
|
-
tree(path: string, depth: number): string[] {
|
|
140
|
-
if (path === '' && depth === -1) {
|
|
141
|
-
return [...this._tree]; // Return a copy
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const out: string[] = [];
|
|
145
|
-
for (const t of this._tree) {
|
|
146
|
-
if (!t.startsWith(path)) {
|
|
147
|
-
continue;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const sub = t.substring(path.length).replace(/^\/+/, '');
|
|
151
|
-
if (sub === '') {
|
|
152
|
-
continue;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (depth < 0) {
|
|
156
|
-
out.push(sub);
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
const parts = sub.split('/');
|
|
161
|
-
if (parts.length <= depth) {
|
|
162
|
-
out.push(sub);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return out;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// 返回节点的所有链接
|
|
170
|
-
links(): Link[] {
|
|
171
|
-
return [...this._links]; // Return a copy
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// 返回节点的原始数据
|
|
175
|
-
rawData(): Uint8Array {
|
|
176
|
-
return new Uint8Array(this._raw); // Return a copy
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// 返回节点的原始数据,兼容IBlock
|
|
180
|
-
data(): Uint8Array {
|
|
181
|
-
return new Uint8Array(this._raw); // Return a copy
|
|
182
|
-
}
|
|
183
|
-
// 返回节点的 CID
|
|
184
|
-
cid(): CID {
|
|
185
|
-
return this._cid;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// 返回可记录的节点表示
|
|
189
|
-
loggable(): Record<string, any> {
|
|
190
|
-
return {
|
|
191
|
-
node_type: 'cbor',
|
|
192
|
-
cid: this.cid.toString(),
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// 返回节点的大小
|
|
197
|
-
size(): number {
|
|
198
|
-
return this._raw.length;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// 返回节点的统计信息
|
|
202
|
-
stat(): NodeStat {
|
|
203
|
-
return {};
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// 返回节点的 CID 字符串表示
|
|
207
|
-
toString(): string {
|
|
208
|
-
return this.cid.toString();
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// 转换为 JSON
|
|
212
|
-
toJSON(): any {
|
|
213
|
-
return this.convertToJSONIsh(this._obj);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// 创建节点的副本
|
|
217
|
-
copy(): Node {
|
|
218
|
-
const links = [...this._links];
|
|
219
|
-
const raw = new Uint8Array(this._raw);
|
|
220
|
-
const tree = [...this._tree];
|
|
221
|
-
|
|
222
|
-
return new Node(
|
|
223
|
-
this.copyObj(this._obj),
|
|
224
|
-
tree,
|
|
225
|
-
links,
|
|
226
|
-
raw,
|
|
227
|
-
this._cid
|
|
228
|
-
);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// 深拷贝对象
|
|
232
|
-
private copyObj(i: any): any {
|
|
233
|
-
if (i === null || i === undefined) {
|
|
234
|
-
return i;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
if (Array.isArray(i)) {
|
|
238
|
-
return i.map(v => this.copyObj(v));
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
if (typeof i === 'object') {
|
|
242
|
-
if (isCID(i)) {
|
|
243
|
-
return i;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
const out: Record<string, any> = {};
|
|
247
|
-
for (const [k, v] of Object.entries(i)) {
|
|
248
|
-
out[k] = this.copyObj(v);
|
|
249
|
-
}
|
|
250
|
-
return out;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
return i; // 原始值直接返回
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
// 转换为 JSON 兼容格式
|
|
257
|
-
private convertToJSONIsh(v: any): any {
|
|
258
|
-
if (v === null || v === undefined) {
|
|
259
|
-
return v;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
if (Array.isArray(v)) {
|
|
263
|
-
if (v.length === 0) {
|
|
264
|
-
return [];
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
return v.map(i => this.convertToJSONIsh(i));
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
if (typeof v === 'object') {
|
|
271
|
-
if (isCID(v)) {
|
|
272
|
-
return { '/': v.toString() };
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
const out: Record<string, any> = {};
|
|
276
|
-
for (const [k, val] of Object.entries(v)) {
|
|
277
|
-
out[k] = this.convertToJSONIsh(val);
|
|
278
|
-
}
|
|
279
|
-
return out;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
return v; // 原始值直接返回
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
// 从 Block 解码节点
|
|
287
|
-
export async function decodeBlock(block: Block): Promise<Node> {
|
|
288
|
-
try {
|
|
289
|
-
const obj = dagCBOR.decode(block.data());
|
|
290
|
-
return await newObject(block, obj);
|
|
291
|
-
} catch (err) {
|
|
292
|
-
throw new Error(`Failed to decode block: ${err instanceof Error ? err.message : String(err)}`);
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// 从原始数据解码节点
|
|
297
|
-
export async function decode(data: Uint8Array, hashAlg: string = 'sha2-256'): Promise<Node> {
|
|
298
|
-
const obj = dagCBOR.decode(data);
|
|
299
|
-
return await wrapObject(obj);
|
|
300
|
-
// try {
|
|
301
|
-
// let canonicalData: Uint8Array = data;
|
|
302
|
-
// let obj: any;
|
|
303
|
-
// try {
|
|
304
|
-
// obj = dagCBOR.decode(data);
|
|
305
|
-
// // 重新编码确保规范化
|
|
306
|
-
// canonicalData = dagCBOR.encode(obj);
|
|
307
|
-
// } catch (err) {
|
|
308
|
-
|
|
309
|
-
// }
|
|
310
|
-
|
|
311
|
-
// // 创建 CID
|
|
312
|
-
// const hash = await sha256.digest(canonicalData);
|
|
313
|
-
// const cid = CID.createV1(dagCBOR.code, hash);
|
|
314
|
-
// const oldCid = new CID_IPLD(cid.toString());
|
|
315
|
-
|
|
316
|
-
// // 创建自定义Block对象
|
|
317
|
-
// const block = new Block(
|
|
318
|
-
// canonicalData,
|
|
319
|
-
// cid
|
|
320
|
-
// )
|
|
321
|
-
// return await newObject(block, obj);
|
|
322
|
-
// } catch (err) {
|
|
323
|
-
// throw new Error(`Failed to decode data: ${err instanceof Error ? err.message : String(err)}`);
|
|
324
|
-
// }
|
|
325
|
-
}
|
|
326
|
-
export async function wrapObject(obj: any): Promise<Node> {
|
|
327
|
-
try {
|
|
328
|
-
// 编码对象
|
|
329
|
-
const data = dagCBOR.encode(obj);
|
|
330
|
-
|
|
331
|
-
// 创建 CID
|
|
332
|
-
const hash = await sha256.digest(data);
|
|
333
|
-
const cid = CID.createV1(dagCBOR.code, hash);
|
|
334
|
-
|
|
335
|
-
// 创建块
|
|
336
|
-
const block = new Block(data, cid);
|
|
337
|
-
|
|
338
|
-
// 创建兼容 Uint8Array 的深拷贝
|
|
339
|
-
const clone = structuredClone(obj) || deepCopyWithTypedArrays(obj);
|
|
340
|
-
|
|
341
|
-
return await newObject(block, clone);
|
|
342
|
-
} catch (err) {
|
|
343
|
-
throw new Error(`Failed to wrap object: ${err instanceof Error ? err.message : String(err)}`);
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
// 兼容性深拷贝函数
|
|
348
|
-
function deepCopyWithTypedArrays(obj: any): any {
|
|
349
|
-
if (obj === null || obj === undefined) {
|
|
350
|
-
return obj;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
// 区分处理 ArrayBuffer 和 ArrayBufferView
|
|
354
|
-
if (obj instanceof ArrayBuffer) {
|
|
355
|
-
// ArrayBuffer 直接创建新副本
|
|
356
|
-
return new Uint8Array(obj).buffer;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
// 处理 TypedArrays (ArrayBufferView)
|
|
360
|
-
if (ArrayBuffer.isView(obj)) {
|
|
361
|
-
// 从视图创建新副本
|
|
362
|
-
return new Uint8Array(obj.buffer, obj.byteOffset, obj.byteLength);
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
if (Array.isArray(obj)) {
|
|
366
|
-
return obj.map(item => deepCopyWithTypedArrays(item));
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
if (typeof obj === 'object' && !isCID(obj)) {
|
|
370
|
-
const copy: Record<string, any> = {};
|
|
371
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
372
|
-
copy[key] = deepCopyWithTypedArrays(value);
|
|
373
|
-
}
|
|
374
|
-
return copy;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
// 原始值、CID 直接返回
|
|
378
|
-
return obj;
|
|
379
|
-
}
|
|
380
|
-
// 从 JSON 创建节点
|
|
381
|
-
export async function fromJSON(json: any): Promise<Node> {
|
|
382
|
-
try {
|
|
383
|
-
// 将 JSON 转换为 CBOR 兼容对象
|
|
384
|
-
const obj = await convertToCborIshObj(json);
|
|
385
|
-
|
|
386
|
-
// 包装对象
|
|
387
|
-
return await wrapObject(obj);
|
|
388
|
-
} catch (err) {
|
|
389
|
-
throw new Error(`Failed to convert from JSON: ${err instanceof Error ? err.message : String(err)}`);
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
// 创建新的节点对象
|
|
394
|
-
async function newObject(block: IBlock, obj: any): Promise<Node> {
|
|
395
|
-
try {
|
|
396
|
-
const [tree, links] = await compute(obj);
|
|
397
|
-
return new Node(
|
|
398
|
-
obj,
|
|
399
|
-
tree,
|
|
400
|
-
links,
|
|
401
|
-
block.data(),
|
|
402
|
-
block.cid()
|
|
403
|
-
);
|
|
404
|
-
} catch (err) {
|
|
405
|
-
throw new Error(`Failed to create node: ${err instanceof Error ? err.message : String(err)}`);
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
// 计算对象的树和链接
|
|
410
|
-
async function compute(obj: any): Promise<[string[], Link[]]> {
|
|
411
|
-
const tree: string[] = [];
|
|
412
|
-
const links: Link[] = [];
|
|
413
|
-
|
|
414
|
-
await traverse(obj, '', (name, val) => {
|
|
415
|
-
if (name !== '') {
|
|
416
|
-
tree.push(name.substring(1)); // 去除开头的 /
|
|
417
|
-
}
|
|
418
|
-
if (val && isCID(val)) {
|
|
419
|
-
links.push(val);
|
|
420
|
-
}
|
|
421
|
-
return null;
|
|
422
|
-
});
|
|
423
|
-
|
|
424
|
-
return [tree, links];
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
// 遍历对象
|
|
428
|
-
async function traverse(
|
|
429
|
-
obj: any,
|
|
430
|
-
cur: string,
|
|
431
|
-
cb: (path: string, val: any) => Error | null
|
|
432
|
-
): Promise<void> {
|
|
433
|
-
const err = cb(cur, obj);
|
|
434
|
-
if (err) throw err;
|
|
435
|
-
|
|
436
|
-
if (obj === null || obj === undefined) {
|
|
437
|
-
return;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
if (Array.isArray(obj)) {
|
|
441
|
-
for (let i = 0; i < obj.length; i++) {
|
|
442
|
-
const path = `${cur}/${i}`;
|
|
443
|
-
await traverse(obj[i], path, cb);
|
|
444
|
-
}
|
|
445
|
-
return;
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
if (typeof obj === 'object' && !isCID(obj)) {
|
|
449
|
-
for (const [k, v] of Object.entries(obj)) {
|
|
450
|
-
const path = `${cur}/${k}`;
|
|
451
|
-
await traverse(v, path, cb);
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
// 将 JSON 对象转换为 CBOR 兼容对象
|
|
457
|
-
async function convertToCborIshObj(obj: any): Promise<any> {
|
|
458
|
-
if (obj === null || obj === undefined) {
|
|
459
|
-
return obj;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
if (Array.isArray(obj)) {
|
|
463
|
-
if (obj.length === 0) {
|
|
464
|
-
return [];
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
// 添加类型注解解决 'never' 错误
|
|
468
|
-
const out: any[] = [];
|
|
469
|
-
for (const item of obj) {
|
|
470
|
-
out.push(await convertToCborIshObj(item));
|
|
471
|
-
}
|
|
472
|
-
return out;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
if (typeof obj === 'object') {
|
|
476
|
-
// 处理 CID 链接
|
|
477
|
-
if (obj['/'] !== undefined && Object.keys(obj).length === 1) {
|
|
478
|
-
if (typeof obj['/'] !== 'string') {
|
|
479
|
-
throw Errors.ErrNonStringLink;
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
try {
|
|
483
|
-
return CID.parse(obj['/']);
|
|
484
|
-
} catch (err) {
|
|
485
|
-
throw new Error(`Invalid CID string: ${obj['/']}`);
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
const out: Record<string, any> = {};
|
|
490
|
-
for (const [k, v] of Object.entries(obj)) {
|
|
491
|
-
out[k] = await convertToCborIshObj(v);
|
|
492
|
-
}
|
|
493
|
-
return out;
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
return obj; // 原始值直接返回
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
/**
|
|
500
|
-
* 将字节数组转换为 CID
|
|
501
|
-
* @param x 字节数组
|
|
502
|
-
* @returns 转换后的 CID
|
|
503
|
-
*/
|
|
504
|
-
export function castBytesToCid(x: Uint8Array): CID {
|
|
505
|
-
if (x.length === 0) {
|
|
506
|
-
throw Errors.ErrEmptyLink;
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
// 检查多重基编码
|
|
510
|
-
if (x[0] !== 0) {
|
|
511
|
-
throw Errors.ErrInvalidMultibase;
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
try {
|
|
515
|
-
return CID.decode(x.slice(1));
|
|
516
|
-
} catch (err) {
|
|
517
|
-
throw Errors.ErrInvalidLink;
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
/**
|
|
522
|
-
* 将 CID 转换为字节数组
|
|
523
|
-
* @param link CID
|
|
524
|
-
* @returns 转换后的字节数组
|
|
525
|
-
*/
|
|
526
|
-
export function castCidToBytes(link: CID): Uint8Array {
|
|
527
|
-
if (!link) {
|
|
528
|
-
throw Errors.ErrEmptyLink;
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
const bytes = link.bytes;
|
|
532
|
-
const result = new Uint8Array(bytes.length + 1);
|
|
533
|
-
result[0] = 0; // 多重基编码前缀
|
|
534
|
-
result.set(bytes, 1);
|
|
535
|
-
|
|
536
|
-
return result;
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
function isCID(value: any): boolean {
|
|
540
|
-
return CID.asCID(value) !== null;
|
|
541
|
-
}
|
|
542
|
-
|