@streamr/node 100.0.0-rc.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.
Files changed (238) hide show
  1. package/LICENSE +78 -0
  2. package/README.md +54 -0
  3. package/bin/broker.ts +36 -0
  4. package/bin/config-wizard.js +4 -0
  5. package/bin/config-wizard.ts +17 -0
  6. package/bin/delete-expired-data.ts +41 -0
  7. package/bin/entry-point.ts +27 -0
  8. package/configs/development-1.env.json +68 -0
  9. package/configs/development-2.env.json +53 -0
  10. package/configs/development-3.env.json +53 -0
  11. package/configs/development-prod-resend.env.json +21 -0
  12. package/configs/docker-1.env.json +72 -0
  13. package/configs/docker-2.env.json +58 -0
  14. package/configs/docker-3.env.json +58 -0
  15. package/configuration.md +38 -0
  16. package/dist/bin/broker.d.ts +2 -0
  17. package/dist/bin/broker.js +42 -0
  18. package/dist/bin/broker.js.map +1 -0
  19. package/dist/bin/config-wizard.d.ts +2 -0
  20. package/dist/bin/config-wizard.js +22 -0
  21. package/dist/bin/config-wizard.js.map +1 -0
  22. package/dist/bin/delete-expired-data.d.ts +2 -0
  23. package/dist/bin/delete-expired-data.js +44 -0
  24. package/dist/bin/delete-expired-data.js.map +1 -0
  25. package/dist/bin/entry-point.d.ts +2 -0
  26. package/dist/bin/entry-point.js +28 -0
  27. package/dist/bin/entry-point.js.map +1 -0
  28. package/dist/package.json +78 -0
  29. package/dist/src/Plugin.d.ts +33 -0
  30. package/dist/src/Plugin.js +43 -0
  31. package/dist/src/Plugin.js.map +1 -0
  32. package/dist/src/apiAuthentication.d.ts +4 -0
  33. package/dist/src/apiAuthentication.js +16 -0
  34. package/dist/src/apiAuthentication.js.map +1 -0
  35. package/dist/src/broker.d.ts +8 -0
  36. package/dist/src/broker.js +69 -0
  37. package/dist/src/broker.js.map +1 -0
  38. package/dist/src/config/ConfigWizard.d.ts +5 -0
  39. package/dist/src/config/ConfigWizard.js +466 -0
  40. package/dist/src/config/ConfigWizard.js.map +1 -0
  41. package/dist/src/config/config.d.ts +26 -0
  42. package/dist/src/config/config.js +92 -0
  43. package/dist/src/config/config.js.map +1 -0
  44. package/dist/src/config/config.schema.json +86 -0
  45. package/dist/src/config/definitions.schema.json +35 -0
  46. package/dist/src/config/migration.d.ts +6 -0
  47. package/dist/src/config/migration.js +210 -0
  48. package/dist/src/config/migration.js.map +1 -0
  49. package/dist/src/config/validateConfig.d.ts +4 -0
  50. package/dist/src/config/validateConfig.js +40 -0
  51. package/dist/src/config/validateConfig.js.map +1 -0
  52. package/dist/src/exports.d.ts +3 -0
  53. package/dist/src/exports.js +6 -0
  54. package/dist/src/exports.js.map +1 -0
  55. package/dist/src/helpers/PayloadFormat.d.ts +19 -0
  56. package/dist/src/helpers/PayloadFormat.js +85 -0
  57. package/dist/src/helpers/PayloadFormat.js.map +1 -0
  58. package/dist/src/helpers/applyPluginClientConfigs.d.ts +3 -0
  59. package/dist/src/helpers/applyPluginClientConfigs.js +29 -0
  60. package/dist/src/helpers/applyPluginClientConfigs.js.map +1 -0
  61. package/dist/src/helpers/fetchOrThrow.d.ts +2 -0
  62. package/dist/src/helpers/fetchOrThrow.js +20 -0
  63. package/dist/src/helpers/fetchOrThrow.js.map +1 -0
  64. package/dist/src/helpers/generateMnemonicFromAddress.d.ts +5 -0
  65. package/dist/src/helpers/generateMnemonicFromAddress.js +16 -0
  66. package/dist/src/helpers/generateMnemonicFromAddress.js.map +1 -0
  67. package/dist/src/helpers/multiply.d.ts +1 -0
  68. package/dist/src/helpers/multiply.js +10 -0
  69. package/dist/src/helpers/multiply.js.map +1 -0
  70. package/dist/src/helpers/parser.d.ts +9 -0
  71. package/dist/src/helpers/parser.js +62 -0
  72. package/dist/src/helpers/parser.js.map +1 -0
  73. package/dist/src/helpers/partitions.d.ts +8 -0
  74. package/dist/src/helpers/partitions.js +32 -0
  75. package/dist/src/helpers/partitions.js.map +1 -0
  76. package/dist/src/helpers/weightedSample.d.ts +16 -0
  77. package/dist/src/helpers/weightedSample.js +35 -0
  78. package/dist/src/helpers/weightedSample.js.map +1 -0
  79. package/dist/src/httpServer.d.ts +16 -0
  80. package/dist/src/httpServer.js +71 -0
  81. package/dist/src/httpServer.js.map +1 -0
  82. package/dist/src/pluginRegistry.d.ts +3 -0
  83. package/dist/src/pluginRegistry.js +35 -0
  84. package/dist/src/pluginRegistry.js.map +1 -0
  85. package/dist/src/plugins/consoleMetrics/ConsoleMetricsPlugin.d.ts +12 -0
  86. package/dist/src/plugins/consoleMetrics/ConsoleMetricsPlugin.js +36 -0
  87. package/dist/src/plugins/consoleMetrics/ConsoleMetricsPlugin.js.map +1 -0
  88. package/dist/src/plugins/consoleMetrics/config.schema.json +18 -0
  89. package/dist/src/plugins/http/HttpPlugin.d.ts +8 -0
  90. package/dist/src/plugins/http/HttpPlugin.js +23 -0
  91. package/dist/src/plugins/http/HttpPlugin.js.map +1 -0
  92. package/dist/src/plugins/http/config.schema.json +12 -0
  93. package/dist/src/plugins/http/publishEndpoint.d.ts +3 -0
  94. package/dist/src/plugins/http/publishEndpoint.js +72 -0
  95. package/dist/src/plugins/http/publishEndpoint.js.map +1 -0
  96. package/dist/src/plugins/info/InfoPlugin.d.ts +9 -0
  97. package/dist/src/plugins/info/InfoPlugin.js +31 -0
  98. package/dist/src/plugins/info/InfoPlugin.js.map +1 -0
  99. package/dist/src/plugins/info/config.schema.json +12 -0
  100. package/dist/src/plugins/mqtt/Bridge.d.ts +40 -0
  101. package/dist/src/plugins/mqtt/Bridge.js +136 -0
  102. package/dist/src/plugins/mqtt/Bridge.js.map +1 -0
  103. package/dist/src/plugins/mqtt/MqttPlugin.d.ts +14 -0
  104. package/dist/src/plugins/mqtt/MqttPlugin.js +30 -0
  105. package/dist/src/plugins/mqtt/MqttPlugin.js.map +1 -0
  106. package/dist/src/plugins/mqtt/MqttServer.d.ts +22 -0
  107. package/dist/src/plugins/mqtt/MqttServer.js +109 -0
  108. package/dist/src/plugins/mqtt/MqttServer.js.map +1 -0
  109. package/dist/src/plugins/mqtt/config.schema.json +26 -0
  110. package/dist/src/plugins/operator/ConsistentHashRing.d.ts +20 -0
  111. package/dist/src/plugins/operator/ConsistentHashRing.js +64 -0
  112. package/dist/src/plugins/operator/ConsistentHashRing.js.map +1 -0
  113. package/dist/src/plugins/operator/ContractFacade.d.ts +80 -0
  114. package/dist/src/plugins/operator/ContractFacade.js +364 -0
  115. package/dist/src/plugins/operator/ContractFacade.js.map +1 -0
  116. package/dist/src/plugins/operator/MaintainTopologyHelper.d.ts +23 -0
  117. package/dist/src/plugins/operator/MaintainTopologyHelper.js +75 -0
  118. package/dist/src/plugins/operator/MaintainTopologyHelper.js.map +1 -0
  119. package/dist/src/plugins/operator/MaintainTopologyService.d.ts +11 -0
  120. package/dist/src/plugins/operator/MaintainTopologyService.js +57 -0
  121. package/dist/src/plugins/operator/MaintainTopologyService.js.map +1 -0
  122. package/dist/src/plugins/operator/OperatorFleetState.d.ts +33 -0
  123. package/dist/src/plugins/operator/OperatorFleetState.js +112 -0
  124. package/dist/src/plugins/operator/OperatorFleetState.js.map +1 -0
  125. package/dist/src/plugins/operator/OperatorPlugin.d.ts +50 -0
  126. package/dist/src/plugins/operator/OperatorPlugin.js +159 -0
  127. package/dist/src/plugins/operator/OperatorPlugin.js.map +1 -0
  128. package/dist/src/plugins/operator/StreamPartAssignments.d.ts +28 -0
  129. package/dist/src/plugins/operator/StreamPartAssignments.js +104 -0
  130. package/dist/src/plugins/operator/StreamPartAssignments.js.map +1 -0
  131. package/dist/src/plugins/operator/announceNodeToContract.d.ts +3 -0
  132. package/dist/src/plugins/operator/announceNodeToContract.js +39 -0
  133. package/dist/src/plugins/operator/announceNodeToContract.js.map +1 -0
  134. package/dist/src/plugins/operator/announceNodeToStream.d.ts +3 -0
  135. package/dist/src/plugins/operator/announceNodeToStream.js +25 -0
  136. package/dist/src/plugins/operator/announceNodeToStream.js.map +1 -0
  137. package/dist/src/plugins/operator/checkOperatorValueBreach.d.ts +2 -0
  138. package/dist/src/plugins/operator/checkOperatorValueBreach.js +21 -0
  139. package/dist/src/plugins/operator/checkOperatorValueBreach.js.map +1 -0
  140. package/dist/src/plugins/operator/closeExpiredFlags.d.ts +3 -0
  141. package/dist/src/plugins/operator/closeExpiredFlags.js +24 -0
  142. package/dist/src/plugins/operator/closeExpiredFlags.js.map +1 -0
  143. package/dist/src/plugins/operator/config.schema.json +152 -0
  144. package/dist/src/plugins/operator/createIsLeaderFn.d.ts +4 -0
  145. package/dist/src/plugins/operator/createIsLeaderFn.js +14 -0
  146. package/dist/src/plugins/operator/createIsLeaderFn.js.map +1 -0
  147. package/dist/src/plugins/operator/fetchRedundancyFactor.d.ts +2 -0
  148. package/dist/src/plugins/operator/fetchRedundancyFactor.js +43 -0
  149. package/dist/src/plugins/operator/fetchRedundancyFactor.js.map +1 -0
  150. package/dist/src/plugins/operator/formCoordinationStreamId.d.ts +3 -0
  151. package/dist/src/plugins/operator/formCoordinationStreamId.js +9 -0
  152. package/dist/src/plugins/operator/formCoordinationStreamId.js.map +1 -0
  153. package/dist/src/plugins/operator/heartbeatUtils.d.ts +67 -0
  154. package/dist/src/plugins/operator/heartbeatUtils.js +26 -0
  155. package/dist/src/plugins/operator/heartbeatUtils.js.map +1 -0
  156. package/dist/src/plugins/operator/inspectOverTime.d.ts +22 -0
  157. package/dist/src/plugins/operator/inspectOverTime.js +146 -0
  158. package/dist/src/plugins/operator/inspectOverTime.js.map +1 -0
  159. package/dist/src/plugins/operator/inspectRandomNode.d.ts +8 -0
  160. package/dist/src/plugins/operator/inspectRandomNode.js +44 -0
  161. package/dist/src/plugins/operator/inspectRandomNode.js.map +1 -0
  162. package/dist/src/plugins/operator/inspectionUtils.d.ts +23 -0
  163. package/dist/src/plugins/operator/inspectionUtils.js +120 -0
  164. package/dist/src/plugins/operator/inspectionUtils.js.map +1 -0
  165. package/dist/src/plugins/operator/maintainOperatorValue.d.ts +2 -0
  166. package/dist/src/plugins/operator/maintainOperatorValue.js +21 -0
  167. package/dist/src/plugins/operator/maintainOperatorValue.js.map +1 -0
  168. package/dist/src/plugins/operator/reviewSuspectNode.d.ts +24 -0
  169. package/dist/src/plugins/operator/reviewSuspectNode.js +56 -0
  170. package/dist/src/plugins/operator/reviewSuspectNode.js.map +1 -0
  171. package/dist/src/plugins/storage/Batch.d.ts +51 -0
  172. package/dist/src/plugins/storage/Batch.js +121 -0
  173. package/dist/src/plugins/storage/Batch.js.map +1 -0
  174. package/dist/src/plugins/storage/BatchManager.d.ts +27 -0
  175. package/dist/src/plugins/storage/BatchManager.js +117 -0
  176. package/dist/src/plugins/storage/BatchManager.js.map +1 -0
  177. package/dist/src/plugins/storage/Bucket.d.ts +23 -0
  178. package/dist/src/plugins/storage/Bucket.js +90 -0
  179. package/dist/src/plugins/storage/Bucket.js.map +1 -0
  180. package/dist/src/plugins/storage/BucketManager.d.ts +56 -0
  181. package/dist/src/plugins/storage/BucketManager.js +306 -0
  182. package/dist/src/plugins/storage/BucketManager.js.map +1 -0
  183. package/dist/src/plugins/storage/DataQueryFormat.d.ts +10 -0
  184. package/dist/src/plugins/storage/DataQueryFormat.js +51 -0
  185. package/dist/src/plugins/storage/DataQueryFormat.js.map +1 -0
  186. package/dist/src/plugins/storage/DeleteExpiredCmd.d.ts +28 -0
  187. package/dist/src/plugins/storage/DeleteExpiredCmd.js +155 -0
  188. package/dist/src/plugins/storage/DeleteExpiredCmd.js.map +1 -0
  189. package/dist/src/plugins/storage/SetMembershipSynchronizer.d.ts +33 -0
  190. package/dist/src/plugins/storage/SetMembershipSynchronizer.js +102 -0
  191. package/dist/src/plugins/storage/SetMembershipSynchronizer.js.map +1 -0
  192. package/dist/src/plugins/storage/Storage.d.ts +47 -0
  193. package/dist/src/plugins/storage/Storage.js +459 -0
  194. package/dist/src/plugins/storage/Storage.js.map +1 -0
  195. package/dist/src/plugins/storage/StorageConfig.d.ts +43 -0
  196. package/dist/src/plugins/storage/StorageConfig.js +83 -0
  197. package/dist/src/plugins/storage/StorageConfig.js.map +1 -0
  198. package/dist/src/plugins/storage/StorageEventListener.d.ts +17 -0
  199. package/dist/src/plugins/storage/StorageEventListener.js +46 -0
  200. package/dist/src/plugins/storage/StorageEventListener.js.map +1 -0
  201. package/dist/src/plugins/storage/StoragePlugin.d.ts +32 -0
  202. package/dist/src/plugins/storage/StoragePlugin.js +103 -0
  203. package/dist/src/plugins/storage/StoragePlugin.js.map +1 -0
  204. package/dist/src/plugins/storage/StoragePoller.d.ts +15 -0
  205. package/dist/src/plugins/storage/StoragePoller.js +47 -0
  206. package/dist/src/plugins/storage/StoragePoller.js.map +1 -0
  207. package/dist/src/plugins/storage/config.schema.json +88 -0
  208. package/dist/src/plugins/storage/dataMetadataEndpoint.d.ts +3 -0
  209. package/dist/src/plugins/storage/dataMetadataEndpoint.js +35 -0
  210. package/dist/src/plugins/storage/dataMetadataEndpoint.js.map +1 -0
  211. package/dist/src/plugins/storage/dataQueryEndpoint.d.ts +6 -0
  212. package/dist/src/plugins/storage/dataQueryEndpoint.js +181 -0
  213. package/dist/src/plugins/storage/dataQueryEndpoint.js.map +1 -0
  214. package/dist/src/plugins/storage/storageConfigEndpoint.d.ts +3 -0
  215. package/dist/src/plugins/storage/storageConfigEndpoint.js +31 -0
  216. package/dist/src/plugins/storage/storageConfigEndpoint.js.map +1 -0
  217. package/dist/src/plugins/subscriber/SubscriberPlugin.d.ts +16 -0
  218. package/dist/src/plugins/subscriber/SubscriberPlugin.js +22 -0
  219. package/dist/src/plugins/subscriber/SubscriberPlugin.js.map +1 -0
  220. package/dist/src/plugins/subscriber/config.schema.json +31 -0
  221. package/dist/src/plugins/websocket/Connection.d.ts +9 -0
  222. package/dist/src/plugins/websocket/Connection.js +45 -0
  223. package/dist/src/plugins/websocket/Connection.js.map +1 -0
  224. package/dist/src/plugins/websocket/PublishConnection.d.ts +12 -0
  225. package/dist/src/plugins/websocket/PublishConnection.js +46 -0
  226. package/dist/src/plugins/websocket/PublishConnection.js.map +1 -0
  227. package/dist/src/plugins/websocket/SubscribeConnection.d.ts +13 -0
  228. package/dist/src/plugins/websocket/SubscribeConnection.js +50 -0
  229. package/dist/src/plugins/websocket/SubscribeConnection.js.map +1 -0
  230. package/dist/src/plugins/websocket/WebsocketPlugin.d.ts +19 -0
  231. package/dist/src/plugins/websocket/WebsocketPlugin.js +26 -0
  232. package/dist/src/plugins/websocket/WebsocketPlugin.js.map +1 -0
  233. package/dist/src/plugins/websocket/WebsocketServer.d.ts +16 -0
  234. package/dist/src/plugins/websocket/WebsocketServer.js +132 -0
  235. package/dist/src/plugins/websocket/WebsocketServer.js.map +1 -0
  236. package/dist/src/plugins/websocket/config.schema.json +51 -0
  237. package/package.json +78 -0
  238. package/plugins.md +318 -0
