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,39 +0,0 @@
1
- export async function loadBabel() {
2
- if (!(globalThis as any).process) {
3
- (globalThis as any).process = { env: {} };
4
- }
5
-
6
- const [parserMod, typesMod, traverseMod] = await Promise.all([
7
- import("@babel/parser"),
8
- import("@babel/types"),
9
- import("@babel/traverse"),
10
- ]);
11
-
12
- // 规范化 parser.parse(兼容多种打包形态)
13
- const parse =
14
- (parserMod as any).parse ??
15
- (parserMod as any).default?.parse ??
16
- (parserMod as any).default; // 有些打包器把默认导出直接设为 parse
17
-
18
- if (typeof parse !== "function") {
19
- console.error("parserMod keys:", Object.keys(parserMod));
20
- throw new Error("Failed to resolve @babel/parser.parse as a function");
21
- }
22
-
23
- // types:有的环境在 default 下
24
- const t = (typesMod as any).default ?? typesMod;
25
-
26
- // 规范化 traverse
27
- const traverse: (node: any, visitors: any) => void =
28
- (traverseMod as any).default?.default ??
29
- (traverseMod as any).default ??
30
- (traverseMod as any).traverse ??
31
- (traverseMod as any);
32
-
33
- if (typeof traverse !== "function") {
34
- console.error("traverseMod keys:", Object.keys(traverseMod));
35
- throw new Error("Failed to resolve @babel/traverse as a function");
36
- }
37
-
38
- return { parse, t, traverse };
39
- }
@@ -1,78 +0,0 @@
1
- // 领域模型基类:不包含任何存储逻辑
2
- export abstract class BaseEntity {
3
- // 默认元字段
4
- public dc_timestamp?: number; // 毫秒时间戳
5
- public dc_opuser?: string; // 操作人
6
-
7
- constructor() {
8
- // 时间戳,opuser 留空,主要用于从dc取回数据时填充
9
-
10
- }
11
-
12
- // 可重写以自定义主键策略
13
- protected getPrimaryKey(): string {
14
- const anySelf = this as any;
15
- const id = anySelf.id ?? anySelf.key ?? anySelf.pk;
16
-
17
- // 仅判 null/undefined,为 0 的数字是合法主键
18
- if (id === null || id === undefined) {
19
- throw new Error(`${this.constructor.name}: primary key (id/key/pk) is required`);
20
- }
21
-
22
- if (typeof id === 'string') {
23
- const s = id.trim();
24
- if (s.length === 0) {
25
- throw new Error(`${this.constructor.name}: primary key (string) cannot be empty`);
26
- }
27
- return s;
28
- }
29
-
30
- if (typeof id === 'number') {
31
- if (Number.isNaN(id)) {
32
- throw new Error(`${this.constructor.name}: primary key (number) cannot be NaN`);
33
- }
34
- return String(id);
35
- }
36
-
37
- if (typeof id === 'bigint') {
38
- return id.toString();
39
- }
40
-
41
- // 其它类型统一转字符串(如需自定义请在子类中重写)
42
- return String(id);
43
- }
44
-
45
- // 标记更新时间与操作人
46
- touch(opuser?: string, timeMs: number = Date.now()): this {
47
- this.dc_timestamp = timeMs;
48
- if (opuser !== undefined) this.dc_opuser = opuser;
49
- return this;
50
- }
51
-
52
- // 设置操作人
53
- setOpUser(opuser: string): this {
54
- this.dc_opuser = opuser;
55
- return this;
56
- }
57
-
58
- // 可选:领域校验(子类覆盖)
59
- validate(): void {
60
- // no-op by default
61
- }
62
-
63
- // 工厂:从 PlainObject 创建实体
64
- static from<T extends BaseEntity>(this: new () => T, data: Partial<T>): T {
65
- const inst = new this();
66
- Object.assign(inst, data);
67
- return inst;
68
- }
69
-
70
- // 导出为可序列化对象(可覆写以裁剪敏感字段)
71
- toJSON(): Record<string, unknown> {
72
- const out: Record<string, unknown> = {};
73
- for (const k of Object.keys(this as any)) {
74
- (out as any)[k] = (this as any)[k];
75
- }
76
- return out;
77
- }
78
- }
@@ -1,414 +0,0 @@
1
- import { Direction } from "../common/define";
2
- import type { IKeyValueOperations } from "../interfaces/keyvalue-interface";
3
- import type { KeyValueDB } from "../implements/keyvalue/manager";
4
- import { metadata } from "./decorator_factory";
5
- import { BaseEntity } from "./base_entity";
6
-
7
- type Ctor<T> = new (...args: any[]) => T;
8
-
9
- const EXTRA_SEP = "$$$dckv_extra$$$";
10
-
11
- function extractRawValue(s: string): [string, string] {
12
- const i = s.indexOf(EXTRA_SEP);
13
- return i >= 0 ? [s.slice(0, i), s.slice(i + EXTRA_SEP.length)] : [s, ""];
14
- }
15
-
16
- function safeParseJSON<T>(s: string | null): T | null {
17
- if (!s) return null;
18
- try { return JSON.parse(s) as T; } catch { return null; }
19
- }
20
-
21
-
22
-
23
-
24
- // 兼容 getWithIndex 返回的两种格式(string[] 或 Record<string,string>[])
25
- function parseIndexResultValues(raw: string): string[] {
26
- const parsed = safeParseJSON<any>(raw);
27
- if (!Array.isArray(parsed)) return [];
28
- const out: string[] = [];
29
- for (const item of parsed) {
30
- if (typeof item === "string") {
31
- out.push(item);
32
- } else if (item && typeof item === "object") {
33
- for (const v of Object.values(item)) {
34
- if (v != null) out.push(String(v));
35
- }
36
- }
37
- }
38
- return out;
39
- }
40
-
41
- function maybeStripKeyPrefix(s: string): string {
42
- const t = s.trimStart();
43
- const i = t.indexOf(":");
44
- if (i > 0 && i < 64 && t[0] !== "{" && t[0] !== "[" && t[0] !== "\"") {
45
- return t.slice(i + 1).trim();
46
- }
47
- return s;
48
- }
49
-
50
-
51
-
52
- // 将列声明类型与实际值映射到 KV 可识别的索引类型和值
53
- function asIndexTypeAndValue(value: unknown, declaredType?: string): { type: string; value: string } {
54
- const t = declaredType ?? (value instanceof Date ? "date" : typeof value);
55
- switch (t) {
56
- case "date":
57
- return { type: "number", value: String(value instanceof Date ? value.getTime() : Number(value)) };
58
- case "boolean":
59
- return { type: "number", value: String(value ? 1 : 0) };
60
- case "number":
61
- return { type: "number", value: String(value ?? 0) };
62
- case "json":
63
- return { type: "json", value: JSON.stringify(value) };
64
- default:
65
- return { type: "string", value: String(value ?? "") };
66
- }
67
- }
68
-
69
- function buildIndexPayload(entity: object, ctor: Function): string {
70
- const cols = metadata.getColumns(ctor);
71
- const colTypeByName = new Map<string, string>();
72
- cols.forEach(c => {
73
- if (c.options?.type) colTypeByName.set(c.resolvedName, c.options.type);
74
- });
75
-
76
- const idxMetas = metadata.getIndexes(ctor);
77
- const items: Array<{ key: string; type: string; value: string }> = [];
78
-
79
- for (const idx of idxMetas) {
80
- if (!idx.fields.length) continue;
81
-
82
- if (idx.fields.length === 1) {
83
- const [first] = idx.fields;
84
- if (!first) continue;
85
- const f = first.field;
86
- const raw = (entity as any)[f];
87
- const { type, value } = asIndexTypeAndValue(raw, colTypeByName.get(f));
88
- // 单列索引用字段名作为索引键
89
- items.push({ key: f, type, value });
90
- } else {
91
- // 复合索引:索引名作为 key,值为字段值数组的 JSON,类型 json
92
- const key = idx.name;
93
- const tuple = idx.fields.map(ff => (entity as any)[ff.field]);
94
- items.push({ key, type: "json", value: JSON.stringify(tuple) });
95
- }
96
- }
97
-
98
- return JSON.stringify(items);
99
- }
100
-
101
- export function composeCompositeIndexValue(values: unknown[]): string {
102
- // 用于复合索引查询:indexValue 需为 JSON 数组字符串
103
- return JSON.stringify(values);
104
- }
105
-
106
- export type FindIndexOptions = {
107
- type?: "string" | "number" | "boolean" | "date" | "json" | "binary";
108
- limit?: number;
109
- seekKey?: string;
110
- direction?: Direction; //Direction.Forward(升序) | Direction.Reverse(降序);
111
- offset?: number;
112
- vaccount?: string;
113
- };
114
-
115
- export type FindValuesOptions = {
116
- limit?: number;
117
- seekKey?: string;
118
- direction?: Direction;//Direction.Forward(升序) | Direction.Reverse(降序);
119
- offset?: number;
120
- vaccount?: string;
121
- };
122
-
123
- type Operator = "=" | ">" | "<" | ">=" | "<=" | "!=";
124
-
125
- interface WhereCond {
126
- field: string;
127
- operator: Operator;
128
- value: any;
129
- }
130
-
131
- function toIndexQuery(
132
- cond: WhereCond
133
- ): { indexKey: string; indexValue: string; options: FindIndexOptions; fullScan?: boolean } {
134
- const { field, operator, value } = cond;
135
- let direction: Direction | undefined;
136
- let seekKey: string | undefined;
137
- let limit: number | undefined;
138
-
139
- switch (operator) {
140
- case "=":
141
- return {
142
- indexKey: field,
143
- indexValue: String(value),
144
- options: {}
145
- };
146
- case ">":
147
- direction = Direction.Forward;
148
- seekKey = String(value);
149
- limit = 1000;
150
- break;
151
- case ">=":
152
- direction = Direction.Forward;
153
- seekKey = String(value);
154
- limit = 1000;
155
- break;
156
- case "<":
157
- direction = Direction.Reverse;
158
- seekKey = String(value);
159
- limit = 1000;
160
- break;
161
- case "<=":
162
- direction = Direction.Reverse;
163
- seekKey = String(value);
164
- limit = 1000;
165
- break;
166
- case "!=":
167
- // 需要全量拉取
168
- return {
169
- indexKey: "",
170
- indexValue: "",
171
- options: {},
172
- fullScan: true
173
- };
174
- default:
175
- throw new Error("不支持的操作符: " + operator);
176
- }
177
-
178
- return {
179
- indexKey: field,
180
- indexValue: "",
181
- options: {
182
- direction,
183
- seekKey,
184
- limit
185
- }
186
- };
187
- }
188
- // 支持 "field>=value" 这种字符串解析
189
- function parseWhereString(whereStr: string): { field: string, operator: Operator, value: any } {
190
- // 支持 >=, <=, >, <, =, !=
191
- const m = whereStr.match(/^(\w+)\s*(>=|<=|=|>|<|!=)\s*(.+)$/);
192
- if (!m) throw new Error("不支持的查询字符串格式: " + whereStr);
193
- // 明确断言为 string,保证类型安全
194
- const field = m[1] as string;
195
- const operator = m[2] as Operator;
196
- const value = m[3] as string;
197
- return { field, operator, value };
198
- }
199
-
200
-
201
- function sanitizeGetWithIndexOptions(options: FindIndexOptions): { type?: string; limit?: number; seekKey?: string; direction?: Direction; offset?: number } {
202
- return {
203
- ...(options.type !== undefined ? { type: options.type } : {}),
204
- ...(options.limit !== undefined ? { limit: options.limit } : {}),
205
- ...(options.seekKey !== undefined ? { seekKey: options.seekKey } : {}),
206
- ...(options.direction !== undefined ? { direction: options.direction } : {}),
207
- ...(options.offset !== undefined ? { offset: options.offset } : {}),
208
- };
209
- }
210
-
211
- function sanitizeGetValuesOptions(options: FindValuesOptions): { limit?: number; seekKey?: string; direction?: Direction; offset?: number } {
212
- return {
213
- ...(options.limit !== undefined ? { limit: options.limit } : {}),
214
- ...(options.seekKey !== undefined ? { seekKey: options.seekKey } : {}),
215
- ...(options.direction !== undefined ? { direction: options.direction } : {}),
216
- ...(options.offset !== undefined ? { offset: options.offset } : {}),
217
- };
218
- }
219
-
220
-
221
-
222
- // 通用仓储:承载所有持久化与查询逻辑
223
- export class EntityRepository<T extends BaseEntity> {
224
- constructor(
225
- private readonly entityCtor: Ctor<T>,
226
- private readonly ops: IKeyValueOperations,
227
- private readonly db: KeyValueDB
228
- ) {}
229
-
230
- // 保存实体(写入并附带索引)
231
- async save(entity: T, vaccount?: string): Promise<number> {
232
- entity.validate();
233
- const key= (entity as any).getPrimaryKey();
234
- //移除dc_timestamp和dc_opuser字段,由dc节点自动维护
235
- delete (entity as any).dc_timestamp;
236
- delete (entity as any).dc_opuser;
237
- const value = JSON.stringify(entity.toJSON());
238
- const indexs = buildIndexPayload(entity, this.entityCtor);
239
-
240
- const [ok,resTimestamp, err] = await this.ops.set(this.db, key, value, indexs, vaccount);
241
- if (err) throw err;
242
- if (!ok) throw new Error(`${this.entityCtor.name}.save failed`);
243
- entity.dc_timestamp = resTimestamp ? resTimestamp : 0; // 设置时间戳
244
- return entity.dc_timestamp;
245
- }
246
-
247
-
248
- async deleteById(id: string, vaccount?: string): Promise<void> {
249
- const key = id;
250
- const [ok,_ ,err] = await this.ops.set(this.db, key, "","", vaccount); // 空值用于标记删除
251
- if (err) throw err;
252
- if (!ok) throw new Error(`${this.entityCtor.name}.deleteById failed`);
253
- }
254
-
255
- // 局部更新(按 id 合并字段后保存)
256
- async update(id: string, patch: Partial<T>, vaccount?: string): Promise<T | null> {
257
- const key = id;
258
- const [curr, err] = await this.ops.getValueSetByCurrentUser(this.db, key, vaccount);
259
- if (err || !curr) return null;
260
- const [json, extra] = extractRawValue(curr);
261
- const obj = safeParseJSON<any>(json);
262
- if (!obj) return null;
263
- if (extra) {
264
- const extraObj = safeParseJSON<any>(extra);
265
- if (extraObj) Object.assign(obj, extraObj);
266
- }
267
- const inst = new this.entityCtor();
268
- Object.assign(inst, obj);
269
- Object.assign(inst as any, patch);
270
- const resTimestamp = await this.save(inst, vaccount);
271
- inst.dc_timestamp = resTimestamp;
272
- return inst;
273
- }
274
-
275
-
276
-
277
- async query(
278
- where: WhereCond | string,
279
- options: FindIndexOptions = {}
280
- ): Promise<T[]> {
281
- let cond: WhereCond;
282
- if (typeof where === "string") {
283
- cond = parseWhereString(where);
284
- } else {
285
- cond = where;
286
- }
287
-
288
- const { indexKey, indexValue, options: indexOptions, fullScan } = toIndexQuery(cond);
289
- const mergedOptions = { ...indexOptions, ...options };
290
-
291
- let list: T[];
292
- if (fullScan) {
293
- // 全量拉取
294
- list = await this.find();
295
- } else {
296
- list = await this.findByIndex(indexKey, indexValue, mergedOptions);
297
- }
298
-
299
- const { field, operator, value } = cond;
300
- const filtered = list.filter(obj => {
301
- const v = (obj as any)[field];
302
- switch (operator) {
303
- case "=": return v == value;
304
- case "!=": return v != value;
305
- case ">": return v > value;
306
- case "<": return v < value;
307
- case ">=": return v >= value;
308
- case "<=": return v <= value;
309
- default: return false;
310
- }
311
- });
312
-
313
- return filtered;
314
- }
315
-
316
- // 获取
317
- async find( options: FindIndexOptions = {}): Promise<T[]> {
318
- return this.getValues("", options);
319
- }
320
-
321
- // 通过 id 获取
322
- async findById(id: string, writerPubkey?: string, vaccount?: string): Promise<T | null> {
323
- const key = id;
324
- const [raw, err] = await this.ops.get(this.db, key, writerPubkey, vaccount);
325
- if (err || !raw) return null;
326
-
327
- const [json, extra] = extractRawValue(raw);
328
- const obj = safeParseJSON<any>(json);
329
- if (!obj) return null;
330
- if (extra) {
331
- const extraObj = safeParseJSON<any>(extra);
332
- if (extraObj) Object.assign(obj, extraObj);
333
- }
334
-
335
-
336
- const inst = new this.entityCtor();
337
- Object.assign(inst, obj);
338
- return inst;
339
- }
340
-
341
-
342
-
343
-
344
- // 通过索引查询(单字段:indexKey=字段名;复合:indexKey=索引名,indexValue=JSON数组字符串)
345
- async findByIndex(indexKey: string, indexValue: string, options: FindIndexOptions = {}): Promise<T[]> {
346
- const [raw, err] = await this.ops.getWithIndex(
347
- this.db,
348
- indexKey,
349
- indexValue,
350
- sanitizeGetWithIndexOptions(options),
351
- options.vaccount
352
- );
353
- if (err || !raw) return [];
354
-
355
- const values = parseIndexResultValues(raw);
356
- const out: T[] = [];
357
- for (let val of values) {
358
- // 兼容老格式 "key:value";新格式是纯 value,不会命中
359
- val = maybeStripKeyPrefix(val);
360
-
361
- const [json, extra] = extractRawValue(val);
362
- const obj = safeParseJSON<any>(json);
363
- if (!obj) continue;
364
- if (extra) {
365
- const extraObj = safeParseJSON<any>(extra);
366
- if (extraObj) Object.assign(obj, extraObj);
367
- }
368
- const inst = new this.entityCtor();
369
- Object.assign(inst, obj);
370
- out.push(inst);
371
- }
372
- return out;
373
- }
374
-
375
- async findOneByIndex(indexKey: string, indexValue: string, options: Omit<FindIndexOptions, "limit"> = {}): Promise<T | null> {
376
- const list = await this.findByIndex(indexKey, indexValue, { ...options, limit: 1 });
377
- return list[0] ?? null;
378
- }
379
-
380
- // 按键前缀遍历(用于分页场景)
381
- async getValues(keyPrefix: string, options: FindValuesOptions = {}): Promise<T[]> {
382
- const [raw, err] = await this.ops.getValues(
383
- this.db,
384
- keyPrefix,
385
- sanitizeGetValuesOptions(options),
386
- options.vaccount
387
- );
388
- if (err || !raw) return [];
389
-
390
- const list = safeParseJSON<string[]>(raw) ?? [];
391
- const out: T[] = [];
392
- for (const item of list) {
393
- let itemValue = String(item);
394
- if (typeof item !== "string") {
395
- //是{key: value}格式,取出value
396
- for (const [_, v] of Object.entries(item)) {
397
- itemValue = String(v);
398
- break;
399
- }
400
- }
401
- const [v,extra] = extractRawValue(itemValue);
402
- const obj = safeParseJSON<any>(v);
403
- if (!obj) continue;
404
- if (extra) {
405
- const extraObj = safeParseJSON<any>(extra);
406
- if (extraObj) Object.assign(obj, extraObj);
407
- }
408
- const inst = new this.entityCtor();
409
- Object.assign(inst, obj);
410
- out.push(inst);
411
- }
412
- return out;
413
- }
414
- }