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