@wetspace/wetrtc 3.0.2 → 4.0.0
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/README.md +156 -29
- package/dist/es/__test__/codec-preference.test.js +36 -0
- package/dist/es/__test__/codec-preference.test.js.map +1 -0
- package/dist/es/__test__/data-manager.test.js +60 -0
- package/dist/es/__test__/data-manager.test.js.map +1 -0
- package/dist/es/__test__/fsm.test.js +33 -0
- package/dist/es/__test__/fsm.test.js.map +1 -0
- package/dist/es/__test__/media-manager.test.js +41 -0
- package/dist/es/__test__/media-manager.test.js.map +1 -0
- package/dist/es/__test__/signal-manager.test.js +100 -0
- package/dist/es/__test__/signal-manager.test.js.map +1 -0
- package/dist/es/__test__/wetrtc-lifecycle.test.js +152 -0
- package/dist/es/__test__/wetrtc-lifecycle.test.js.map +1 -0
- package/dist/es/data/data-manager.d.ts +37 -0
- package/dist/es/data/data-manager.d.ts.map +1 -0
- package/dist/es/data/data-manager.js +282 -0
- package/dist/es/data/data-manager.js.map +1 -0
- package/dist/es/data/types.d.ts +34 -0
- package/dist/es/data/types.d.ts.map +1 -0
- package/dist/es/data/types.js +0 -0
- package/dist/es/disposable.d.ts +12 -0
- package/dist/es/disposable.d.ts.map +1 -0
- package/dist/es/disposable.js +36 -0
- package/dist/es/disposable.js.map +1 -0
- package/dist/es/fsm.d.ts +26 -0
- package/dist/es/fsm.d.ts.map +1 -0
- package/dist/es/fsm.js +63 -0
- package/dist/es/fsm.js.map +1 -0
- package/dist/es/index.d.ts +22 -0
- package/dist/es/index.d.ts.map +1 -0
- package/dist/es/index.js +48 -0
- package/dist/es/index.js.map +1 -0
- package/dist/es/media/audio-encoding.d.ts +10 -0
- package/dist/es/media/audio-encoding.d.ts.map +1 -0
- package/dist/es/media/audio-encoding.js +41 -0
- package/dist/es/media/audio-encoding.js.map +1 -0
- package/dist/es/media/codec-preference.d.ts +11 -0
- package/dist/es/media/codec-preference.d.ts.map +1 -0
- package/dist/es/media/codec-preference.js +77 -0
- package/dist/es/media/codec-preference.js.map +1 -0
- package/dist/es/media/encoding-utils.d.ts +2 -0
- package/dist/es/media/encoding-utils.d.ts.map +1 -0
- package/dist/es/media/encoding-utils.js +8 -0
- package/dist/es/media/encoding-utils.js.map +1 -0
- package/dist/es/media/media-manager.d.ts +39 -0
- package/dist/es/media/media-manager.d.ts.map +1 -0
- package/dist/es/media/media-manager.js +121 -0
- package/dist/es/media/media-manager.js.map +1 -0
- package/dist/es/media/types.d.ts +25 -0
- package/dist/es/media/types.d.ts.map +1 -0
- package/dist/es/media/types.js +0 -0
- package/dist/es/media/video-encoding.d.ts +12 -0
- package/dist/es/media/video-encoding.d.ts.map +1 -0
- package/dist/es/media/video-encoding.js +60 -0
- package/dist/es/media/video-encoding.js.map +1 -0
- package/dist/es/signal/signal-manager.d.ts +45 -0
- package/dist/es/signal/signal-manager.d.ts.map +1 -0
- package/dist/es/signal/signal-manager.js +250 -0
- package/dist/es/signal/signal-manager.js.map +1 -0
- package/dist/es/signal/types.d.ts +26 -0
- package/dist/es/signal/types.d.ts.map +1 -0
- package/dist/es/signal/types.js +8 -0
- package/dist/es/signal/types.js.map +1 -0
- package/dist/es/stats/stats-monitor.d.ts +32 -0
- package/dist/es/stats/stats-monitor.d.ts.map +1 -0
- package/dist/es/stats/stats-monitor.js +191 -0
- package/dist/es/stats/stats-monitor.js.map +1 -0
- package/dist/es/stats/types.d.ts +33 -0
- package/dist/es/stats/types.d.ts.map +1 -0
- package/dist/es/stats/types.js +0 -0
- package/dist/es/utils/types.d.ts +46 -0
- package/dist/es/utils/types.d.ts.map +1 -0
- package/dist/es/utils/types.js +80 -0
- package/dist/es/utils/types.js.map +1 -0
- package/dist/es/wetrtc.d.ts +92 -0
- package/dist/es/wetrtc.d.ts.map +1 -0
- package/dist/es/wetrtc.js +403 -0
- package/dist/es/wetrtc.js.map +1 -0
- package/dist/lib/__test__/codec-preference.test.js +34 -0
- package/dist/lib/__test__/codec-preference.test.js.map +1 -0
- package/dist/lib/__test__/data-manager.test.js +61 -0
- package/dist/lib/__test__/data-manager.test.js.map +1 -0
- package/dist/lib/__test__/fsm.test.js +34 -0
- package/dist/lib/__test__/fsm.test.js.map +1 -0
- package/dist/lib/__test__/media-manager.test.js +42 -0
- package/dist/lib/__test__/media-manager.test.js.map +1 -0
- package/dist/lib/__test__/signal-manager.test.js +101 -0
- package/dist/lib/__test__/signal-manager.test.js.map +1 -0
- package/dist/lib/__test__/wetrtc-lifecycle.test.js +153 -0
- package/dist/lib/__test__/wetrtc-lifecycle.test.js.map +1 -0
- package/dist/lib/data/data-manager.js +306 -0
- package/dist/lib/data/data-manager.js.map +1 -0
- package/dist/lib/data/types.js +18 -0
- package/dist/lib/data/types.js.map +1 -0
- package/dist/lib/disposable.js +60 -0
- package/dist/lib/disposable.js.map +1 -0
- package/dist/lib/fsm.js +87 -0
- package/dist/lib/fsm.js.map +1 -0
- package/dist/lib/index.js +75 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/media/audio-encoding.js +66 -0
- package/dist/lib/media/audio-encoding.js.map +1 -0
- package/dist/lib/media/codec-preference.js +106 -0
- package/dist/lib/media/codec-preference.js.map +1 -0
- package/dist/lib/media/encoding-utils.js +32 -0
- package/dist/lib/media/encoding-utils.js.map +1 -0
- package/dist/lib/media/media-manager.js +145 -0
- package/dist/lib/media/media-manager.js.map +1 -0
- package/dist/lib/media/types.js +18 -0
- package/dist/lib/media/types.js.map +1 -0
- package/dist/lib/media/video-encoding.js +87 -0
- package/dist/lib/media/video-encoding.js.map +1 -0
- package/dist/lib/signal/signal-manager.js +274 -0
- package/dist/lib/signal/signal-manager.js.map +1 -0
- package/dist/lib/signal/types.js +32 -0
- package/dist/lib/signal/types.js.map +1 -0
- package/dist/lib/stats/stats-monitor.js +215 -0
- package/dist/lib/stats/stats-monitor.js.map +1 -0
- package/dist/lib/stats/types.js +18 -0
- package/dist/lib/stats/types.js.map +1 -0
- package/dist/lib/utils/types.js +108 -0
- package/dist/lib/utils/types.js.map +1 -0
- package/dist/lib/wetrtc.js +415 -0
- package/dist/lib/wetrtc.js.map +1 -0
- package/package.json +38 -42
- package/es/core/constant.d.ts +0 -6
- package/es/core/hook.d.ts +0 -31
- package/es/core/index.d.ts +0 -39
- package/es/index.d.ts +0 -6
- package/es/index.js +0 -1
- package/es/libs/index.d.ts +0 -41
- package/es/libs/record.d.ts +0 -8
- package/lib/core/constant.d.ts +0 -6
- package/lib/core/hook.d.ts +0 -31
- package/lib/core/index.d.ts +0 -39
- package/lib/index.d.ts +0 -6
- package/lib/index.js +0 -1
- package/lib/libs/index.d.ts +0 -41
- package/lib/libs/record.d.ts +0 -8
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var data_manager_exports = {};
|
|
20
|
+
__export(data_manager_exports, {
|
|
21
|
+
DataManager: () => DataManager
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(data_manager_exports);
|
|
24
|
+
var import_types = require("../utils/types");
|
|
25
|
+
const MAX_BUFFER = 256 * 1024;
|
|
26
|
+
class DataManager {
|
|
27
|
+
constructor(pc) {
|
|
28
|
+
this.pc = pc;
|
|
29
|
+
this.channels = /* @__PURE__ */ new Map();
|
|
30
|
+
this.channelConfigs = [];
|
|
31
|
+
this.messageHandlers = [];
|
|
32
|
+
this.fileHandlers = [];
|
|
33
|
+
this.fileReceives = /* @__PURE__ */ new Map();
|
|
34
|
+
this.logger = (0, import_types.createLogger)();
|
|
35
|
+
}
|
|
36
|
+
/** 切换 PeerConnection(disconnect / reconnect 后 rebind) */
|
|
37
|
+
setPeerConnection(pc) {
|
|
38
|
+
for (const [, channel] of this.channels) {
|
|
39
|
+
channel.close();
|
|
40
|
+
}
|
|
41
|
+
this.channels.clear();
|
|
42
|
+
this.fileReceives.clear();
|
|
43
|
+
this.pc = pc;
|
|
44
|
+
}
|
|
45
|
+
createChannel(label, options) {
|
|
46
|
+
if (this.channels.has(label)) {
|
|
47
|
+
return this.channels.get(label);
|
|
48
|
+
}
|
|
49
|
+
const channel = this.pc.createDataChannel(label, options);
|
|
50
|
+
this.registerChannel(label, channel);
|
|
51
|
+
return channel;
|
|
52
|
+
}
|
|
53
|
+
registerRemoteChannel(event) {
|
|
54
|
+
const { channel } = event;
|
|
55
|
+
this.registerChannel(channel.label, channel);
|
|
56
|
+
}
|
|
57
|
+
configureChannels(configs) {
|
|
58
|
+
this.channelConfigs = configs;
|
|
59
|
+
}
|
|
60
|
+
initConfiguredChannels() {
|
|
61
|
+
for (const config of this.channelConfigs) {
|
|
62
|
+
this.createChannel(config.label, config.options);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
getChannel(label) {
|
|
66
|
+
return this.channels.get(label);
|
|
67
|
+
}
|
|
68
|
+
send(data, channelLabel) {
|
|
69
|
+
if (channelLabel) {
|
|
70
|
+
const ch = this.channels.get(channelLabel);
|
|
71
|
+
if (!ch || ch.readyState !== "open") {
|
|
72
|
+
this.logger.warn(`DataChannel "${channelLabel}" not ready`);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
this.doSend(ch, data);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
let sent = false;
|
|
79
|
+
for (const ch of this.channels.values()) {
|
|
80
|
+
if (ch.readyState === "open") {
|
|
81
|
+
this.doSend(ch, data);
|
|
82
|
+
sent = true;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (!sent) {
|
|
86
|
+
this.logger.warn("No open DataChannel available");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
onMessage(handler) {
|
|
90
|
+
this.messageHandlers.push(handler);
|
|
91
|
+
return () => {
|
|
92
|
+
this.messageHandlers = this.messageHandlers.filter((h) => h !== handler);
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/** 订阅文件接收(与 sendFile 协议对称) */
|
|
96
|
+
onFile(handler) {
|
|
97
|
+
this.fileHandlers.push(handler);
|
|
98
|
+
return () => {
|
|
99
|
+
this.fileHandlers = this.fileHandlers.filter((h) => h !== handler);
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
async sendFile(file, options) {
|
|
103
|
+
const chunkSize = options?.chunkSize ?? 16384;
|
|
104
|
+
const maxRetries = options?.maxRetries ?? 3;
|
|
105
|
+
const bufferThreshold = options?.bufferThreshold ?? MAX_BUFFER;
|
|
106
|
+
const bufferTimeout = options?.bufferTimeout ?? 1e4;
|
|
107
|
+
const total = Math.ceil(file.size / chunkSize);
|
|
108
|
+
this.throwIfAborted(options?.signal);
|
|
109
|
+
if (options?.maxFileSize && file.size > options.maxFileSize) {
|
|
110
|
+
throw new Error(`File exceeds maxFileSize (${file.size} > ${options.maxFileSize})`);
|
|
111
|
+
}
|
|
112
|
+
const fileChannel = this.createChannel(`file-${file.name}`, {
|
|
113
|
+
ordered: true
|
|
114
|
+
});
|
|
115
|
+
await this.waitForChannelOpen(fileChannel);
|
|
116
|
+
await this.waitForBuffer(fileChannel, bufferThreshold, bufferTimeout);
|
|
117
|
+
fileChannel.send(JSON.stringify({
|
|
118
|
+
type: "file-meta",
|
|
119
|
+
name: file.name,
|
|
120
|
+
size: file.size,
|
|
121
|
+
chunks: total,
|
|
122
|
+
mimeType: file.type
|
|
123
|
+
}));
|
|
124
|
+
let offset = 0;
|
|
125
|
+
while (offset < file.size) {
|
|
126
|
+
this.throwIfAborted(options?.signal);
|
|
127
|
+
const end = Math.min(offset + chunkSize, file.size);
|
|
128
|
+
const chunk = file.slice(offset, end);
|
|
129
|
+
await this.waitForBuffer(fileChannel, bufferThreshold, bufferTimeout);
|
|
130
|
+
await this.sendChunkWithRetry(fileChannel, chunk, maxRetries);
|
|
131
|
+
offset = end;
|
|
132
|
+
options?.onProgress?.(offset, file.size);
|
|
133
|
+
}
|
|
134
|
+
await this.waitForBuffer(fileChannel, bufferThreshold, bufferTimeout);
|
|
135
|
+
fileChannel.send(JSON.stringify({ type: "file-complete", name: file.name }));
|
|
136
|
+
}
|
|
137
|
+
dispose() {
|
|
138
|
+
for (const [, channel] of this.channels) {
|
|
139
|
+
channel.close();
|
|
140
|
+
}
|
|
141
|
+
this.channels.clear();
|
|
142
|
+
this.messageHandlers.length = 0;
|
|
143
|
+
this.fileHandlers.length = 0;
|
|
144
|
+
this.fileReceives.clear();
|
|
145
|
+
this.logger.info("DataManager disposed");
|
|
146
|
+
}
|
|
147
|
+
// ── private ──
|
|
148
|
+
registerChannel(label, channel) {
|
|
149
|
+
channel.onopen = () => this.logger.info(`DataChannel "${label}" opened`);
|
|
150
|
+
channel.onclose = () => {
|
|
151
|
+
this.logger.info(`DataChannel "${label}" closed`);
|
|
152
|
+
this.fileReceives.delete(label);
|
|
153
|
+
};
|
|
154
|
+
channel.onerror = (ev) => this.logger.warn(`DataChannel "${label}" error:`, ev);
|
|
155
|
+
channel.onmessage = (ev) => {
|
|
156
|
+
this.handleChannelMessage(label, ev.data);
|
|
157
|
+
};
|
|
158
|
+
this.channels.set(label, channel);
|
|
159
|
+
}
|
|
160
|
+
handleChannelMessage(label, data) {
|
|
161
|
+
if (typeof data === "string") {
|
|
162
|
+
try {
|
|
163
|
+
const msg = JSON.parse(data);
|
|
164
|
+
if (msg.type === "file-meta") {
|
|
165
|
+
this.fileReceives.set(label, {
|
|
166
|
+
meta: {
|
|
167
|
+
name: msg.name,
|
|
168
|
+
size: msg.size,
|
|
169
|
+
type: msg.mimeType ?? "application/octet-stream"
|
|
170
|
+
},
|
|
171
|
+
chunks: [],
|
|
172
|
+
expectedChunks: msg.chunks,
|
|
173
|
+
receivedBytes: 0
|
|
174
|
+
});
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
if (msg.type === "file-complete") {
|
|
178
|
+
const state = this.fileReceives.get(label);
|
|
179
|
+
if (state) {
|
|
180
|
+
if (state.chunks.length !== state.expectedChunks) {
|
|
181
|
+
this.logger.warn(
|
|
182
|
+
`File "${state.meta.name}" incomplete: ${state.chunks.length}/${state.expectedChunks} chunks`
|
|
183
|
+
);
|
|
184
|
+
this.fileReceives.delete(label);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
if (state.receivedBytes !== state.meta.size) {
|
|
188
|
+
this.logger.warn(
|
|
189
|
+
`File "${state.meta.name}" size mismatch: ${state.receivedBytes}/${state.meta.size}`
|
|
190
|
+
);
|
|
191
|
+
this.fileReceives.delete(label);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
const blob = new Blob(state.chunks, { type: state.meta.type });
|
|
195
|
+
for (const handler of this.fileHandlers) {
|
|
196
|
+
try {
|
|
197
|
+
handler(state.meta, blob);
|
|
198
|
+
} catch {
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
this.fileReceives.delete(label);
|
|
202
|
+
}
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
} catch {
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
const receiveState = this.fileReceives.get(label);
|
|
209
|
+
if (receiveState && (data instanceof Blob || data instanceof ArrayBuffer)) {
|
|
210
|
+
const size = data instanceof Blob ? data.size : data.byteLength;
|
|
211
|
+
receiveState.chunks.push(
|
|
212
|
+
data instanceof Blob ? data : new Blob([data])
|
|
213
|
+
);
|
|
214
|
+
receiveState.receivedBytes += size;
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
for (const handler of this.messageHandlers) {
|
|
218
|
+
try {
|
|
219
|
+
handler(data, label);
|
|
220
|
+
} catch {
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
doSend(channel, data) {
|
|
225
|
+
if (typeof data === "string") {
|
|
226
|
+
channel.send(data);
|
|
227
|
+
} else if (data instanceof ArrayBuffer) {
|
|
228
|
+
if (data.byteLength > 256 * 1024) {
|
|
229
|
+
this.logger.warn(`Large message (${data.byteLength} bytes), consider chunking`);
|
|
230
|
+
}
|
|
231
|
+
channel.send(data);
|
|
232
|
+
} else {
|
|
233
|
+
channel.send(data);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
waitForChannelOpen(channel, timeout = 1e4) {
|
|
237
|
+
return new Promise((resolve, reject) => {
|
|
238
|
+
if (channel.readyState === "open")
|
|
239
|
+
return resolve();
|
|
240
|
+
const timer = setTimeout(() => reject(new Error("DataChannel open timeout")), timeout);
|
|
241
|
+
const prev = channel.onopen;
|
|
242
|
+
channel.onopen = (ev) => {
|
|
243
|
+
clearTimeout(timer);
|
|
244
|
+
prev?.call(channel, ev);
|
|
245
|
+
resolve();
|
|
246
|
+
};
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
waitForBuffer(channel, maxBuffer = MAX_BUFFER, timeout = 1e4) {
|
|
250
|
+
if (channel.bufferedAmount <= maxBuffer)
|
|
251
|
+
return Promise.resolve();
|
|
252
|
+
return new Promise((resolve, reject) => {
|
|
253
|
+
const timer = setTimeout(() => {
|
|
254
|
+
cleanup();
|
|
255
|
+
reject(new Error("DataChannel buffer drain timeout"));
|
|
256
|
+
}, timeout);
|
|
257
|
+
const onClose = () => {
|
|
258
|
+
cleanup();
|
|
259
|
+
reject(new Error("DataChannel closed while waiting for buffer"));
|
|
260
|
+
};
|
|
261
|
+
const onError = () => {
|
|
262
|
+
cleanup();
|
|
263
|
+
reject(new Error("DataChannel error while waiting for buffer"));
|
|
264
|
+
};
|
|
265
|
+
const cleanup = () => {
|
|
266
|
+
clearTimeout(timer);
|
|
267
|
+
channel.removeEventListener("bufferedamountlow", check);
|
|
268
|
+
channel.removeEventListener("close", onClose);
|
|
269
|
+
channel.removeEventListener("error", onError);
|
|
270
|
+
};
|
|
271
|
+
const check = () => {
|
|
272
|
+
if (channel.bufferedAmount <= maxBuffer) {
|
|
273
|
+
cleanup();
|
|
274
|
+
resolve();
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
channel.bufferedAmountLowThreshold = maxBuffer;
|
|
278
|
+
channel.addEventListener("bufferedamountlow", check);
|
|
279
|
+
channel.addEventListener("close", onClose, { once: true });
|
|
280
|
+
channel.addEventListener("error", onError, { once: true });
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
throwIfAborted(signal) {
|
|
284
|
+
if (signal?.aborted) {
|
|
285
|
+
throw new DOMException("File transfer aborted", "AbortError");
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
async sendChunkWithRetry(channel, chunk, maxRetries) {
|
|
289
|
+
for (let i = 0; i <= maxRetries; i++) {
|
|
290
|
+
try {
|
|
291
|
+
channel.send(chunk);
|
|
292
|
+
return;
|
|
293
|
+
} catch {
|
|
294
|
+
if (i === maxRetries)
|
|
295
|
+
throw new Error("Chunk send failed after retries");
|
|
296
|
+
await new Promise((r) => setTimeout(r, 500 * (i + 1)));
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
302
|
+
0 && (module.exports = {
|
|
303
|
+
DataManager
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
//# sourceMappingURL=data-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"mappings":"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","names":[],"ignoreList":[],"sources":["../../../src/data/data-manager.ts"],"sourcesContent":["import { createLogger, type Logger } from '../utils/types';\r\nimport type { IDisposable } from '../disposable';\r\nimport type { DataChannelOptions, DataChannelConfig, FileTransferOptions, FileMeta } from './types';\r\n\r\nexport type { DataChannelOptions, DataChannelConfig, FileTransferOptions, FileMeta } from './types';\r\n\r\ninterface FileReceiveState {\r\n meta: FileMeta;\r\n chunks: Blob[];\r\n expectedChunks: number;\r\n receivedBytes: number;\r\n}\r\n\r\nconst MAX_BUFFER = 256 * 1024;\r\n\r\n/**\r\n * 数据通道管理器 — DataChannel + 文件传输\r\n */\r\nexport class DataManager implements IDisposable {\r\n private logger: Logger;\r\n private channels = new Map<string, RTCDataChannel>();\r\n private channelConfigs: DataChannelConfig[] = [];\r\n private messageHandlers: ((data: ArrayBuffer | Blob | string, channel?: string) => void)[] = [];\r\n private fileHandlers: ((meta: FileMeta, blob: Blob) => void)[] = [];\r\n private fileReceives = new Map<string, FileReceiveState>();\r\n\r\n constructor(private pc: RTCPeerConnection) {\r\n this.logger = createLogger();\r\n }\r\n\r\n /** 切换 PeerConnection(disconnect / reconnect 后 rebind) */\r\n setPeerConnection(pc: RTCPeerConnection): void {\r\n for (const [, channel] of this.channels) {\r\n channel.close();\r\n }\r\n this.channels.clear();\r\n this.fileReceives.clear();\r\n this.pc = pc;\r\n }\r\n\r\n createChannel(label: string, options?: DataChannelOptions): RTCDataChannel {\r\n if (this.channels.has(label)) {\r\n return this.channels.get(label)!;\r\n }\r\n\r\n const channel = this.pc.createDataChannel(label, options);\r\n this.registerChannel(label, channel);\r\n return channel;\r\n }\r\n\r\n registerRemoteChannel(event: RTCDataChannelEvent): void {\r\n const { channel } = event;\r\n this.registerChannel(channel.label, channel);\r\n }\r\n\r\n configureChannels(configs: DataChannelConfig[]): void {\r\n this.channelConfigs = configs;\r\n }\r\n\r\n initConfiguredChannels(): void {\r\n for (const config of this.channelConfigs) {\r\n this.createChannel(config.label, config.options);\r\n }\r\n }\r\n\r\n getChannel(label: string): RTCDataChannel | undefined {\r\n return this.channels.get(label);\r\n }\r\n\r\n send(data: ArrayBuffer | Blob | string, channelLabel?: string): void {\r\n if (channelLabel) {\r\n const ch = this.channels.get(channelLabel);\r\n if (!ch || ch.readyState !== 'open') {\r\n this.logger.warn(`DataChannel \"${channelLabel}\" not ready`);\r\n return;\r\n }\r\n this.doSend(ch, data);\r\n return;\r\n }\r\n\r\n let sent = false;\r\n for (const ch of this.channels.values()) {\r\n if (ch.readyState === 'open') {\r\n this.doSend(ch, data);\r\n sent = true;\r\n }\r\n }\r\n if (!sent) {\r\n this.logger.warn('No open DataChannel available');\r\n }\r\n }\r\n\r\n onMessage(handler: (data: ArrayBuffer | Blob | string, channel?: string) => void): () => void {\r\n this.messageHandlers.push(handler);\r\n return () => {\r\n this.messageHandlers = this.messageHandlers.filter(h => h !== handler);\r\n };\r\n }\r\n\r\n /** 订阅文件接收(与 sendFile 协议对称) */\r\n onFile(handler: (meta: FileMeta, blob: Blob) => void): () => void {\r\n this.fileHandlers.push(handler);\r\n return () => {\r\n this.fileHandlers = this.fileHandlers.filter(h => h !== handler);\r\n };\r\n }\r\n\r\n async sendFile(file: File, options?: FileTransferOptions): Promise<void> {\r\n const chunkSize = options?.chunkSize ?? 16384;\r\n const maxRetries = options?.maxRetries ?? 3;\r\n const bufferThreshold = options?.bufferThreshold ?? MAX_BUFFER;\r\n const bufferTimeout = options?.bufferTimeout ?? 10_000;\r\n const total = Math.ceil(file.size / chunkSize);\r\n\r\n this.throwIfAborted(options?.signal);\r\n if (options?.maxFileSize && file.size > options.maxFileSize) {\r\n throw new Error(`File exceeds maxFileSize (${file.size} > ${options.maxFileSize})`);\r\n }\r\n\r\n const fileChannel = this.createChannel(`file-${file.name}`, {\r\n ordered: true,\r\n });\r\n\r\n await this.waitForChannelOpen(fileChannel);\r\n\r\n await this.waitForBuffer(fileChannel, bufferThreshold, bufferTimeout);\r\n fileChannel.send(JSON.stringify({\r\n type: 'file-meta',\r\n name: file.name,\r\n size: file.size,\r\n chunks: total,\r\n mimeType: file.type,\r\n }));\r\n\r\n let offset = 0;\r\n\r\n while (offset < file.size) {\r\n this.throwIfAborted(options?.signal);\r\n const end = Math.min(offset + chunkSize, file.size);\r\n const chunk = file.slice(offset, end);\r\n await this.waitForBuffer(fileChannel, bufferThreshold, bufferTimeout);\r\n await this.sendChunkWithRetry(fileChannel, chunk, maxRetries);\r\n offset = end;\r\n options?.onProgress?.(offset, file.size);\r\n }\r\n\r\n await this.waitForBuffer(fileChannel, bufferThreshold, bufferTimeout);\r\n fileChannel.send(JSON.stringify({ type: 'file-complete', name: file.name }));\r\n }\r\n\r\n dispose(): void {\r\n for (const [, channel] of this.channels) {\r\n channel.close();\r\n }\r\n this.channels.clear();\r\n this.messageHandlers.length = 0;\r\n this.fileHandlers.length = 0;\r\n this.fileReceives.clear();\r\n this.logger.info('DataManager disposed');\r\n }\r\n\r\n // ── private ──\r\n\r\n private registerChannel(label: string, channel: RTCDataChannel): void {\r\n channel.onopen = () => this.logger.info(`DataChannel \"${label}\" opened`);\r\n channel.onclose = () => {\r\n this.logger.info(`DataChannel \"${label}\" closed`);\r\n this.fileReceives.delete(label);\r\n };\r\n channel.onerror = (ev) => this.logger.warn(`DataChannel \"${label}\" error:`, ev);\r\n\r\n channel.onmessage = (ev) => {\r\n this.handleChannelMessage(label, ev.data);\r\n };\r\n\r\n this.channels.set(label, channel);\r\n }\r\n\r\n private handleChannelMessage(label: string, data: unknown): void {\r\n if (typeof data === 'string') {\r\n try {\r\n const msg = JSON.parse(data);\r\n if (msg.type === 'file-meta') {\r\n this.fileReceives.set(label, {\r\n meta: {\r\n name: msg.name,\r\n size: msg.size,\r\n type: msg.mimeType ?? 'application/octet-stream',\r\n },\r\n chunks: [],\r\n expectedChunks: msg.chunks,\r\n receivedBytes: 0,\r\n });\r\n return;\r\n }\r\n if (msg.type === 'file-complete') {\r\n const state = this.fileReceives.get(label);\r\n if (state) {\r\n if (state.chunks.length !== state.expectedChunks) {\r\n this.logger.warn(\r\n `File \"${state.meta.name}\" incomplete: ${state.chunks.length}/${state.expectedChunks} chunks`,\r\n );\r\n this.fileReceives.delete(label);\r\n return;\r\n }\r\n if (state.receivedBytes !== state.meta.size) {\r\n this.logger.warn(\r\n `File \"${state.meta.name}\" size mismatch: ${state.receivedBytes}/${state.meta.size}`,\r\n );\r\n this.fileReceives.delete(label);\r\n return;\r\n }\r\n const blob = new Blob(state.chunks, { type: state.meta.type });\r\n for (const handler of this.fileHandlers) {\r\n try { handler(state.meta, blob); } catch {}\r\n }\r\n this.fileReceives.delete(label);\r\n }\r\n return;\r\n }\r\n } catch {\r\n // 非 JSON,继续作为普通消息\r\n }\r\n }\r\n\r\n const receiveState = this.fileReceives.get(label);\r\n if (receiveState && (data instanceof Blob || data instanceof ArrayBuffer)) {\r\n const size = data instanceof Blob ? data.size : data.byteLength;\r\n receiveState.chunks.push(\r\n data instanceof Blob ? data : new Blob([data]),\r\n );\r\n receiveState.receivedBytes += size;\r\n return;\r\n }\r\n\r\n for (const handler of this.messageHandlers) {\r\n try {\r\n handler(data as ArrayBuffer | Blob | string, label);\r\n } catch {}\r\n }\r\n }\r\n\r\n private doSend(channel: RTCDataChannel, data: ArrayBuffer | Blob | string): void {\r\n if (typeof data === 'string') {\r\n channel.send(data);\r\n } else if (data instanceof ArrayBuffer) {\r\n if (data.byteLength > 256 * 1024) {\r\n this.logger.warn(`Large message (${data.byteLength} bytes), consider chunking`);\r\n }\r\n channel.send(data);\r\n } else {\r\n channel.send(data);\r\n }\r\n }\r\n\r\n private waitForChannelOpen(channel: RTCDataChannel, timeout = 10_000): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n if (channel.readyState === 'open') return resolve();\r\n const timer = setTimeout(() => reject(new Error('DataChannel open timeout')), timeout);\r\n const prev = channel.onopen;\r\n channel.onopen = (ev) => {\r\n clearTimeout(timer);\r\n prev?.call(channel, ev);\r\n resolve();\r\n };\r\n });\r\n }\r\n\r\n private waitForBuffer(\r\n channel: RTCDataChannel,\r\n maxBuffer = MAX_BUFFER,\r\n timeout = 10_000,\r\n ): Promise<void> {\r\n if (channel.bufferedAmount <= maxBuffer) return Promise.resolve();\r\n return new Promise((resolve, reject) => {\r\n const timer = setTimeout(() => {\r\n cleanup();\r\n reject(new Error('DataChannel buffer drain timeout'));\r\n }, timeout);\r\n const onClose = () => {\r\n cleanup();\r\n reject(new Error('DataChannel closed while waiting for buffer'));\r\n };\r\n const onError = () => {\r\n cleanup();\r\n reject(new Error('DataChannel error while waiting for buffer'));\r\n };\r\n const cleanup = () => {\r\n clearTimeout(timer);\r\n channel.removeEventListener('bufferedamountlow', check);\r\n channel.removeEventListener('close', onClose);\r\n channel.removeEventListener('error', onError);\r\n };\r\n const check = () => {\r\n if (channel.bufferedAmount <= maxBuffer) {\r\n cleanup();\r\n resolve();\r\n }\r\n };\r\n channel.bufferedAmountLowThreshold = maxBuffer;\r\n channel.addEventListener('bufferedamountlow', check);\r\n channel.addEventListener('close', onClose, { once: true });\r\n channel.addEventListener('error', onError, { once: true });\r\n });\r\n }\r\n\r\n private throwIfAborted(signal?: AbortSignal): void {\r\n if (signal?.aborted) {\r\n throw new DOMException('File transfer aborted', 'AbortError');\r\n }\r\n }\r\n\r\n private async sendChunkWithRetry(\r\n channel: RTCDataChannel,\r\n chunk: Blob,\r\n maxRetries: number,\r\n ): Promise<void> {\r\n for (let i = 0; i <= maxRetries; i++) {\r\n try {\r\n channel.send(chunk);\r\n return;\r\n } catch {\r\n if (i === maxRetries) throw new Error('Chunk send failed after retries');\r\n await new Promise(r => setTimeout(r, 500 * (i + 1)));\r\n }\r\n }\r\n }\r\n}\r\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJtYXBwaW5ncyI6IiIsIm5hbWVzIjpbXSwiaWdub3JlTGlzdCI6W10sInNvdXJjZXMiOltdLCJzb3VyY2VzQ29udGVudCI6W119"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __copyProps = (to, from, except, desc) => {
|
|
7
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
8
|
+
for (let key of __getOwnPropNames(from))
|
|
9
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
10
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
11
|
+
}
|
|
12
|
+
return to;
|
|
13
|
+
};
|
|
14
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
15
|
+
var types_exports = {};
|
|
16
|
+
module.exports = __toCommonJS(types_exports);
|
|
17
|
+
|
|
18
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"mappings":";;;;;;;;;;;;;;AAAA;AAAA","names":[],"ignoreList":[],"sources":["../../../src/data/types.ts"],"sourcesContent":["export interface DataChannelOptions {\r\n ordered?: boolean;\r\n maxPacketLifeTime?: number;\r\n maxRetransmits?: number;\r\n protocol?: string;\r\n negotiated?: boolean;\r\n id?: number;\r\n}\r\n\r\nexport interface DataChannelConfig {\r\n label: string;\r\n options?: DataChannelOptions;\r\n}\r\n\r\nexport interface FileTransferOptions {\r\n /** 分片大小 (bytes),默认 16384 */\r\n chunkSize?: number;\r\n /** 超时重试次数,默认 3 */\r\n maxRetries?: number;\r\n /** 进度回调 */\r\n onProgress?: (sent: number, total: number) => void;\r\n /** 最大文件大小,默认不限制 */\r\n maxFileSize?: number;\r\n /** 取消传输 */\r\n signal?: AbortSignal;\r\n /** DataChannel 背压阈值,默认 256 KiB */\r\n bufferThreshold?: number;\r\n /** 等待背压释放超时,默认 10000ms */\r\n bufferTimeout?: number;\r\n}\r\n\r\nexport interface FileMeta {\r\n name: string;\r\n size: number;\r\n type: string;\r\n}"]}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var disposable_exports = {};
|
|
20
|
+
__export(disposable_exports, {
|
|
21
|
+
DisposableStack: () => DisposableStack
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(disposable_exports);
|
|
24
|
+
class DisposableStack {
|
|
25
|
+
constructor() {
|
|
26
|
+
this.disposables = [];
|
|
27
|
+
this.disposed = false;
|
|
28
|
+
}
|
|
29
|
+
push(d) {
|
|
30
|
+
if (this.disposed) {
|
|
31
|
+
d.dispose();
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
this.disposables.push(d);
|
|
35
|
+
}
|
|
36
|
+
defer(fn) {
|
|
37
|
+
this.push({ dispose: fn });
|
|
38
|
+
}
|
|
39
|
+
dispose() {
|
|
40
|
+
if (this.disposed)
|
|
41
|
+
return;
|
|
42
|
+
this.disposed = true;
|
|
43
|
+
for (let i = this.disposables.length - 1; i >= 0; i--) {
|
|
44
|
+
try {
|
|
45
|
+
this.disposables[i].dispose();
|
|
46
|
+
} catch {
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
this.disposables.length = 0;
|
|
50
|
+
}
|
|
51
|
+
get isDisposed() {
|
|
52
|
+
return this.disposed;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
56
|
+
0 && (module.exports = {
|
|
57
|
+
DisposableStack
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
//# sourceMappingURL=disposable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIO,MAAM,gBAAuC;AAAA,EAA7C;AACL,SAAQ,cAA6B,CAAC;AACtC,SAAQ,WAAW;AAAA;AAAA,EAEnB,KAAK,GAAsB;AACzB,QAAI,KAAK,UAAU;AACjB,QAAE,QAAQ;AACV;AAAA,IACF;AACA,SAAK,YAAY,KAAK,CAAC;AAAA,EACzB;AAAA,EAEA,MAAM,IAAsB;AAC1B,SAAK,KAAK,EAAE,SAAS,GAAG,CAAC;AAAA,EAC3B;AAAA,EAEA,UAAgB;AACd,QAAI,KAAK;AAAU;AACnB,SAAK,WAAW;AAChB,aAAS,IAAI,KAAK,YAAY,SAAS,GAAG,KAAK,GAAG,KAAK;AACrD,UAAI;AACF,aAAK,YAAY,CAAC,EAAE,QAAQ;AAAA,MAC9B,QAAQ;AAAA,MAER;AAAA,IACF;AACA,SAAK,YAAY,SAAS;AAAA,EAC5B;AAAA,EAEA,IAAI,aAAsB;AACxB,WAAO,KAAK;AAAA,EACd;AACF","names":[],"ignoreList":[],"sources":["../../src/disposable.ts"],"sourcesContent":["export interface IDisposable {\r\n dispose(): void;\r\n}\r\n\r\nexport class DisposableStack implements IDisposable {\r\n private disposables: IDisposable[] = [];\r\n private disposed = false;\r\n\r\n push(d: IDisposable): void {\r\n if (this.disposed) {\r\n d.dispose();\r\n return;\r\n }\r\n this.disposables.push(d);\r\n }\r\n\r\n defer(fn: () => void): void {\r\n this.push({ dispose: fn });\r\n }\r\n\r\n dispose(): void {\r\n if (this.disposed) return;\r\n this.disposed = true;\r\n for (let i = this.disposables.length - 1; i >= 0; i--) {\r\n try {\r\n this.disposables[i].dispose();\r\n } catch {\r\n // 忽略单个资源释放错误,继续释放其他资源\r\n }\r\n }\r\n this.disposables.length = 0;\r\n }\r\n\r\n get isDisposed(): boolean {\r\n return this.disposed;\r\n }\r\n}"]}
|
package/dist/lib/fsm.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var fsm_exports = {};
|
|
20
|
+
__export(fsm_exports, {
|
|
21
|
+
ConnectionStateMachine: () => ConnectionStateMachine
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(fsm_exports);
|
|
24
|
+
const _ConnectionStateMachine = class _ConnectionStateMachine {
|
|
25
|
+
constructor() {
|
|
26
|
+
this._state = "idle";
|
|
27
|
+
this.listeners = [];
|
|
28
|
+
}
|
|
29
|
+
get state() {
|
|
30
|
+
return this._state;
|
|
31
|
+
}
|
|
32
|
+
/** 尝试转换状态,非法转换抛错 */
|
|
33
|
+
transition(to) {
|
|
34
|
+
const allowed = _ConnectionStateMachine.transitions[this._state];
|
|
35
|
+
if (!allowed.includes(to)) {
|
|
36
|
+
throw new Error(
|
|
37
|
+
`[WetRTC] Invalid state transition: ${this._state} → ${to}. Allowed: ${allowed.join(", ")}`
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
const prev = this._state;
|
|
41
|
+
this._state = to;
|
|
42
|
+
this.notify(to, prev);
|
|
43
|
+
}
|
|
44
|
+
/** 强制设置状态(仅用于 dispose / 错误恢复) */
|
|
45
|
+
force(to) {
|
|
46
|
+
const prev = this._state;
|
|
47
|
+
this._state = to;
|
|
48
|
+
this.notify(to, prev);
|
|
49
|
+
}
|
|
50
|
+
is(...states) {
|
|
51
|
+
return states.includes(this._state);
|
|
52
|
+
}
|
|
53
|
+
onChange(fn) {
|
|
54
|
+
this.listeners.push(fn);
|
|
55
|
+
return () => {
|
|
56
|
+
this.listeners = this.listeners.filter((l) => l !== fn);
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
notify(newState, prev) {
|
|
60
|
+
for (const fn of this.listeners) {
|
|
61
|
+
try {
|
|
62
|
+
fn(newState, prev);
|
|
63
|
+
} catch {
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
dispose() {
|
|
68
|
+
this.listeners.length = 0;
|
|
69
|
+
this.force("disposed");
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
_ConnectionStateMachine.transitions = {
|
|
73
|
+
idle: ["signaling", "disposed"],
|
|
74
|
+
signaling: ["connecting", "failed", "disposed"],
|
|
75
|
+
connecting: ["connected", "failed", "disposed"],
|
|
76
|
+
connected: ["reconnecting", "failed", "disposed"],
|
|
77
|
+
reconnecting: ["connected", "failed", "disposed"],
|
|
78
|
+
failed: ["idle", "disposed"],
|
|
79
|
+
disposed: []
|
|
80
|
+
};
|
|
81
|
+
let ConnectionStateMachine = _ConnectionStateMachine;
|
|
82
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
83
|
+
0 && (module.exports = {
|
|
84
|
+
ConnectionStateMachine
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
//# sourceMappingURL=fsm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAwBO,MAAM,0BAAN,MAAM,wBAA8C;AAAA,EAApD;AACL,SAAQ,SAA0B;AAClC,SAAQ,YAA4E,CAAC;AAAA;AAAA,EAYrF,IAAI,QAAyB;AAC3B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,WAAW,IAA2B;AACpC,UAAM,UAAU,wBAAuB,YAAY,KAAK,MAAM;AAC9D,QAAI,CAAC,QAAQ,SAAS,EAAE,GAAG;AACzB,YAAM,IAAI;AAAA,QACR,sCAAsC,KAAK,MAAM,MAAM,EAAE,cAC7C,QAAQ,KAAK,IAAI,CAAC;AAAA,MAChC;AAAA,IACF;AACA,UAAM,OAAO,KAAK;AAClB,SAAK,SAAS;AACd,SAAK,OAAO,IAAI,IAAI;AAAA,EACtB;AAAA;AAAA,EAGA,MAAM,IAA2B;AAC/B,UAAM,OAAO,KAAK;AAClB,SAAK,SAAS;AACd,SAAK,OAAO,IAAI,IAAI;AAAA,EACtB;AAAA,EAEA,MAAM,QAAoC;AACxC,WAAO,OAAO,SAAS,KAAK,MAAM;AAAA,EACpC;AAAA,EAEA,SAAS,IAA4E;AACnF,SAAK,UAAU,KAAK,EAAE;AACtB,WAAO,MAAM;AACX,WAAK,YAAY,KAAK,UAAU,OAAO,OAAK,MAAM,EAAE;AAAA,IACtD;AAAA,EACF;AAAA,EAEQ,OAAO,UAA2B,MAA6B;AACrE,eAAW,MAAM,KAAK,WAAW;AAC/B,UAAI;AAAE,WAAG,UAAU,IAAI;AAAA,MAAG,QAAQ;AAAA,MAAgB;AAAA,IACpD;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,SAAK,UAAU,SAAS;AACxB,SAAK,MAAM,UAAU;AAAA,EACvB;AACF;AA5Da,wBAII,cAAkC;AAAA,EAC/C,MAAc,CAAC,aAAa,UAAU;AAAA,EACtC,WAAc,CAAC,cAAc,UAAU,UAAU;AAAA,EACjD,YAAc,CAAC,aAAa,UAAU,UAAU;AAAA,EAChD,WAAc,CAAC,gBAAgB,UAAU,UAAU;AAAA,EACnD,cAAc,CAAC,aAAa,UAAU,UAAU;AAAA,EAChD,QAAc,CAAC,QAAQ,UAAU;AAAA,EACjC,UAAc,CAAC;AACjB;AAZK,IAAM,yBAAN","names":[],"ignoreList":[],"sources":["../../src/fsm.ts"],"sourcesContent":["import type { IDisposable } from './disposable';\r\n\r\nexport type ConnectionState =\r\n | 'idle'\r\n | 'signaling'\r\n | 'connecting'\r\n | 'connected'\r\n | 'reconnecting'\r\n | 'failed'\r\n | 'disposed';\r\n\r\ntype StateTransitionMap = {\r\n [S in ConnectionState]: ConnectionState[];\r\n};\r\n\r\n/**\r\n * 连接状态机 — 防止非法状态调用\r\n *\r\n * idle → signaling → connecting → connected\r\n * ↓ ↓ ↓\r\n * disposed failed reconnecting\r\n * ↓ ↓\r\n * connected failed\r\n */\r\nexport class ConnectionStateMachine implements IDisposable {\r\n private _state: ConnectionState = 'idle';\r\n private listeners: ((newState: ConnectionState, prev: ConnectionState) => void)[] = [];\r\n\r\n private static transitions: StateTransitionMap = {\r\n idle: ['signaling', 'disposed'],\r\n signaling: ['connecting', 'failed', 'disposed'],\r\n connecting: ['connected', 'failed', 'disposed'],\r\n connected: ['reconnecting', 'failed', 'disposed'],\r\n reconnecting: ['connected', 'failed', 'disposed'],\r\n failed: ['idle', 'disposed'],\r\n disposed: [],\r\n };\r\n\r\n get state(): ConnectionState {\r\n return this._state;\r\n }\r\n\r\n /** 尝试转换状态,非法转换抛错 */\r\n transition(to: ConnectionState): void {\r\n const allowed = ConnectionStateMachine.transitions[this._state];\r\n if (!allowed.includes(to)) {\r\n throw new Error(\r\n `[WetRTC] Invalid state transition: ${this._state} → ${to}. ` +\r\n `Allowed: ${allowed.join(', ')}`\r\n );\r\n }\r\n const prev = this._state;\r\n this._state = to;\r\n this.notify(to, prev);\r\n }\r\n\r\n /** 强制设置状态(仅用于 dispose / 错误恢复) */\r\n force(to: ConnectionState): void {\r\n const prev = this._state;\r\n this._state = to;\r\n this.notify(to, prev);\r\n }\r\n\r\n is(...states: ConnectionState[]): boolean {\r\n return states.includes(this._state);\r\n }\r\n\r\n onChange(fn: (newState: ConnectionState, prev: ConnectionState) => void): () => void {\r\n this.listeners.push(fn);\r\n return () => {\r\n this.listeners = this.listeners.filter(l => l !== fn);\r\n };\r\n }\r\n\r\n private notify(newState: ConnectionState, prev: ConnectionState): void {\r\n for (const fn of this.listeners) {\r\n try { fn(newState, prev); } catch { /* 忽略监听器异常 */ }\r\n }\r\n }\r\n\r\n dispose(): void {\r\n this.listeners.length = 0;\r\n this.force('disposed');\r\n }\r\n}//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJtYXBwaW5ncyI6IiIsIm5hbWVzIjpbXSwiaWdub3JlTGlzdCI6W10sInNvdXJjZXMiOltdLCJzb3VyY2VzQ29udGVudCI6W119"]}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var src_exports = {};
|
|
20
|
+
__export(src_exports, {
|
|
21
|
+
ConnectionStateMachine: () => import_fsm.ConnectionStateMachine,
|
|
22
|
+
DataManager: () => import_data_manager.DataManager,
|
|
23
|
+
DisposableStack: () => import_disposable.DisposableStack,
|
|
24
|
+
MediaManager: () => import_media_manager.MediaManager,
|
|
25
|
+
SignalManager: () => import_signal_manager.SignalManager,
|
|
26
|
+
StatsMonitor: () => import_stats_monitor.StatsMonitor,
|
|
27
|
+
WetRTC: () => import_wetrtc.WetRTC,
|
|
28
|
+
applyAudioEncodingToConnection: () => import_audio_encoding.applyAudioEncodingToConnection,
|
|
29
|
+
applyAudioSenderEncoding: () => import_audio_encoding.applyAudioSenderEncoding,
|
|
30
|
+
applyH264CodecPreference: () => import_codec_preference.applyH264CodecPreference,
|
|
31
|
+
applyH264CodecPreferences: () => import_codec_preference.applyH264CodecPreferences,
|
|
32
|
+
applyOpusCodecPreference: () => import_codec_preference.applyOpusCodecPreference,
|
|
33
|
+
applyOpusCodecPreferences: () => import_codec_preference.applyOpusCodecPreferences,
|
|
34
|
+
applyReceiverPlayoutDelay: () => import_video_encoding.applyReceiverPlayoutDelay,
|
|
35
|
+
applyVideoEncodingToConnection: () => import_video_encoding.applyVideoEncodingToConnection,
|
|
36
|
+
applyVideoSenderEncoding: () => import_video_encoding.applyVideoSenderEncoding,
|
|
37
|
+
applyVideoTrackContentHint: () => import_video_encoding.applyVideoTrackContentHint,
|
|
38
|
+
sortAudioCodecsOpusFirst: () => import_codec_preference.sortAudioCodecsOpusFirst,
|
|
39
|
+
sortVideoCodecsH264First: () => import_codec_preference.sortVideoCodecsH264First
|
|
40
|
+
});
|
|
41
|
+
module.exports = __toCommonJS(src_exports);
|
|
42
|
+
var import_wetrtc = require("./wetrtc");
|
|
43
|
+
var import_signal_manager = require("./signal/signal-manager");
|
|
44
|
+
var import_media_manager = require("./media/media-manager");
|
|
45
|
+
var import_data_manager = require("./data/data-manager");
|
|
46
|
+
var import_stats_monitor = require("./stats/stats-monitor");
|
|
47
|
+
var import_fsm = require("./fsm");
|
|
48
|
+
var import_disposable = require("./disposable");
|
|
49
|
+
var import_video_encoding = require("./media/video-encoding");
|
|
50
|
+
var import_audio_encoding = require("./media/audio-encoding");
|
|
51
|
+
var import_codec_preference = require("./media/codec-preference");
|
|
52
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
53
|
+
0 && (module.exports = {
|
|
54
|
+
ConnectionStateMachine,
|
|
55
|
+
DataManager,
|
|
56
|
+
DisposableStack,
|
|
57
|
+
MediaManager,
|
|
58
|
+
SignalManager,
|
|
59
|
+
StatsMonitor,
|
|
60
|
+
WetRTC,
|
|
61
|
+
applyAudioEncodingToConnection,
|
|
62
|
+
applyAudioSenderEncoding,
|
|
63
|
+
applyH264CodecPreference,
|
|
64
|
+
applyH264CodecPreferences,
|
|
65
|
+
applyOpusCodecPreference,
|
|
66
|
+
applyOpusCodecPreferences,
|
|
67
|
+
applyReceiverPlayoutDelay,
|
|
68
|
+
applyVideoEncodingToConnection,
|
|
69
|
+
applyVideoSenderEncoding,
|
|
70
|
+
applyVideoTrackContentHint,
|
|
71
|
+
sortAudioCodecsOpusFirst,
|
|
72
|
+
sortVideoCodecsH264First
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAuB;AACvB,4BAA8B;AAC9B,2BAA6B;AAC7B,0BAA4B;AAC5B,2BAA6B;AAC7B,iBAAuC;AAEvC,wBAAkD;AAmBlD,4BAKO;AACP,4BAGO;AACP,8BAOO","names":[],"ignoreList":[],"sources":["../../src/index.ts"],"sourcesContent":["export { WetRTC } from './wetrtc';\r\nexport { SignalManager } from './signal/signal-manager';\r\nexport { MediaManager } from './media/media-manager';\r\nexport { DataManager } from './data/data-manager';\r\nexport { StatsMonitor } from './stats/stats-monitor';\r\nexport { ConnectionStateMachine } from './fsm';\r\nexport type { ConnectionState } from './fsm';\r\nexport { DisposableStack, type IDisposable } from './disposable';\r\n\r\nexport type { WetRTCConfig } from './wetrtc';\r\nexport type { SignalChannel, SignalMessage } from './signal/types';\r\nexport type { SignalConfig } from './signal/signal-manager';\r\nexport type {\r\n DeviceInfo,\r\n DisplayMediaOptions,\r\n UserMediaOptions,\r\n MediaConstraints,\r\n} from './media/types';\r\nexport type { VideoEncodingOptions } from './media/video-encoding';\r\nexport type { AudioEncodingOptions } from './media/audio-encoding';\r\nexport type {\r\n PreferredVideoCodec,\r\n PreferredAudioCodec,\r\n VideoRtpCodec,\r\n AudioRtpCodec,\r\n} from './media/codec-preference';\r\nexport {\r\n applyVideoTrackContentHint,\r\n applyVideoSenderEncoding,\r\n applyReceiverPlayoutDelay,\r\n applyVideoEncodingToConnection,\r\n} from './media/video-encoding';\r\nexport {\r\n applyAudioSenderEncoding,\r\n applyAudioEncodingToConnection,\r\n} from './media/audio-encoding';\r\nexport {\r\n sortVideoCodecsH264First,\r\n applyH264CodecPreference,\r\n applyH264CodecPreferences,\r\n sortAudioCodecsOpusFirst,\r\n applyOpusCodecPreference,\r\n applyOpusCodecPreferences,\r\n} from './media/codec-preference';\r\nexport type {\r\n DataChannelOptions,\r\n DataChannelConfig,\r\n FileTransferOptions,\r\n FileMeta,\r\n} from './data/types';\r\nexport type {\r\n StatsSnapshot,\r\n DiagnosticReport,\r\n StatsMonitorOptions,\r\n} from './stats/types';\r\nexport type {\r\n WetRTCEvent,\r\n WetRTCEventMap,\r\n WetRTCError,\r\n WetRTCErrorCode,\r\n} from './utils/types';//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJtYXBwaW5ncyI6IiIsIm5hbWVzIjpbXSwiaWdub3JlTGlzdCI6W10sInNvdXJjZXMiOltdLCJzb3VyY2VzQ29udGVudCI6W119"]}
|