@@ -0,0 +1,16 @@
1
+ import { Plugin } from '../../Plugin';
2
+ import { StreamrClient } from '@streamr/sdk';
3
+ interface ConfigStream {
4
+ streamId: string;
5
+ streamPartition: number;
6
+ }
7
+ export interface SubscriberPluginConfig {
8
+ streams: ConfigStream[];
9
+ }
10
+ export declare class SubscriberPlugin extends Plugin<SubscriberPluginConfig> {
11
+ private subscriptions;
12
+ private subscribeToStreamParts;
13
+ start(streamrClient: StreamrClient): Promise<void>;
14
+ stop(): Promise<void>;
15
+ }
16
+ export {};
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SubscriberPlugin = void 0;
4
+ const Plugin_1 = require("../../Plugin");
5
+ const utils_1 = require("@streamr/utils");
6
+ const logger = new utils_1.Logger(module);
7
+ class SubscriberPlugin extends Plugin_1.Plugin {
8
+ subscriptions = [];
9
+ async subscribeToStreamParts(streamrClient) {
10
+ this.subscriptions = await (0, utils_1.pTransaction)(this.pluginConfig.streams.map(({ streamId, streamPartition }) => (streamrClient.subscribe({ id: streamId, partition: streamPartition, raw: true }))), (sub) => sub.unsubscribe());
11
+ }
12
+ async start(streamrClient) {
13
+ await this.subscribeToStreamParts(streamrClient);
14
+ logger.info('Started subscriber plugin');
15
+ }
16
+ async stop() {
17
+ logger.info('Stop subscriber plugin');
18
+ await Promise.all(this.subscriptions.map((sub) => sub.unsubscribe()));
19
+ }
20
+ }
21
+ exports.SubscriberPlugin = SubscriberPlugin;
22
+ //# sourceMappingURL=SubscriberPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubscriberPlugin.js","sourceRoot":"","sources":["../../../../src/plugins/subscriber/SubscriberPlugin.ts"],"names":[],"mappings":";;;AAAA,yCAAqC;AACrC,0CAAqD;AAYrD,MAAM,MAAM,GAAG,IAAI,cAAM,CAAC,MAAM,CAAC,CAAA;AAEjC,MAAa,gBAAiB,SAAQ,eAA8B;IAExD,aAAa,GAAmB,EAAE,CAAA;IAElC,KAAK,CAAC,sBAAsB,CAAC,aAA4B;QAC7D,IAAI,CAAC,aAAa,GAAG,MAAM,IAAA,oBAAY,EAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC,CACrG,aAAa,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,eAAe,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CACnF,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAA;IACnC,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,aAA4B;QACpC,MAAM,IAAI,CAAC,sBAAsB,CAAC,aAAa,CAAC,CAAA;QAChD,MAAM,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAA;IAC5C,CAAC;IAED,KAAK,CAAC,IAAI;QACN,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAA;QACrC,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAA;IACzE,CAAC;CAEJ;AApBD,4CAoBC"}
@@ -0,0 +1,31 @@
1
+ {
2
+ "$id": "config.schema.json",
3
+ "$schema": "http://json-schema.org/draft-07/schema#",
4
+ "type": "object",
5
+ "description": "Subscriber plugin configuration",
6
+ "additionalProperties": false,
7
+ "properties": {
8
+ "streams": {
9
+ "type": "array",
10
+ "items": {
11
+ "type": "object",
12
+ "properties": {
13
+ "streamId": {
14
+ "type": "string"
15
+ },
16
+ "streamPartition": {
17
+ "type": "number"
18
+ },
19
+ "additionalProperties": false
20
+ }
21
+ },
22
+ "uniqueItems": true,
23
+ "default": []
24
+ },
25
+ "subscriptionRetryInterval": {
26
+ "type": "number",
27
+ "description": "DEPRECATED",
28
+ "default": 30000
29
+ }
30
+ }
31
+ }
@@ -0,0 +1,9 @@
1
+ import WebSocket from 'ws';
2
+ import { StreamrClient } from '@streamr/sdk';
3
+ import { PayloadFormat } from '../../helpers/PayloadFormat';
4
+ export declare const PING_PAYLOAD = "ping";
5
+ export interface Connection {
6
+ init(ws: WebSocket, socketId: string, streamrClient: StreamrClient, payloadFormat: PayloadFormat): Promise<void>;
7
+ }
8
+ export declare const addPingListener: (ws: WebSocket) => void;
9
+ export declare const addPingSender: (ws: WebSocket, socketId: string, sendInterval: number, disconnectTimeout: number) => void;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addPingSender = exports.addPingListener = exports.PING_PAYLOAD = void 0;
4
+ const utils_1 = require("@streamr/utils");
5
+ const logger = new utils_1.Logger(module);
6
+ exports.PING_PAYLOAD = 'ping';
7
+ const PONG_PAYLOAD = 'pong';
8
+ // Implements application layer ping support. We have this feature because
9
+ // browsers can't send pings in protocol level
10
+ const addPingListener = (ws) => {
11
+ ws.on('message', (data) => {
12
+ const payload = data.toString();
13
+ if (payload === exports.PING_PAYLOAD) {
14
+ ws.send(PONG_PAYLOAD);
15
+ }
16
+ });
17
+ };
18
+ exports.addPingListener = addPingListener;
19
+ const addPingSender = (ws, socketId, sendInterval, disconnectTimeout) => {
20
+ let pendingStateChange;
21
+ const setState = (state) => {
22
+ clearTimeout(pendingStateChange);
23
+ if (state === 'active') {
24
+ pendingStateChange = setTimeout(() => setState('idle'), sendInterval);
25
+ }
26
+ else if (state === 'idle') {
27
+ ws.ping();
28
+ if (disconnectTimeout !== 0) {
29
+ pendingStateChange = setTimeout(() => setState('disconnected'), disconnectTimeout);
30
+ }
31
+ }
32
+ else if (state === 'disconnected') {
33
+ logger.debug('Terminate connection', { socketId });
34
+ ws.terminate();
35
+ }
36
+ };
37
+ const events = ['message', 'ping', 'pong'];
38
+ events.forEach((eventName) => {
39
+ ws.on(eventName, () => setState('active'));
40
+ });
41
+ ws.on('close', () => clearTimeout(pendingStateChange));
42
+ setState('idle');
43
+ };
44
+ exports.addPingSender = addPingSender;
45
+ //# sourceMappingURL=Connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Connection.js","sourceRoot":"","sources":["../../../../src/plugins/websocket/Connection.ts"],"names":[],"mappings":";;;AAGA,0CAAuC;AAEvC,MAAM,MAAM,GAAG,IAAI,cAAM,CAAC,MAAM,CAAC,CAAA;AAEpB,QAAA,YAAY,GAAG,MAAM,CAAA;AAClC,MAAM,YAAY,GAAG,MAAM,CAAA;AAM3B,2EAA2E;AAC3E,8CAA8C;AACvC,MAAM,eAAe,GAAG,CAAC,EAAa,EAAQ,EAAE;IACnD,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,IAAuB,EAAE,EAAE;QACzC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAA;QAC/B,IAAI,OAAO,KAAK,oBAAY,EAAE,CAAC;YAC3B,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;QACzB,CAAC;IACL,CAAC,CAAC,CAAA;AACN,CAAC,CAAA;AAPY,QAAA,eAAe,mBAO3B;AAEM,MAAM,aAAa,GAAG,CACzB,EAAa,EACb,QAAgB,EAChB,YAAoB,EACpB,iBAAyB,EACrB,EAAE;IACN,IAAI,kBAAkC,CAAA;IAGtC,MAAM,QAAQ,GAAG,CAAC,KAAY,EAAE,EAAE;QAC9B,YAAY,CAAC,kBAAkB,CAAC,CAAA;QAChC,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;YACrB,kBAAkB,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC,CAAA;QACzE,CAAC;aAAM,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;YAC1B,EAAE,CAAC,IAAI,EAAE,CAAA;YACT,IAAI,iBAAiB,KAAK,CAAC,EAAE,CAAC;gBAC1B,kBAAkB,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,iBAAiB,CAAC,CAAA;YACtF,CAAC;QACL,CAAC;aAAM,IAAI,KAAK,KAAK,cAAc,EAAE,CAAC;YAClC,MAAM,CAAC,KAAK,CAAC,sBAAsB,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAA;YAClD,EAAE,CAAC,SAAS,EAAE,CAAA;QAClB,CAAC;IACL,CAAC,CAAA;IAED,MAAM,MAAM,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IAC1C,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE;QACzB,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAA;IAC9C,CAAC,CAAC,CAAA;IACF,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,kBAAkB,CAAC,CAAC,CAAA;IAEtD,QAAQ,CAAC,MAAM,CAAC,CAAA;AACpB,CAAC,CAAA;AA/BY,QAAA,aAAa,iBA+BzB"}
@@ -0,0 +1,12 @@
1
+ import WebSocket from 'ws';
2
+ import { StreamrClient } from '@streamr/sdk';
3
+ import { ParsedQs } from 'qs';
4
+ import { Connection } from './Connection';
5
+ import { PayloadFormat } from '../../helpers/PayloadFormat';
6
+ import { PublishPartitionDefinition } from '../../helpers/partitions';
7
+ export declare class PublishConnection implements Connection {
8
+ streamId: string;
9
+ partitionDefinition: PublishPartitionDefinition;
10
+ constructor(streamId: string, queryParams: ParsedQs);
11
+ init(ws: WebSocket, socketId: string, streamrClient: StreamrClient, payloadFormat: PayloadFormat): Promise<void>;
12
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PublishConnection = void 0;
4
+ const utils_1 = require("@streamr/utils");
5
+ const uuid_1 = require("uuid");
6
+ const Connection_1 = require("./Connection");
7
+ const partitions_1 = require("../../helpers/partitions");
8
+ class PublishConnection {
9
+ streamId;
10
+ partitionDefinition;
11
+ constructor(streamId, queryParams) {
12
+ this.streamId = streamId;
13
+ this.partitionDefinition = (0, partitions_1.parsePublishPartitionDefinition)(queryParams);
14
+ }
15
+ async init(ws, socketId, streamrClient, payloadFormat) {
16
+ const logger = new utils_1.Logger(module, { socketId });
17
+ const msgChainId = (0, uuid_1.v4)();
18
+ ws.on('message', async (data) => {
19
+ const payload = data.toString();
20
+ if (payload !== Connection_1.PING_PAYLOAD) {
21
+ try {
22
+ const { content, metadata } = payloadFormat.createMessage(payload);
23
+ await streamrClient.publish({
24
+ id: this.streamId,
25
+ partition: this.partitionDefinition.partition
26
+ }, content, {
27
+ timestamp: metadata.timestamp,
28
+ partitionKey: (0, partitions_1.getPartitionKey)(content, this.partitionDefinition),
29
+ msgChainId
30
+ });
31
+ }
32
+ catch (err) {
33
+ logger.warn('Unable to publish', {
34
+ err,
35
+ streamId: this.streamId,
36
+ partition: this.partitionDefinition.partition,
37
+ partitionKey: this.partitionDefinition.partitionKey,
38
+ msgChainId,
39
+ });
40
+ }
41
+ }
42
+ });
43
+ }
44
+ }
45
+ exports.PublishConnection = PublishConnection;
46
+ //# sourceMappingURL=PublishConnection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PublishConnection.js","sourceRoot":"","sources":["../../../../src/plugins/websocket/PublishConnection.ts"],"names":[],"mappings":";;;AAEA,0CAAuC;AAEvC,+BAAiC;AACjC,6CAAuD;AAEvD,yDAAuH;AAEvH,MAAa,iBAAiB;IAE1B,QAAQ,CAAQ;IAChB,mBAAmB,CAA4B;IAE/C,YAAY,QAAgB,EAAE,WAAqB;QAC/C,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QACxB,IAAI,CAAC,mBAAmB,GAAG,IAAA,4CAA+B,EAAC,WAAW,CAAC,CAAA;IAC3E,CAAC;IAED,KAAK,CAAC,IAAI,CACN,EAAa,EACb,QAAgB,EAChB,aAA4B,EAC5B,aAA4B;QAE5B,MAAM,MAAM,GAAG,IAAI,cAAM,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAA;QAC/C,MAAM,UAAU,GAAG,IAAA,SAAI,GAAE,CAAA;QACzB,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,IAAuB,EAAE,EAAE;YAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAA;YAC/B,IAAI,OAAO,KAAK,yBAAY,EAAE,CAAC;gBAC3B,IAAI,CAAC;oBACD,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,aAAa,CAAC,aAAa,CAAC,OAAO,CAAC,CAAA;oBAClE,MAAM,aAAa,CAAC,OAAO,CAAC;wBACxB,EAAE,EAAE,IAAI,CAAC,QAAQ;wBACjB,SAAS,EAAE,IAAI,CAAC,mBAAmB,CAAC,SAAS;qBAChD,EAAE,OAAO,EAAE;wBACR,SAAS,EAAE,QAAQ,CAAC,SAAS;wBAC7B,YAAY,EAAE,IAAA,4BAAe,EAAC,OAAO,EAAE,IAAI,CAAC,mBAAmB,CAAC;wBAChE,UAAU;qBACb,CAAC,CAAA;gBACN,CAAC;gBAAC,OAAO,GAAQ,EAAE,CAAC;oBAChB,MAAM,CAAC,IAAI,CAAC,mBAAmB,EAAE;wBAC7B,GAAG;wBACH,QAAQ,EAAE,IAAI,CAAC,QAAQ;wBACvB,SAAS,EAAE,IAAI,CAAC,mBAAmB,CAAC,SAAS;wBAC7C,YAAY,EAAE,IAAI,CAAC,mBAAmB,CAAC,YAAY;wBACnD,UAAU;qBACb,CAAC,CAAA;gBACN,CAAC;YACL,CAAC;QACL,CAAC,CAAC,CAAA;IACN,CAAC;CACJ;AA3CD,8CA2CC"}
@@ -0,0 +1,13 @@
1
+ import WebSocket from 'ws';
2
+ import { StreamrClient } from '@streamr/sdk';
3
+ import { Connection } from './Connection';
4
+ import { ParsedQs } from 'qs';
5
+ import { PayloadFormat } from '../../helpers/PayloadFormat';
6
+ export declare class SubscribeConnection implements Connection {
7
+ private readonly streamId;
8
+ private readonly partitions?;
9
+ private readonly subscriptions;
10
+ constructor(streamId: string, queryParams: ParsedQs);
11
+ init(ws: WebSocket, socketId: string, streamrClient: StreamrClient, payloadFormat: PayloadFormat): Promise<void>;
12
+ private unsubAll;
13
+ }
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SubscribeConnection = void 0;
4
+ const parser_1 = require("../../helpers/parser");
5
+ const utils_1 = require("@streamr/utils");
6
+ class SubscribeConnection {
7
+ streamId;
8
+ partitions;
9
+ subscriptions;
10
+ constructor(streamId, queryParams) {
11
+ this.streamId = streamId;
12
+ this.partitions = (0, parser_1.parseQueryParameterArray)('partitions', queryParams, parser_1.parsePositiveInteger);
13
+ this.subscriptions = [];
14
+ }
15
+ async init(ws, socketId, streamrClient, payloadFormat) {
16
+ const logger = new utils_1.Logger(module, { socketId });
17
+ const streamPartDefinitions = (this.partitions !== undefined)
18
+ ? this.partitions.map((partition) => ({ id: this.streamId, partition }))
19
+ : [{ id: this.streamId }];
20
+ logger.debug('Subscribing to stream partitions', {
21
+ streamId: this.streamId,
22
+ partitions: this.partitions
23
+ });
24
+ const msgCallback = (content, metadata) => {
25
+ const payload = payloadFormat.createPayload(content, metadata);
26
+ ws.send(payload);
27
+ };
28
+ this.subscriptions.push(...await (0, utils_1.pTransaction)(streamPartDefinitions.map((sd) => streamrClient.subscribe(sd, msgCallback)), (sub) => sub.unsubscribe()));
29
+ ws.once('close', async () => {
30
+ try {
31
+ await this.unsubAll(logger);
32
+ }
33
+ finally {
34
+ logger.info('Disconnected from client', { socketId });
35
+ }
36
+ });
37
+ logger.debug('Subscribed to stream partitions', {
38
+ streamId: this.streamId,
39
+ partitions: this.partitions
40
+ });
41
+ }
42
+ async unsubAll(logger) {
43
+ logger.debug('Unsubscribe from streams', {
44
+ subscriptions: this.subscriptions.map(({ streamPartId }) => streamPartId)
45
+ });
46
+ await Promise.all(this.subscriptions.map((sub) => sub.unsubscribe()));
47
+ }
48
+ }
49
+ exports.SubscribeConnection = SubscribeConnection;
50
+ //# sourceMappingURL=SubscribeConnection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubscribeConnection.js","sourceRoot":"","sources":["../../../../src/plugins/websocket/SubscribeConnection.ts"],"names":[],"mappings":";;;AAGA,iDAAqF;AAGrF,0CAAqD;AAErD,MAAa,mBAAmB;IAEX,QAAQ,CAAQ;IAChB,UAAU,CAAW;IACrB,aAAa,CAAgB;IAE9C,YAAY,QAAgB,EAAE,WAAqB;QAC/C,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QACxB,IAAI,CAAC,UAAU,GAAG,IAAA,iCAAwB,EAAC,YAAY,EAAE,WAAW,EAAE,6BAAoB,CAAC,CAAA;QAC3F,IAAI,CAAC,aAAa,GAAG,EAAE,CAAA;IAC3B,CAAC;IAED,KAAK,CAAC,IAAI,CACN,EAAa,EACb,QAAgB,EAChB,aAA4B,EAC5B,aAA4B;QAE5B,MAAM,MAAM,GAAG,IAAI,cAAM,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAA;QAC/C,MAAM,qBAAqB,GAAG,CAAC,IAAI,CAAC,UAAU,KAAK,SAAS,CAAC;YACzD,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,SAAiB,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;YAChF,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAA;QAE7B,MAAM,CAAC,KAAK,CAAC,kCAAkC,EAAE;YAC7C,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,UAAU,EAAE,IAAI,CAAC,UAAU;SAC9B,CAAC,CAAA;QACF,MAAM,WAAW,GAAG,CAAC,OAAgB,EAAE,QAAyB,EAAE,EAAE;YAChE,MAAM,OAAO,GAAG,aAAa,CAAC,aAAa,CAAC,OAAc,EAAE,QAAQ,CAAC,CAAA;YACrE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACpB,CAAC,CAAA;QACD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,MAAM,IAAA,oBAAY,EACzC,qBAAqB,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC,EAC3E,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,CAC7B,CAAC,CAAA;QAEF,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE;YACxB,IAAI,CAAC;gBACD,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;YAC/B,CAAC;oBAAS,CAAC;gBACP,MAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAA;YACzD,CAAC;QACL,CAAC,CAAC,CAAA;QAEF,MAAM,CAAC,KAAK,CAAC,iCAAiC,EAAE;YAC5C,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,UAAU,EAAE,IAAI,CAAC,UAAU;SAC9B,CAAC,CAAA;IACN,CAAC;IAEO,KAAK,CAAC,QAAQ,CAAC,MAAc;QACjC,MAAM,CAAC,KAAK,CAAC,0BAA0B,EAAE;YACrC,aAAa,EAAE,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,YAAY,CAAC;SAC5E,CAAC,CAAA;QACF,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAA;IACzE,CAAC;CACJ;AAxDD,kDAwDC"}
@@ -0,0 +1,19 @@
1
+ import { Schema } from 'ajv';
2
+ import { StreamrClient } from '@streamr/sdk';
3
+ import { Plugin } from '../../Plugin';
4
+ export interface WebsocketPluginConfig {
5
+ port: number;
6
+ payloadMetadata: boolean;
7
+ pingSendInterval: number;
8
+ disconnectTimeout: number;
9
+ sslCertificate?: {
10
+ privateKeyFileName: string;
11
+ certFileName: string;
12
+ };
13
+ }
14
+ export declare class WebsocketPlugin extends Plugin<WebsocketPluginConfig> {
15
+ private server?;
16
+ start(streamrClient: StreamrClient): Promise<void>;
17
+ stop(): Promise<void>;
18
+ getConfigSchema(): Schema;
19
+ }
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.WebsocketPlugin = void 0;
7
+ const Plugin_1 = require("../../Plugin");
8
+ const PayloadFormat_1 = require("../../helpers/PayloadFormat");
9
+ const WebsocketServer_1 = require("./WebsocketServer");
10
+ const config_schema_json_1 = __importDefault(require("./config.schema.json"));
11
+ class WebsocketPlugin extends Plugin_1.Plugin {
12
+ server;
13
+ async start(streamrClient) {
14
+ this.server = new WebsocketServer_1.WebsocketServer(streamrClient, this.pluginConfig.pingSendInterval, this.pluginConfig.disconnectTimeout);
15
+ await this.server.start(this.pluginConfig.port, (0, PayloadFormat_1.getPayloadFormat)(this.pluginConfig.payloadMetadata), this.getApiAuthentication(), this.pluginConfig.sslCertificate);
16
+ }
17
+ async stop() {
18
+ await this.server.stop();
19
+ }
20
+ // eslint-disable-next-line class-methods-use-this
21
+ getConfigSchema() {
22
+ return config_schema_json_1.default;
23
+ }
24
+ }
25
+ exports.WebsocketPlugin = WebsocketPlugin;
26
+ //# sourceMappingURL=WebsocketPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebsocketPlugin.js","sourceRoot":"","sources":["../../../../src/plugins/websocket/WebsocketPlugin.ts"],"names":[],"mappings":";;;;;;AAEA,yCAAqC;AACrC,+DAA8D;AAC9D,uDAAmD;AACnD,8EAAuD;AAavD,MAAa,eAAgB,SAAQ,eAA6B;IAEtD,MAAM,CAAkB;IAEhC,KAAK,CAAC,KAAK,CAAC,aAA4B;QACpC,IAAI,CAAC,MAAM,GAAG,IAAI,iCAAe,CAAC,aAAa,EAAE,IAAI,CAAC,YAAY,CAAC,gBAAgB,EAAE,IAAI,CAAC,YAAY,CAAC,iBAAiB,CAAC,CAAA;QACzH,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CACnB,IAAI,CAAC,YAAY,CAAC,IAAI,EACtB,IAAA,gCAAgB,EAAC,IAAI,CAAC,YAAY,CAAC,eAAe,CAAC,EACnD,IAAI,CAAC,oBAAoB,EAAE,EAC3B,IAAI,CAAC,YAAY,CAAC,cAAc,CACnC,CAAA;IACL,CAAC;IAED,KAAK,CAAC,IAAI;QACN,MAAM,IAAI,CAAC,MAAO,CAAC,IAAI,EAAE,CAAA;IAC7B,CAAC;IAED,kDAAkD;IACzC,eAAe;QACpB,OAAO,4BAAoB,CAAA;IAC/B,CAAC;CACJ;AAtBD,0CAsBC"}
@@ -0,0 +1,16 @@
1
+ import { StreamrClient } from '@streamr/sdk';
2
+ import { ApiAuthentication } from '../../apiAuthentication';
3
+ import { PayloadFormat } from '../../helpers/PayloadFormat';
4
+ import { WebsocketPluginConfig } from './WebsocketPlugin';
5
+ export declare class WebsocketServer {
6
+ private wss?;
7
+ private httpServer?;
8
+ private streamrClient;
9
+ private pingSendInterval;
10
+ private disconnectTimeout;
11
+ constructor(streamrClient: StreamrClient, pingSendInterval: number, disconnectTimeout: number);
12
+ start(port: number, payloadFormat: PayloadFormat, apiAuthentication?: ApiAuthentication, sslCertificateConfig?: WebsocketPluginConfig['sslCertificate']): Promise<void>;
13
+ private createConnection;
14
+ private parseUrl;
15
+ stop(): Promise<void>;
16
+ }
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.WebsocketServer = void 0;
7
+ const http_1 = __importDefault(require("http"));
8
+ const https_1 = __importDefault(require("https"));
9
+ const fs_1 = __importDefault(require("fs"));
10
+ const ws_1 = __importDefault(require("ws"));
11
+ const events_1 = require("events");
12
+ const qs_1 = __importDefault(require("qs"));
13
+ const utils_1 = require("@streamr/utils");
14
+ const Connection_1 = require("./Connection");
15
+ const apiAuthentication_1 = require("../../apiAuthentication");
16
+ const PublishConnection_1 = require("./PublishConnection");
17
+ const SubscribeConnection_1 = require("./SubscribeConnection");
18
+ const logger = new utils_1.Logger(module);
19
+ var Action;
20
+ (function (Action) {
21
+ Action["PUBLISH"] = "publish";
22
+ Action["SUBSCRIBE"] = "subscribe";
23
+ })(Action || (Action = {}));
24
+ const sendHttpError = (status, socket) => {
25
+ socket.write(`HTTP/1.1 ${status}\r\n\r\n`);
26
+ socket.destroy();
27
+ };
28
+ class WebsocketServer {
29
+ wss;
30
+ httpServer;
31
+ streamrClient;
32
+ pingSendInterval;
33
+ disconnectTimeout;
34
+ constructor(streamrClient, pingSendInterval, disconnectTimeout) {
35
+ this.streamrClient = streamrClient;
36
+ this.pingSendInterval = pingSendInterval;
37
+ this.disconnectTimeout = disconnectTimeout;
38
+ }
39
+ async start(port, payloadFormat, apiAuthentication, sslCertificateConfig) {
40
+ this.httpServer = (sslCertificateConfig !== undefined)
41
+ ? https_1.default.createServer({
42
+ key: fs_1.default.readFileSync(sslCertificateConfig.privateKeyFileName),
43
+ cert: fs_1.default.readFileSync(sslCertificateConfig.certFileName)
44
+ })
45
+ : http_1.default.createServer();
46
+ this.wss = new ws_1.default.Server({ noServer: true });
47
+ this.httpServer.on('upgrade', (request, socket, head) => {
48
+ let connectionUrl;
49
+ let connection;
50
+ try {
51
+ connectionUrl = this.parseUrl(request.url);
52
+ connection = this.createConnection(connectionUrl);
53
+ }
54
+ catch (err) {
55
+ logger.warn('Reject incoming connection', {
56
+ requestUrl: request.url,
57
+ reason: err?.message
58
+ });
59
+ sendHttpError('400 Bad Request', socket);
60
+ return;
61
+ }
62
+ const apiKey = connectionUrl.queryParams.apiKey;
63
+ if (!(0, apiAuthentication_1.isValidAuthentication)(apiKey, apiAuthentication)) {
64
+ logger.warn('Reject incoming connection', {
65
+ requestUrl: request.url,
66
+ includesApiKey: apiKey !== undefined,
67
+ reason: 'Invalid authentication'
68
+ });
69
+ sendHttpError((apiKey === undefined) ? '401 Unauthorized' : '403 Forbidden', socket);
70
+ return;
71
+ }
72
+ this.wss.handleUpgrade(request, socket, head, (ws) => {
73
+ this.wss.emit('connection', ws, request, connection);
74
+ });
75
+ });
76
+ this.wss.on('connection', async (ws, _request, connection) => {
77
+ const socketId = (0, utils_1.randomString)(5);
78
+ logger.info('Accept connection', { socketId });
79
+ try {
80
+ await connection.init(ws, socketId, this.streamrClient, payloadFormat);
81
+ (0, Connection_1.addPingListener)(ws);
82
+ if (this.pingSendInterval !== 0) {
83
+ (0, Connection_1.addPingSender)(ws, socketId, this.pingSendInterval, this.disconnectTimeout);
84
+ }
85
+ }
86
+ catch (err) {
87
+ logger.warn('Close connection', { socketId, reason: err?.message });
88
+ ws.close();
89
+ }
90
+ });
91
+ this.httpServer.listen(port);
92
+ await (0, events_1.once)(this.httpServer, 'listening');
93
+ logger.info(`Started Websocket server on port ${port}`);
94
+ }
95
+ // eslint-disable-next-line class-methods-use-this
96
+ createConnection(connectionUrl) {
97
+ switch (connectionUrl.action) {
98
+ case Action.PUBLISH:
99
+ return new PublishConnection_1.PublishConnection(connectionUrl.streamId, connectionUrl.queryParams);
100
+ case Action.SUBSCRIBE:
101
+ return new SubscribeConnection_1.SubscribeConnection(connectionUrl.streamId, connectionUrl.queryParams);
102
+ default:
103
+ throw new Error(`Assertion failed: unknown action "${connectionUrl.action}"`);
104
+ }
105
+ }
106
+ // eslint-disable-next-line class-methods-use-this
107
+ parseUrl(url) {
108
+ const PATH_PATTERN = new RegExp(`^.*/streams/(.*)/(${Action.PUBLISH}|${Action.SUBSCRIBE})(\\?.*)?$`);
109
+ const groups = url.match(PATH_PATTERN);
110
+ if (groups !== null) {
111
+ return {
112
+ streamId: decodeURIComponent(groups[1]),
113
+ action: groups[2],
114
+ queryParams: qs_1.default.parse(groups[3], { ignoreQueryPrefix: true })
115
+ };
116
+ }
117
+ else {
118
+ throw new Error('Malformed path');
119
+ }
120
+ }
121
+ async stop() {
122
+ this.wss.close();
123
+ for (const ws of this.wss.clients) {
124
+ ws.terminate();
125
+ }
126
+ this.httpServer.close();
127
+ await (0, events_1.once)(this.httpServer, 'close');
128
+ logger.info('Stopped Websocket server');
129
+ }
130
+ }
131
+ exports.WebsocketServer = WebsocketServer;
132
+ //# sourceMappingURL=WebsocketServer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebsocketServer.js","sourceRoot":"","sources":["../../../../src/plugins/websocket/WebsocketServer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ {
2
+ "$id": "config.schema.json",
3
+ "$schema": "http://json-schema.org/draft-07/schema#",
4
+ "type": "object",
5
+ "description": "WebSocket plugin configuration",
6
+ "additionalProperties": false,
7
+ "properties": {
8
+ "port": {
9
+ "type": "integer",
10
+ "description": "Port to start plugin on",
11
+ "default": 7170
12
+ },
13
+ "payloadMetadata": {
14
+ "type": "boolean",
15
+ "description": "The format of payloads: payload is wrapped as { content, metadata } or is a plain content JSON",
16
+ "default": false
17
+ },
18
+ "pingSendInterval": {
19
+ "type": "integer",
20
+ "description": "Interval (in milliseconds) in which to pings are sent to clients if there is no other trafic in the connection (0 = disable)",
21
+ "default": 15000
22
+ },
23
+ "disconnectTimeout": {
24
+ "type": "integer",
25
+ "description": "Timeout (in milliseconds) after a connection is closed if there is no trafic after ping is sent (0 = disable)",
26
+ "default": 15000
27
+ },
28
+ "sslCertificate": {
29
+ "description": "Files to use for SSL",
30
+ "type": "object",
31
+ "required": [
32
+ "certFileName",
33
+ "privateKeyFileName"
34
+ ],
35
+ "additionalProperties": false,
36
+ "properties": {
37
+ "certFileName": {
38
+ "type": "string",
39
+ "description": "Path of certificate file"
40
+ },
41
+ "privateKeyFileName": {
42
+ "type": "string",
43
+ "description": "Path of private key file"
44
+ }
45
+ }
46
+ },
47
+ "apiAuthentication": {
48
+ "$ref": "definitions.schema.json#/definitions/apiAuthenticationOverride"
49
+ }
50
+ }
51
+ }
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "@streamr/node",
3
+ "version": "100.0.0-rc.0",
4
+ "description": "A full-featured node implementation for the Streamr Network",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/streamr-dev/network.git",
8
+ "directory": "packages/broker"
9
+ },
10
+ "bin": {
11
+ "streamr-broker": "dist/bin/broker.js",
12
+ "streamr-broker-init": "dist/bin/config-wizard.js",
13
+ "delete-expired-data": "dist/bin/delete-expired-data.js",
14
+ "entry-point": "dist/bin/entry-point.js"
15
+ },
16
+ "main": "./dist/src/exports.js",
17
+ "types": "./dist/src/exports.d.ts",
18
+ "scripts": {
19
+ "build": "tsc -b tsconfig.node.json",
20
+ "check": "tsc -p ./tsconfig.jest.json --noEmit",
21
+ "clean": "jest --clearCache || true; rm -rf dist *.tsbuildinfo node_modules/.cache || true",
22
+ "eslint": "eslint --cache --cache-location=node_modules/.cache/.eslintcache/ '*/**/*.{js,ts}'",
23
+ "test": "npm run test-unit && npm run test-integration && npm run test-sequential",
24
+ "test-unit": "jest test/unit",
25
+ "test-sequential": "jest --bail --forceExit --maxWorkers=1 test/sequential # always run sequential tests with maxWorkers=1",
26
+ "test-integration": "jest --bail --forceExit test/integration && npm run test-sequential"
27
+ },
28
+ "author": "Streamr Network AG <contact@streamr.network>",
29
+ "license": "STREAMR NETWORK OPEN SOURCE LICENSE",
30
+ "dependencies": {
31
+ "@ethersproject/hdnode": "^5.4.0",
32
+ "@inquirer/prompts": "^4.0.0",
33
+ "@streamr/config": "^5.1.2",
34
+ "@streamr/network-contracts": "^7.0.8",
35
+ "@streamr/protocol": "100.0.0-rc.0",
36
+ "@streamr/sdk": "100.0.0-rc.0",
37
+ "@streamr/utils": "100.0.0-rc.0",
38
+ "aedes": "^0.51.0",
39
+ "ajv": "^8.8.2",
40
+ "ajv-formats": "^2.1.1",
41
+ "cassandra-driver": "^4.7.2",
42
+ "chalk": "^4.0.0",
43
+ "commander": "^12.0.0",
44
+ "consistent-hash": "^1.1.1",
45
+ "cors": "^2.8.5",
46
+ "ethers": "^5.4.7",
47
+ "express": "^4.17.1",
48
+ "heap": "^0.2.6",
49
+ "lodash": "^4.17.21",
50
+ "merge2": "^1.4.1",
51
+ "nat-type-identifier": "^2.0.9",
52
+ "node-fetch": "^2.7.0",
53
+ "p-limit": "^3.1.0",
54
+ "qs": "^6.10.1",
55
+ "uuid": "^9.0.1",
56
+ "ws": "^8.16.0",
57
+ "zod": "^3.22.4"
58
+ },
59
+ "devDependencies": {
60
+ "@inquirer/testing": "^2.1.11",
61
+ "@streamr/dht": "100.0.0-rc.0",
62
+ "@streamr/test-utils": "100.0.0-rc.0",
63
+ "@types/cors": "^2.8.17",
64
+ "@types/express": "^4.17.21",
65
+ "@types/heap": "^0.2.34",
66
+ "@types/lodash": "^4.14.202",
67
+ "@types/merge2": "^1.4.4",
68
+ "@types/node-fetch": "^2.6.4",
69
+ "@types/qs": "^6.9.11",
70
+ "@types/stream-to-array": "^2.3.3",
71
+ "@types/supertest": "^6.0.2",
72
+ "@types/uuid": "^9.0.8",
73
+ "@types/ws": "^8.5.10",
74
+ "async-mqtt": "^2.6.1",
75
+ "stream-to-array": "^2.3.0",
76
+ "supertest": "^6.3.4"
77
+ }
78
+ }