rascal 14.0.1 → 14.3.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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Change Log
2
2
 
3
+ ## 14.3.0
4
+
5
+ - Clone config instead of freezing it so buffers will work - See https://github.com/guidesmiths/rascal/issues/92
6
+
7
+ ## 14.2.1
8
+
9
+ - Fix schema bug
10
+
11
+ ## 14.2.0
12
+
13
+ - Add json schema (lib/config/schema.json) - See https://github.com/guidesmiths/rascal/issues/168
14
+
15
+ ## 14.1.0
16
+
17
+ - Adds support for custom user agents - See https://github.com/guidesmiths/rascal/issues/170
18
+
3
19
  ## 14.0.1
4
20
 
5
21
  - Fixes https://github.com/guidesmiths/rascal/issues/178
package/README.md CHANGED
@@ -273,10 +273,11 @@ The most common configuration options are
273
273
  - [publications](#publications)
274
274
  - [subscriptions](#subscriptions)
275
275
 
276
- A simple configuration is shown below.
276
+ A simple configuration is shown below. You can reference Rascal's JSON schema from the config to enable validation and suggestions in compatible IDEs.
277
277
 
278
278
  ```json
279
279
  {
280
+ "$schema": "./node_modules/rascal/lib/config/schema.json",
280
281
  "vhosts": {
281
282
  "/": {
282
283
  "connection": {
@@ -483,6 +484,15 @@ Rascal uses [superagent](https://github.com/visionmedia/superagent) under the ho
483
484
  }
484
485
  ```
485
486
 
487
+ You can also supply your own agent via the broker components. Use this when you need to set [TLS options](https://visionmedia.github.io/superagent/#tls-options).
488
+
489
+ ```js
490
+ const superagent = require('superagent-defaults');
491
+ const agent = superagent().on('request', (req) => console.log(req.url));
492
+ const components = { agent };
493
+ const broker = await Broker.create(config, components);
494
+ ```
495
+
486
496
  #### assert
487
497
 
488
498
  When set to true, Rascal will create the vhost if one doesn't exist using the RabbitMQ management API. This requires the [management plugin](https://www.rabbitmq.com/management.html) to be installed on the broker and for the management user to have necessary permissions.
@@ -0,0 +1,40 @@
1
+ {
2
+ "$schema": "../../lib/config/schema.json",
3
+ "vhosts": {
4
+ "/": {
5
+ "publicationChannelPools": {
6
+ "confirmPool": {
7
+ "max": 10,
8
+ "min": 10,
9
+ "evictionRunIntervalMillis": 1000,
10
+ "idleTimeoutMillis": 5000,
11
+ "autostart": true
12
+ }
13
+ },
14
+ "connection": {
15
+ "heartbeat": 5,
16
+ "socketOptions": {
17
+ "timeout": 1000
18
+ }
19
+ },
20
+ "exchanges": ["demo_ex"],
21
+ "queues": ["demo_q"],
22
+ "bindings": ["demo_ex[a.b.c] -> demo_q"],
23
+ "publications": {
24
+ "demo_pub": {
25
+ "exchange": "demo_ex",
26
+ "routingKey": "a.b.c",
27
+ "confirm": false,
28
+ "options": {
29
+ "persistent": false
30
+ }
31
+ }
32
+ },
33
+ "subscriptions": {
34
+ "demo_sub": {
35
+ "queue": "demo_q"
36
+ }
37
+ }
38
+ }
39
+ }
40
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "../../lib/config/schema.json",
3
+ "vhosts": {
4
+ "/": {
5
+ "connection": {
6
+ "heartbeat": 1,
7
+ "socketOptions": {
8
+ "timeout": 1000
9
+ }
10
+ },
11
+ "exchanges": [""],
12
+ "queues": ["demo_q"],
13
+ "publications": {
14
+ "demo_pub": {
15
+ "exchange": ""
16
+ }
17
+ },
18
+ "subscriptions": {
19
+ "demo_sub": {
20
+ "queue": "demo_q"
21
+ }
22
+ }
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "$schema": "../../lib/config/schema.json",
3
+ "vhosts": {
4
+ "/": {
5
+ "exchanges": ["demo_ex"],
6
+ "queues": ["demo_q"],
7
+ "bindings": ["demo_ex[a.b.c] -> demo_q"],
8
+ "publications": {
9
+ "demo_pub": {
10
+ "exchange": "demo_ex",
11
+ "routingKey": "a.b.c"
12
+ }
13
+ },
14
+ "subscriptions": {
15
+ "demo_sub": {
16
+ "queue": "demo_q"
17
+ }
18
+ }
19
+ }
20
+ }
21
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "$schema": "../../lib/config/schema.json",
3
+ "vhosts": {
4
+ "/": {
5
+ "connection": {
6
+ "heartbeat": 1,
7
+ "socketOptions": {
8
+ "timeout": 1000
9
+ }
10
+ },
11
+ "exchanges": ["demo_ex"],
12
+ "queues": ["demo_q"],
13
+ "bindings": ["demo_ex[a.b.c] -> demo_q"],
14
+ "publications": {
15
+ "demo_pub": {
16
+ "exchange": "demo_ex",
17
+ "routingKey": "a.b.c"
18
+ }
19
+ },
20
+ "subscriptions": {
21
+ "demo_sub": {
22
+ "queue": "demo_q"
23
+ }
24
+ }
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "$schema": "../../lib/config/schema.json",
3
+ "vhosts": {
4
+ "/": {
5
+ "publicationChannelPools": {
6
+ "confirmPool": {
7
+ "autostart": true
8
+ }
9
+ },
10
+ "connection": {
11
+ "options": {
12
+ "heartbeat": 10
13
+ },
14
+ "socketOptions": {
15
+ "timeout": 1000
16
+ }
17
+ },
18
+ "exchanges": ["demo_ex"],
19
+ "queues": ["demo_q"],
20
+ "bindings": ["demo_ex[a.b.c] -> demo_q"],
21
+ "publications": {
22
+ "demo_pub": {
23
+ "exchange": "demo_ex",
24
+ "routingKey": "a.b.c",
25
+ "options": {
26
+ "persistent": false
27
+ }
28
+ }
29
+ },
30
+ "subscriptions": {
31
+ "demo_sub": {
32
+ "queue": "demo_q"
33
+ }
34
+ }
35
+ }
36
+ }
37
+ }
@@ -18,9 +18,16 @@ const maxInterval = 2147483647;
18
18
  module.exports = {
19
19
  create: function create(config, components, next) {
20
20
  if (arguments.length === 2) return create(config, {}, arguments[1]);
21
+
22
+ const counters = _.defaults({}, components.counters, {
23
+ stub,
24
+ inMemory,
25
+ inMemoryCluster,
26
+ });
27
+
21
28
  preflight(_.cloneDeep(config), (err, config) => {
22
29
  if (err) return next(err);
23
- new Broker(config, components)._init(next);
30
+ new Broker(config, _.assign({}, components, { counters }))._init(next);
24
31
  });
25
32
  },
26
33
  };
@@ -39,13 +46,8 @@ function Broker(config, components) {
39
46
  const forewarnVhost = tasks.forewarnVhost;
40
47
  const shutdownVhost = tasks.shutdownVhost;
41
48
  const bounceVhost = tasks.bounceVhost;
42
- const counters = _.defaults({}, components.counters, {
43
- stub,
44
- inMemory,
45
- inMemoryCluster,
46
- });
47
49
 
48
- this.config = config;
50
+ this.config = _.cloneDeep(config);
49
51
  this.promises = false;
50
52
 
51
53
  this._init = function (next) {
@@ -54,7 +56,7 @@ function Broker(config, components) {
54
56
  publications = {};
55
57
  subscriptions = {};
56
58
  sessions = [];
57
- init(config, { broker: self, components: { counters } }, (err) => {
59
+ init(config, { broker: self, components }, (err) => {
58
60
  self.keepActive = setInterval(_.noop, maxInterval);
59
61
  setImmediate(() => {
60
62
  next(err, self);
@@ -135,7 +137,7 @@ function Broker(config, components) {
135
137
  async.eachSeries(
136
138
  _.values(vhosts),
137
139
  (vhost, callback) => {
138
- nukeVhost(config, { vhost }, callback);
140
+ nukeVhost(config, { vhost, components }, callback);
139
141
  },
140
142
  (err) => {
141
143
  if (err) return next(err);
package/lib/amqp/Vhost.js CHANGED
@@ -11,14 +11,14 @@ const backoff = require('../backoff');
11
11
  const setTimeoutUnref = require('../utils/setTimeoutUnref');
12
12
 
13
13
  module.exports = {
14
- create(config, next) {
15
- new Vhost(config).init(next);
14
+ create(config, components, next) {
15
+ new Vhost(config, components).init(next);
16
16
  },
17
17
  };
18
18
 
19
19
  inherits(Vhost, EventEmitter);
20
20
 
21
- function Vhost(config) {
21
+ function Vhost(config, components) {
22
22
  const self = this;
23
23
  let connection;
24
24
  let connectionConfig;
@@ -49,7 +49,7 @@ function Vhost(config) {
49
49
  debug('Initialising vhost: %s', self.name);
50
50
  pauseChannelAllocation();
51
51
 
52
- init(config, { connectionIndex: self.connectionIndex }, (err, config, ctx) => {
52
+ init(config, { connectionIndex: self.connectionIndex, components }, (err, config, ctx) => {
53
53
  if (err) return next(err);
54
54
 
55
55
  connection = ctx.connection;
@@ -1,11 +1,13 @@
1
1
  const debug = require('debug')('rascal:tasks:assertVhost');
2
2
  const _ = require('lodash');
3
3
  const async = require('async');
4
- const client = require('../../management/client');
4
+ const Client = require('../../management/Client');
5
5
 
6
6
  module.exports = _.curry((config, ctx, next) => {
7
7
  if (!config.assert) return next(null, config, ctx);
8
+
8
9
  const candidates = config.connections;
10
+ const client = new Client(ctx.components.agent);
9
11
 
10
12
  async.retry(
11
13
  candidates.length,
@@ -1,11 +1,13 @@
1
1
  const debug = require('debug')('rascal:tasks:checkVhost');
2
2
  const _ = require('lodash');
3
3
  const async = require('async');
4
- const client = require('../../management/client');
4
+ const Client = require('../../management/Client');
5
5
 
6
6
  module.exports = _.curry((config, ctx, next) => {
7
7
  if (!config.check) return next(null, config, ctx);
8
+
8
9
  const candidates = config.connections;
10
+ const client = new Client(ctx.components.agent);
9
11
 
10
12
  async.retry(
11
13
  candidates.length,
@@ -1,13 +1,14 @@
1
1
  const debug = require('debug')('rascal:tasks:deleteVhost');
2
2
  const _ = require('lodash');
3
3
  const async = require('async');
4
- const client = require('../../management/client');
4
+ const Client = require('../../management/Client');
5
5
 
6
6
  module.exports = _.curry((config, ctx, next) => {
7
7
  const vhostConfig = config.vhosts[ctx.vhost.name];
8
8
  if (!vhostConfig.assert) return next(null, config, ctx);
9
9
 
10
10
  const candidates = vhostConfig.connections;
11
+ const client = new Client(ctx.components.agent);
11
12
 
12
13
  async.retry(
13
14
  candidates.length,
@@ -9,7 +9,7 @@ module.exports = _.curry((config, ctx, next) => {
9
9
  async.eachSeries(
10
10
  _.values(config.vhosts),
11
11
  (vhostConfig, callback) => {
12
- initVhost(vhostConfig, (err, vhost) => {
12
+ initVhost(vhostConfig, ctx.components, (err, vhost) => {
13
13
  if (err) return callback(err);
14
14
  vhost.setMaxListeners(0);
15
15
  forwardEvents(vhost, ctx.broker);
@@ -24,6 +24,6 @@ module.exports = _.curry((config, ctx, next) => {
24
24
  );
25
25
  });
26
26
 
27
- function initVhost(config, next) {
28
- Vhost.create(config, next);
27
+ function initVhost(config, components, next) {
28
+ Vhost.create(config, components, next);
29
29
  }
@@ -6,7 +6,6 @@ const uuid = require('uuid').v4;
6
6
  const baseline = require('./baseline');
7
7
  const fqn = require('./fqn');
8
8
  const XRegExp = require('xregexp');
9
- const freeze = require('deep-freeze');
10
9
 
11
10
  module.exports = _.curry((rascalConfig, next) => {
12
11
  rascalConfig = _.defaultsDeep(rascalConfig, baseline);
@@ -24,7 +23,7 @@ module.exports = _.curry((rascalConfig, next) => {
24
23
  err = _err;
25
24
  }
26
25
 
27
- return err ? next(err) : next(null, freeze(rascalConfig));
26
+ return err ? next(err) : next(null, rascalConfig);
28
27
 
29
28
  function configureVhosts(vhosts) {
30
29
  _.each(vhosts, (vhostConfig, name) => {
@@ -0,0 +1,682 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema",
3
+ "type": "object",
4
+ "properties": {
5
+ "vhosts": {
6
+ "type": "object",
7
+ "patternProperties": {
8
+ ".*": {
9
+ "$ref": "#/definitions/vhost"
10
+ }
11
+ }
12
+ },
13
+ "publications": {
14
+ "type": "object",
15
+ "patternProperties": {
16
+ ".*": {
17
+ "$ref": "#/definitions/publication"
18
+ }
19
+ }
20
+ },
21
+ "subscriptions": {
22
+ "type": "object",
23
+ "patternProperties": {
24
+ ".*": {
25
+ "$ref": "#/definitions/subscription"
26
+ }
27
+ }
28
+ },
29
+ "redeliveries": {
30
+ "$ref": "#/definitions/redeliveries"
31
+ },
32
+ "encryption": {
33
+ "type": "object",
34
+ "$ref": "#/definitions/encryption"
35
+ }
36
+ },
37
+ "definitions": {
38
+ "vhost": {
39
+ "type": "object",
40
+ "properties": {
41
+ "assert": {
42
+ "type": "boolean"
43
+ },
44
+ "check": {
45
+ "type": "boolean"
46
+ },
47
+ "connectionStrategy": {
48
+ "type": "string",
49
+ "enum": ["random", "fixed"]
50
+ },
51
+ "connection": {
52
+ "$ref": "#/definitions/connection"
53
+ },
54
+ "connections": {
55
+ "type": "array",
56
+ "items": {
57
+ "$ref": "#/definitions/connection"
58
+ }
59
+ },
60
+ "exchanges": {
61
+ "oneOf": [
62
+ {
63
+ "type": "array",
64
+ "items": {
65
+ "type": "string"
66
+ }
67
+ },
68
+ {
69
+ "type": "object",
70
+ "patternProperties": {
71
+ ".*": {
72
+ "$ref": "#/definitions/exchange"
73
+ }
74
+ }
75
+ }
76
+ ]
77
+ },
78
+ "queues": {
79
+ "oneOf": [
80
+ {
81
+ "type": "array",
82
+ "items": {
83
+ "type": "string"
84
+ }
85
+ },
86
+ {
87
+ "type": "object",
88
+ "patternProperties": {
89
+ ".*": {
90
+ "$ref": "#/definitions/queue"
91
+ }
92
+ }
93
+ }
94
+ ]
95
+ },
96
+ "bindings": {
97
+ "oneOf": [
98
+ {
99
+ "type": "array",
100
+ "items": {
101
+ "type": "string"
102
+ }
103
+ },
104
+ {
105
+ "type": "object",
106
+ "patternProperties": {
107
+ ".*": {
108
+ "$ref": "#/definitions/binding"
109
+ }
110
+ }
111
+ }
112
+ ]
113
+ },
114
+ "publications": {
115
+ "type": "object",
116
+ "patternProperties": {
117
+ ".*": {
118
+ "$ref": "#/definitions/publication"
119
+ }
120
+ }
121
+ },
122
+ "subscriptions": {
123
+ "type": "object",
124
+ "patternProperties": {
125
+ ".*": {
126
+ "$ref": "#/definitions/subscription"
127
+ }
128
+ }
129
+ },
130
+ "publicationChannelPools": {
131
+ "type": "object",
132
+ "properties": {
133
+ "regularPool": {
134
+ "$ref": "#/definitions/channelPool"
135
+ },
136
+ "confirmPool": {
137
+ "$ref": "#/definitions/channelPool"
138
+ }
139
+ }
140
+ }
141
+ }
142
+ },
143
+ "channelPool": {
144
+ "type": "object",
145
+ "properties": {
146
+ "autostart": {
147
+ "type": "boolean"
148
+ },
149
+ "max": {
150
+ "type": "integer",
151
+ "minimum": 0
152
+ },
153
+ "min": {
154
+ "type": "integer",
155
+ "minimum": 0
156
+ },
157
+ "evictionRunIntervalMillis": {
158
+ "type": "integer",
159
+ "minimum": 0
160
+ },
161
+ "idleTimeoutMillis": {
162
+ "type": "integer",
163
+ "minimum": 0
164
+ },
165
+ "rejectionDelayMillis": {
166
+ "type": "integer",
167
+ "minimum": 0
168
+ },
169
+ "testOnBorrow": {
170
+ "type": "boolean"
171
+ },
172
+ "acquireTimeoutMillis": {
173
+ "type": "integer",
174
+ "minimum": 0
175
+ },
176
+ "destroyTimeoutMillis": {
177
+ "type": "integer",
178
+ "minimum": 0
179
+ }
180
+ }
181
+ },
182
+ "connection": {
183
+ "anyOf": [
184
+ {
185
+ "type": "string"
186
+ },
187
+ {
188
+ "type": "object",
189
+ "properties": {
190
+ "url": {
191
+ "type": "string"
192
+ },
193
+ "options": {
194
+ "$ref": "#/definitions/connectOptions"
195
+ },
196
+ "socketOptions": {
197
+ "$ref": "#/definitions/socketOptions"
198
+ },
199
+ "retry": {
200
+ "$ref": "#/definitions/retry"
201
+ },
202
+ "management": {
203
+ "$ref": "#/definitions/management"
204
+ }
205
+ }
206
+ },
207
+ {
208
+ "type": "object",
209
+ "properties": {
210
+ "protocol": {
211
+ "type": "string",
212
+ "enum": ["amqp", "amqps"]
213
+ },
214
+ "hostname": {
215
+ "type": "string"
216
+ },
217
+ "user": {
218
+ "type": "string"
219
+ },
220
+ "password": {
221
+ "type": "string"
222
+ },
223
+ "port": {
224
+ "type": "integer",
225
+ "minimum": 1
226
+ },
227
+ "vhost": {
228
+ "type": "string"
229
+ },
230
+ "options": {
231
+ "$ref": "#/definitions/connectOptions"
232
+ },
233
+ "socketOptions": {
234
+ "type": "object"
235
+ },
236
+ "retry": {
237
+ "$ref": "#/definitions/retry"
238
+ },
239
+ "management": {
240
+ "$ref": "#/definitions/management"
241
+ }
242
+ }
243
+ }
244
+ ]
245
+ },
246
+ "connectOptions": {
247
+ "type": "object",
248
+ "properties": {
249
+ "frameMax": {
250
+ "type": "integer",
251
+ "minimum": 0
252
+ },
253
+ "heartbeat": {
254
+ "type": "integer",
255
+ "minimum": 0
256
+ },
257
+ "connection_timeout": {
258
+ "type": "integer",
259
+ "minimum": 0
260
+ },
261
+ "channelMax": {
262
+ "type": "integer",
263
+ "minimum": 0
264
+ }
265
+ }
266
+ },
267
+ "socketOptions": {
268
+ "type": "object",
269
+ "properties": {
270
+ "timeout": {
271
+ "type": "integer",
272
+ "minimum": 0
273
+ }
274
+ }
275
+ },
276
+ "management": {
277
+ "anyOf": [
278
+ {
279
+ "type": "object",
280
+ "properties": {
281
+ "url": {
282
+ "type": "string"
283
+ },
284
+ "options": {
285
+ "type": "object",
286
+ "properties": {
287
+ "timeout": {
288
+ "type": "integer",
289
+ "minimum": 0
290
+ }
291
+ }
292
+ }
293
+ }
294
+ },
295
+ {
296
+ "type": "object",
297
+ "properties": {
298
+ "protocol": {
299
+ "type": "string",
300
+ "enum": ["http", "https"]
301
+ },
302
+ "hostname": {
303
+ "type": "string"
304
+ },
305
+ "user": {
306
+ "type": "string"
307
+ },
308
+ "password": {
309
+ "type": "string"
310
+ },
311
+ "port": {
312
+ "type": "integer",
313
+ "minimum": 1
314
+ },
315
+ "options": {
316
+ "type": "object",
317
+ "properties": {
318
+ "timeout": {
319
+ "type": "integer",
320
+ "minimum": 0
321
+ }
322
+ }
323
+ }
324
+ }
325
+ }
326
+ ]
327
+ },
328
+ "exchange": {
329
+ "type": "object",
330
+ "properties": {
331
+ "name": {
332
+ "type": "string"
333
+ },
334
+ "assert": {
335
+ "type": "boolean"
336
+ },
337
+ "check": {
338
+ "type": "boolean"
339
+ },
340
+ "type": {
341
+ "type": "string"
342
+ },
343
+ "options": {
344
+ "type": "object",
345
+ "properties": {
346
+ "durable": {
347
+ "type": "boolean"
348
+ },
349
+ "internal": {
350
+ "type": "boolean"
351
+ },
352
+ "autoDelete": {
353
+ "type": "boolean"
354
+ },
355
+ "alternateExchange": {
356
+ "type": "string"
357
+ },
358
+ "expires": {
359
+ "type": "integer",
360
+ "minimum": 0
361
+ },
362
+ "arguments": {
363
+ "type": "object"
364
+ }
365
+ }
366
+ }
367
+ }
368
+ },
369
+ "queue": {
370
+ "type": "object",
371
+ "properties": {
372
+ "name": {
373
+ "type": "string"
374
+ },
375
+ "assert": {
376
+ "type": "boolean"
377
+ },
378
+ "check": {
379
+ "type": "boolean"
380
+ },
381
+ "type": {
382
+ "type": "string"
383
+ },
384
+ "purge": {
385
+ "type": "boolean"
386
+ },
387
+ "options": {
388
+ "type": "object",
389
+ "properties": {
390
+ "exclusive": {
391
+ "type": "boolean"
392
+ },
393
+ "durable": {
394
+ "type": "boolean"
395
+ },
396
+ "autoDelete": {
397
+ "type": "boolean"
398
+ },
399
+ "messageTtl": {
400
+ "type": "integer",
401
+ "minimum": 0
402
+ },
403
+ "expires": {
404
+ "type": "integer",
405
+ "minimum": 0
406
+ },
407
+ "deadLetterExchange": {
408
+ "type": "string"
409
+ },
410
+ "deadLetterRoutingKey": {
411
+ "type": "string"
412
+ },
413
+ "maxLength": {
414
+ "type": "integer",
415
+ "minimum": 0
416
+ },
417
+ "maxPriority": {
418
+ "type": "integer",
419
+ "minimum": 0
420
+ },
421
+ "arguments": {
422
+ "type": "object"
423
+ }
424
+ }
425
+ }
426
+ }
427
+ },
428
+ "binding": {
429
+ "type": "object",
430
+ "properties": {
431
+ "name": {
432
+ "type": "string"
433
+ },
434
+ "source": {
435
+ "type": "string"
436
+ },
437
+ "destination": {
438
+ "type": "string"
439
+ },
440
+ "destinationType": {
441
+ "type": "string",
442
+ "enum": ["queue", "exchange"]
443
+ },
444
+ "bindingKey": {
445
+ "type": "string"
446
+ },
447
+ "bindingKeys": {
448
+ "type": "array",
449
+ "items": {
450
+ "type": "string"
451
+ }
452
+ },
453
+ "qualifyBindingKeys": {
454
+ "type": "boolean"
455
+ },
456
+ "options": {
457
+ "type": "object"
458
+ }
459
+ }
460
+ },
461
+ "publication": {
462
+ "type": "object",
463
+ "properties": {
464
+ "name": {
465
+ "type": "string"
466
+ },
467
+ "vhost": {
468
+ "type": "string"
469
+ },
470
+ "exchange": {
471
+ "type": "string"
472
+ },
473
+ "queue": {
474
+ "type": "string"
475
+ },
476
+ "routingKey": {
477
+ "type": "string"
478
+ },
479
+ "confirm": {
480
+ "type": "boolean"
481
+ },
482
+ "timeout": {
483
+ "type": "integer",
484
+ "minimum": 0
485
+ },
486
+ "encryption": {
487
+ "type": "string"
488
+ },
489
+ "options": {
490
+ "type": "object",
491
+ "properties": {
492
+ "expiration": {
493
+ "type": "string"
494
+ },
495
+ "userId": {
496
+ "type": "string"
497
+ },
498
+ "CC": {
499
+ "oneOf": [
500
+ {
501
+ "type": "string"
502
+ },
503
+ {
504
+ "type": "array",
505
+ "items": {
506
+ "type": "string"
507
+ }
508
+ }
509
+ ]
510
+ },
511
+ "BCC": {
512
+ "oneOf": [
513
+ {
514
+ "type": "string"
515
+ },
516
+ {
517
+ "type": "array",
518
+ "items": {
519
+ "type": "string"
520
+ }
521
+ }
522
+ ]
523
+ },
524
+ "priority": {
525
+ "type": "integer",
526
+ "minimum": 0
527
+ },
528
+ "persistent": {
529
+ "type": "boolean"
530
+ },
531
+ "mandatory": {
532
+ "type": "boolean"
533
+ },
534
+ "contentType": {
535
+ "type": "string"
536
+ },
537
+ "contentEncoding": {
538
+ "type": "string"
539
+ },
540
+ "headers": {
541
+ "type": "object"
542
+ },
543
+ "replyTo": {
544
+ "type": "string"
545
+ },
546
+ "type": {
547
+ "type": "string"
548
+ },
549
+ "appId": {
550
+ "type": "string"
551
+ }
552
+ }
553
+ }
554
+ }
555
+ },
556
+ "subscription": {
557
+ "type": "object",
558
+ "properties": {
559
+ "name": {
560
+ "type": "string"
561
+ },
562
+ "vhost": {
563
+ "type": "string"
564
+ },
565
+ "queue": {
566
+ "type": "string"
567
+ },
568
+ "contentType": {
569
+ "type": "string"
570
+ },
571
+ "prefetch": {
572
+ "type": "integer",
573
+ "minimum": 0
574
+ },
575
+ "retry": {
576
+ "$ref": "#/definitions/retry"
577
+ },
578
+ "redeliveries": {
579
+ "properties": {
580
+ "limit": {
581
+ "type": "integer",
582
+ "minimum": 0
583
+ },
584
+ "timeout": {
585
+ "type": "integer",
586
+ "minimum": 0
587
+ },
588
+ "counter": {
589
+ "type": "string"
590
+ }
591
+ }
592
+ },
593
+ "closeTimeout": {
594
+ "type": "integer",
595
+ "minimum": 0
596
+ },
597
+ "encryption": {
598
+ "type": "string"
599
+ },
600
+ "promisifyAckOrNack": {
601
+ "type": "boolean"
602
+ },
603
+ "options": {
604
+ "type": "object",
605
+ "properties": {
606
+ "noAck": {
607
+ "type": "boolean"
608
+ },
609
+ "exclusive": {
610
+ "type": "boolean"
611
+ },
612
+ "priority": {
613
+ "type": "integer",
614
+ "minimum": 0
615
+ },
616
+ "arguments": {
617
+ "type": "object"
618
+ }
619
+ }
620
+ }
621
+ }
622
+ },
623
+ "shovel": {
624
+ "type": "object",
625
+ "properties": {
626
+ "name": {
627
+ "type": "string"
628
+ },
629
+ "subscription": {
630
+ "type": "string"
631
+ },
632
+ "publication": {
633
+ "type": "string"
634
+ }
635
+ }
636
+ },
637
+ "retry": {
638
+ "type": "object",
639
+ "properties": {
640
+ "min": {
641
+ "type": "integer",
642
+ "minimum": 0
643
+ },
644
+ "max": {
645
+ "type": "integer",
646
+ "minimum": 0
647
+ },
648
+ "factor": {
649
+ "type": "number",
650
+ "minimum": 0
651
+ },
652
+ "strategy": {
653
+ "type": "string",
654
+ "enum": ["exponential", "linear"]
655
+ }
656
+ }
657
+ },
658
+ "redeliveries": {
659
+ "type": "object",
660
+ "properties": {
661
+ "counters": {
662
+ "type": "object"
663
+ }
664
+ }
665
+ },
666
+ "encryption": {
667
+ "type": "object",
668
+ "properties": {
669
+ "key": {
670
+ "type": "string"
671
+ },
672
+ "algorithm": {
673
+ "type": "string"
674
+ },
675
+ "ivLength": {
676
+ "type": "integer",
677
+ "minimum": 1
678
+ }
679
+ }
680
+ }
681
+ }
682
+ }
@@ -0,0 +1,55 @@
1
+ const debug = require('debug')('rascal:management:client');
2
+ const format = require('util').format;
3
+ const _ = require('lodash');
4
+ const defaultAgent = require('superagent');
5
+
6
+ function Client(suppliedAgent) {
7
+ const agent = suppliedAgent || defaultAgent;
8
+ const self = this;
9
+
10
+ this.assertVhost = function (name, config, next) {
11
+ debug('Asserting vhost: %s', name);
12
+ const options = getVhostOptions(name, config);
13
+ self._request('put', options.url, options.timeout, (err) => {
14
+ if (!err) return next();
15
+ const message = err.status ? format('Failed to assert vhost: %s. %s returned status %d', name, config.loggableUrl, err.status) : format('Failed to assert vhost: %s. %s errored with: %s', name, config.loggableUrl, err.message);
16
+ return next(new Error(message));
17
+ });
18
+ };
19
+
20
+ this.checkVhost = function (name, config, next) {
21
+ debug('Checking vhost: %s', name);
22
+ const options = getVhostOptions(name, config);
23
+ self._request('get', options.url, options.timeout, (err) => {
24
+ if (!err) return next();
25
+ const message = err.status ? format('Failed to check vhost: %s. %s returned status %d', name, config.loggableUrl, err.status) : format('Failed to check vhost: %s. %s errored with: %s', name, config.loggableUrl, err.message);
26
+ return next(new Error(message));
27
+ });
28
+ };
29
+
30
+ this.deleteVhost = function (name, config, next) {
31
+ debug('Deleting vhost: %s', name);
32
+ const options = getVhostOptions(name, config);
33
+ self._request('delete', options.url, options.timeout, (err) => {
34
+ if (!err) return next();
35
+ const message = err.status ? format('Failed to delete vhost: %s. %s returned status %d', name, config.loggableUrl, err.status) : format('Failed to delete vhost: %s. %s errored with: %s', name, config.loggableUrl, err.message);
36
+ return next(new Error(message));
37
+ });
38
+ };
39
+
40
+ this._request = function (method, url, timeout, next) {
41
+ agent[method](url)
42
+ .timeout({ deadline: timeout })
43
+ .then(() => {
44
+ next();
45
+ })
46
+ .catch(next);
47
+ };
48
+
49
+ function getVhostOptions(name, config) {
50
+ const url = format('%s/%s/%s', config.url, 'api/vhosts', name);
51
+ return _.defaultsDeep({ url }, config.options);
52
+ }
53
+ }
54
+
55
+ module.exports = Client;
package/package.json CHANGED
@@ -1,12 +1,11 @@
1
1
  {
2
2
  "name": "rascal",
3
- "version": "14.0.1",
3
+ "version": "14.3.0",
4
4
  "description": "A config driven wrapper for amqplib supporting multi-host connections, automatic error recovery, redelivery flood protection, transparent encryption / decryption, channel pooling and publication timeouts",
5
5
  "main": "index.js",
6
6
  "dependencies": {
7
7
  "async": "^3.2.1",
8
8
  "debug": "^4.1.1",
9
- "deep-freeze": "0.0.1",
10
9
  "forward-emitter": "^0.1.1",
11
10
  "generic-pool": "^3.7.1",
12
11
  "lodash": "^4.17.21",
@@ -29,6 +28,7 @@
29
28
  "nyc": "^15.1.0",
30
29
  "prettier": "2.4.1",
31
30
  "random-readable": "^1.0.1",
31
+ "superagent-defaults": "^0.1.14",
32
32
  "zunit": "^3.0.8"
33
33
  },
34
34
  "peerDependencies": {
@@ -1,39 +0,0 @@
1
- module.exports = {
2
- vhosts: {
3
- '/': {
4
- publicationChannelPools: {
5
- confirmPool: {
6
- max: 10,
7
- min: 10,
8
- evictionRunIntervalMillis: 1000,
9
- idleTimeoutMillis: 5000,
10
- autostart: true,
11
- },
12
- },
13
- connection: {
14
- heartbeat: 5,
15
- socketOptions: {
16
- timeout: 1000,
17
- },
18
- },
19
- exchanges: ['demo_ex'],
20
- queues: ['demo_q'],
21
- bindings: ['demo_ex[a.b.c] -> demo_q'],
22
- publications: {
23
- demo_pub: {
24
- exchange: 'demo_ex',
25
- routingKey: 'a.b.c',
26
- confirm: false,
27
- options: {
28
- persistent: false,
29
- },
30
- },
31
- },
32
- subscriptions: {
33
- demo_sub: {
34
- queue: 'demo_q',
35
- },
36
- },
37
- },
38
- },
39
- };
@@ -1,24 +0,0 @@
1
- module.exports = {
2
- vhosts: {
3
- '/': {
4
- connection: {
5
- heartbeat: 1,
6
- socketOptions: {
7
- timeout: 1000,
8
- },
9
- },
10
- exchanges: [''],
11
- queues: ['demo_q'],
12
- publications: {
13
- demo_pub: {
14
- exchange: '',
15
- },
16
- },
17
- subscriptions: {
18
- demo_sub: {
19
- queue: 'demo_q',
20
- },
21
- },
22
- },
23
- },
24
- };
@@ -1,20 +0,0 @@
1
- module.exports = {
2
- vhosts: {
3
- '/': {
4
- exchanges: ['demo_ex'],
5
- queues: ['demo_q'],
6
- bindings: ['demo_ex[a.b.c] -> demo_q'],
7
- publications: {
8
- demo_pub: {
9
- exchange: 'demo_ex',
10
- routingKey: 'a.b.c',
11
- },
12
- },
13
- subscriptions: {
14
- demo_sub: {
15
- queue: 'demo_q',
16
- },
17
- },
18
- },
19
- },
20
- };
@@ -1,26 +0,0 @@
1
- module.exports = {
2
- vhosts: {
3
- '/': {
4
- connection: {
5
- heartbeat: 1,
6
- socketOptions: {
7
- timeout: 1000,
8
- },
9
- },
10
- exchanges: ['demo_ex'],
11
- queues: ['demo_q'],
12
- bindings: ['demo_ex[a.b.c] -> demo_q'],
13
- publications: {
14
- demo_pub: {
15
- exchange: 'demo_ex',
16
- routingKey: 'a.b.c',
17
- },
18
- },
19
- subscriptions: {
20
- demo_sub: {
21
- queue: 'demo_q',
22
- },
23
- },
24
- },
25
- },
26
- };
@@ -1,36 +0,0 @@
1
- module.exports = {
2
- vhosts: {
3
- '/': {
4
- publicationChannelPools: {
5
- confirmPool: {
6
- autostart: true,
7
- },
8
- },
9
- connection: {
10
- options: {
11
- heartbeat: 10,
12
- },
13
- socketOptions: {
14
- timeout: 1000,
15
- },
16
- },
17
- exchanges: ['demo_ex'],
18
- queues: ['demo_q'],
19
- bindings: ['demo_ex[a.b.c] -> demo_q'],
20
- publications: {
21
- demo_pub: {
22
- exchange: 'demo_ex',
23
- routingKey: 'a.b.c',
24
- options: {
25
- persistent: false,
26
- },
27
- },
28
- },
29
- subscriptions: {
30
- demo_sub: {
31
- queue: 'demo_q',
32
- },
33
- },
34
- },
35
- },
36
- };
@@ -1,54 +0,0 @@
1
- const debug = require('debug')('rascal:management:client');
2
- const format = require('util').format;
3
- const _ = require('lodash');
4
- const agent = require('superagent');
5
-
6
- function assertVhost(name, config, next) {
7
- debug('Asserting vhost: %s', name);
8
- const options = getVhostOptions(name, config);
9
- request('put', options.url, options.timeout, (err) => {
10
- if (!err) return next();
11
- const message = err.status ? format('Failed to assert vhost: %s. %s returned status %d', name, config.loggableUrl, err.status) : format('Failed to assert vhost: %s. %s errored with: %s', name, config.loggableUrl, err.message);
12
- return next(new Error(message));
13
- });
14
- }
15
-
16
- function checkVhost(name, config, next) {
17
- debug('Checking vhost: %s', name);
18
- const options = getVhostOptions(name, config);
19
- request('get', options.url, options.timeout, (err) => {
20
- if (!err) return next();
21
- const message = err.status ? format('Failed to check vhost: %s. %s returned status %d', name, config.loggableUrl, err.status) : format('Failed to check vhost: %s. %s errored with: %s', name, config.loggableUrl, err.message);
22
- return next(new Error(message));
23
- });
24
- }
25
-
26
- function deleteVhost(name, config, next) {
27
- debug('Deleting vhost: %s', name);
28
- const options = getVhostOptions(name, config);
29
- request('delete', options.url, options.timeout, (err) => {
30
- if (!err) return next();
31
- const message = err.status ? format('Failed to delete vhost: %s. %s returned status %d', name, config.loggableUrl, err.status) : format('Failed to delete vhost: %s. %s errored with: %s', name, config.loggableUrl, err.message);
32
- return next(new Error(message));
33
- });
34
- }
35
-
36
- function getVhostOptions(name, config) {
37
- const url = format('%s/%s/%s', config.url, 'api/vhosts', name);
38
- return _.defaultsDeep({ url }, config.options);
39
- }
40
-
41
- function request(method, url, timeout, next) {
42
- agent[method](url)
43
- .timeout({ deadline: timeout })
44
- .then(() => {
45
- next();
46
- })
47
- .catch(next);
48
- }
49
-
50
- module.exports = {
51
- assertVhost,
52
- checkVhost,
53
- deleteVhost,
54
- };