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,67 +0,0 @@
1
-
2
-
3
- export class AppError extends Error {
4
- constructor(
5
- public readonly code: string,
6
- message: string,
7
- public readonly statusCode: number = 400
8
- ) {
9
- super(message);
10
- this.name = code;
11
- }
12
- }
13
-
14
- export const Errors = {
15
- // Authentication errors (400-499)
16
- // INVALID_SIGNATURE: new AppError('INVALID_SIGNATURE', 'bad signature', 401),
17
- INVALID_TOKEN: new AppError('INVALID_TOKEN', 'invalid token', 401),
18
- // REQ_TOKEN_TOO_OFTEN: new AppError('REQ_TOKEN_TOO_OFTEN', 'request token too often', 429),
19
-
20
- // user not bind to this peer
21
- USER_NOT_BIND_TO_PEER: new AppError('USER_NOT_BIND_TO_PEER', 'user not bind to this peer'),
22
-
23
- NO_USER_INFO: new AppError("NO_USER_INFO", "no user info found"),
24
- NO_DC_PEER_CONNECTED: new AppError("NO_DC_PEER_CONNECTED", "no dc peer connected"),
25
- FAIL_TO_GET_BLOCKHEIGHT: new AppError("FAIL_TO_GET_BLOCKHEIGHT", "fail to get blockheight"),
26
- FAIL_TO_GET_TOKEN: new AppError("FAIL_TO_GET_TOKEN", "fail to get token"),
27
- NO_CHAIN_UTIL: new AppError("NO_CHAIN_UTIL", "no chain util found"),
28
- // // User management errors
29
- // USER_BINDED: new AppError('USER_BINDED', 'user has binded an account'),
30
- // ACCOUNT_BINDED: new AppError('ACCOUNT_BINDED', 'account has been Binded with other user'),
31
-
32
- // // Resource management errors
33
- // NO_ENOUGH_USER_SPACE: new AppError('NO_ENOUGH_USER_SPACE', 'no enough user space', 507),
34
- // DB_SPACE_LIMIT: new AppError('DB_SPACE_LIMIT', 'db space limit', 507),
35
- // USER_SPACE_EXPIRED: new AppError('USER_SPACE_EXPIRED', 'store space has expired'),
36
-
37
- // // Blockchain related errors
38
- // BLOCKCHAIN_NOT_INIT: new AppError('BLOCKCHAIN_NOT_INIT', 'blockchain not init', 503),
39
- // INVALID_ENCLAVE: new AppError('INVALID_ENCLAVE', 'invalid enclave'),
40
-
41
- // // Network errors
42
- // LOCAL_NET_FAIL: new AppError('LOCAL_NET_FAIL', 'local net fail', 502),
43
-
44
- // // Thread management errors
45
- // INVALID_THREADID: new AppError('INVALID_THREADID', 'invalid threadid'),
46
- // THREAD_NOT_FOUND: new AppError('THREAD_NOT_FOUND', 'thread not found', 404),
47
-
48
- // // Security errors
49
- // INVALID_PRIVKEY: new AppError('INVALID_PRIVKEY', 'invalid privkey', 403),
50
-
51
- // // Additional errors from original list
52
- // INVALID_CID: new AppError('INVALID_CID', 'invalid cid'),
53
- // PEER_NOT_INIT: new AppError('PEER_NOT_INIT', 'general datastore didn\'t init'),
54
- // INVALID_IDENTITY: new AppError('INVALID_IDENTITY', 'invalid identity'),
55
- // INVALID_REQUEST: new AppError('INVALID_REQUEST', 'invalid request', 400),
56
- // INVALID_PEERID: new AppError('INVALID_PEERID', 'invalid peerid'),
57
- // INVALID_PUBKEY: new AppError('INVALID_PUBKEY', 'invalid pubkey'),
58
- // USER_NOT_OWN_THREAD: new AppError('USER_NOT_OWN_THREAD', 'user not own thread', 403),
59
- // SUB_ACCOUNT_EXIST: new AppError('SUB_ACCOUNT_EXIST', 'sub account exist'),
60
- // SELF_IS_SUB_ACCOUNT: new AppError('SELF_IS_SUB_ACCOUNT', 'self is sub account'),
61
- // INVALID_SUB_ACCOUNT: new AppError('INVALID_SUB_ACCOUNT', 'invalid sub account'),
62
- // INVALID_TEE_REPORT: new AppError('INVALID_TEE_REPORT', 'invalid tee report'),
63
- // VACOUNT_MISMATCH: new AppError('VACOUNT_MISMATCH', 'vaccount mismatch')
64
- };
65
-
66
- // Type helper for error codes
67
- export type ErrorCode = keyof typeof Errors;
@@ -1,104 +0,0 @@
1
- import type { Libp2p } from "libp2p";
2
- import type { Multiaddr } from "@multiformats/multiaddr";
3
- import { dcnet } from "../proto/dcnet_proto";
4
- import { Libp2pGrpcClient } from "grpc-libp2p-client";
5
- import { DataSource } from "../proto/datasource";
6
- import { Ed25519PubKey } from "./dc-key/ed25519";
7
-
8
- export class DCGrpcClient {
9
- grpcClient: Libp2pGrpcClient;
10
- token: string;
11
-
12
- constructor(
13
- node: Libp2p,
14
- peerAddr: Multiaddr,
15
- token: string,
16
- protocol?: string
17
- ) {
18
- this.grpcClient = new Libp2pGrpcClient(node, peerAddr, token, protocol);
19
- this.token = token;
20
- }
21
-
22
- async GetToken(
23
- appId: string,
24
- pubkey: string,
25
- signCallback: (payload: Uint8Array) => Promise<Uint8Array> ,
26
- ): Promise<string> {
27
- let token: string = "";
28
- try {
29
- let error: Error | null = null;
30
- const signatureDataSource = new DataSource();
31
- const message = new dcnet.pb.GetTokenRequest({});
32
- message.key = appId + "_" + pubkey;
33
- const messageBytes = dcnet.pb.GetTokenRequest.encode(message).finish();
34
- const onDataCallback = async (payload: Uint8Array) => {
35
- const decodedPayload = dcnet.pb.GetTokenReply.decode(payload);
36
- if (decodedPayload.challenge) {
37
- const challenge = decodedPayload.challenge;
38
- const signature = await signCallback(challenge);
39
- const message = new dcnet.pb.GetTokenRequest({});
40
-
41
- message.signature = signature;
42
- const messageBytes =
43
- dcnet.pb.GetTokenRequest.encode(message).finish();
44
- signatureDataSource.setData(messageBytes);
45
- } else if (decodedPayload.token) {
46
- //获取到token
47
- console.log("GetToken success");
48
- token = decodedPayload.token;
49
- signatureDataSource.close(); //关闭数据源
50
- }
51
- };
52
- // 使用方法
53
- const dataSourceCallback = (): AsyncIterable<Uint8Array> => {
54
- console.log("dataSourceCallback");
55
- return signatureDataSource.getDataSource();
56
- };
57
- const onEndCallback = async () => {
58
- signatureDataSource.close();
59
- }
60
- const onErrorCallback = async (err: unknown) => {
61
- console.log("onErrorCallback", err);
62
- error = err instanceof Error ? err : new Error(String(err));
63
- signatureDataSource.close();
64
- }
65
- await this.grpcClient.Call(
66
- "/dcnet.pb.Service/GetToken",
67
- messageBytes,
68
- 30000,
69
- "bidirectional",
70
- onDataCallback,
71
- dataSourceCallback,
72
- onEndCallback,
73
- onErrorCallback
74
- );
75
- if(error){
76
- throw error;
77
- }
78
- this.token = token;
79
- this.grpcClient.setToken(token);
80
- return token;
81
- } catch (err) {
82
- throw err;
83
- }
84
- }
85
-
86
- async ValidToken(): Promise<boolean> {
87
- try {
88
- const message = new dcnet.pb.ValidTokenRequest({});
89
- const messageBytes =
90
- dcnet.pb.ValidTokenRequest.encode(message).finish();
91
- const responseData = await this.grpcClient.unaryCall(
92
- "/dcnet.pb.Service/ValidToken",
93
- messageBytes,
94
- 30000
95
- );
96
- dcnet.pb.ValidTokenReply.decode(responseData);
97
- return true;
98
- } catch (err) {
99
- throw err;
100
- }
101
- }
102
-
103
-
104
- }
@@ -1,184 +0,0 @@
1
- // module-system.ts
2
- // 定义模块注册和管理系统
3
-
4
- import { DCContext } from "../../lib/interfaces/DCContext";
5
- import { createLogger } from "../util/logger";
6
-
7
- const logger = createLogger("ModuleSystem");
8
-
9
- /**
10
- * 模块接口,所有功能模块必须实现此接口
11
- */
12
- export interface DCModule {
13
- /**
14
- * 模块名称,用于标识和日志
15
- */
16
- readonly moduleName: string;
17
-
18
- /**
19
- * 模块初始化方法
20
- * @param context DC上下文
21
- * @returns 是否初始化成功
22
- */
23
- initialize(context: DCContext): Promise<boolean>;
24
-
25
- /**
26
- * 模块关闭方法
27
- */
28
- shutdown(): Promise<void>;
29
- }
30
-
31
- /**
32
- * 核心模块名称枚举
33
- */
34
- export enum CoreModuleName {
35
- FILE = "file",
36
- AUTH = "auth",
37
- COMMENT = "comment",
38
- DATABASE = "database",
39
- MESSAGE = "message",
40
- KEYVALUE = "keyvalue",
41
- CACHE = "cache",
42
- CLIENT = "client",
43
- AIPROXY = "aiproxy",
44
- UTIL = "util",
45
- }
46
-
47
- /**
48
- * 模块系统
49
- * 负责管理和协调所有功能模块
50
- */
51
- export class ModuleSystem {
52
- private modules: Map<string, DCModule> = new Map();
53
- private context: DCContext;
54
- private initialized: boolean = false;
55
-
56
- /**
57
- * 创建模块系统
58
- * @param context DC上下文
59
- */
60
- constructor(context: DCContext) {
61
- this.context = context;
62
- }
63
-
64
- /**
65
- * 注册模块
66
- * @param module 要注册的模块
67
- * @returns 是否注册成功
68
- */
69
- registerModule(module: DCModule): boolean {
70
- if (this.modules.has(module.moduleName)) {
71
- logger.warn(`模块 ${module.moduleName} 已存在,无法重复注册`);
72
- return false;
73
- }
74
-
75
- this.modules.set(module.moduleName, module);
76
- return true;
77
- }
78
-
79
- /**
80
- * 获取模块
81
- * @param moduleName 模块名称
82
- * @returns 模块实例或undefined
83
- */
84
- getModule<T extends DCModule>(moduleName: string): T | undefined {
85
- return this.modules.get(moduleName) as T | undefined;
86
- }
87
-
88
- /**
89
- * 初始化所有已注册的模块
90
- * @returns 是否所有模块都成功初始化
91
- */
92
- async initializeAll(): Promise<boolean> {
93
- logger.info("开始初始化所有模块...");
94
-
95
- // 按照特定顺序初始化核心模块
96
- const initOrder = [
97
- CoreModuleName.AUTH, // 认证模块优先,因为其他模块可能依赖认证
98
- CoreModuleName.FILE, // 文件模块其次,许多功能依赖文件操作
99
- CoreModuleName.DATABASE, // 数据库模块
100
- CoreModuleName.COMMENT, // 评论模块
101
- CoreModuleName.MESSAGE, // 消息模块
102
- CoreModuleName.KEYVALUE, // 键值存储模块
103
- CoreModuleName.CLIENT, // 客户端模块
104
- CoreModuleName.CACHE, // 缓存模块
105
- CoreModuleName.AIPROXY, // AIProxy模块
106
- CoreModuleName.UTIL, // 工具模块
107
- ];
108
-
109
- // 先初始化核心模块
110
- for (const moduleName of initOrder) {
111
- const module = this.modules.get(moduleName);
112
- if (module) {
113
- try {
114
- const success = await module.initialize(this.context);
115
- if (!success) {
116
- logger.error(`核心模块 ${moduleName} 初始化失败`);
117
- return false;
118
- }
119
- logger.info(`核心模块 ${moduleName} 初始化成功`);
120
- } catch (error) {
121
- logger.error(`核心模块 ${moduleName} 初始化出错:`, error);
122
- return false;
123
- }
124
- }
125
- }
126
-
127
- // 然后初始化其余的扩展模块
128
- for (const [name, module] of this.modules.entries()) {
129
- if (!initOrder.includes(name as CoreModuleName)) {
130
- logger.info(`初始化扩展模块: ${name}`);
131
- try {
132
- const success = await module.initialize(this.context);
133
- if (!success) {
134
- logger.error(`扩展模块 ${name} 初始化失败`);
135
- return false;
136
- }
137
- } catch (error) {
138
- logger.error(`扩展模块 ${name} 初始化出错:`, error);
139
- return false;
140
- }
141
- }
142
- }
143
-
144
- this.initialized = true;
145
- logger.info("所有模块初始化完成");
146
- return true;
147
- }
148
-
149
- /**
150
- * 关闭所有模块
151
- */
152
- async shutdownAll(): Promise<void> {
153
- logger.info("开始关闭所有模块...");
154
-
155
- // 逆序关闭模块
156
- const modules = Array.from(this.modules.entries());
157
- for (let i = modules.length - 1; i >= 0; i--) {
158
- const [name, module] = modules[i]!;
159
- try {
160
- logger.info(`关闭模块: ${name}`);
161
- await module.shutdown();
162
- } catch (error) {
163
- logger.error(`关闭模块 ${name} 时出错:`, error);
164
- }
165
- }
166
-
167
- this.initialized = false;
168
- logger.info("所有模块已关闭");
169
- }
170
-
171
- /**
172
- * 检查模块系统是否已初始化
173
- */
174
- isInitialized(): boolean {
175
- return this.initialized;
176
- }
177
-
178
- /**
179
- * 获取已注册的模块列表
180
- */
181
- getRegisteredModules(): string[] {
182
- return Array.from(this.modules.keys());
183
- }
184
- }
@@ -1,234 +0,0 @@
1
- // service-worker.ts
2
- // 负责处理 Service Worker 相关的功能
3
-
4
- import { IFileOperations } from "../interfaces";
5
- import { createLogger } from "../util/logger";
6
-
7
- const logger = createLogger('ServiceWorker');
8
-
9
-
10
- let swMessageHandler: ((event: MessageEvent) => void) | null = null;
11
-
12
- /**
13
- * 注册 Service Worker 并设置消息监听器
14
- * @param fileOps 文件操作对象,用于处理IPFS请求
15
- * @returns Promise<ServiceWorkerRegistration | null>
16
- */
17
- export async function registerServiceWorker(fileOps?: IFileOperations, swUrl: string = ''): Promise<ServiceWorkerRegistration | null> {
18
- if (!('serviceWorker' in navigator)) return Promise.reject('Service Worker not supported');
19
- if (location.protocol !== 'https:' && location.hostname !== 'localhost') {
20
- logger.error('ServiceWorker 仅支持 https 或 localhost');
21
- return null;
22
- }
23
- if (window.location.protocol != 'https:' && window.location.hostname != 'localhost') {
24
- logger.error('ServiceWorker 仅支持https协议');
25
- return null;
26
- }
27
- const swPath = new URL(swUrl || '/sw.js', location.origin).href;
28
- const registration = await navigator.serviceWorker.register(swPath);
29
- // 只保留一个监听器,避免重复处理同一请求
30
- if (swMessageHandler) {
31
- navigator.serviceWorker.removeEventListener('message', swMessageHandler);
32
- }
33
- swMessageHandler = async (event: MessageEvent) => {
34
- if (event.data && event.data.type === 'ipfs-fetch') {
35
- const port = event.ports?.[0];
36
- if (!port) {
37
- logger.warn('SW 未提供 MessagePort');
38
- return;
39
- }
40
- //里面回一个消息,通知已经收到请求
41
- port.postMessage({ success: true, message: 'Request received' ,status: 999 });
42
- try {
43
- await handleIpfsRequest(event.data, port, fileOps);
44
- } catch (e) {
45
- logger.error('handleIpfsRequest 处理异常:', e);
46
- port.postMessage({ success: false, error: String(e) });
47
- }
48
- }
49
- };
50
- navigator.serviceWorker.addEventListener('message', swMessageHandler);
51
- // 确保 SW 已 active
52
- await navigator.serviceWorker.ready;
53
- // 确保当前页已被控制,否则等待接管
54
- if (!navigator.serviceWorker.controller) {
55
- await new Promise<void>((resolve) => {
56
- navigator.serviceWorker.addEventListener('controllerchange', () => resolve(), { once: true });
57
- });
58
- }
59
- return registration;
60
- }
61
-
62
- /**
63
- * 处理IPFS请求
64
- * @param data 请求数据
65
- * @param port 消息端口
66
- * @param fileOps 文件操作对象
67
- */
68
- export async function handleIpfsRequest(
69
- data: { id: string, pathname: string, range?: string },
70
- port: MessagePort,
71
- fileOps?: IFileOperations
72
- ): Promise<void> {
73
- const { id, pathname, range } = data;
74
- let fileSize = 0;
75
-
76
- try {
77
- // 从路径提取IPFS路径和解密密钥
78
- const pathParts = pathname.split('/');
79
- let ipfsPath = pathParts[3]!; // <ipfs-hash>[_<key>]
80
-
81
- // 提取加密密钥(如果有)
82
- let decryptKey = '';
83
- const keyParts = ipfsPath.split('_');
84
- if (keyParts.length > 1) {
85
- ipfsPath = keyParts[0]!;
86
- decryptKey = keyParts[1]!;
87
- }
88
-
89
- let fileData: Uint8Array | null = null;
90
- const DEFAULT_CHUNK_SIZE = 3 * 1024 * 1024; // 默认返回3MB数据块
91
- let start = 0;
92
- let end = 0;
93
-
94
- if (fileOps) {
95
- if (range) {
96
- // 处理范围请求(视频跳转等)
97
- try {
98
- const fileStream = await fileOps.getSeekableFileStream(ipfsPath, decryptKey);
99
- fileSize = fileStream.getSize();
100
- if (fileStream) {
101
- const match = range.match(/bytes=(\d+)-(\d+)?/);
102
- if (match) {
103
- start = parseInt(match[1]!);
104
- end = match[2] ? parseInt(match[2]) : start + DEFAULT_CHUNK_SIZE-1;
105
- if (end >= fileSize) {
106
- // 如果请求的结束范围超过文件大小,则调整为文件大小
107
- end = fileSize - 1;
108
- }
109
- logger.info(`处理范围请求: ${start}-${end}, 总大小: ${fileStream.getSize()}`);
110
- fileStream.seek(start);
111
- fileData = await fileStream.read(end - start + 1);
112
-
113
- // 如果读取到文件末尾,清理缓存
114
- if (end >= fileStream.getSize() - 1) {
115
- logger.info(`文件读取完成,清理缓存: ${pathname}`);
116
- fileOps.clearFileCache(pathname);
117
- }
118
- }
119
- }
120
- } catch (err) {
121
- logger.error('文件流操作失败:', err);
122
- // 发生错误时清理缓存
123
- fileOps.clearFileCache(pathname);
124
- port.postMessage({
125
- success: false,
126
- error: err instanceof Error ? err.message : 'File stream operation failed'
127
- });
128
- return;
129
- }
130
- } else {
131
- const [fileContent, error] = await fileOps.getFile(ipfsPath, decryptKey);
132
- fileData = fileContent;
133
- // 普通文件请求
134
- fileSize = fileData ? fileData.length : 0;
135
- // 非范围请求的文件读取完成后,清理缓存
136
- fileOps.clearFileCache(pathname);
137
- }
138
-
139
- if (!fileData) {
140
- port.postMessage({
141
- success: false,
142
- error: 'no data',
143
- });
144
- return
145
- }
146
-
147
- if (fileData && fileData.buffer) {
148
- // 创建不包含 buffer 的基本响应对象
149
- const responseObj = {
150
- success: true,
151
- status: range ? 206 : 200,
152
- headers: {
153
- 'Content-Range': range ? `bytes ${start}-${end}/${fileSize}` : undefined,
154
- 'Accept-Ranges': 'bytes',
155
- 'Cache-Control': 'no-cache',
156
- 'Content-Length': fileData.length,
157
- },
158
- };
159
-
160
- // 传递时才添加 data 字段
161
- // 注意:在这个方法里 fileData.buffer 被转移后,fileData 将不再可用
162
- port.postMessage({
163
- ...responseObj,
164
- data: fileData.buffer
165
- }, [fileData.buffer]);
166
-
167
- // 手动清除引用
168
- fileData = null;
169
- } else {
170
- port.postMessage({
171
- success: false,
172
- error: 'Missing data buffer'
173
- });
174
- }
175
- } else {
176
- // 文件操作对象不可用
177
- port.postMessage({
178
- success: false,
179
- error: 'File operations not available'
180
- });
181
- }
182
- } catch (error) {
183
- logger.error('处理IPFS请求失败:', error);
184
- // 全局错误捕获时也清理缓存
185
- if (fileOps && pathname) {
186
- fileOps.clearFileCache(pathname);
187
- }
188
- port.postMessage({
189
- success: false,
190
- error: error instanceof Error ? error.message : 'Unknown error'
191
- });
192
- }
193
- }
194
-
195
- /**
196
- * 检查Service Worker状态
197
- * @returns Promise<boolean> Service Worker是否活跃
198
- */
199
- export async function isServiceWorkerActive(): Promise<boolean> {
200
- if (!('serviceWorker' in navigator)) {
201
- return false;
202
- }
203
-
204
- try {
205
- const registration = await navigator.serviceWorker.ready;
206
- return !!registration.active;
207
- } catch (error) {
208
- logger.error('检查Service Worker状态失败:', error);
209
- return false;
210
- }
211
- }
212
-
213
- /**
214
- * 强制更新Service Worker
215
- * @returns Promise<boolean> 是否成功更新
216
- */
217
- export async function updateServiceWorker(): Promise<boolean> {
218
- if (!('serviceWorker' in navigator)) {
219
- return false;
220
- }
221
-
222
- try {
223
- const registration = await navigator.serviceWorker.getRegistration();
224
- if (registration) {
225
- await registration.update();
226
- logger.info('Service Worker 已更新');
227
- return true;
228
- }
229
- return false;
230
- } catch (error) {
231
- logger.error('更新Service Worker失败:', error);
232
- return false;
233
- }
234
- }