@hapi/nes 12.0.3 → 13.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/LICENSE.md +2 -1
- package/lib/client.js +4 -0
- package/lib/index.js +38 -38
- package/lib/listener.js +17 -17
- package/lib/socket.js +3 -3
- package/package.json +19 -16
package/LICENSE.md
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
Copyright (c) 2016-
|
|
1
|
+
Copyright (c) 2016-2022, Project contributors
|
|
2
|
+
Copyright (c) 2016-2020, Sideway Inc
|
|
2
3
|
All rights reserved.
|
|
3
4
|
|
|
4
5
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
package/lib/client.js
CHANGED
package/lib/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const Cryptiles = require('@hapi/cryptiles');
|
|
4
4
|
const Hoek = require('@hapi/hoek');
|
|
5
5
|
const Iron = require('@hapi/iron');
|
|
6
|
-
const
|
|
6
|
+
const Validate = require('@hapi/validate');
|
|
7
7
|
const Ws = require('ws');
|
|
8
8
|
|
|
9
9
|
const Client = require('./client');
|
|
@@ -38,53 +38,53 @@ const internals = {
|
|
|
38
38
|
};
|
|
39
39
|
|
|
40
40
|
|
|
41
|
-
internals.schema =
|
|
42
|
-
onConnection:
|
|
43
|
-
onDisconnection:
|
|
44
|
-
onMessage:
|
|
45
|
-
auth:
|
|
46
|
-
endpoint:
|
|
47
|
-
id:
|
|
48
|
-
type:
|
|
41
|
+
internals.schema = Validate.object({
|
|
42
|
+
onConnection: Validate.function(), // async function (socket) {}
|
|
43
|
+
onDisconnection: Validate.function(), // function (socket) {}
|
|
44
|
+
onMessage: Validate.function(), // async function (socket, message) { return data; } // Or throw errors
|
|
45
|
+
auth: Validate.object({
|
|
46
|
+
endpoint: Validate.string().required(),
|
|
47
|
+
id: Validate.string(),
|
|
48
|
+
type: Validate.valid('cookie', 'token', 'direct').required(),
|
|
49
49
|
route: [
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
Validate.object(),
|
|
51
|
+
Validate.string()
|
|
52
52
|
],
|
|
53
|
-
cookie:
|
|
54
|
-
isSecure:
|
|
55
|
-
isHttpOnly:
|
|
56
|
-
isSameSite:
|
|
57
|
-
path:
|
|
58
|
-
domain:
|
|
59
|
-
ttl:
|
|
60
|
-
iron:
|
|
61
|
-
password:
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
53
|
+
cookie: Validate.string().required(),
|
|
54
|
+
isSecure: Validate.boolean(),
|
|
55
|
+
isHttpOnly: Validate.boolean(),
|
|
56
|
+
isSameSite: Validate.valid('Strict', 'Lax').allow(false),
|
|
57
|
+
path: Validate.string().allow(null),
|
|
58
|
+
domain: Validate.string().allow(null),
|
|
59
|
+
ttl: Validate.number().allow(null),
|
|
60
|
+
iron: Validate.object(),
|
|
61
|
+
password: Validate.alternatives([
|
|
62
|
+
Validate.string(),
|
|
63
|
+
Validate.binary(),
|
|
64
|
+
Validate.object()
|
|
65
65
|
]),
|
|
66
|
-
index:
|
|
67
|
-
timeout:
|
|
68
|
-
maxConnectionsPerUser:
|
|
69
|
-
minAuthVerifyInterval:
|
|
66
|
+
index: Validate.boolean(),
|
|
67
|
+
timeout: Validate.number().integer().min(1).allow(false),
|
|
68
|
+
maxConnectionsPerUser: Validate.number().integer().min(1).allow(false).when('index', { is: true, otherwise: Validate.valid(false) }),
|
|
69
|
+
minAuthVerifyInterval: Validate.number().integer().allow(false).when('...heartbeat', {
|
|
70
70
|
is: false,
|
|
71
|
-
then:
|
|
72
|
-
otherwise:
|
|
71
|
+
then: Validate.number().min(1),
|
|
72
|
+
otherwise: Validate.number().min(Validate.ref('...heartbeat.interval'))
|
|
73
73
|
})
|
|
74
74
|
})
|
|
75
75
|
.allow(false)
|
|
76
76
|
.required(),
|
|
77
|
-
headers:
|
|
77
|
+
headers: Validate.array().items(Validate.string().lowercase()).min(1).allow('*', null),
|
|
78
78
|
payload: {
|
|
79
|
-
maxChunkChars:
|
|
79
|
+
maxChunkChars: Validate.number().integer().min(1).allow(false)
|
|
80
80
|
},
|
|
81
|
-
heartbeat:
|
|
82
|
-
interval:
|
|
83
|
-
timeout:
|
|
81
|
+
heartbeat: Validate.object({
|
|
82
|
+
interval: Validate.number().integer().min(1).required(),
|
|
83
|
+
timeout: Validate.number().integer().min(1).less(Validate.ref('interval')).required()
|
|
84
84
|
})
|
|
85
85
|
.allow(false),
|
|
86
|
-
maxConnections:
|
|
87
|
-
origin:
|
|
86
|
+
maxConnections: Validate.number().integer().min(1).allow(false),
|
|
87
|
+
origin: Validate.array().items(Validate.string()).single().min(1)
|
|
88
88
|
});
|
|
89
89
|
|
|
90
90
|
|
|
@@ -107,7 +107,7 @@ exports.plugin = {
|
|
|
107
107
|
settings.auth.minAuthVerifyInterval = (settings.heartbeat ? settings.heartbeat.interval : internals.defaults.heartbeat.interval);
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
|
|
110
|
+
Validate.assert(settings, internals.schema, 'Invalid nes configuration');
|
|
111
111
|
|
|
112
112
|
// Authentication endpoint
|
|
113
113
|
|
|
@@ -205,7 +205,7 @@ internals.auth = function (server, settings) {
|
|
|
205
205
|
return h.response(result).state(config.cookie, credentials);
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
-
const sealed = await Iron.seal(credentials, config.password, config.iron
|
|
208
|
+
const sealed = await Iron.seal(credentials, config.password, config.iron ?? Iron.defaults);
|
|
209
209
|
result.token = sealed;
|
|
210
210
|
return result;
|
|
211
211
|
}
|
package/lib/listener.js
CHANGED
|
@@ -4,7 +4,7 @@ const Boom = require('@hapi/boom');
|
|
|
4
4
|
const Bounce = require('@hapi/bounce');
|
|
5
5
|
const Call = require('@hapi/call');
|
|
6
6
|
const Hoek = require('@hapi/hoek');
|
|
7
|
-
const
|
|
7
|
+
const Validate = require('@hapi/validate');
|
|
8
8
|
const Ws = require('ws');
|
|
9
9
|
|
|
10
10
|
const Socket = require('./socket');
|
|
@@ -165,7 +165,7 @@ internals.Listener.prototype._beat = function () {
|
|
|
165
165
|
|
|
166
166
|
internals.Listener.broadcast = function (message, options) {
|
|
167
167
|
|
|
168
|
-
options = options
|
|
168
|
+
options = options ?? {};
|
|
169
169
|
|
|
170
170
|
const update = {
|
|
171
171
|
type: 'update',
|
|
@@ -199,15 +199,15 @@ internals.Listener.prototype._broadcast = function (update, options) {
|
|
|
199
199
|
};
|
|
200
200
|
|
|
201
201
|
|
|
202
|
-
internals.subSchema =
|
|
203
|
-
filter:
|
|
204
|
-
onSubscribe:
|
|
205
|
-
onUnsubscribe:
|
|
206
|
-
auth:
|
|
207
|
-
mode:
|
|
208
|
-
scope:
|
|
209
|
-
entity:
|
|
210
|
-
index:
|
|
202
|
+
internals.subSchema = Validate.object({
|
|
203
|
+
filter: Validate.func(), // async function (path, update, options), where options: { credentials, params }, returns true, false, { override }, or throws an error
|
|
204
|
+
onSubscribe: Validate.func(), // async function (socket, path, params)
|
|
205
|
+
onUnsubscribe: Validate.func(), // async function (socket, path, params)
|
|
206
|
+
auth: Validate.object({
|
|
207
|
+
mode: Validate.string().valid('required', 'optional'),
|
|
208
|
+
scope: Validate.array().items(Validate.string()).single().min(1),
|
|
209
|
+
entity: Validate.valid('user', 'app', 'any'),
|
|
210
|
+
index: Validate.boolean()
|
|
211
211
|
})
|
|
212
212
|
.allow(false)
|
|
213
213
|
});
|
|
@@ -216,9 +216,9 @@ internals.subSchema = Joi.object({
|
|
|
216
216
|
internals.Listener.subscription = function (path, options) {
|
|
217
217
|
|
|
218
218
|
Hoek.assert(path, 'Subscription missing path');
|
|
219
|
-
|
|
219
|
+
Validate.assert(options, internals.subSchema, 'Invalid subscription options: ' + path);
|
|
220
220
|
|
|
221
|
-
const settings = Hoek.clone(options
|
|
221
|
+
const settings = Hoek.clone(options ?? {});
|
|
222
222
|
|
|
223
223
|
// Auth configuration
|
|
224
224
|
|
|
@@ -261,7 +261,7 @@ internals.Listener.publish = function (path, update, options) {
|
|
|
261
261
|
|
|
262
262
|
Hoek.assert(path && path[0] === '/', 'Missing or invalid subscription path:', path || 'empty');
|
|
263
263
|
|
|
264
|
-
options = options
|
|
264
|
+
options = options ?? {};
|
|
265
265
|
|
|
266
266
|
const message = {
|
|
267
267
|
type: 'pub',
|
|
@@ -382,7 +382,7 @@ internals.Listener.prototype._subscribe = async function (path, socket) {
|
|
|
382
382
|
|
|
383
383
|
internals.Listener.eachSocket = function (each, options) {
|
|
384
384
|
|
|
385
|
-
options = options
|
|
385
|
+
options = options ?? {};
|
|
386
386
|
|
|
387
387
|
return this.plugins.nes._listener._eachSocket(each, options);
|
|
388
388
|
};
|
|
@@ -454,7 +454,7 @@ internals.Sockets.prototype.auth = function (socket) {
|
|
|
454
454
|
throw Boom.serverUnavailable('Too many connections for the authenticated user');
|
|
455
455
|
}
|
|
456
456
|
|
|
457
|
-
this._byUser[user] = this._byUser[user]
|
|
457
|
+
this._byUser[user] = this._byUser[user] ?? [];
|
|
458
458
|
this._byUser[user].push(socket);
|
|
459
459
|
};
|
|
460
460
|
|
|
@@ -522,7 +522,7 @@ internals.Subscribers.prototype.add = async function (socket, path, match) {
|
|
|
522
522
|
socket.auth.credentials.user) {
|
|
523
523
|
|
|
524
524
|
const user = socket.auth.credentials.user;
|
|
525
|
-
this._byUser[user] = this._byUser[user]
|
|
525
|
+
this._byUser[user] = this._byUser[user] ?? [];
|
|
526
526
|
this._byUser[user].push(this._items[socket.id]);
|
|
527
527
|
}
|
|
528
528
|
}
|
package/lib/socket.js
CHANGED
|
@@ -118,7 +118,7 @@ internals.Socket.prototype.isOpen = function () {
|
|
|
118
118
|
|
|
119
119
|
internals.Socket.prototype._send = function (message, options) {
|
|
120
120
|
|
|
121
|
-
options = options
|
|
121
|
+
options = options ?? {};
|
|
122
122
|
|
|
123
123
|
if (!this.isOpen()) { // Open
|
|
124
124
|
return Promise.reject(Boom.internal('Socket not open'));
|
|
@@ -544,7 +544,7 @@ internals.Socket.prototype._authenticate = async function (request) {
|
|
|
544
544
|
const config = this._listener._settings.auth;
|
|
545
545
|
if (config.type === 'direct') {
|
|
546
546
|
const route = this.server.lookup(config.id);
|
|
547
|
-
request.auth.headers = request.auth.headers
|
|
547
|
+
request.auth.headers = request.auth.headers ?? {};
|
|
548
548
|
request.auth.headers['x-forwarded-for'] = this.info['x-forwarded-for'];
|
|
549
549
|
const res = await this.server.inject({ url: route.path, method: 'auth', headers: request.auth.headers, remoteAddress: this.info.remoteAddress, allowInternals: true, validate: false });
|
|
550
550
|
if (res.statusCode !== 200) {
|
|
@@ -560,7 +560,7 @@ internals.Socket.prototype._authenticate = async function (request) {
|
|
|
560
560
|
}
|
|
561
561
|
|
|
562
562
|
try {
|
|
563
|
-
const auth = await Iron.unseal(request.auth, config.password, config.iron
|
|
563
|
+
const auth = await Iron.unseal(request.auth, config.password, config.iron ?? Iron.defaults);
|
|
564
564
|
this._setCredentials(auth);
|
|
565
565
|
}
|
|
566
566
|
catch (err) {
|
package/package.json
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hapi/nes",
|
|
3
3
|
"description": "WebSocket adapter plugin for hapi routes",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "13.0.0",
|
|
5
5
|
"repository": "git://github.com/hapijs/nes",
|
|
6
|
-
"engines": {
|
|
7
|
-
"node": ">=12.0.0"
|
|
8
|
-
},
|
|
9
6
|
"main": "lib/index.js",
|
|
10
7
|
"files": [
|
|
11
8
|
"lib"
|
|
@@ -15,21 +12,27 @@
|
|
|
15
12
|
"plugin",
|
|
16
13
|
"websocket"
|
|
17
14
|
],
|
|
15
|
+
"eslintConfig": {
|
|
16
|
+
"extends": [
|
|
17
|
+
"plugin:@hapi/module"
|
|
18
|
+
]
|
|
19
|
+
},
|
|
18
20
|
"dependencies": {
|
|
19
|
-
"@hapi/boom": "
|
|
20
|
-
"@hapi/bounce": "
|
|
21
|
-
"@hapi/call": "
|
|
22
|
-
"@hapi/cryptiles": "
|
|
23
|
-
"@hapi/hoek": "
|
|
24
|
-
"@hapi/iron": "
|
|
25
|
-
"@hapi/
|
|
26
|
-
"@hapi/
|
|
27
|
-
"ws": "
|
|
21
|
+
"@hapi/boom": "^10.x.x",
|
|
22
|
+
"@hapi/bounce": "^3.0.0",
|
|
23
|
+
"@hapi/call": "^9.0.0",
|
|
24
|
+
"@hapi/cryptiles": "^6.0.0",
|
|
25
|
+
"@hapi/hoek": "^10.0.0",
|
|
26
|
+
"@hapi/iron": "^7.0.0",
|
|
27
|
+
"@hapi/teamwork": "^6.0.0",
|
|
28
|
+
"@hapi/validate": "^2.0.0",
|
|
29
|
+
"ws": "^7.3.1"
|
|
28
30
|
},
|
|
29
31
|
"devDependencies": {
|
|
30
|
-
"@hapi/code": "
|
|
31
|
-
"@hapi/
|
|
32
|
-
"@hapi/
|
|
32
|
+
"@hapi/code": "^9.0.0",
|
|
33
|
+
"@hapi/eslint-plugin": "*",
|
|
34
|
+
"@hapi/hapi": "^21.0.0-beta.1",
|
|
35
|
+
"@hapi/lab": "^25.0.1"
|
|
33
36
|
},
|
|
34
37
|
"scripts": {
|
|
35
38
|
"test": "lab -a @hapi/code -t 100 -L -m 10000",
|