@ziplayer/plugin 0.2.1-dev-3 → 0.2.1-dev-4
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.
|
@@ -1,13 +1,3 @@
|
|
|
1
1
|
import { Readable } from "stream";
|
|
2
|
-
/**
|
|
3
|
-
* Converts a Web ReadableStream to a Node.js Readable stream
|
|
4
|
-
* with proper backpressure handling to prevent memory bloat
|
|
5
|
-
*
|
|
6
|
-
* Optimization:
|
|
7
|
-
* - Respects highWaterMark (64KB buffer)
|
|
8
|
-
* - Handles backpressure by pausing reads when buffer is full
|
|
9
|
-
* - Batches small chunks to reduce overhead
|
|
10
|
-
* - Lazy evaluation - only reads when consumer is ready
|
|
11
|
-
*/
|
|
12
2
|
export declare function webStreamToNodeStream(webStream: ReadableStream, highWaterMark?: number): Readable;
|
|
13
3
|
//# sourceMappingURL=stream-converter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream-converter.d.ts","sourceRoot":"","sources":["../../src/utils/stream-converter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC
|
|
1
|
+
{"version":3,"file":"stream-converter.d.ts","sourceRoot":"","sources":["../../src/utils/stream-converter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,cAAc,EAAE,aAAa,GAAE,MAAkB,GAAG,QAAQ,CAkB5G"}
|
|
@@ -2,140 +2,24 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.webStreamToNodeStream = webStreamToNodeStream;
|
|
4
4
|
const stream_1 = require("stream");
|
|
5
|
-
/**
|
|
6
|
-
* Converts a Web ReadableStream to a Node.js Readable stream
|
|
7
|
-
* with proper backpressure handling to prevent memory bloat
|
|
8
|
-
*
|
|
9
|
-
* Optimization:
|
|
10
|
-
* - Respects highWaterMark (64KB buffer)
|
|
11
|
-
* - Handles backpressure by pausing reads when buffer is full
|
|
12
|
-
* - Batches small chunks to reduce overhead
|
|
13
|
-
* - Lazy evaluation - only reads when consumer is ready
|
|
14
|
-
*/
|
|
15
5
|
function webStreamToNodeStream(webStream, highWaterMark = 64 * 1024) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
// Set buffer size to 64KB - balance between memory and throughput
|
|
22
|
-
highWaterMark: highWaterMark,
|
|
23
|
-
read(size) {
|
|
24
|
-
// Resume reading when stream is ready for more data
|
|
25
|
-
if (!isReading && pumpActive && reader) {
|
|
26
|
-
isReading = true;
|
|
27
|
-
pump().catch((error) => {
|
|
28
|
-
if (pumpActive) {
|
|
29
|
-
console.error("[stream-converter] Pump error:", error);
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
|
-
destroy(error, callback) {
|
|
35
|
-
// Gracefully stop the pump when stream is destroyed
|
|
36
|
-
pumpActive = false;
|
|
37
|
-
// Cancel reader if active
|
|
38
|
-
if (reader) {
|
|
39
|
-
try {
|
|
40
|
-
reader.cancel().catch(() => {
|
|
41
|
-
// Ignore cancel errors
|
|
42
|
-
});
|
|
43
|
-
reader = null;
|
|
44
|
-
}
|
|
45
|
-
catch { }
|
|
46
|
-
}
|
|
47
|
-
// Abort any pending operations
|
|
48
|
-
if (abortController) {
|
|
49
|
-
try {
|
|
50
|
-
abortController.abort();
|
|
51
|
-
}
|
|
52
|
-
catch { }
|
|
53
|
-
abortController = null;
|
|
54
|
-
}
|
|
55
|
-
callback(error);
|
|
56
|
-
},
|
|
57
|
-
});
|
|
58
|
-
// Define pump function with backpressure handling
|
|
59
|
-
const pump = async () => {
|
|
60
|
-
let cleanup = false;
|
|
61
|
-
try {
|
|
62
|
-
while (pumpActive && reader) {
|
|
6
|
+
const reader = webStream.getReader();
|
|
7
|
+
return new stream_1.Readable({
|
|
8
|
+
highWaterMark: highWaterMark ?? 64 * 1024,
|
|
9
|
+
async read() {
|
|
10
|
+
try {
|
|
63
11
|
const { done, value } = await reader.read();
|
|
64
|
-
// Check if pump was stopped during read
|
|
65
|
-
if (!pumpActive || !reader) {
|
|
66
|
-
cleanup = true;
|
|
67
|
-
break;
|
|
68
|
-
}
|
|
69
12
|
if (done) {
|
|
70
|
-
|
|
71
|
-
cleanup = true;
|
|
72
|
-
break;
|
|
73
|
-
}
|
|
74
|
-
if (value && pumpActive) {
|
|
75
|
-
// Convert to Buffer and push
|
|
76
|
-
const buffer = Buffer.from(value);
|
|
77
|
-
// Check backpressure: push() returns false if internal buffer is full
|
|
78
|
-
const shouldContinue = nodeStream.push(buffer);
|
|
79
|
-
if (!shouldContinue) {
|
|
80
|
-
// Internal buffer is full, pause reading
|
|
81
|
-
isReading = false;
|
|
82
|
-
return; // exit pump early; resume on drain or read
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
catch (error) {
|
|
88
|
-
cleanup = true;
|
|
89
|
-
if (pumpActive) {
|
|
90
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
91
|
-
if (errorMsg.includes("Controller is already closed") ||
|
|
92
|
-
errorMsg.includes("already been cancelled") ||
|
|
93
|
-
errorMsg.includes("stream closed") ||
|
|
94
|
-
errorMsg.includes("aborted")) {
|
|
95
|
-
nodeStream.push(null);
|
|
13
|
+
this.push(null);
|
|
96
14
|
}
|
|
97
15
|
else {
|
|
98
|
-
|
|
16
|
+
this.push(value);
|
|
99
17
|
}
|
|
100
18
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
isReading = false;
|
|
104
|
-
if (cleanup) {
|
|
105
|
-
try {
|
|
106
|
-
if (reader) {
|
|
107
|
-
await reader.cancel();
|
|
108
|
-
reader = null;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
catch { }
|
|
112
|
-
pumpActive = false;
|
|
19
|
+
catch (err) {
|
|
20
|
+
this.destroy(err);
|
|
113
21
|
}
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
// Restart pump when backpressure is relieved
|
|
117
|
-
nodeStream.on("drain", () => {
|
|
118
|
-
if (!isReading && pumpActive && reader) {
|
|
119
|
-
isReading = true;
|
|
120
|
-
pump().catch((error) => {
|
|
121
|
-
if (pumpActive) {
|
|
122
|
-
console.error("[stream-converter] Pump error on drain:", error);
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
// Start initial pump when stream is requested
|
|
128
|
-
// Note: pump will be called by read() callback for backpressure compliance
|
|
129
|
-
setImmediate(() => {
|
|
130
|
-
if (pumpActive && reader && !isReading) {
|
|
131
|
-
isReading = true;
|
|
132
|
-
pump().catch((error) => {
|
|
133
|
-
if (pumpActive) {
|
|
134
|
-
console.error("[stream-converter] Initial pump error:", error);
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
}
|
|
22
|
+
},
|
|
138
23
|
});
|
|
139
|
-
return nodeStream;
|
|
140
24
|
}
|
|
141
25
|
//# sourceMappingURL=stream-converter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream-converter.js","sourceRoot":"","sources":["../../src/utils/stream-converter.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"stream-converter.js","sourceRoot":"","sources":["../../src/utils/stream-converter.ts"],"names":[],"mappings":";;AAEA,sDAkBC;AApBD,mCAAkC;AAElC,SAAgB,qBAAqB,CAAC,SAAyB,EAAE,gBAAwB,EAAE,GAAG,IAAI;IACjG,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,EAAE,CAAC;IAErC,OAAO,IAAI,iBAAQ,CAAC;QACnB,aAAa,EAAE,aAAa,IAAI,EAAE,GAAG,IAAI;QACzC,KAAK,CAAC,IAAI;YACT,IAAI,CAAC;gBACJ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;gBAC5C,IAAI,IAAI,EAAE,CAAC;oBACV,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACjB,CAAC;qBAAM,CAAC;oBACP,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAClB,CAAC;YACF,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACd,IAAI,CAAC,OAAO,CAAC,GAAY,CAAC,CAAC;YAC5B,CAAC;QACF,CAAC;KACD,CAAC,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,149 +1,21 @@
|
|
|
1
1
|
import { Readable } from "stream";
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* Converts a Web ReadableStream to a Node.js Readable stream
|
|
5
|
-
* with proper backpressure handling to prevent memory bloat
|
|
6
|
-
*
|
|
7
|
-
* Optimization:
|
|
8
|
-
* - Respects highWaterMark (64KB buffer)
|
|
9
|
-
* - Handles backpressure by pausing reads when buffer is full
|
|
10
|
-
* - Batches small chunks to reduce overhead
|
|
11
|
-
* - Lazy evaluation - only reads when consumer is ready
|
|
12
|
-
*/
|
|
13
3
|
export function webStreamToNodeStream(webStream: ReadableStream, highWaterMark: number = 64 * 1024): Readable {
|
|
14
|
-
|
|
15
|
-
let pumpActive = true;
|
|
16
|
-
let abortController: AbortController | null = null;
|
|
17
|
-
let isReading = false; // Prevent concurrent reads
|
|
4
|
+
const reader = webStream.getReader();
|
|
18
5
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
read(size?: number) {
|
|
24
|
-
// Resume reading when stream is ready for more data
|
|
25
|
-
if (!isReading && pumpActive && reader) {
|
|
26
|
-
isReading = true;
|
|
27
|
-
pump().catch((error) => {
|
|
28
|
-
if (pumpActive) {
|
|
29
|
-
console.error("[stream-converter] Pump error:", error);
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
|
-
|
|
35
|
-
destroy(error: Error | null, callback: (error?: Error | null) => void) {
|
|
36
|
-
// Gracefully stop the pump when stream is destroyed
|
|
37
|
-
pumpActive = false;
|
|
38
|
-
|
|
39
|
-
// Cancel reader if active
|
|
40
|
-
if (reader) {
|
|
41
|
-
try {
|
|
42
|
-
reader.cancel().catch(() => {
|
|
43
|
-
// Ignore cancel errors
|
|
44
|
-
});
|
|
45
|
-
reader = null;
|
|
46
|
-
} catch {}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Abort any pending operations
|
|
50
|
-
if (abortController) {
|
|
51
|
-
try {
|
|
52
|
-
abortController.abort();
|
|
53
|
-
} catch {}
|
|
54
|
-
abortController = null;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
callback(error);
|
|
58
|
-
},
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
// Define pump function with backpressure handling
|
|
62
|
-
const pump = async () => {
|
|
63
|
-
let cleanup = false;
|
|
64
|
-
try {
|
|
65
|
-
while (pumpActive && reader) {
|
|
6
|
+
return new Readable({
|
|
7
|
+
highWaterMark: highWaterMark ?? 64 * 1024,
|
|
8
|
+
async read() {
|
|
9
|
+
try {
|
|
66
10
|
const { done, value } = await reader.read();
|
|
67
|
-
|
|
68
|
-
// Check if pump was stopped during read
|
|
69
|
-
if (!pumpActive || !reader) {
|
|
70
|
-
cleanup = true;
|
|
71
|
-
break;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
11
|
if (done) {
|
|
75
|
-
|
|
76
|
-
cleanup = true;
|
|
77
|
-
break;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (value && pumpActive) {
|
|
81
|
-
// Convert to Buffer and push
|
|
82
|
-
const buffer = Buffer.from(value);
|
|
83
|
-
|
|
84
|
-
// Check backpressure: push() returns false if internal buffer is full
|
|
85
|
-
const shouldContinue = nodeStream.push(buffer);
|
|
86
|
-
|
|
87
|
-
if (!shouldContinue) {
|
|
88
|
-
// Internal buffer is full, pause reading
|
|
89
|
-
isReading = false;
|
|
90
|
-
return; // exit pump early; resume on drain or read
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
} catch (error) {
|
|
95
|
-
cleanup = true;
|
|
96
|
-
if (pumpActive) {
|
|
97
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
98
|
-
if (
|
|
99
|
-
errorMsg.includes("Controller is already closed") ||
|
|
100
|
-
errorMsg.includes("already been cancelled") ||
|
|
101
|
-
errorMsg.includes("stream closed") ||
|
|
102
|
-
errorMsg.includes("aborted")
|
|
103
|
-
) {
|
|
104
|
-
nodeStream.push(null);
|
|
12
|
+
this.push(null);
|
|
105
13
|
} else {
|
|
106
|
-
|
|
14
|
+
this.push(value);
|
|
107
15
|
}
|
|
16
|
+
} catch (err) {
|
|
17
|
+
this.destroy(err as Error);
|
|
108
18
|
}
|
|
109
|
-
}
|
|
110
|
-
isReading = false;
|
|
111
|
-
if (cleanup) {
|
|
112
|
-
try {
|
|
113
|
-
if (reader) {
|
|
114
|
-
await reader.cancel();
|
|
115
|
-
reader = null;
|
|
116
|
-
}
|
|
117
|
-
} catch {}
|
|
118
|
-
pumpActive = false;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
// Restart pump when backpressure is relieved
|
|
124
|
-
nodeStream.on("drain", () => {
|
|
125
|
-
if (!isReading && pumpActive && reader) {
|
|
126
|
-
isReading = true;
|
|
127
|
-
pump().catch((error) => {
|
|
128
|
-
if (pumpActive) {
|
|
129
|
-
console.error("[stream-converter] Pump error on drain:", error);
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
// Start initial pump when stream is requested
|
|
136
|
-
// Note: pump will be called by read() callback for backpressure compliance
|
|
137
|
-
setImmediate(() => {
|
|
138
|
-
if (pumpActive && reader && !isReading) {
|
|
139
|
-
isReading = true;
|
|
140
|
-
pump().catch((error) => {
|
|
141
|
-
if (pumpActive) {
|
|
142
|
-
console.error("[stream-converter] Initial pump error:", error);
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
}
|
|
19
|
+
},
|
|
146
20
|
});
|
|
147
|
-
|
|
148
|
-
return nodeStream;
|
|
149
21
|
}
|