web-dc-api 0.1.5 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +1 -1
- package/dist/dc.min.js +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/index.d.ts +934 -878
- package/package.json +4 -8
- package/dist/cjs/helia-core-B1Xqha7a.js +0 -1
- package/dist/cjs/helia-core-D8Uv1KjQ.js +0 -1
- package/dist/cjs/polkadot-api-7PhQf3ws.js +0 -1
- package/dist/cjs/polkadot-api-CtrJVWuZ.js +0 -1
- package/dist/esm/chunks/helia-core-BxMqyK2Y.js +0 -1
- package/dist/esm/chunks/helia-core-DMXRpcO-.js +0 -1
- package/dist/esm/chunks/polkadot-api-5Y9Bw8VT.js +0 -1
- package/dist/esm/chunks/polkadot-api-D69Ioun_.js +0 -1
- package/lib/common/blowfish/block.ts +0 -259
- package/lib/common/blowfish/cipher.ts +0 -144
- package/lib/common/blowfish/const.ts +0 -195
- package/lib/common/chain.ts +0 -469
- package/lib/common/commonclient.ts +0 -202
- package/lib/common/constants.ts +0 -55
- package/lib/common/dc-key/ed25519.ts +0 -343
- package/lib/common/dc-key/keyManager.ts +0 -424
- package/lib/common/dcapi.ts +0 -98
- package/lib/common/dcutil.ts +0 -627
- package/lib/common/define.ts +0 -70
- package/lib/common/error.ts +0 -67
- package/lib/common/grpc-dc.ts +0 -104
- package/lib/common/module-system.ts +0 -184
- package/lib/common/service-worker.ts +0 -234
- package/lib/common/types/types.ts +0 -344
- package/lib/dc.ts +0 -701
- package/lib/implements/account/client.ts +0 -185
- package/lib/implements/account/manager.ts +0 -683
- package/lib/implements/aiproxy/client.ts +0 -357
- package/lib/implements/aiproxy/manager.ts +0 -670
- package/lib/implements/cache/client.ts +0 -105
- package/lib/implements/cache/manager.ts +0 -127
- package/lib/implements/comment/client.ts +0 -982
- package/lib/implements/comment/manager.ts +0 -1151
- package/lib/implements/dc/client.ts +0 -51
- package/lib/implements/dc/manager.ts +0 -33
- package/lib/implements/file/client.ts +0 -253
- package/lib/implements/file/file-cache-manager.ts +0 -142
- package/lib/implements/file/manager.ts +0 -1240
- package/lib/implements/file/seekableFileStream.ts +0 -344
- package/lib/implements/file/streamwriter.ts +0 -322
- package/lib/implements/keyvalue/client.ts +0 -376
- package/lib/implements/keyvalue/manager.ts +0 -759
- package/lib/implements/message/client.ts +0 -250
- package/lib/implements/message/manager.ts +0 -215
- package/lib/implements/threaddb/cbor/coding.ts +0 -62
- package/lib/implements/threaddb/cbor/event.ts +0 -336
- package/lib/implements/threaddb/cbor/node.ts +0 -542
- package/lib/implements/threaddb/cbor/record.ts +0 -398
- package/lib/implements/threaddb/common/AsyncMutex.ts +0 -24
- package/lib/implements/threaddb/common/addrinfo.ts +0 -135
- package/lib/implements/threaddb/common/dispatcher.ts +0 -81
- package/lib/implements/threaddb/common/idbstore-adapter.ts +0 -260
- package/lib/implements/threaddb/common/json-patcher.ts +0 -204
- package/lib/implements/threaddb/common/key.ts +0 -290
- package/lib/implements/threaddb/common/level-adapter.ts +0 -235
- package/lib/implements/threaddb/common/lineReader.ts +0 -79
- package/lib/implements/threaddb/common/logstore.ts +0 -215
- package/lib/implements/threaddb/common/transformed-datastore.ts +0 -308
- package/lib/implements/threaddb/core/app.ts +0 -206
- package/lib/implements/threaddb/core/core.ts +0 -230
- package/lib/implements/threaddb/core/db.ts +0 -249
- package/lib/implements/threaddb/core/event.ts +0 -54
- package/lib/implements/threaddb/core/head.ts +0 -89
- package/lib/implements/threaddb/core/identity.ts +0 -171
- package/lib/implements/threaddb/core/logstore.ts +0 -137
- package/lib/implements/threaddb/core/options.ts +0 -14
- package/lib/implements/threaddb/core/record.ts +0 -54
- package/lib/implements/threaddb/db/collection.ts +0 -1910
- package/lib/implements/threaddb/db/db.ts +0 -698
- package/lib/implements/threaddb/db/json2Query.ts +0 -192
- package/lib/implements/threaddb/db/query.ts +0 -524
- package/lib/implements/threaddb/dbclient.ts +0 -543
- package/lib/implements/threaddb/dbmanager.ts +0 -1906
- package/lib/implements/threaddb/lsstoreds/addr_book.ts +0 -549
- package/lib/implements/threaddb/lsstoreds/cache.ts +0 -36
- package/lib/implements/threaddb/lsstoreds/cyclic_batch.ts +0 -87
- package/lib/implements/threaddb/lsstoreds/global.ts +0 -151
- package/lib/implements/threaddb/lsstoreds/headbook.ts +0 -373
- package/lib/implements/threaddb/lsstoreds/keybook.ts +0 -297
- package/lib/implements/threaddb/lsstoreds/logstore.ts +0 -29
- package/lib/implements/threaddb/lsstoreds/metadata.ts +0 -223
- package/lib/implements/threaddb/net/define.ts +0 -149
- package/lib/implements/threaddb/net/grpcClient.ts +0 -589
- package/lib/implements/threaddb/net/grpcserver.ts +0 -146
- package/lib/implements/threaddb/net/net.ts +0 -2047
- package/lib/implements/threaddb/pb/lstore.proto +0 -38
- package/lib/implements/threaddb/pb/lstore.ts +0 -393
- package/lib/implements/threaddb/pb/lstore_pb.d.ts +0 -433
- package/lib/implements/threaddb/pb/lstore_pb.js +0 -1085
- package/lib/implements/threaddb/pb/net.proto +0 -194
- package/lib/implements/threaddb/pb/net_pb.d.ts +0 -2349
- package/lib/implements/threaddb/pb/net_pb.js +0 -5525
- package/lib/implements/threaddb/pb/proto-custom-types.ts +0 -212
- package/lib/implements/util/client.ts +0 -72
- package/lib/implements/util/manager.ts +0 -146
- package/lib/implements/wallet/manager.ts +0 -671
- package/lib/index.ts +0 -57
- package/lib/interfaces/DCContext.ts +0 -51
- package/lib/interfaces/aiproxy-interface.ts +0 -145
- package/lib/interfaces/auth-interface.ts +0 -118
- package/lib/interfaces/cache-interface.ts +0 -22
- package/lib/interfaces/client-interface.ts +0 -11
- package/lib/interfaces/comment-interface.ts +0 -167
- package/lib/interfaces/components/news-component.ts +0 -0
- package/lib/interfaces/database-interface.ts +0 -169
- package/lib/interfaces/file-interface.ts +0 -120
- package/lib/interfaces/index.ts +0 -10
- package/lib/interfaces/keyvalue-interface.ts +0 -156
- package/lib/interfaces/message-interface.ts +0 -22
- package/lib/interfaces/util-interface.ts +0 -31
- package/lib/modules/aiproxy-module.ts +0 -246
- package/lib/modules/auth-module.ts +0 -753
- package/lib/modules/cache-module.ts +0 -99
- package/lib/modules/client-module.ts +0 -71
- package/lib/modules/comment-module.ts +0 -429
- package/lib/modules/components/news-components.ts +0 -390
- package/lib/modules/database-module.ts +0 -598
- package/lib/modules/file-module.ts +0 -291
- package/lib/modules/index.ts +0 -13
- package/lib/modules/keyvalue-module.ts +0 -379
- package/lib/modules/message-module.ts +0 -107
- package/lib/modules/util-module.ts +0 -148
- package/lib/polyfills/process-env-browser.ts +0 -1
- package/lib/proto/datasource.ts +0 -93
- package/lib/proto/dcnet.proto +0 -1601
- package/lib/proto/dcnet_proto.d.ts +0 -22857
- package/lib/proto/dcnet_proto.js +0 -55204
- package/lib/proto/dcnet_proto_sparse.js +0 -55166
- package/lib/proto/oidfetch.proto +0 -25
- package/lib/proto/oidfetch_proto.d.ts +0 -585
- package/lib/proto/oidfetch_proto.js +0 -1247
- package/lib/serverless/babel-browser.ts +0 -39
- package/lib/serverless/base_entity.ts +0 -78
- package/lib/serverless/base_repository.ts +0 -414
- package/lib/serverless/browser_schema_extractor.ts +0 -283
- package/lib/serverless/decorator_factory.ts +0 -322
- package/lib/util/BrowserLineReader.ts +0 -73
- package/lib/util/base64.ts +0 -105
- package/lib/util/bcrypt.ts +0 -206
- package/lib/util/curve25519Encryption.ts +0 -418
- package/lib/util/dccrypt.ts +0 -73
- package/lib/util/logger.ts +0 -104
- package/lib/util/utils.ts +0 -289
|
@@ -1,283 +0,0 @@
|
|
|
1
|
-
import "../polyfills/process-env-browser";
|
|
2
|
-
import type { NodePath, Visitor } from "@babel/traverse";
|
|
3
|
-
import type * as T from "@babel/types";
|
|
4
|
-
import { loadBabel } from "./babel-browser";
|
|
5
|
-
|
|
6
|
-
export type PrintableSchema = {
|
|
7
|
-
entityName: string;
|
|
8
|
-
namespace?: string;
|
|
9
|
-
ttlSeconds?: number;
|
|
10
|
-
versioned?: boolean;
|
|
11
|
-
columns: Array<{
|
|
12
|
-
name: string;
|
|
13
|
-
type?: string;
|
|
14
|
-
required?: boolean;
|
|
15
|
-
unique?: boolean;
|
|
16
|
-
index?: boolean;
|
|
17
|
-
default?: unknown;
|
|
18
|
-
}>;
|
|
19
|
-
indexes: Array<{
|
|
20
|
-
name: string;
|
|
21
|
-
fields: Array<{ field: string; order: "asc" | "desc" }>;
|
|
22
|
-
unique?: boolean;
|
|
23
|
-
ttlSeconds?: number;
|
|
24
|
-
}>;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
interface FileContentMap {
|
|
28
|
-
[fileName: string]: string;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export async function extractSchemasFromSources(sources: FileContentMap): Promise<PrintableSchema[]> {
|
|
32
|
-
const { parse, t, traverse } = await loadBabel();
|
|
33
|
-
const result: PrintableSchema[] = [];
|
|
34
|
-
|
|
35
|
-
// 解析源码(优先标准装饰器,失败回退 legacy)
|
|
36
|
-
function tryParse(code: string) {
|
|
37
|
-
const common = {
|
|
38
|
-
sourceType: "module" as const,
|
|
39
|
-
errorRecovery: true,
|
|
40
|
-
plugins: ["typescript"] as any[],
|
|
41
|
-
};
|
|
42
|
-
try {
|
|
43
|
-
return parse(code, {
|
|
44
|
-
...common,
|
|
45
|
-
plugins: [
|
|
46
|
-
["decorators", { decoratorsBeforeExport: true }],
|
|
47
|
-
"classProperties",
|
|
48
|
-
"classPrivateProperties",
|
|
49
|
-
...common.plugins,
|
|
50
|
-
],
|
|
51
|
-
} as any);
|
|
52
|
-
} catch {
|
|
53
|
-
return parse(code, {
|
|
54
|
-
...common,
|
|
55
|
-
plugins: [
|
|
56
|
-
"decorators-legacy",
|
|
57
|
-
"classProperties",
|
|
58
|
-
"classPrivateProperties",
|
|
59
|
-
...common.plugins,
|
|
60
|
-
],
|
|
61
|
-
} as any);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// 将装饰器参数表达式转 JS 值(常见字面量/对象/数组)
|
|
66
|
-
function exprToValue(node: any): any {
|
|
67
|
-
if (!node) return undefined;
|
|
68
|
-
if (t.isStringLiteral(node) || t.isNumericLiteral(node) || t.isBooleanLiteral(node)) return (node as any).value;
|
|
69
|
-
if (t.isNullLiteral(node)) return null;
|
|
70
|
-
if (t.isIdentifier(node) && (node.name === "undefined")) return undefined;
|
|
71
|
-
if (t.isObjectExpression(node)) {
|
|
72
|
-
const obj: any = {};
|
|
73
|
-
for (const p of node.properties) {
|
|
74
|
-
if (t.isObjectProperty(p)) {
|
|
75
|
-
const key = t.isIdentifier(p.key) ? p.key.name : t.isStringLiteral(p.key) ? p.key.value : undefined;
|
|
76
|
-
if (!key) continue;
|
|
77
|
-
obj[key] = exprToValue(p.value as any);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
return obj;
|
|
81
|
-
}
|
|
82
|
-
if (t.isArrayExpression(node)) return node.elements.map((e: any) => exprToValue(e ));
|
|
83
|
-
return undefined;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// 规范化索引字段
|
|
87
|
-
function normIndexFields(fields: any, fallbackField?: string): Array<{ field: string; order: "asc" | "desc" }> {
|
|
88
|
-
const out: Array<{ field: string; order: "asc" | "desc" }> = [];
|
|
89
|
-
const arr = Array.isArray(fields) ? fields : (fields ? [fields] : []);
|
|
90
|
-
if (arr.length === 0 && fallbackField) return [{ field: fallbackField, order: "asc" }];
|
|
91
|
-
for (const it of arr) {
|
|
92
|
-
if (typeof it === "string") out.push({ field: it, order: "asc" });
|
|
93
|
-
else if (it && typeof it === "object" && typeof it.field === "string") {
|
|
94
|
-
out.push({ field: it.field, order: it.order === "desc" ? "desc" : "asc" });
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return out;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// 默认索引名
|
|
101
|
-
function defaultIndexName(fields: Array<{ field: string; order: "asc" | "desc" }>) {
|
|
102
|
-
const seg = fields.map(f => f.field + (f.order === "desc" ? "_desc" : "")).join("_");
|
|
103
|
-
return `idx_${seg}`;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// 去重 key
|
|
107
|
-
function indexKey(name: string | undefined, fields: Array<{ field: string; order: "asc" | "desc" }>) {
|
|
108
|
-
const seg = fields.map(f => `${f.field}:${f.order}`).join(",");
|
|
109
|
-
return `${name ?? defaultIndexName(fields)}|${seg}`;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// 装饰器名/参数
|
|
113
|
-
function getDecoratorName(dec: any): string | undefined {
|
|
114
|
-
const ex = dec.expression;
|
|
115
|
-
if (t.isIdentifier(ex)) return ex.name;
|
|
116
|
-
if (t.isCallExpression(ex) && t.isIdentifier(ex.callee)) return ex.callee.name;
|
|
117
|
-
return undefined;
|
|
118
|
-
}
|
|
119
|
-
function getDecoratorArgs(dec: any): any[] {
|
|
120
|
-
const ex = dec.expression;
|
|
121
|
-
if (t.isCallExpression(ex)) return ex.arguments.map((arg: any) => exprToValue(arg as any));
|
|
122
|
-
return [];
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// 统一处理类(ClassDeclaration / ClassExpression)
|
|
126
|
-
const visitClass = (path: NodePath<T.ClassDeclaration | T.ClassExpression>) => {
|
|
127
|
-
const node = path.node as any;
|
|
128
|
-
const className = (node.id && node.id.name) || "AnonymousClass";
|
|
129
|
-
const decorators: any[] = node.decorators ?? [];
|
|
130
|
-
|
|
131
|
-
// 解析 @Entity
|
|
132
|
-
let entityName = className;
|
|
133
|
-
let entityOpts: any = {};
|
|
134
|
-
for (const d of decorators) {
|
|
135
|
-
const name = getDecoratorName(d);
|
|
136
|
-
if (name === "Entity") {
|
|
137
|
-
const [opt] = getDecoratorArgs(d);
|
|
138
|
-
if (opt && typeof opt === "object") {
|
|
139
|
-
entityOpts = opt;
|
|
140
|
-
if (typeof opt.name === "string") entityName = opt.name;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// 字段与字段级装饰器
|
|
146
|
-
const columns: PrintableSchema["columns"] = [];
|
|
147
|
-
const fieldLevelIndexes: PrintableSchema["indexes"] = [];
|
|
148
|
-
|
|
149
|
-
for (const m of node.body.body as any[]) {
|
|
150
|
-
const isClassProp = (t as any).isClassProperty?.(m) || (t as any).isPropertyDefinition?.(m);
|
|
151
|
-
const isPrivateProp = (t as any).isClassPrivateProperty?.(m);
|
|
152
|
-
if (!isClassProp && !isPrivateProp) continue;
|
|
153
|
-
|
|
154
|
-
const keyNode = m.key;
|
|
155
|
-
const key =
|
|
156
|
-
t.isIdentifier(keyNode) ? keyNode.name :
|
|
157
|
-
t.isStringLiteral(keyNode) ? keyNode.value :
|
|
158
|
-
undefined;
|
|
159
|
-
if (!key) continue;
|
|
160
|
-
|
|
161
|
-
let columnOpts: any | undefined = undefined;
|
|
162
|
-
const explicitIndexFromDecorator: any[] = [];
|
|
163
|
-
const mDecos: any[] = m.decorators ?? [];
|
|
164
|
-
|
|
165
|
-
for (const d of mDecos) {
|
|
166
|
-
const dn = getDecoratorName(d);
|
|
167
|
-
const args = getDecoratorArgs(d);
|
|
168
|
-
if (dn === "Column") {
|
|
169
|
-
columnOpts = args[0] && typeof args[0] === "object" ? args[0] : {};
|
|
170
|
-
} else if (dn === "Index") {
|
|
171
|
-
explicitIndexFromDecorator.push(args);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const resolvedName = (columnOpts?.name as string) ?? key;
|
|
176
|
-
columns.push({
|
|
177
|
-
name: resolvedName,
|
|
178
|
-
...(columnOpts?.type !== undefined ? { type: columnOpts.type } : {}),
|
|
179
|
-
...(columnOpts?.required !== undefined ? { required: !!columnOpts.required } : {}),
|
|
180
|
-
...(columnOpts?.unique !== undefined ? { unique: !!columnOpts.unique } : {}),
|
|
181
|
-
...(columnOpts?.index !== undefined ? { index: !!columnOpts.index } : {}),
|
|
182
|
-
...(columnOpts?.default !== undefined ? { default: columnOpts.default } : {}),
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
// Column 的 index/unique → 单列索引
|
|
186
|
-
if (columnOpts?.index || columnOpts?.unique) {
|
|
187
|
-
const fields = [{ field: resolvedName, order: "asc" as const }];
|
|
188
|
-
fieldLevelIndexes.push({
|
|
189
|
-
name: defaultIndexName(fields),
|
|
190
|
-
fields,
|
|
191
|
-
...(columnOpts?.unique ? { unique: true } : {}),
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// 字段级 @Index
|
|
196
|
-
for (const args of explicitIndexFromDecorator) {
|
|
197
|
-
let idxName: string | undefined;
|
|
198
|
-
let idxFields: any;
|
|
199
|
-
let idxUnique: boolean | undefined;
|
|
200
|
-
let idxTTL: number | undefined;
|
|
201
|
-
if (args.length === 0) {
|
|
202
|
-
idxFields = [resolvedName];
|
|
203
|
-
} else if (typeof args[0] === "string") {
|
|
204
|
-
idxName = args[0];
|
|
205
|
-
idxFields = args[1] ?? [resolvedName];
|
|
206
|
-
} else if (typeof args[0] === "object") {
|
|
207
|
-
idxName = args[0].name;
|
|
208
|
-
idxFields = args[0].fields ?? [resolvedName];
|
|
209
|
-
idxUnique = args[0].unique;
|
|
210
|
-
idxTTL = args[0].ttlSeconds;
|
|
211
|
-
}
|
|
212
|
-
const fields = normIndexFields(idxFields, resolvedName);
|
|
213
|
-
if (fields.length === 0) continue;
|
|
214
|
-
const name2 = idxName ?? defaultIndexName(fields);
|
|
215
|
-
fieldLevelIndexes.push({
|
|
216
|
-
name: name2,
|
|
217
|
-
fields,
|
|
218
|
-
...(idxUnique !== undefined ? { unique: !!idxUnique } : {}),
|
|
219
|
-
...(idxTTL !== undefined ? { ttlSeconds: idxTTL } : {}),
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// 类级 @Index
|
|
225
|
-
const classLevelIndexes: PrintableSchema["indexes"] = [];
|
|
226
|
-
for (const d of decorators) {
|
|
227
|
-
const dn = getDecoratorName(d);
|
|
228
|
-
if (dn !== "Index") continue;
|
|
229
|
-
const args = getDecoratorArgs(d);
|
|
230
|
-
let idxName: string | undefined;
|
|
231
|
-
let idxFields: any;
|
|
232
|
-
let idxUnique: boolean | undefined;
|
|
233
|
-
let idxTTL: number | undefined;
|
|
234
|
-
if (args.length === 0) continue;
|
|
235
|
-
else if (typeof args[0] === "string") {
|
|
236
|
-
idxName = args[0]; idxFields = args[1] ?? [];
|
|
237
|
-
} else if (typeof args[0] === "object") {
|
|
238
|
-
idxName = args[0].name; idxFields = args[0].fields ?? [];
|
|
239
|
-
idxUnique = args[0].unique; idxTTL = args[0].ttlSeconds;
|
|
240
|
-
}
|
|
241
|
-
const fields = normIndexFields(idxFields);
|
|
242
|
-
if (fields.length === 0) continue;
|
|
243
|
-
const name2 = idxName ?? defaultIndexName(fields);
|
|
244
|
-
classLevelIndexes.push({
|
|
245
|
-
name: name2,
|
|
246
|
-
fields,
|
|
247
|
-
...(idxUnique !== undefined ? { unique: !!idxUnique } : {}),
|
|
248
|
-
...(idxTTL !== undefined ? { ttlSeconds: idxTTL } : {}),
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// 合并去重
|
|
253
|
-
const allIndexes = [...fieldLevelIndexes, ...classLevelIndexes];
|
|
254
|
-
const dedup = new Map<string, PrintableSchema["indexes"][number]>();
|
|
255
|
-
for (const ix of allIndexes) {
|
|
256
|
-
const key = indexKey(ix.name, ix.fields);
|
|
257
|
-
if (!dedup.has(key)) dedup.set(key, ix);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
const printable: PrintableSchema = {
|
|
261
|
-
entityName: (entityOpts?.name as string) ?? entityName,
|
|
262
|
-
...(entityOpts?.namespace !== undefined ? { namespace: entityOpts.namespace } : {}),
|
|
263
|
-
...(entityOpts?.ttlSeconds !== undefined ? { ttlSeconds: entityOpts.ttlSeconds } : {}),
|
|
264
|
-
...(entityOpts?.versioned !== undefined ? { versioned: entityOpts.versioned } : {}),
|
|
265
|
-
columns,
|
|
266
|
-
indexes: Array.from(dedup.values()),
|
|
267
|
-
};
|
|
268
|
-
|
|
269
|
-
result.push(printable);
|
|
270
|
-
};
|
|
271
|
-
|
|
272
|
-
// 遍历每个文件的 AST
|
|
273
|
-
for (const [, content] of Object.entries(sources)) {
|
|
274
|
-
const ast = tryParse(content);
|
|
275
|
-
const visitors: Visitor = {
|
|
276
|
-
ClassDeclaration(path: NodePath<T.ClassDeclaration>) { visitClass(path); },
|
|
277
|
-
ClassExpression(path: NodePath<T.ClassExpression>) { visitClass(path); },
|
|
278
|
-
};
|
|
279
|
-
traverse(ast as any, visitors);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
return result;
|
|
283
|
-
}
|
|
@@ -1,322 +0,0 @@
|
|
|
1
|
-
/* Serverless-friendly decorators (TS 5 standard + legacy)
|
|
2
|
-
- @Entity(options?)
|
|
3
|
-
- @Column(options?)
|
|
4
|
-
- @Index(nameOrOptions[, fields])
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export type PrimitiveType = 'string' | 'number' | 'boolean' | 'date' | 'json' | 'binary';
|
|
8
|
-
|
|
9
|
-
export interface EntityOptions {
|
|
10
|
-
name?: string; // 实体名(默认类名)
|
|
11
|
-
namespace?: string; // 可选命名空间/前缀
|
|
12
|
-
ttlSeconds?: number; // 过期秒数,用于 serverless KV/缓存等
|
|
13
|
-
versioned?: boolean; // 是否启用版本
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface ColumnOptions<T = unknown> {
|
|
17
|
-
name?: string; // 存储层字段名(默认属性名)
|
|
18
|
-
type?: PrimitiveType; // 简化类型映射
|
|
19
|
-
required?: boolean; // 是否必填
|
|
20
|
-
default?: T | (() => T); // 默认值
|
|
21
|
-
index?: boolean; // 单列索引
|
|
22
|
-
unique?: boolean; // 唯一约束(需要底层支持)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export type IndexField =
|
|
26
|
-
| string
|
|
27
|
-
| { field: string; order?: 'asc' | 'desc' };
|
|
28
|
-
|
|
29
|
-
export interface IndexOptions {
|
|
30
|
-
name?: string;
|
|
31
|
-
fields: IndexField[];
|
|
32
|
-
unique?: boolean;
|
|
33
|
-
ttlSeconds?: number;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export interface EntityMeta {
|
|
37
|
-
target: Function;
|
|
38
|
-
name: string;
|
|
39
|
-
options: EntityOptions;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export interface ColumnMeta {
|
|
43
|
-
target: Function;
|
|
44
|
-
propertyKey: string | symbol;
|
|
45
|
-
options: ColumnOptions;
|
|
46
|
-
resolvedName: string;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export interface NormalizedIndexField {
|
|
50
|
-
field: string;
|
|
51
|
-
order: 'asc' | 'desc';
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export interface IndexMeta {
|
|
55
|
-
target: Function;
|
|
56
|
-
name: string;
|
|
57
|
-
fields: NormalizedIndexField[];
|
|
58
|
-
unique?: boolean;
|
|
59
|
-
ttlSeconds?: number;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
type StdDecoratorContext = {
|
|
63
|
-
kind: 'class' | 'field' | 'accessor' | 'method' | 'getter' | 'setter';
|
|
64
|
-
name?: string | symbol;
|
|
65
|
-
addInitializer?: (fn: () => void) => void;
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
function isStdCtx(v: unknown): v is StdDecoratorContext {
|
|
69
|
-
return !!v && typeof v === 'object' && 'kind' in (v as any);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
class MetadataStorage {
|
|
73
|
-
private entities = new WeakMap<Function, EntityMeta>();
|
|
74
|
-
private columns = new WeakMap<Function, Map<string | symbol, ColumnMeta>>();
|
|
75
|
-
private indexes = new WeakMap<Function, IndexMeta[]>();
|
|
76
|
-
|
|
77
|
-
registerEntity(target: Function, options: EntityOptions = {}, nameHint?: string) {
|
|
78
|
-
const name = options.name ?? nameHint ?? target.name;
|
|
79
|
-
const meta: EntityMeta = { target, name, options: { ...options, name } };
|
|
80
|
-
this.entities.set(target, meta);
|
|
81
|
-
return meta;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
registerColumn(target: Function, propertyKey: string | symbol, options: ColumnOptions = {}) {
|
|
85
|
-
const colMap = this.columns.get(target) ?? new Map();
|
|
86
|
-
const resolvedName = options.name ?? String(propertyKey);
|
|
87
|
-
const meta: ColumnMeta = { target, propertyKey, options, resolvedName };
|
|
88
|
-
colMap.set(propertyKey, meta);
|
|
89
|
-
this.columns.set(target, colMap);
|
|
90
|
-
return meta;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
registerIndex(target: Function, input: { name?: string; fields: IndexField[]; unique?: boolean; ttlSeconds?: number }) {
|
|
94
|
-
if (!input.fields || input.fields.length === 0) {
|
|
95
|
-
throw new Error('@Index requires at least one field');
|
|
96
|
-
}
|
|
97
|
-
const normalizedFields: NormalizedIndexField[] = input.fields.map(f =>
|
|
98
|
-
typeof f === 'string' ? { field: f, order: 'asc' } : { field: f.field, order: f.order ?? 'asc' }
|
|
99
|
-
);
|
|
100
|
-
const name = input.name ?? this.defaultIndexName(normalizedFields);
|
|
101
|
-
|
|
102
|
-
const arr = this.indexes.get(target) ?? [];
|
|
103
|
-
const dedupKey = this.makeIndexKey(name, normalizedFields);
|
|
104
|
-
const exists = arr.some(i => this.makeIndexKey(i.name, i.fields) === dedupKey);
|
|
105
|
-
|
|
106
|
-
if (!exists) {
|
|
107
|
-
const norm: IndexMeta = {
|
|
108
|
-
target,
|
|
109
|
-
name,
|
|
110
|
-
fields: normalizedFields,
|
|
111
|
-
...(input.unique !== undefined ? { unique: input.unique } : {}),
|
|
112
|
-
...(input.ttlSeconds !== undefined ? { ttlSeconds: input.ttlSeconds } : {}),
|
|
113
|
-
};
|
|
114
|
-
arr.push(norm);
|
|
115
|
-
this.indexes.set(target, arr);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
getEntity(target: Function | object): EntityMeta | undefined {
|
|
120
|
-
const ctor = typeof target === 'function' ? target : (target as any)?.constructor;
|
|
121
|
-
return this.entities.get(ctor);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
getColumns(target: Function | object): ColumnMeta[] {
|
|
125
|
-
const ctor = typeof target === 'function' ? target : (target as any)?.constructor;
|
|
126
|
-
const map = this.columns.get(ctor);
|
|
127
|
-
return map ? Array.from(map.values()) : [];
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
getIndexes(target: Function | object): IndexMeta[] {
|
|
131
|
-
const ctor = typeof target === 'function' ? target : (target as any)?.constructor;
|
|
132
|
-
return this.indexes.get(ctor) ?? [];
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
getSchema(target: Function | object) {
|
|
136
|
-
return {
|
|
137
|
-
entity: this.getEntity(target),
|
|
138
|
-
columns: this.getColumns(target),
|
|
139
|
-
indexes: this.getIndexes(target),
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
private defaultIndexName(fields: NormalizedIndexField[]) {
|
|
144
|
-
const part = fields.map(f => `${f.field}_${f.order}`).join('_');
|
|
145
|
-
return `idx_${part}`;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
private makeIndexKey(name: string, fields: NormalizedIndexField[]) {
|
|
149
|
-
return `${name}|${fields.map(f => `${f.field}:${f.order}`).join(',')}`;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
export const metadata = new MetadataStorage();
|
|
154
|
-
|
|
155
|
-
// ---------- Decorators (dual-mode: standard + legacy) ----------
|
|
156
|
-
|
|
157
|
-
export function Entity(options: EntityOptions = {}) {
|
|
158
|
-
// Standard: (value, context)
|
|
159
|
-
// Legacy: (ctor)
|
|
160
|
-
return function entityDecorator(valueOrTarget: any, maybeContext?: unknown) {
|
|
161
|
-
if (isStdCtx(maybeContext) && maybeContext.kind === 'class') {
|
|
162
|
-
const ctor = valueOrTarget as Function;
|
|
163
|
-
metadata.registerEntity(ctor, options, maybeContext.name ? String(maybeContext.name) : undefined);
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
// Legacy
|
|
167
|
-
const ctor = valueOrTarget as Function;
|
|
168
|
-
metadata.registerEntity(ctor, options, ctor.name);
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
export function Column(options: ColumnOptions = {}) {
|
|
173
|
-
// Standard: (initialValue, context)
|
|
174
|
-
// Legacy: (target, propertyKey)
|
|
175
|
-
return function columnDecorator(a: any, b: any) {
|
|
176
|
-
// Standard field/accessor
|
|
177
|
-
if (isStdCtx(b) && (b.kind === 'field' || b.kind === 'accessor')) {
|
|
178
|
-
const ctx = b as StdDecoratorContext;
|
|
179
|
-
const prop = ctx.name as string | symbol;
|
|
180
|
-
|
|
181
|
-
ctx.addInitializer?.(function (this: any) {
|
|
182
|
-
const ctor = this?.constructor;
|
|
183
|
-
if (!ctor) return;
|
|
184
|
-
const colMeta = metadata.registerColumn(ctor, prop, options);
|
|
185
|
-
if (options.index || options.unique) {
|
|
186
|
-
metadata.registerIndex(ctor, {
|
|
187
|
-
name: `idx_${String(colMeta.resolvedName)}`,
|
|
188
|
-
fields: [String(colMeta.resolvedName)],
|
|
189
|
-
...(options.unique !== undefined ? { unique: options.unique } : {}),
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
});
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
195
|
-
// Legacy property decorator
|
|
196
|
-
const target = a;
|
|
197
|
-
const propertyKey = b as string | symbol;
|
|
198
|
-
const ctor = target?.constructor;
|
|
199
|
-
const colMeta = metadata.registerColumn(ctor, propertyKey, options);
|
|
200
|
-
if (options.index || options.unique) {
|
|
201
|
-
metadata.registerIndex(ctor, {
|
|
202
|
-
name: `idx_${String(colMeta.resolvedName)}`,
|
|
203
|
-
fields: [String(colMeta.resolvedName)],
|
|
204
|
-
...(options.unique !== undefined ? { unique: options.unique } : {}),
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
export function Index(nameOrOptions: string | IndexOptions, fields?: IndexOptions['fields']) {
|
|
211
|
-
return function indexDecorator(valueOrTarget: any, maybeContext?: unknown) {
|
|
212
|
-
// Standard mode
|
|
213
|
-
if (isStdCtx(maybeContext)) {
|
|
214
|
-
const ctx = maybeContext as StdDecoratorContext;
|
|
215
|
-
|
|
216
|
-
if (ctx.kind === 'class') {
|
|
217
|
-
const ctor = valueOrTarget as Function;
|
|
218
|
-
const opts: IndexOptions = typeof nameOrOptions === 'string'
|
|
219
|
-
? { name: nameOrOptions, fields: fields ?? [] }
|
|
220
|
-
: nameOrOptions;
|
|
221
|
-
if (!opts.fields || opts.fields.length === 0) {
|
|
222
|
-
throw new Error(`@Index on class ${ctx.name?.toString() ?? ctor.name} requires fields`);
|
|
223
|
-
}
|
|
224
|
-
metadata.registerIndex(ctor, opts as any);
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
if (ctx.kind === 'field' || ctx.kind === 'accessor') {
|
|
229
|
-
const prop = ctx.name as string | symbol;
|
|
230
|
-
const base: IndexOptions =
|
|
231
|
-
typeof nameOrOptions === 'string'
|
|
232
|
-
? { name: nameOrOptions, fields: [String(prop)] }
|
|
233
|
-
: { ...(nameOrOptions ?? {}), fields: (nameOrOptions as IndexOptions)?.fields?.length ? (nameOrOptions as IndexOptions).fields : [String(prop)] };
|
|
234
|
-
|
|
235
|
-
ctx.addInitializer?.(function (this: any) {
|
|
236
|
-
const ctor = this?.constructor;
|
|
237
|
-
if (!ctor) return;
|
|
238
|
-
metadata.registerIndex(ctor, {
|
|
239
|
-
...(base.name ? { name: base.name } : {}),
|
|
240
|
-
fields: base.fields,
|
|
241
|
-
...(base.unique !== undefined ? { unique: base.unique } : {}),
|
|
242
|
-
...(base.ttlSeconds !== undefined ? { ttlSeconds: base.ttlSeconds } : {}),
|
|
243
|
-
});
|
|
244
|
-
});
|
|
245
|
-
return;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// Legacy mode
|
|
250
|
-
if (typeof maybeContext === 'string' || typeof maybeContext === 'symbol') {
|
|
251
|
-
// Property decorator
|
|
252
|
-
const target = valueOrTarget;
|
|
253
|
-
const prop = maybeContext as string | symbol;
|
|
254
|
-
const ctor = target?.constructor;
|
|
255
|
-
const base: IndexOptions =
|
|
256
|
-
typeof nameOrOptions === 'string'
|
|
257
|
-
? { name: nameOrOptions, fields: [String(prop)] }
|
|
258
|
-
: { ...(nameOrOptions ?? {}), fields: (nameOrOptions as IndexOptions)?.fields?.length ? (nameOrOptions as IndexOptions).fields : [String(prop)] };
|
|
259
|
-
|
|
260
|
-
metadata.registerIndex(ctor, {
|
|
261
|
-
...(base.name ? { name: base.name } : {}),
|
|
262
|
-
fields: base.fields,
|
|
263
|
-
...(base.unique !== undefined ? { unique: base.unique } : {}),
|
|
264
|
-
...(base.ttlSeconds !== undefined ? { ttlSeconds: base.ttlSeconds } : {}),
|
|
265
|
-
});
|
|
266
|
-
} else {
|
|
267
|
-
// Class decorator
|
|
268
|
-
const ctor = valueOrTarget as Function;
|
|
269
|
-
const opts: IndexOptions =
|
|
270
|
-
typeof nameOrOptions === 'string'
|
|
271
|
-
? { name: nameOrOptions, fields: fields ?? [] }
|
|
272
|
-
: nameOrOptions;
|
|
273
|
-
|
|
274
|
-
if (!opts.fields || opts.fields.length === 0) {
|
|
275
|
-
throw new Error(`@Index on class ${ctor.name} requires fields`);
|
|
276
|
-
}
|
|
277
|
-
metadata.registerIndex(ctor, {
|
|
278
|
-
...(opts.name ? { name: opts.name } : {}),
|
|
279
|
-
fields: opts.fields,
|
|
280
|
-
...(opts.unique !== undefined ? { unique: opts.unique } : {}),
|
|
281
|
-
...(opts.ttlSeconds !== undefined ? { ttlSeconds: opts.ttlSeconds } : {}),
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
};
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// ---------- Helpers for consumers ----------
|
|
288
|
-
|
|
289
|
-
export function getEntitySchema(target: Function | object) {
|
|
290
|
-
return metadata.getSchema(target);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
export function getEntityName(target: Function | object) {
|
|
294
|
-
return metadata.getEntity(target)?.name;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
export function getColumns(target: Function | object) {
|
|
298
|
-
return metadata.getColumns(target);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
export function getIndexes(target: Function | object) {
|
|
302
|
-
return metadata.getIndexes(target);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
/*
|
|
306
|
-
Usage example:
|
|
307
|
-
|
|
308
|
-
@Entity({ name: 'User', namespace: 'app', ttlSeconds: 86400 })
|
|
309
|
-
class User {
|
|
310
|
-
@Column({ type: 'string', required: true })
|
|
311
|
-
id!: string;
|
|
312
|
-
|
|
313
|
-
@Column({ type: 'string', index: true })
|
|
314
|
-
email!: string;
|
|
315
|
-
|
|
316
|
-
@Column({ type: 'date', default: () => new Date() })
|
|
317
|
-
createdAt!: Date;
|
|
318
|
-
|
|
319
|
-
@Index('idx_email_unique', ['email'])
|
|
320
|
-
// or put @Index() on the field to use single-column default index
|
|
321
|
-
}
|
|
322
|
-
*/
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 浏览器环境的行读取器
|
|
3
|
-
* 实现类似Go bufio.Reader的行读取功能
|
|
4
|
-
*/
|
|
5
|
-
export class BrowserLineReader {
|
|
6
|
-
text: any;
|
|
7
|
-
position: number;
|
|
8
|
-
lines: any;
|
|
9
|
-
currentLine: number;
|
|
10
|
-
constructor(text: string) {
|
|
11
|
-
this.text = text;
|
|
12
|
-
this.position = 0;
|
|
13
|
-
this.lines = text.split(/\r?\n/);
|
|
14
|
-
this.currentLine = 0;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* 读取一行,模拟Go的bufio.Reader.ReadLine()
|
|
19
|
-
* @returns {{line: Uint8Array, isPrefix: boolean, error: Error|null}} 读取结果
|
|
20
|
-
*/
|
|
21
|
-
readLine() {
|
|
22
|
-
if (this.currentLine >= this.lines.length) {
|
|
23
|
-
return {
|
|
24
|
-
line: new Uint8Array(0),
|
|
25
|
-
isPrefix: false,
|
|
26
|
-
error: new Error('EOF')
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const line = this.lines[this.currentLine];
|
|
31
|
-
this.currentLine++;
|
|
32
|
-
|
|
33
|
-
// 将字符串转换为Uint8Array (类似Go的[]byte)
|
|
34
|
-
const encoder = new TextEncoder();
|
|
35
|
-
const lineBytes = encoder.encode(line);
|
|
36
|
-
|
|
37
|
-
// 这里简化了,假设单次可以读完整行
|
|
38
|
-
return {
|
|
39
|
-
line: lineBytes,
|
|
40
|
-
isPrefix: false,
|
|
41
|
-
error: null
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* 从Reader中读取完整行
|
|
48
|
-
* @param {BrowserLineReader} reader - 行读取器
|
|
49
|
-
* @returns {{line: Uint8Array, error: Error|null}} 读取结果
|
|
50
|
-
*/
|
|
51
|
-
export function readLine(reader: BrowserLineReader): {line: Uint8Array, error: Error|null} {
|
|
52
|
-
let ln = new Uint8Array(0);
|
|
53
|
-
let isPrefix = true;
|
|
54
|
-
let error = null;
|
|
55
|
-
|
|
56
|
-
while (isPrefix && error === null) {
|
|
57
|
-
const result = reader.readLine();
|
|
58
|
-
|
|
59
|
-
// 更新变量
|
|
60
|
-
isPrefix = result.isPrefix;
|
|
61
|
-
error = result.error;
|
|
62
|
-
|
|
63
|
-
if (result.line.length > 0) {
|
|
64
|
-
// 合并数组 (类似Go的append)
|
|
65
|
-
const newArray = new Uint8Array(ln.length + result.line.length);
|
|
66
|
-
newArray.set(ln);
|
|
67
|
-
newArray.set(result.line, ln.length);
|
|
68
|
-
ln = newArray;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return { line: ln, error };
|
|
73
|
-
}
|