@sawa-siemens/socket.io-stream 0.10.1 → 1.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/.github/workflows/test.yml +34 -0
- package/README.md +54 -42
- package/esbuild.config.js +29 -0
- package/lib/iostream.js +50 -7
- package/package.json +13 -9
- package/socket.io-stream.js +19 -9911
- package/vitest.config.mjs +11 -0
- package/.travis.yml +0 -28
- package/.zuul.yml +0 -6
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master, main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [master, main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
|
|
13
|
+
strategy:
|
|
14
|
+
matrix:
|
|
15
|
+
node-version: [18.x, 20.x, 22.x]
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- name: Checkout repository
|
|
19
|
+
uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Setup Node.js ${{ matrix.node-version }}
|
|
22
|
+
uses: actions/setup-node@v4
|
|
23
|
+
with:
|
|
24
|
+
node-version: ${{ matrix.node-version }}
|
|
25
|
+
cache: 'npm'
|
|
26
|
+
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
run: npm ci
|
|
29
|
+
|
|
30
|
+
- name: Run tests
|
|
31
|
+
run: npm test
|
|
32
|
+
|
|
33
|
+
- name: Build
|
|
34
|
+
run: npm run build
|
package/README.md
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @sawa-siemens/socket.io-stream
|
|
2
2
|
|
|
3
|
-
[](https://github.com/sawa-siemens/socket.io-stream/actions/workflows/test.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/@sawa-siemens/socket.io-stream)
|
|
5
5
|
|
|
6
|
-
This is the module for bidirectional binary data transfer with Stream API through [Socket.IO](https://github.com/socketio/socket.io).
|
|
6
|
+
This is the module for bidirectional binary data transfer with Stream API through [Socket.IO](https://github.com/socketio/socket.io).
|
|
7
|
+
🚨 The purpose of fork @sawa-siemens/socket-io.stream:
|
|
8
|
+
|
|
9
|
+
1. Add support for Typescript type interface
|
|
10
|
+
2. Original package is lack of maintenance in security auditing. Aim at free npm audit vulnerabilities for it's dependency.
|
|
7
11
|
|
|
8
12
|
## Installation
|
|
9
13
|
|
|
10
|
-
npm install socket.io-stream
|
|
14
|
+
npm install @sawa-siemens/socket.io-stream
|
|
11
15
|
|
|
12
16
|
## Usage
|
|
13
17
|
|
|
@@ -20,12 +24,12 @@ To receive streams, you just wrap `socket` with `socket.io-stream`, then listen
|
|
|
20
24
|
Server:
|
|
21
25
|
|
|
22
26
|
```js
|
|
23
|
-
var io = require(
|
|
24
|
-
var ss = require(
|
|
25
|
-
var path = require(
|
|
27
|
+
var io = require("socket.io").listen(80);
|
|
28
|
+
var ss = require("@sawa-siemens/socket.io-stream");
|
|
29
|
+
var path = require("path");
|
|
26
30
|
|
|
27
|
-
io.of(
|
|
28
|
-
ss(socket).on(
|
|
31
|
+
io.of("/user").on("connection", function (socket) {
|
|
32
|
+
ss(socket).on("profile-image", function (stream, data) {
|
|
29
33
|
var filename = path.basename(data.name);
|
|
30
34
|
stream.pipe(fs.createWriteStream(filename));
|
|
31
35
|
});
|
|
@@ -37,14 +41,14 @@ io.of('/user').on('connection', function(socket) {
|
|
|
37
41
|
Client:
|
|
38
42
|
|
|
39
43
|
```js
|
|
40
|
-
var io = require(
|
|
41
|
-
var ss = require(
|
|
44
|
+
var io = require("socket.io-client");
|
|
45
|
+
var ss = require("@sawa-siemens/socket.io-stream");
|
|
42
46
|
|
|
43
|
-
var socket = io.connect(
|
|
47
|
+
var socket = io.connect("http://example.com/user");
|
|
44
48
|
var stream = ss.createStream();
|
|
45
|
-
var filename =
|
|
49
|
+
var filename = "profile.jpg";
|
|
46
50
|
|
|
47
|
-
ss(socket).emit(
|
|
51
|
+
ss(socket).emit("profile-image", stream, { name: filename });
|
|
48
52
|
fs.createReadStream(filename).pipe(stream);
|
|
49
53
|
```
|
|
50
54
|
|
|
@@ -52,25 +56,34 @@ You can stream data from a client to server, and vice versa.
|
|
|
52
56
|
|
|
53
57
|
```js
|
|
54
58
|
// send data
|
|
55
|
-
ss(socket).on(
|
|
56
|
-
fs.createReadStream(
|
|
59
|
+
ss(socket).on("file", function (stream) {
|
|
60
|
+
fs.createReadStream("/path/to/file").pipe(stream);
|
|
57
61
|
});
|
|
58
62
|
|
|
59
63
|
// receive data
|
|
60
|
-
ss(socket).emit(
|
|
61
|
-
stream.pipe(fs.createWriteStream(
|
|
64
|
+
ss(socket).emit("file", stream);
|
|
65
|
+
stream.pipe(fs.createWriteStream("file.txt"));
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Support ESM import style
|
|
69
|
+
|
|
70
|
+
```js
|
|
71
|
+
import ss from "@sawa-siemens/socket.io-stream";
|
|
72
|
+
// ...
|
|
73
|
+
const stream = ss.createStream({ highWaterMark: 512 * 1024 });
|
|
74
|
+
//...
|
|
62
75
|
```
|
|
63
76
|
|
|
64
77
|
### Browser
|
|
65
78
|
|
|
66
79
|
This module can be used on the browser. To do so, just copy a file to a public directory.
|
|
67
80
|
|
|
68
|
-
$ cp node_modules/socket.io-stream/socket.io-stream.js somewhere/public/
|
|
81
|
+
$ cp node_modules/@sawa-siemens/socket.io-stream/socket.io-stream.js somewhere/public/
|
|
69
82
|
|
|
70
83
|
You can also use [browserify](http://github.com/substack/node-browserify) to create your own bundle.
|
|
71
84
|
|
|
72
85
|
$ npm install browserify -g
|
|
73
|
-
$ cd node_modules/socket.io-stream
|
|
86
|
+
$ cd node_modules/@sawa-siemens/socket.io-stream
|
|
74
87
|
$ browserify index.js -s ss > socket.io-stream.js
|
|
75
88
|
|
|
76
89
|
```html
|
|
@@ -80,18 +93,18 @@ You can also use [browserify](http://github.com/substack/node-browserify) to cre
|
|
|
80
93
|
<script src="/js/socket.io-stream.js"></script>
|
|
81
94
|
<script src="/js/jquery.js"></script>
|
|
82
95
|
<script>
|
|
83
|
-
$(function() {
|
|
84
|
-
|
|
96
|
+
$(function () {
|
|
97
|
+
var socket = io.connect("/foo");
|
|
85
98
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
99
|
+
$("#file").change(function (e) {
|
|
100
|
+
var file = e.target.files[0];
|
|
101
|
+
var stream = ss.createStream();
|
|
89
102
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
103
|
+
// upload a file to the server.
|
|
104
|
+
ss(socket).emit("file", stream, { size: file.size });
|
|
105
|
+
ss.createBlobReadStream(file).pipe(stream);
|
|
106
|
+
});
|
|
93
107
|
});
|
|
94
|
-
});
|
|
95
108
|
</script>
|
|
96
109
|
```
|
|
97
110
|
|
|
@@ -103,9 +116,9 @@ You can track upload progress like the following:
|
|
|
103
116
|
var blobStream = ss.createBlobReadStream(file);
|
|
104
117
|
var size = 0;
|
|
105
118
|
|
|
106
|
-
blobStream.on(
|
|
119
|
+
blobStream.on("data", function (chunk) {
|
|
107
120
|
size += chunk.length;
|
|
108
|
-
console.log(Math.floor(size / file.size * 100) +
|
|
121
|
+
console.log(Math.floor((size / file.size) * 100) + "%");
|
|
109
122
|
// -> e.g. '42%'
|
|
110
123
|
});
|
|
111
124
|
|
|
@@ -120,7 +133,6 @@ You have to set `forceBase64` option `true` when using the library with socket.i
|
|
|
120
133
|
ss.forceBase64 = true;
|
|
121
134
|
```
|
|
122
135
|
|
|
123
|
-
|
|
124
136
|
## Documentation
|
|
125
137
|
|
|
126
138
|
### ss(sio)
|
|
@@ -171,11 +183,11 @@ ss(socket).on('foo', function(stream) {
|
|
|
171
183
|
### ss.createStream([options])
|
|
172
184
|
|
|
173
185
|
- options `Object`
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
186
|
+
- highWaterMark `Number`
|
|
187
|
+
- encoding `String`
|
|
188
|
+
- decodeStrings `Boolean`
|
|
189
|
+
- objectMode `Boolean`
|
|
190
|
+
- allowHalfOpen `Boolean` if `true`, then the stream won't automatically close when the other endpoint ends. Default to `false`.
|
|
179
191
|
- return `Duplex Stream`
|
|
180
192
|
|
|
181
193
|
Create a new duplex stream. See [the docs](http://nodejs.org/api/stream.html) for the details of stream and `options`.
|
|
@@ -187,16 +199,16 @@ var stream = ss.createStream();
|
|
|
187
199
|
var stream = ss.createStream({
|
|
188
200
|
highWaterMark: 1024,
|
|
189
201
|
objectMode: true,
|
|
190
|
-
allowHalfOpen: true
|
|
202
|
+
allowHalfOpen: true,
|
|
191
203
|
});
|
|
192
204
|
```
|
|
193
205
|
|
|
194
206
|
### ss.createBlobReadStream(blob, [options])
|
|
195
207
|
|
|
196
208
|
- options `Object`
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
209
|
+
- highWaterMark `Number`
|
|
210
|
+
- encoding `String`
|
|
211
|
+
- objectMode `Boolean`
|
|
200
212
|
- return `Readable Stream`
|
|
201
213
|
|
|
202
214
|
Create a new readable stream for [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) and [File](https://developer.mozilla.org/en-US/docs/Web/API/File) on browser. See [the docs](http://nodejs.org/api/stream.html) for the details of stream and `options`.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const esbuild = require('esbuild');
|
|
2
|
+
const { polyfillNode } = require('esbuild-plugin-polyfill-node');
|
|
3
|
+
|
|
4
|
+
esbuild.build({
|
|
5
|
+
entryPoints: ['index.js'],
|
|
6
|
+
bundle: true,
|
|
7
|
+
minify: true,
|
|
8
|
+
globalName: 'ss',
|
|
9
|
+
platform: 'browser',
|
|
10
|
+
target: 'es2018',
|
|
11
|
+
outfile: 'socket.io-stream.js',
|
|
12
|
+
plugins: [
|
|
13
|
+
polyfillNode({
|
|
14
|
+
// Polyfills needed for this library
|
|
15
|
+
polyfills: {
|
|
16
|
+
util: true,
|
|
17
|
+
events: true,
|
|
18
|
+
buffer: true,
|
|
19
|
+
stream: true,
|
|
20
|
+
crypto: true,
|
|
21
|
+
},
|
|
22
|
+
}),
|
|
23
|
+
],
|
|
24
|
+
}).then(() => {
|
|
25
|
+
console.log('Build complete: socket.io-stream.js');
|
|
26
|
+
}).catch((err) => {
|
|
27
|
+
console.error('Build failed:', err);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
});
|
package/lib/iostream.js
CHANGED
|
@@ -184,6 +184,39 @@ IOStream.prototype._done = function() {
|
|
|
184
184
|
return this.push(null);
|
|
185
185
|
};
|
|
186
186
|
|
|
187
|
+
/**
|
|
188
|
+
* Helper to check if readable side has ended.
|
|
189
|
+
* Uses public API (readableEnded) with fallback to internal state for compatibility.
|
|
190
|
+
*
|
|
191
|
+
* @api private
|
|
192
|
+
*/
|
|
193
|
+
IOStream.prototype._isReadableEnded = function() {
|
|
194
|
+
// Use public API if available (readable-stream v3.6+, v4.x, Node.js 12.9+)
|
|
195
|
+
if (typeof this.readableEnded === 'boolean') {
|
|
196
|
+
return this.readableEnded;
|
|
197
|
+
}
|
|
198
|
+
// Fallback to internal state
|
|
199
|
+
return this._readableState && this._readableState.ended;
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Helper to check if writable side has finished.
|
|
204
|
+
* Uses public API (writableFinished/writableEnded) with fallback to internal state.
|
|
205
|
+
*
|
|
206
|
+
* @api private
|
|
207
|
+
*/
|
|
208
|
+
IOStream.prototype._isWritableFinished = function() {
|
|
209
|
+
// Use public API if available (readable-stream v3.6+, v4.x, Node.js 12.9+)
|
|
210
|
+
if (typeof this.writableFinished === 'boolean') {
|
|
211
|
+
return this.writableFinished;
|
|
212
|
+
}
|
|
213
|
+
if (typeof this.writableEnded === 'boolean') {
|
|
214
|
+
return this.writableEnded;
|
|
215
|
+
}
|
|
216
|
+
// Fallback to internal state
|
|
217
|
+
return this._writableState && this._writableState.finished;
|
|
218
|
+
};
|
|
219
|
+
|
|
187
220
|
/**
|
|
188
221
|
* the user has called .end(), and all the bytes have been
|
|
189
222
|
* sent out to the other side.
|
|
@@ -203,10 +236,12 @@ IOStream.prototype._onfinish = function() {
|
|
|
203
236
|
}
|
|
204
237
|
|
|
205
238
|
this.writable = false;
|
|
206
|
-
this._writableState
|
|
239
|
+
if (this._writableState) {
|
|
240
|
+
this._writableState.ended = true;
|
|
241
|
+
}
|
|
207
242
|
|
|
208
|
-
if (!this.readable || this.
|
|
209
|
-
debug('_onfinish: ended, destroy
|
|
243
|
+
if (!this.readable || this._isReadableEnded()) {
|
|
244
|
+
debug('_onfinish: ended, destroy');
|
|
210
245
|
return this.destroy();
|
|
211
246
|
}
|
|
212
247
|
|
|
@@ -216,7 +251,8 @@ IOStream.prototype._onfinish = function() {
|
|
|
216
251
|
this.push(null);
|
|
217
252
|
|
|
218
253
|
// just in case we're waiting for an EOF.
|
|
219
|
-
|
|
254
|
+
var endEmitted = this._readableState && this._readableState.endEmitted;
|
|
255
|
+
if (this.readable && !endEmitted) {
|
|
220
256
|
this.read(0);
|
|
221
257
|
}
|
|
222
258
|
}
|
|
@@ -232,17 +268,24 @@ IOStream.prototype._onfinish = function() {
|
|
|
232
268
|
IOStream.prototype._onend = function() {
|
|
233
269
|
debug('_onend');
|
|
234
270
|
this.readable = false;
|
|
235
|
-
this._readableState
|
|
271
|
+
if (this._readableState) {
|
|
272
|
+
this._readableState.ended = true;
|
|
273
|
+
}
|
|
236
274
|
|
|
237
|
-
if (!this.writable || this.
|
|
238
|
-
debug('_onend:
|
|
275
|
+
if (!this.writable || this._isWritableFinished()) {
|
|
276
|
+
debug('_onend: finished, destroy');
|
|
239
277
|
return this.destroy();
|
|
240
278
|
}
|
|
241
279
|
|
|
242
280
|
debug('_onend: not finished');
|
|
243
281
|
|
|
244
282
|
if (!this.allowHalfOpen) {
|
|
283
|
+
// When allowHalfOpen is false, we should clean up immediately
|
|
284
|
+
// after the readable side ends. Call end() to signal writable end,
|
|
285
|
+
// then destroy to clean up. This ensures synchronous cleanup
|
|
286
|
+
// which is expected by the tests and maintains v3.x behavior.
|
|
245
287
|
this.end();
|
|
288
|
+
return this.destroy();
|
|
246
289
|
}
|
|
247
290
|
};
|
|
248
291
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sawa-siemens/socket.io-stream",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "stream for socket.io",
|
|
5
5
|
"author": "Naoyuki Kanezawa <naoyuki.kanezawa@gmail.com>",
|
|
6
6
|
"contributors": [
|
|
@@ -37,24 +37,28 @@
|
|
|
37
37
|
"./package.json": "./package.json"
|
|
38
38
|
},
|
|
39
39
|
"engines": {
|
|
40
|
-
"node": ">=0.
|
|
40
|
+
"node": ">=18.0.0"
|
|
41
41
|
},
|
|
42
42
|
"repository": {
|
|
43
43
|
"type": "git",
|
|
44
|
-
"url": "https://github.com/sawa-siemens/socket.io-stream.git"
|
|
44
|
+
"url": "git+https://github.com/sawa-siemens/socket.io-stream.git"
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
|
-
"
|
|
48
|
-
"
|
|
47
|
+
"build": "node esbuild.config.js",
|
|
48
|
+
"prepare": "npm run build",
|
|
49
|
+
"test": "vitest run",
|
|
50
|
+
"test:watch": "vitest"
|
|
49
51
|
},
|
|
50
52
|
"dependencies": {
|
|
51
53
|
"component-bind": "~1.0.0",
|
|
52
|
-
"debug": "^4.3.4"
|
|
54
|
+
"debug": "^4.3.4",
|
|
55
|
+
"readable-stream": "^4.5.2"
|
|
53
56
|
},
|
|
54
57
|
"devDependencies": {
|
|
55
|
-
"
|
|
56
|
-
"
|
|
58
|
+
"esbuild": "^0.27.2",
|
|
59
|
+
"esbuild-plugin-polyfill-node": "^0.3.0",
|
|
57
60
|
"socket.io": "^4.8.3",
|
|
58
|
-
"socket.io-client": "^4.8.3"
|
|
61
|
+
"socket.io-client": "^4.8.3",
|
|
62
|
+
"vitest": "^3.0.4"
|
|
59
63
|
}
|
|
60
64
|
}
|