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,290 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { secretbox, randomBytes } from 'tweetnacl'
|
|
3
|
-
|
|
4
|
-
import { base32 } from 'multiformats/bases/base32';
|
|
5
|
-
import { SymKey } from '../core/core';
|
|
6
|
-
import { symKeyFromBytes } from '../../../common/dc-key/keyManager';
|
|
7
|
-
import type { PublicKey,PrivateKey } from "@libp2p/interface";
|
|
8
|
-
import * as JsCrypto from "jscrypto/es6";
|
|
9
|
-
const { Word32Array, AES, pad, mode, Base64 } = JsCrypto;
|
|
10
|
-
|
|
11
|
-
// Constants
|
|
12
|
-
const NonceBytes = 12;
|
|
13
|
-
const TagBytes = 16;
|
|
14
|
-
const KeyBytes = 32;
|
|
15
|
-
|
|
16
|
-
interface EncryptedData {
|
|
17
|
-
iv: Uint8Array; // 初始化向量
|
|
18
|
-
ciphertext: ArrayBuffer; // 密文
|
|
19
|
-
tag: ArrayBuffer; // 认证标签
|
|
20
|
-
}
|
|
21
|
-
// Error classes
|
|
22
|
-
class CipherTextError extends Error {
|
|
23
|
-
constructor() {
|
|
24
|
-
super('malformed cipher text');
|
|
25
|
-
this.name = 'CipherTextError';
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
class InvalidKeyError extends Error {
|
|
30
|
-
constructor() {
|
|
31
|
-
super('invalid key');
|
|
32
|
-
this.name = 'InvalidKeyError';
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Key is a wrapper for a symmetric key
|
|
38
|
-
*/
|
|
39
|
-
export class SymmetricKey {
|
|
40
|
-
static readonly keyBytes: number = 32;
|
|
41
|
-
private _raw: Uint8Array;
|
|
42
|
-
|
|
43
|
-
constructor(rawBytes: Uint8Array) {
|
|
44
|
-
this._raw = rawBytes;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Generate a new random key
|
|
49
|
-
*/
|
|
50
|
-
static newRandom(): SymmetricKey {
|
|
51
|
-
const rawBytes = randomBytes(KeyBytes);
|
|
52
|
-
return new SymmetricKey(rawBytes);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Creates a key without error handling (will throw if fails)
|
|
57
|
-
*/
|
|
58
|
-
static new(): SymmetricKey {
|
|
59
|
-
return SymmetricKey.newRandom();
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Create a key from raw bytes
|
|
64
|
-
*/
|
|
65
|
-
static fromBytes(k: Uint8Array): SymmetricKey {
|
|
66
|
-
if (k.length !== KeyBytes) {
|
|
67
|
-
throw new InvalidKeyError();
|
|
68
|
-
}
|
|
69
|
-
return new SymmetricKey(k);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Create a key from a base32-encoded string
|
|
74
|
-
*/
|
|
75
|
-
static fromString(k: string): SymmetricKey {
|
|
76
|
-
try {
|
|
77
|
-
const bytes = base32.decode(k);
|
|
78
|
-
return SymmetricKey.fromBytes(bytes);
|
|
79
|
-
} catch (err) {
|
|
80
|
-
throw new Error(`Failed to decode key: ${err instanceof Error ? err.message : String(err)}`);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
async toSymKey(): Promise<SymKey> {
|
|
85
|
-
const symKey = symKeyFromBytes(this._raw);
|
|
86
|
-
return symKey
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
static fromSymKey(symKey: SymKey): SymmetricKey {
|
|
90
|
-
return new SymmetricKey(symKey.raw)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Get raw key bytes
|
|
95
|
-
*/
|
|
96
|
-
get raw(): Uint8Array {
|
|
97
|
-
return this._raw;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Return raw key bytes
|
|
102
|
-
*/
|
|
103
|
-
bytes(): Uint8Array {
|
|
104
|
-
return this._raw;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Convert key to binary format
|
|
109
|
-
*/
|
|
110
|
-
marshalBinary(): Uint8Array {
|
|
111
|
-
return this._raw;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Return base32-encoded string representation
|
|
116
|
-
*/
|
|
117
|
-
toString(): string {
|
|
118
|
-
try {
|
|
119
|
-
return base32.encode(this.raw);
|
|
120
|
-
} catch (err) {
|
|
121
|
-
throw new Error(`Failed to encode key: ${err instanceof Error ? err.message : String(err)}`);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// /**
|
|
126
|
-
// * Encrypt performs AES-256 GCM encryption on plaintext
|
|
127
|
-
// */
|
|
128
|
-
// encrypt(plaintext: Uint8Array): Uint8Array {
|
|
129
|
-
// // Generate a random nonce
|
|
130
|
-
// const nonce = randomBytes(secretbox.nonceLength) ;
|
|
131
|
-
|
|
132
|
-
// const box = secretbox(plaintext, nonce, this._raw)
|
|
133
|
-
// const encrypted = new Uint8Array(nonce.length + box.length)
|
|
134
|
-
// encrypted.set(nonce)
|
|
135
|
-
// encrypted.set(box, nonce.length)
|
|
136
|
-
// return encrypted
|
|
137
|
-
// }
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
async encrypt(
|
|
141
|
-
plaintext: Uint8Array,
|
|
142
|
-
exNonce?: Uint8Array
|
|
143
|
-
): Promise<Uint8Array> {
|
|
144
|
-
let nonce = randomBytes(NonceBytes);
|
|
145
|
-
if(exNonce && exNonce.length === NonceBytes) {
|
|
146
|
-
nonce = exNonce;
|
|
147
|
-
}
|
|
148
|
-
// 生成随机初始化向量 (96 bits)
|
|
149
|
-
const iv = crypto.getRandomValues(nonce);
|
|
150
|
-
// 加密配置
|
|
151
|
-
const algorithm = {
|
|
152
|
-
name: "AES-GCM",
|
|
153
|
-
iv: iv,
|
|
154
|
-
tagLength: 128 // 认证标签长度 (bits)
|
|
155
|
-
};
|
|
156
|
-
const symKey = await this.toSymKey();
|
|
157
|
-
// 执行加密
|
|
158
|
-
const ciphertext = await crypto.subtle.encrypt(
|
|
159
|
-
algorithm,
|
|
160
|
-
symKey.key,
|
|
161
|
-
plaintext as any
|
|
162
|
-
);
|
|
163
|
-
// 提取认证标签(最后16字节)
|
|
164
|
-
//const tag = ciphertext.slice(ciphertext.byteLength - 16);
|
|
165
|
-
|
|
166
|
-
// 分离密文主体(去除标签)
|
|
167
|
-
// const ciphertextBody = ciphertext.slice(0, ciphertext.byteLength - 16);
|
|
168
|
-
const result = new Uint8Array(nonce.length + ciphertext.byteLength);
|
|
169
|
-
result.set(nonce, 0);
|
|
170
|
-
result.set(new Uint8Array(ciphertext), nonce.length);
|
|
171
|
-
return result;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Decrypt uses key to perform AES-256 GCM decryption on ciphertext
|
|
180
|
-
*/
|
|
181
|
-
async decrypt(encryptBuffer: Uint8Array): Promise<Uint8Array> {
|
|
182
|
-
|
|
183
|
-
if (encryptBuffer.length <= 28) {
|
|
184
|
-
return encryptBuffer;
|
|
185
|
-
}
|
|
186
|
-
const nonce = encryptBuffer.subarray(0, NonceBytes);
|
|
187
|
-
const iv = new Word32Array(nonce);
|
|
188
|
-
const tag = encryptBuffer.subarray(
|
|
189
|
-
encryptBuffer.length - TagBytes,
|
|
190
|
-
encryptBuffer.length
|
|
191
|
-
);
|
|
192
|
-
const kdfSalt = new Word32Array(tag);
|
|
193
|
-
const encryptContent = encryptBuffer.subarray(
|
|
194
|
-
NonceBytes,
|
|
195
|
-
encryptBuffer.length - TagBytes
|
|
196
|
-
);
|
|
197
|
-
const cipherText = new Word32Array(encryptContent);
|
|
198
|
-
const key = new Word32Array(this._raw);
|
|
199
|
-
const decrypted = AES.decrypt(cipherText.toString(Base64), key, {
|
|
200
|
-
iv: iv,
|
|
201
|
-
padding: pad.NoPadding,
|
|
202
|
-
mode: mode.GCM,
|
|
203
|
-
kdfSalt: kdfSalt,
|
|
204
|
-
});
|
|
205
|
-
return decrypted.toUint8Array();
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
export type LogKey = PrivateKey | PublicKey
|
|
214
|
-
|
|
215
|
-
export class Key {
|
|
216
|
-
private sk?: SymmetricKey
|
|
217
|
-
private rk?: SymmetricKey
|
|
218
|
-
|
|
219
|
-
constructor(sk: SymmetricKey , rk?: SymmetricKey ) {
|
|
220
|
-
this.sk = sk
|
|
221
|
-
if(rk) {
|
|
222
|
-
this.rk = rk
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
static new(sk: SymmetricKey, rk?: SymmetricKey ): Key {
|
|
227
|
-
if (!sk) {
|
|
228
|
-
throw new Error('service-key must not be null')
|
|
229
|
-
}
|
|
230
|
-
return new Key(sk, rk)
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
static newRandom(): Key {
|
|
234
|
-
return new Key(SymmetricKey.new(), SymmetricKey.new())
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
static newRandomService(): Key {
|
|
238
|
-
return new Key(SymmetricKey.new())
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
static fromBytes(b: Uint8Array): Key {
|
|
242
|
-
if (b.length !== SymmetricKey.keyBytes && b.length !== SymmetricKey.keyBytes * 2) {
|
|
243
|
-
throw new Error('invalid key')
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
const sk = SymmetricKey.fromBytes(b.slice(0, SymmetricKey.keyBytes))
|
|
247
|
-
if (b.length === SymmetricKey.keyBytes * 2) {
|
|
248
|
-
const rk = SymmetricKey.fromBytes(b.slice(SymmetricKey.keyBytes))
|
|
249
|
-
return new Key(sk,rk)
|
|
250
|
-
}
|
|
251
|
-
return new Key(sk)
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
static fromString(s: string): Key {
|
|
255
|
-
const decoded = base32.decode(s)
|
|
256
|
-
return Key.fromBytes(decoded)
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
service(): SymmetricKey|undefined {
|
|
260
|
-
return this.sk
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
read(): SymmetricKey|undefined {
|
|
264
|
-
return this.rk
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
defined(): boolean {
|
|
268
|
-
return this.sk !== null
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
canRead(): boolean {
|
|
272
|
-
return this.rk !== null
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
toBytes(): Uint8Array {
|
|
276
|
-
if (this.rk && this.sk) {
|
|
277
|
-
return new Uint8Array([...this.sk.bytes(), ...this.rk.bytes()])
|
|
278
|
-
} else if (this.sk ) {
|
|
279
|
-
return this.sk.bytes()
|
|
280
|
-
} else {
|
|
281
|
-
return new Uint8Array(0)
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
toString(): string {
|
|
286
|
-
return base32.encode(this.toBytes())
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
}
|
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
import { Key, Query, Batch, Pair, KeyQuery } from 'interface-datastore'
|
|
2
|
-
import { LevelDatastore } from 'datastore-level'
|
|
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 LevelDatastoreAdapter implements TxnDatastoreExtended {
|
|
9
|
-
private store: LevelDatastore;
|
|
10
|
-
private txn: any;
|
|
11
|
-
|
|
12
|
-
constructor(store: LevelDatastore) {
|
|
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 queryOptions: Query = {};
|
|
24
|
-
if (prefix !== undefined) {
|
|
25
|
-
queryOptions.prefix = prefix;
|
|
26
|
-
}
|
|
27
|
-
for await (const { key } of this.store.query(queryOptions)) {
|
|
28
|
-
let match = true;
|
|
29
|
-
|
|
30
|
-
// 应用所有过滤器
|
|
31
|
-
for (const filter of filters) {
|
|
32
|
-
if (!filter(key)) {
|
|
33
|
-
match = false;
|
|
34
|
-
break;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (match) {
|
|
39
|
-
yield key;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// 修改 query 方法
|
|
45
|
-
async *query(
|
|
46
|
-
query: Query,
|
|
47
|
-
options?: AbortOptions
|
|
48
|
-
): AsyncIterable<{ key: Key; value: Uint8Array }> {
|
|
49
|
-
yield* this.store.query(query);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// 扩展查询方法
|
|
53
|
-
|
|
54
|
-
// 修改 queryExtended 的实现
|
|
55
|
-
async *queryExtended(
|
|
56
|
-
q: QueryExt
|
|
57
|
-
): AsyncIterable<QueryResult> {
|
|
58
|
-
const { prefix, filters = [] } = q;
|
|
59
|
-
const queryOptions: Query = {};
|
|
60
|
-
if (prefix !== undefined) {
|
|
61
|
-
queryOptions.prefix = prefix;
|
|
62
|
-
}
|
|
63
|
-
for await (const entry of this.store.query(queryOptions)) {
|
|
64
|
-
let match = true;
|
|
65
|
-
|
|
66
|
-
// 应用所有过滤器
|
|
67
|
-
for (const filter of filters) {
|
|
68
|
-
if (!filter(entry)) {
|
|
69
|
-
match = false;
|
|
70
|
-
break;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (match) {
|
|
75
|
-
yield {
|
|
76
|
-
key: entry.key.toString(),
|
|
77
|
-
value: entry.value,
|
|
78
|
-
size: entry.value.length
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// 其他批量操作方法
|
|
85
|
-
async *putMany(
|
|
86
|
-
source: AwaitIterable<Pair>,
|
|
87
|
-
options?: AbortOptions
|
|
88
|
-
): AsyncIterable<Key> {
|
|
89
|
-
const batch = this.batch();
|
|
90
|
-
|
|
91
|
-
for await (const entry of source) {
|
|
92
|
-
const key = entry.key;
|
|
93
|
-
batch.put(key, entry.value);
|
|
94
|
-
yield key;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
await batch.commit();
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
async *getMany(
|
|
101
|
-
source: AwaitIterable<Key>,
|
|
102
|
-
options?: AbortOptions
|
|
103
|
-
): AsyncIterable<Pair> {
|
|
104
|
-
for await (const key of source) {
|
|
105
|
-
try {
|
|
106
|
-
const value = await this.get(key);
|
|
107
|
-
yield {
|
|
108
|
-
key: key,
|
|
109
|
-
value
|
|
110
|
-
};
|
|
111
|
-
} catch (err) {
|
|
112
|
-
console.error(`Error getting key ${key}:`, err);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
async *deleteMany(
|
|
118
|
-
source: AwaitIterable<Key>,
|
|
119
|
-
options?: AbortOptions
|
|
120
|
-
): AsyncIterable<Key> {
|
|
121
|
-
const batch = this.batch();
|
|
122
|
-
|
|
123
|
-
for await (const key of source) {
|
|
124
|
-
batch.delete(key);
|
|
125
|
-
yield key;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
await batch.commit();
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// 基本操作方法
|
|
132
|
-
async put(key: Key, value: Uint8Array): Promise<Key> {
|
|
133
|
-
return this.store.put(key, value);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
async get(key: Key): Promise<Uint8Array> {
|
|
137
|
-
return this.store.get(key);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
async has(key: Key): Promise<boolean> {
|
|
141
|
-
return this.store.has(key);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
async delete(key: Key): Promise<void> {
|
|
145
|
-
return this.store.delete(key);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
batch(): Batch {
|
|
149
|
-
return this.store.batch();
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
// 实现 TxnDatastoreExtended 接口的方法
|
|
154
|
-
async newTransactionExtended(
|
|
155
|
-
|
|
156
|
-
readOnly: boolean
|
|
157
|
-
): Promise<Transaction> {
|
|
158
|
-
const store = this.store;
|
|
159
|
-
// 由于 LevelDatastore 不支持原生事务,我们创建一个简单的包装器
|
|
160
|
-
const txn: Transaction = {
|
|
161
|
-
put: async ( key: Key, value: Uint8Array): Promise<Key> => {
|
|
162
|
-
if (readOnly) throw new Error('Transaction is read-only');
|
|
163
|
-
await this.store.put(key, value);
|
|
164
|
-
return key;
|
|
165
|
-
},
|
|
166
|
-
|
|
167
|
-
get: async ( key: Key): Promise<Uint8Array> => {
|
|
168
|
-
return this.store.get(key);
|
|
169
|
-
},
|
|
170
|
-
|
|
171
|
-
has: async ( key: Key): Promise<boolean> => {
|
|
172
|
-
return this.store.has(key);
|
|
173
|
-
},
|
|
174
|
-
|
|
175
|
-
delete: async ( key: Key): Promise<void> => {
|
|
176
|
-
if (readOnly) throw new Error('Transaction is read-only');
|
|
177
|
-
await this.store.delete(key);
|
|
178
|
-
return ;
|
|
179
|
-
},
|
|
180
|
-
|
|
181
|
-
query: async function*( q: Query): AsyncIterable<QueryResult> {
|
|
182
|
-
for await (const entry of store.query(q)) {
|
|
183
|
-
yield {
|
|
184
|
-
key: entry.key.toString(),
|
|
185
|
-
value: entry.value,
|
|
186
|
-
size: entry.value.length
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
}.bind(this),
|
|
190
|
-
|
|
191
|
-
queryExtended: async function*( q: QueryExt): AsyncIterable<QueryResult> {
|
|
192
|
-
const { prefix, filters = [] } = q;
|
|
193
|
-
const queryOptions: Query = {};
|
|
194
|
-
if (prefix !== undefined) {
|
|
195
|
-
queryOptions.prefix = prefix;
|
|
196
|
-
}
|
|
197
|
-
for await (const entry of store.query(queryOptions)) {
|
|
198
|
-
let match = true;
|
|
199
|
-
for (const filter of filters) {
|
|
200
|
-
if (!filter(entry)) {
|
|
201
|
-
match = false;
|
|
202
|
-
break;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
if (match) {
|
|
206
|
-
yield {
|
|
207
|
-
key: entry.key.toString(),
|
|
208
|
-
value: entry.value,
|
|
209
|
-
size: entry.value.length
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}.bind(this),
|
|
214
|
-
|
|
215
|
-
commit: async (): Promise<void> => {
|
|
216
|
-
// 由于没有实际的事务支持,这里是一个空操作
|
|
217
|
-
return Promise.resolve();
|
|
218
|
-
} ,
|
|
219
|
-
discard: async (): Promise<void> => {
|
|
220
|
-
// 由于没有实际的事务支持,这里是一个空操作
|
|
221
|
-
return Promise.resolve();
|
|
222
|
-
}
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
return txn;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
// 工厂函数
|
|
230
|
-
export function createTxnDatastore(path: string): TxnDatastoreExtended {
|
|
231
|
-
const levelStore = new LevelDatastore(path);
|
|
232
|
-
const adapter = new LevelDatastoreAdapter(levelStore);
|
|
233
|
-
return adapter;
|
|
234
|
-
|
|
235
|
-
}
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 从ReadableStream逐行读取数据的工具类
|
|
3
|
-
*/
|
|
4
|
-
export class LineReader {
|
|
5
|
-
private reader: ReadableStreamDefaultReader<Uint8Array>;
|
|
6
|
-
private textDecoder: TextDecoder;
|
|
7
|
-
private buffer: string = '';
|
|
8
|
-
private isEOF: boolean = false;
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* 创建LineReader实例
|
|
12
|
-
* @param stream 可读数据流
|
|
13
|
-
* @param encoding 文本编码(默认为'utf-8')
|
|
14
|
-
*/
|
|
15
|
-
constructor(
|
|
16
|
-
stream: ReadableStream<Uint8Array>,
|
|
17
|
-
encoding: string = 'utf-8'
|
|
18
|
-
) {
|
|
19
|
-
this.reader = stream.getReader();
|
|
20
|
-
this.textDecoder = new TextDecoder(encoding);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* 读取下一行数据
|
|
25
|
-
* @returns 返回一行数据,如果到达流末尾则返回null
|
|
26
|
-
*/
|
|
27
|
-
async readLine(): Promise<string | null> {
|
|
28
|
-
// 如果已经到达EOF且缓冲区为空,则返回null
|
|
29
|
-
if (this.isEOF && this.buffer.length === 0) {
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// 尝试从缓冲区中找到一行
|
|
34
|
-
const newlineIndex = this.buffer.indexOf('\n');
|
|
35
|
-
|
|
36
|
-
if (newlineIndex !== -1) {
|
|
37
|
-
// 找到完整行,提取并更新缓冲区
|
|
38
|
-
const line = this.buffer.substring(0, newlineIndex);
|
|
39
|
-
this.buffer = this.buffer.substring(newlineIndex + 1);
|
|
40
|
-
return line;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// 需要读取更多数据
|
|
44
|
-
if (!this.isEOF) {
|
|
45
|
-
const { value, done } = await this.reader.read();
|
|
46
|
-
|
|
47
|
-
if (done) {
|
|
48
|
-
// 流结束,返回剩余的缓冲区内容作为最后一行
|
|
49
|
-
this.isEOF = true;
|
|
50
|
-
if (this.buffer.length > 0) {
|
|
51
|
-
const lastLine = this.buffer;
|
|
52
|
-
this.buffer = '';
|
|
53
|
-
return lastLine;
|
|
54
|
-
}
|
|
55
|
-
return null;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// 将新数据添加到缓冲区并递归调用
|
|
59
|
-
this.buffer += this.textDecoder.decode(value, { stream: true });
|
|
60
|
-
return this.readLine();
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// 已到达EOF,但缓冲区还有内容
|
|
64
|
-
if (this.buffer.length > 0) {
|
|
65
|
-
const lastLine = this.buffer;
|
|
66
|
-
this.buffer = '';
|
|
67
|
-
return lastLine;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* 释放读取器资源
|
|
75
|
-
*/
|
|
76
|
-
release(): void {
|
|
77
|
-
this.reader.releaseLock();
|
|
78
|
-
}
|
|
79
|
-
}
|