1 | # ZeroMQ.js Next Generation
|
2 |
|
3 | [](https://www.npmjs.com/package/zeromq)
|
4 |
|
5 | [ØMQ](http://zeromq.org) bindings for Node.js. The goals of this library are:
|
6 |
|
7 | - Semantically similar to the [native](https://github.com/zeromq/libzmq) ØMQ
|
8 | library, while sticking to JavaScript idioms.
|
9 | - Use modern JavaScript and Node.js features such as `async`/`await` and async
|
10 | iterators.
|
11 | - High performance.
|
12 | - Fully usable with TypeScript (3+).
|
13 | - Compatible with Zeromq 4/5 via "zeromq/v5-compat"
|
14 |
|
15 | ## Useful links
|
16 |
|
17 | - [ZeroMQ.js API reference](http://zeromq.github.io/zeromq.js/modules.html).
|
18 | - [ZeroMQ project documentation](https://zeromq.org/get-started/).
|
19 | - **Note:** The Node.js examples on zeromq.org do not yet reflect the new API,
|
20 | but [the Guide](http://zguide.zeromq.org) in particular is still a good
|
21 | introduction to ZeroMQ for new users.
|
22 |
|
23 | ## Table of contents
|
24 |
|
25 | - [ZeroMQ.js Next Generation](#zeromqjs-next-generation)
|
26 | - [Useful links](#useful-links)
|
27 | - [Table of contents](#table-of-contents)
|
28 | - [Installation](#installation)
|
29 | - [Prebuilt binaries](#prebuilt-binaries)
|
30 | - [Building from source](#building-from-source)
|
31 | - [Available Build Options](#available-build-options)
|
32 | - [Curve support](#curve-support)
|
33 | - [Libsodium for Curve](#libsodium-for-curve)
|
34 | - [Draft support](#draft-support)
|
35 | - [Websocket support](#websocket-support)
|
36 | - [Secure Websocket support](#secure-websocket-support)
|
37 | - [Not Synchronous Resolve](#not-synchronous-resolve)
|
38 | - [MacOS Deployment Target](#macos-deployment-target)
|
39 | - [Examples](#examples)
|
40 | - [Basic Usage](#basic-usage)
|
41 | - [Push/Pull](#pushpull)
|
42 | - [`producer.js`](#producerjs)
|
43 | - [`worker.js`](#workerjs)
|
44 | - [Pub/Sub](#pubsub)
|
45 | - [`publisher.js`](#publisherjs)
|
46 | - [`subscriber.js`](#subscriberjs)
|
47 | - [Req/Rep](#reqrep)
|
48 | - [`client.js`](#clientjs)
|
49 | - [`server.js`](#serverjs)
|
50 | - [Zeromq 4 and 5 Compatibility layer](#zeromq-4-and-5-compatibility-layer)
|
51 | - [TypeScript](#typescript)
|
52 | - [Contribution](#contribution)
|
53 | - [Dependencies](#dependencies)
|
54 | - [Defining new options](#defining-new-options)
|
55 | - [Testing](#testing)
|
56 | - [Publishing](#publishing)
|
57 | - [History](#history)
|
58 |
|
59 | ## Installation
|
60 |
|
61 | Install **ZeroMQ.js** with prebuilt binaries:
|
62 |
|
63 | ```sh
|
64 | npm install zeromq
|
65 | ```
|
66 |
|
67 | Supported versions:
|
68 |
|
69 | - Node.js v12 (requires a [N-API](https://nodejs.org/api/n-api.html))
|
70 |
|
71 | ### Prebuilt binaries
|
72 |
|
73 | The following platforms have a **prebuilt binary** available:
|
74 |
|
75 | - Windows on x86/x86-64
|
76 |
|
77 | Zeromq binaries on Windows 10 or older need
|
78 | [Visual C++ Redistributable](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170#latest-microsoft-visual-c-redistributable-version)
|
79 | to be installed.
|
80 |
|
81 | - Linux on x86-64 with libstdc++.so.6.0.21+ (glibc++ 3.4.21+), for example:
|
82 | - Debian 9+ (Stretch or later)
|
83 | - Ubuntu 16.04+ (Xenial or later)
|
84 | - CentOS 8+
|
85 | - Linux on x86-64 with musl, for example:
|
86 | - Alpine 3.3+
|
87 | - MacOS 10.9+ on x86-64
|
88 |
|
89 | If a prebuilt binary is not available for your platform, installing will attempt
|
90 | to start a build from source.
|
91 |
|
92 | ### Building from source
|
93 |
|
94 | If a prebuilt binary is unavailable or if you want to pass certain options
|
95 | during build, you can build this package from source.
|
96 |
|
97 | Make sure you have the following installed before attempting to build from
|
98 | source:
|
99 |
|
100 | - Node.js 10+ or Electron
|
101 | - A working C++17 compiler toolchain with make
|
102 | - Python 3 with Node 10+ (or legacy Python 2.7)
|
103 | - CMake 2.8+
|
104 | - curl
|
105 |
|
106 | To install from source, specify `build_from_source=true` in a `.npmrc` file
|
107 |
|
108 | ```
|
109 | build_from_source=true
|
110 | ```
|
111 |
|
112 | When building from source, you can also specify additional build options in a
|
113 | `.npmrc` file in your project:
|
114 |
|
115 | ### Available Build Options
|
116 |
|
117 | <details>
|
118 | <summary>👉🏻 Options</summary>
|
119 |
|
120 | ### Curve support
|
121 |
|
122 | Enables CURVE security for encrypted communications. To enable CURVE support,
|
123 | add the following to your .npmrc:
|
124 |
|
125 | ```ini
|
126 | zmq_curve="true"
|
127 | ```
|
128 |
|
129 | ### Libsodium for Curve
|
130 |
|
131 | Enable libsodium for CURVE security instead of the built-in tweetnacl
|
132 | implementation. This can provide better performance for CURVE operations. To use
|
133 | libsodium, add the following to your .npmrc:
|
134 |
|
135 | ```ini
|
136 | zmq_sodium="true"
|
137 | ```
|
138 |
|
139 | #### Draft support
|
140 |
|
141 | By default `libzmq` is built with support for `Draft` patterns (e.g.
|
142 | `server-client`, `radio-dish`, `scatter-gather`). If you want to build `libzmq`
|
143 | without support for `Draft`, you can specify the following in `.npmrc`:
|
144 |
|
145 | ```ini
|
146 | zmq_draft=false
|
147 | ```
|
148 |
|
149 | #### Websocket support
|
150 |
|
151 | Enables WebSocket transport, allowing ZeroMQ to communicate over WebSockets. To
|
152 | enable WebSocket support, add the following to your .npmrc:
|
153 |
|
154 | ```ini
|
155 | zmq_websockets="true"
|
156 | ```
|
157 |
|
158 | #### Secure Websocket support
|
159 |
|
160 | Enables WebSocket transport with TLS (wss), providing secure WebSocket
|
161 | communications. To enable secure WebSocket support, add the following to your
|
162 | .npmrc:
|
163 |
|
164 | ```ini
|
165 | zmq_websockets_secure="true"
|
166 | ```
|
167 |
|
168 | #### Not Synchronous Resolve
|
169 |
|
170 | Enables immediate send/receive on the socket without synchronous resolution.
|
171 | This option can improve performance in certain scenarios by allowing operations
|
172 | to proceed without waiting for synchronous resolution. To enable this feature,
|
173 | add the following to your `.npmrc`:
|
174 |
|
175 | ```ini
|
176 | zmq_no_sync_resolve="true"
|
177 | ```
|
178 |
|
179 | #### MacOS Deployment Target
|
180 |
|
181 | Specifies the minimum macOS version that the binary will be compatible with.
|
182 | This is particularly useful when building for different macOS versions. To set
|
183 | this, add the following to your .npmrc, replacing 10.15 with your desired
|
184 | minimum macOS version:
|
185 |
|
186 | ```ini
|
187 | macosx_deployment_target="10.15"
|
188 | ```
|
189 |
|
190 | </details>
|
191 |
|
192 | ## Examples
|
193 |
|
194 | Here some examples of different features are provided. More examples can be
|
195 | found in the [examples directory](examples).
|
196 |
|
197 | You can also browse
|
198 | [the API reference documentation](http://zeromq.github.io/zeromq.js/globals.html)
|
199 | to see all socket types, methods & options as well as more detailed information
|
200 | about how to apply them.
|
201 |
|
202 | **Note:** If you are new to ZeroMQ, please start with the
|
203 | [ZeroMQ documentation](https://zeromq.org/get-started/).
|
204 |
|
205 | ### Basic Usage
|
206 |
|
207 | ES modules:
|
208 |
|
209 | ```typescript
|
210 | import {Request} from "zeromq"
|
211 | // or as namespace
|
212 | import * as zmq from "zeromq"
|
213 |
|
214 | const reqSock = new Request()
|
215 | //...
|
216 | const repSock = new zmq.Reply()
|
217 | ```
|
218 |
|
219 | Commonjs:
|
220 |
|
221 | ```js
|
222 | const zmq = require("zeromq")
|
223 |
|
224 | const reqSock = new zmq.Request()
|
225 | //...
|
226 | const repSock = new zmq.Reply()
|
227 | ```
|
228 |
|
229 | ### Push/Pull
|
230 |
|
231 | This example demonstrates how a producer pushes information onto a socket and
|
232 | how a worker pulls information from the socket.
|
233 |
|
234 | #### `producer.js`
|
235 |
|
236 | Creates a producer to push information onto a socket.
|
237 |
|
238 | ```js
|
239 | import * as zmq from "zeromq"
|
240 |
|
241 | async function run() {
|
242 | const sock = new zmq.Push()
|
243 |
|
244 | await sock.bind("tcp://127.0.0.1:3000")
|
245 | console.log("Producer bound to port 3000")
|
246 |
|
247 | while (true) {
|
248 | await sock.send("some work")
|
249 | await new Promise(resolve => {
|
250 | setTimeout(resolve, 500)
|
251 | })
|
252 | }
|
253 | }
|
254 |
|
255 | run()
|
256 | ```
|
257 |
|
258 | #### `worker.js`
|
259 |
|
260 | Creates a worker to pull information from the socket.
|
261 |
|
262 | ```js
|
263 | import * as zmq from "zeromq"
|
264 |
|
265 | async function run() {
|
266 | const sock = new zmq.Pull()
|
267 |
|
268 | sock.connect("tcp://127.0.0.1:3000")
|
269 | console.log("Worker connected to port 3000")
|
270 |
|
271 | for await (const [msg] of sock) {
|
272 | console.log("work: %s", msg.toString())
|
273 | }
|
274 | }
|
275 |
|
276 | run()
|
277 | ```
|
278 |
|
279 | ### Pub/Sub
|
280 |
|
281 | This example demonstrates using `zeromq` in a classic Pub/Sub,
|
282 | Publisher/Subscriber, application.
|
283 |
|
284 | #### `publisher.js`
|
285 |
|
286 | Create the publisher which sends messages.
|
287 |
|
288 | ```js
|
289 | import * as zmq from "zeromq"
|
290 |
|
291 | async function run() {
|
292 | const sock = new zmq.Publisher()
|
293 |
|
294 | await sock.bind("tcp://127.0.0.1:3000")
|
295 | console.log("Publisher bound to port 3000")
|
296 |
|
297 | while (true) {
|
298 | console.log("sending a multipart message envelope")
|
299 | await sock.send(["kitty cats", "meow!"])
|
300 | await new Promise(resolve => {
|
301 | setTimeout(resolve, 500)
|
302 | })
|
303 | }
|
304 | }
|
305 |
|
306 | run()
|
307 | ```
|
308 |
|
309 | #### `subscriber.js`
|
310 |
|
311 | Create a subscriber to connect to a publisher's port to receive messages.
|
312 |
|
313 | ```js
|
314 | import * as zmq from "zeromq"
|
315 |
|
316 | async function run() {
|
317 | const sock = new zmq.Subscriber()
|
318 |
|
319 | sock.connect("tcp://127.0.0.1:3000")
|
320 | sock.subscribe("kitty cats")
|
321 | console.log("Subscriber connected to port 3000")
|
322 |
|
323 | for await (const [topic, msg] of sock) {
|
324 | console.log(
|
325 | "received a message related to:",
|
326 | topic,
|
327 | "containing message:",
|
328 | msg,
|
329 | )
|
330 | }
|
331 | }
|
332 |
|
333 | run()
|
334 | ```
|
335 |
|
336 | ### Req/Rep
|
337 |
|
338 | This example illustrates a request from a client and a reply from a server.
|
339 |
|
340 | #### `client.js`
|
341 |
|
342 | ```js
|
343 | import * as zmq from "zeromq"
|
344 |
|
345 | async function run() {
|
346 | const sock = new zmq.Request()
|
347 |
|
348 | sock.connect("tcp://127.0.0.1:3000")
|
349 | console.log("Producer bound to port 3000")
|
350 |
|
351 | await sock.send("4")
|
352 | const [result] = await sock.receive()
|
353 |
|
354 | console.log(result)
|
355 | }
|
356 |
|
357 | run()
|
358 | ```
|
359 |
|
360 | #### `server.js`
|
361 |
|
362 | ```js
|
363 | import * as zmq from "zeromq"
|
364 |
|
365 | async function run() {
|
366 | const sock = new zmq.Reply()
|
367 |
|
368 | await sock.bind("tcp://127.0.0.1:3000")
|
369 |
|
370 | for await (const [msg] of sock) {
|
371 | await sock.send((2 * parseInt(msg.toString(), 10)).toString())
|
372 | }
|
373 | }
|
374 |
|
375 | run()
|
376 | ```
|
377 |
|
378 | ## Zeromq 4 and 5 Compatibility layer
|
379 |
|
380 | The next generation version of the library features a compatibility layer for
|
381 | ZeroMQ.js versions 4 and 5. This is recommended for users upgrading from
|
382 | previous versions.
|
383 |
|
384 | Example:
|
385 |
|
386 | ```js
|
387 | const zmq = require("zeromq/v5-compat")
|
388 |
|
389 | const pub = zmq.socket("pub")
|
390 | const sub = zmq.socket("sub")
|
391 |
|
392 | pub.bind("tcp://*:3456", err => {
|
393 | if (err) throw err
|
394 |
|
395 | sub.connect("tcp://127.0.0.1:3456")
|
396 |
|
397 | pub.send("message")
|
398 |
|
399 | sub.on("message", msg => {
|
400 | // Handle received message...
|
401 | })
|
402 | })
|
403 | ```
|
404 |
|
405 | ## TypeScript
|
406 |
|
407 | This library provides typings for TypeScript version 3.0.x and later.
|
408 |
|
409 | _Requirements_
|
410 |
|
411 | - For TypeScript version >= 3:
|
412 | - [compilerOptions](https://www.typescriptlang.org/docs/handbook/compiler-options.html)
|
413 | - For TypeScript version < 3.6:
|
414 | - either set `compilerOptions.target` to `esnext` or later (e.g. `es2018`)
|
415 | - or add the following, or similar, libraries to `compilerOptions.lib` (and
|
416 | include their corresponding polyfills if needed): `es2015`,
|
417 | `ESNext.AsyncIterable`
|
418 |
|
419 | ## Contribution
|
420 |
|
421 | If you are interested in making contributions to this project, please read the
|
422 | following sections.
|
423 |
|
424 | ### Dependencies
|
425 |
|
426 | In order to develop and test the library, you'll need the tools required to
|
427 | build from source ([see above](#building-from-source)).
|
428 |
|
429 | Additionally, having clang-format is strongly recommended.
|
430 |
|
431 | ### Defining new options
|
432 |
|
433 | Socket and context options can be set at runtime, even if they are not
|
434 | implemented by this library. By design, this requires no recompilation if the
|
435 | built version of ZeroMQ has support for them. This allows library users to test
|
436 | and use options that have been introduced in recent versions of ZeroMQ without
|
437 | having to modify this library. Of course we'd love to include support for new
|
438 | options in an idiomatic way.
|
439 |
|
440 | Options can be set as follows:
|
441 |
|
442 | ```js
|
443 | const {Dealer} = require("zeromq")
|
444 |
|
445 | /* This defines an accessor named 'sendHighWaterMark', which corresponds to
|
446 | the constant ZMQ_SNDHWM, which is defined as '23' in zmq.h. The option takes
|
447 | integers. The accessor name has been converted to idiomatic JavaScript.
|
448 | Of course, this particular option already exists in this library. */
|
449 | class MyDealer extends Dealer {
|
450 | get sendHighWaterMark(): number {
|
451 | return this.getInt32Option(23)
|
452 | }
|
453 |
|
454 | set sendHighWaterMark(value: number) {
|
455 | this.setInt32Option(23, value)
|
456 | }
|
457 | }
|
458 |
|
459 | const sock = new MyDealer({sendHighWaterMark: 456})
|
460 | ```
|
461 |
|
462 | When submitting pull requests for new socket/context options, please consider
|
463 | the following:
|
464 |
|
465 | - The option is documented in the TypeScript interface.
|
466 | - The option is only added to relevant socket types, and if the ZMQ\_ constant
|
467 | has a prefix indicating which type it applies to, it is stripped from the name
|
468 | as it is exposed in JavaScript.
|
469 | - The name as exposed in this library is idiomatic for JavaScript, spelling out
|
470 | any abbreviations and using proper `camelCase` naming conventions.
|
471 | - The option is a value that can be set on a socket, and you don't think it
|
472 | should actually be a method.
|
473 |
|
474 | ### Testing
|
475 |
|
476 | The test suite can be run with:
|
477 |
|
478 | ```sh
|
479 | npm install
|
480 | npm run build
|
481 | npm run test
|
482 | ```
|
483 |
|
484 | The test suite will validate and fix the coding style, run all unit tests and
|
485 | verify the validity of the included TypeScript type definitions.
|
486 |
|
487 | Some tests are not enabled by default:
|
488 |
|
489 | - API Compatibility tests from ZeroMQ 5.x have been disabled by default. You can
|
490 | include the tests with `INCLUDE_COMPAT_TESTS=1 npm run test`
|
491 | - Some transports are not reliable on some older versions of ZeroMQ, the
|
492 | relevant tests will be skipped for those versions automatically.
|
493 |
|
494 | ### Publishing
|
495 |
|
496 | To publish a new version, run:
|
497 |
|
498 | ```sh
|
499 | npm version <new version>
|
500 | git push && git push --tags
|
501 | ```
|
502 |
|
503 | Wait for continuous integration to finish. Prebuilds will be generated for all
|
504 | supported platforms and attached to a Github release. Documentation is
|
505 | automatically generated and committed to `gh-pages`. Finally, a new NPM package
|
506 | version will be automatically released.
|
507 |
|
508 | ## History
|
509 |
|
510 | Version 6+ is a complete rewrite of previous versions of ZeroMQ.js in order to
|
511 | be more reliable, correct, and usable in modern JavaScript & TypeScript code as
|
512 | first outlined in [this issue](https://github.com/zeromq/zeromq.js/issues/189).
|
513 | Previous versions of ZeroMQ.js were based on `zmq` and a fork that included
|
514 | prebuilt binaries.
|
515 |
|
516 | See detailed changes in the [CHANGELOG](CHANGELOG.md).
|
517 |
|
\ | No newline at end of file |