@onify/fake-amqplib 0.9.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +89 -29
- package/index.d.ts +60 -0
- package/index.js +451 -360
- package/main.cjs +591 -0
- package/package.json +30 -13
- package/CHANGELOG.md +0 -61
package/main.cjs
ADDED
|
@@ -0,0 +1,591 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var smqp = require('smqp');
|
|
4
|
+
var events = require('events');
|
|
5
|
+
var url = require('url');
|
|
6
|
+
|
|
7
|
+
const kSmqp = Symbol.for('smqp');
|
|
8
|
+
const kClosed = Symbol.for('closed');
|
|
9
|
+
const kEmitter = Symbol.for('event emitter');
|
|
10
|
+
const kPrefetch = Symbol.for('prefetch');
|
|
11
|
+
|
|
12
|
+
class FakeAmqpError extends Error {
|
|
13
|
+
constructor(message, code, killChannel, killConnection) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.code = code;
|
|
16
|
+
this._killChannel = killChannel;
|
|
17
|
+
this._killConnection = killConnection;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
class FakeAmqpNotFoundError extends FakeAmqpError {
|
|
22
|
+
constructor(type, name, vhost, killConnection = false) {
|
|
23
|
+
super(`Channel closed by server: 404 (NOT-FOUND) with message "NOT_FOUND - no ${type} '${name}' in vhost '${vhost || '/'}'`, 404, true, killConnection);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
class FakeAmqplibChannel {
|
|
28
|
+
constructor(broker, connection) {
|
|
29
|
+
this.connection = connection;
|
|
30
|
+
|
|
31
|
+
this[kPrefetch] = 10000;
|
|
32
|
+
this[kClosed] = false;
|
|
33
|
+
this[kEmitter] = new events.EventEmitter();
|
|
34
|
+
this._channelName = `channel-${generateId()}`;
|
|
35
|
+
this._version = connection._version;
|
|
36
|
+
this._broker = broker;
|
|
37
|
+
|
|
38
|
+
this._emitReturn = this._emitReturn.bind(this);
|
|
39
|
+
|
|
40
|
+
broker.on('return', this._emitReturn);
|
|
41
|
+
}
|
|
42
|
+
get _emitter() {
|
|
43
|
+
return this[kEmitter];
|
|
44
|
+
}
|
|
45
|
+
get _closed() {
|
|
46
|
+
return this[kClosed];
|
|
47
|
+
}
|
|
48
|
+
assertExchange(...args) {
|
|
49
|
+
return this._callBroker(assertExchange, ...args);
|
|
50
|
+
|
|
51
|
+
function assertExchange(exchange, ...assertArgs) {
|
|
52
|
+
this.assertExchange(exchange, ...assertArgs);
|
|
53
|
+
return { exchange };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
assertQueue(...args) {
|
|
57
|
+
const connection = this.connection;
|
|
58
|
+
return this._callBroker(assertQueue, ...args);
|
|
59
|
+
|
|
60
|
+
function assertQueue(queueName, ...assertArgs) {
|
|
61
|
+
const name = queueName ? queueName : `amqp.gen-${generateId()}`;
|
|
62
|
+
const options = typeof assertArgs[0] === 'object' ? assertArgs.shift() : {};
|
|
63
|
+
const queue = this.assertQueue(name, { ...options, _connectionId: connection._id }, ...assertArgs);
|
|
64
|
+
return {
|
|
65
|
+
queue: name,
|
|
66
|
+
messageCount: queue.messageCount,
|
|
67
|
+
consumerCount: queue.consumerCount,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
bindExchange(destination, source, ...args) {
|
|
72
|
+
const broker = this._broker;
|
|
73
|
+
return Promise.all([ this.checkExchange(source), this.checkExchange(destination) ]).then(() => {
|
|
74
|
+
return this._callBroker(broker.bindExchange, source, destination, ...args);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
bindQueue(queue, source, ...args) {
|
|
78
|
+
return Promise.all([ this.checkQueue(queue), this.checkExchange(source) ]).then(() => {
|
|
79
|
+
return this._callBroker(this._broker.bindQueue, queue, source, ...args);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
checkExchange(name, ...args) {
|
|
83
|
+
const connPath = this.connection._url.pathname;
|
|
84
|
+
return this._callBroker(check, ...args);
|
|
85
|
+
|
|
86
|
+
function check() {
|
|
87
|
+
if (!this.getExchange(name)) throw new FakeAmqpNotFoundError('exchange', name, connPath);
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
checkQueue(name, ...args) {
|
|
92
|
+
const connPath = this.connection._url.pathname;
|
|
93
|
+
return this._callBroker(check, ...args);
|
|
94
|
+
|
|
95
|
+
function check() {
|
|
96
|
+
let queue;
|
|
97
|
+
if (!(queue = this.getQueue(name))) {
|
|
98
|
+
throw new FakeAmqpNotFoundError('queue', name, connPath);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
messageCount: queue.messageCount,
|
|
103
|
+
consumerCount: queue.consumerCount,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
get(queue, ...args) {
|
|
108
|
+
const connPath = this.connection._url.pathname;
|
|
109
|
+
return this._callBroker(getMessage, ...args);
|
|
110
|
+
|
|
111
|
+
function getMessage(...getargs) {
|
|
112
|
+
const q = this.getQueue(queue);
|
|
113
|
+
if (!q) throw new FakeAmqpNotFoundError('queue', queue, connPath._url.pathname);
|
|
114
|
+
const msg = q.get(...getargs) || false;
|
|
115
|
+
if (!msg) return msg;
|
|
116
|
+
return new Message(msg);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
deleteExchange(exchange, ...args) {
|
|
120
|
+
const connPath = this.connection._url.pathname;
|
|
121
|
+
return this._callBroker(check, ...args);
|
|
122
|
+
|
|
123
|
+
function check() {
|
|
124
|
+
const result = this.deleteExchange(exchange, ...args);
|
|
125
|
+
if (!result && this.owner.version < 3.2) throw new FakeAmqpNotFoundError('exchange', exchange, connPath);
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
deleteQueue(queue, ...args) {
|
|
130
|
+
const connPath = this.connection._url.pathname;
|
|
131
|
+
return this._callBroker(check, ...args);
|
|
132
|
+
|
|
133
|
+
function check() {
|
|
134
|
+
const result = this.deleteQueue(queue, ...args);
|
|
135
|
+
if (!result && this.owner.version < 3.2) throw new FakeAmqpNotFoundError('queue', queue, connPath);
|
|
136
|
+
return result;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
publish(exchange, routingKey, content, options, callback) {
|
|
140
|
+
if (!Buffer.isBuffer(content)) throw new TypeError('content is not a buffer');
|
|
141
|
+
if (exchange === '') return this.sendToQueue(routingKey, content, options, callback);
|
|
142
|
+
|
|
143
|
+
const args = [ this._broker.publish, exchange, routingKey, content ];
|
|
144
|
+
|
|
145
|
+
args.push(options, callback);
|
|
146
|
+
|
|
147
|
+
this.checkExchange(exchange).then(() => {
|
|
148
|
+
return this._callBroker(...args);
|
|
149
|
+
}).catch((err) => {
|
|
150
|
+
this[kEmitter].emit('error', err);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
purgeQueue(queue, ...args) {
|
|
156
|
+
const connPath = this.connection._url.pathname;
|
|
157
|
+
return this._callBroker(check, ...args);
|
|
158
|
+
|
|
159
|
+
function check() {
|
|
160
|
+
const result = this.purgeQueue(queue);
|
|
161
|
+
if (!result && this.owner.version < 3.2) throw new FakeAmqpNotFoundError('queue', queue, connPath);
|
|
162
|
+
return result === undefined ? undefined : { messageCount: result };
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
sendToQueue(queue, content, options, callback) {
|
|
166
|
+
if (!Buffer.isBuffer(content)) throw new TypeError('content is not a buffer');
|
|
167
|
+
|
|
168
|
+
const args = [ this._broker.sendToQueue, queue, content ];
|
|
169
|
+
|
|
170
|
+
args.push(options, callback);
|
|
171
|
+
|
|
172
|
+
this.checkQueue(queue).then(() => {
|
|
173
|
+
return this._callBroker(...args);
|
|
174
|
+
}).catch((err) => {
|
|
175
|
+
this[kEmitter].emit('error', err);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
unbindExchange(destination, source, pattern, ...args) {
|
|
181
|
+
const connPath = this.connection._url.pathname;
|
|
182
|
+
return this._callBroker(check, ...args);
|
|
183
|
+
|
|
184
|
+
function check() {
|
|
185
|
+
const q = this.getExchange(destination);
|
|
186
|
+
if (!q) throw new FakeAmqpNotFoundError('exchange', destination);
|
|
187
|
+
|
|
188
|
+
const exchange = this.getExchange(source);
|
|
189
|
+
if (!exchange) throw new FakeAmqpNotFoundError('exchange', source);
|
|
190
|
+
|
|
191
|
+
const result = this.unbindExchange(source, destination, pattern);
|
|
192
|
+
if (!result && this.owner.version <= 3.2) throw new FakeAmqpNotFoundError('binding', pattern, connPath);
|
|
193
|
+
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
unbindQueue(queue, source, pattern, ...args) {
|
|
198
|
+
const connPath = this.connection._url.pathname;
|
|
199
|
+
return this._callBroker(check, ...args);
|
|
200
|
+
|
|
201
|
+
function check() {
|
|
202
|
+
const q = this.getQueue(queue);
|
|
203
|
+
if (!q) throw new FakeAmqpNotFoundError('queue', queue);
|
|
204
|
+
|
|
205
|
+
const exchange = this.getExchange(source);
|
|
206
|
+
if (!exchange) throw new FakeAmqpNotFoundError('exchange', source);
|
|
207
|
+
|
|
208
|
+
const binding = exchange.getBinding(queue, pattern);
|
|
209
|
+
if (!binding && this.owner.version <= 3.2) {
|
|
210
|
+
throw new FakeAmqpNotFoundError('binding', pattern, connPath, this.owner.version < 3.2);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
this.unbindQueue(queue, source, pattern);
|
|
214
|
+
return true;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
consume(queue, onMessage, options = {}, callback) {
|
|
218
|
+
const { _id: connId, _url: connUrl } = this.connection;
|
|
219
|
+
const channelName = this._channelName;
|
|
220
|
+
const prefetch = this[kPrefetch];
|
|
221
|
+
|
|
222
|
+
return this._callBroker(check, callback);
|
|
223
|
+
|
|
224
|
+
function check() {
|
|
225
|
+
const q = queue && this.getQueue(queue);
|
|
226
|
+
if (!q) {
|
|
227
|
+
throw new FakeAmqpNotFoundError('queue', queue, connUrl.pathname);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (q.exclusive || (q.options.exclusive && q.options._connectionId !== connId)) {
|
|
231
|
+
throw new FakeAmqpError(`Channel closed by server: 403 (ACCESS-REFUSED) with message "ACCESS_REFUSED - queue '${queue}' in vhost '${connUrl.pathname}' in exclusive use"`, 403, true, true);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const { consumerTag } = this.consume(queue, onMessage && handler, {
|
|
235
|
+
...options,
|
|
236
|
+
channelName,
|
|
237
|
+
prefetch,
|
|
238
|
+
});
|
|
239
|
+
return { consumerTag };
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function handler(_, msg) {
|
|
243
|
+
onMessage(new Message(msg));
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
cancel(consumerTag, ...args) {
|
|
247
|
+
return this._callBroker(this._broker.cancel, consumerTag, ...args);
|
|
248
|
+
}
|
|
249
|
+
close(callback) {
|
|
250
|
+
if (this[kClosed]) return;
|
|
251
|
+
const channelName = this._channelName;
|
|
252
|
+
const broker = this._broker;
|
|
253
|
+
|
|
254
|
+
broker.off('return', this._emitReturn);
|
|
255
|
+
const channelConsumers = broker.getConsumers().filter((f) => f.options.channelName === channelName);
|
|
256
|
+
channelConsumers.forEach((c) => broker.cancel(c.consumerTag));
|
|
257
|
+
this[kClosed] = true;
|
|
258
|
+
this[kEmitter].emit('close');
|
|
259
|
+
return resolveOrCallback(callback);
|
|
260
|
+
}
|
|
261
|
+
ack(message, ...args) {
|
|
262
|
+
this._broker.ack(message[kSmqp], ...args);
|
|
263
|
+
}
|
|
264
|
+
ackAll() {
|
|
265
|
+
const broker = this._broker;
|
|
266
|
+
const channelName = this._channelName;
|
|
267
|
+
|
|
268
|
+
const consumers = broker.getConsumers().filter(({ options }) => options.channelName === channelName);
|
|
269
|
+
consumers.forEach((c) => broker.getConsumer(c.consumerTag).ackAll());
|
|
270
|
+
}
|
|
271
|
+
nack(message, ...args) {
|
|
272
|
+
if (this.connection._version >= 2.3) throw new Error(`Nack is not implemented in versions before 2.3 (${this.connection._version})`);
|
|
273
|
+
return this._broker.nack(message[kSmqp], ...args);
|
|
274
|
+
}
|
|
275
|
+
reject(message, ...args) {
|
|
276
|
+
this._broker.reject(message[kSmqp], ...args);
|
|
277
|
+
}
|
|
278
|
+
nackAll(requeue = false) {
|
|
279
|
+
const broker = this._broker;
|
|
280
|
+
const channelName = this._channelName;
|
|
281
|
+
|
|
282
|
+
const consumers = broker.getConsumers().filter(({ options }) => options.channelName === channelName);
|
|
283
|
+
consumers.forEach((c) => broker.getConsumer(c.consumerTag).nackAll(requeue));
|
|
284
|
+
}
|
|
285
|
+
prefetch(val) {
|
|
286
|
+
this[kPrefetch] = val;
|
|
287
|
+
}
|
|
288
|
+
on(...args) {
|
|
289
|
+
return this[kEmitter].on(...args);
|
|
290
|
+
}
|
|
291
|
+
once(...args) {
|
|
292
|
+
return this[kEmitter].once(...args);
|
|
293
|
+
}
|
|
294
|
+
_callBroker(fn, ...args) {
|
|
295
|
+
let [ poppedCb ] = args.slice(-1);
|
|
296
|
+
if (typeof poppedCb === 'function') args.splice(-1);
|
|
297
|
+
else poppedCb = null;
|
|
298
|
+
|
|
299
|
+
if (this.connection._closed) throw new FakeAmqpError('Connection is closed', 504);
|
|
300
|
+
if (this[kClosed]) throw new Error('Channel is closed');
|
|
301
|
+
|
|
302
|
+
return new Promise((resolve, reject) => {
|
|
303
|
+
try {
|
|
304
|
+
const result = fn.call(this._broker, ...args);
|
|
305
|
+
if (poppedCb) poppedCb(null, result);
|
|
306
|
+
return resolve(result);
|
|
307
|
+
} catch (err) {
|
|
308
|
+
if (err._killConnection) this.connection.close();
|
|
309
|
+
else if (err._killChannel) this[kClosed] = true;
|
|
310
|
+
if (!poppedCb) return reject(err);
|
|
311
|
+
poppedCb(err);
|
|
312
|
+
return resolve();
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
_emitReturn({ fields, content, properties }) {
|
|
317
|
+
process.nextTick(() => {
|
|
318
|
+
this[kEmitter].emit('return', { fields, content, properties });
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
class FakeAmqplibConfirmChannel extends FakeAmqplibChannel {
|
|
324
|
+
publish(exchange, routingKey, content, options, callback) {
|
|
325
|
+
if (!Buffer.isBuffer(content)) throw new TypeError('content is not a buffer');
|
|
326
|
+
if (exchange === '') return this.sendToQueue(routingKey, content, options, callback);
|
|
327
|
+
|
|
328
|
+
const args = [ this._broker.publish, exchange, routingKey, content ];
|
|
329
|
+
|
|
330
|
+
args.push(...addConfirmCallback(this._broker, options, callback));
|
|
331
|
+
|
|
332
|
+
this.checkExchange(exchange).then(() => {
|
|
333
|
+
return this._callBroker(...args);
|
|
334
|
+
}).catch((err) => {
|
|
335
|
+
this[kEmitter].emit('error', err);
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
return true;
|
|
339
|
+
}
|
|
340
|
+
sendToQueue(queue, content, options, callback) {
|
|
341
|
+
if (!Buffer.isBuffer(content)) throw new TypeError('content is not a buffer');
|
|
342
|
+
|
|
343
|
+
const args = [ this._broker.sendToQueue, queue, content ];
|
|
344
|
+
|
|
345
|
+
args.push(...addConfirmCallback(this._broker, options, callback));
|
|
346
|
+
|
|
347
|
+
this.checkQueue(queue).then(() => {
|
|
348
|
+
return this._callBroker(...args);
|
|
349
|
+
}).catch((err) => {
|
|
350
|
+
this[kEmitter].emit('error', err);
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
return true;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
class FakeAmqplibConnection {
|
|
358
|
+
constructor(broker, version, amqpUrl) {
|
|
359
|
+
this[kEmitter] = new events.EventEmitter();
|
|
360
|
+
this[kClosed] = false;
|
|
361
|
+
this._channels = [];
|
|
362
|
+
this._url = normalizeAmqpUrl(amqpUrl);
|
|
363
|
+
this._id = generateId();
|
|
364
|
+
this._broker = broker;
|
|
365
|
+
this._version = version;
|
|
366
|
+
}
|
|
367
|
+
get _closed() {
|
|
368
|
+
return this[kClosed];
|
|
369
|
+
}
|
|
370
|
+
get _emitter() {
|
|
371
|
+
return this[kEmitter];
|
|
372
|
+
}
|
|
373
|
+
get connection() {
|
|
374
|
+
return {
|
|
375
|
+
serverProperties: {
|
|
376
|
+
host: this._url.host,
|
|
377
|
+
product: 'RabbitMQ',
|
|
378
|
+
version: `${this._version.toString()}.0`,
|
|
379
|
+
platform: 'OS',
|
|
380
|
+
copyright: 'MIT',
|
|
381
|
+
information: 'fake',
|
|
382
|
+
},
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
createChannel(...args) {
|
|
386
|
+
const callback = args.slice(-1)[0];
|
|
387
|
+
if (this[kClosed]) return resolveOrCallback(callback, new FakeAmqpError('Connection closed: 504', 504));
|
|
388
|
+
|
|
389
|
+
const channel = new FakeAmqplibChannel(this._broker, this);
|
|
390
|
+
this._channels.push(channel);
|
|
391
|
+
return resolveOrCallback(callback, null, channel);
|
|
392
|
+
}
|
|
393
|
+
createConfirmChannel(...args) {
|
|
394
|
+
if (this[kClosed]) return resolveOrCallback(args.slice(-1)[0], new FakeAmqpError('Connection closed: 504', 504));
|
|
395
|
+
|
|
396
|
+
const channel = new FakeAmqplibConfirmChannel(this._broker, this);
|
|
397
|
+
this._channels.push(channel);
|
|
398
|
+
return resolveOrCallback(args.slice(-1)[0], null, channel);
|
|
399
|
+
}
|
|
400
|
+
close(...args) {
|
|
401
|
+
if (this[kClosed]) return resolveOrCallback(args.slice(-1)[0]);
|
|
402
|
+
this[kClosed] = true;
|
|
403
|
+
|
|
404
|
+
this._channels.splice(0).forEach((channel) => channel.close());
|
|
405
|
+
|
|
406
|
+
this[kEmitter].emit('close');
|
|
407
|
+
|
|
408
|
+
return resolveOrCallback(args.slice(-1)[0]);
|
|
409
|
+
}
|
|
410
|
+
on(...args) {
|
|
411
|
+
return this[kEmitter].on(...args);
|
|
412
|
+
}
|
|
413
|
+
once(...args) {
|
|
414
|
+
return this[kEmitter].once(...args);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
function FakeAmqplib(minorVersion = '3.5') {
|
|
419
|
+
if (!(this instanceof FakeAmqplib)) {
|
|
420
|
+
return new FakeAmqplib(minorVersion);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
this.version = Number(minorVersion);
|
|
424
|
+
this.connections = [];
|
|
425
|
+
|
|
426
|
+
this.connect = this.connect.bind(this);
|
|
427
|
+
this.connectSync = this.connectSync.bind(this);
|
|
428
|
+
this.resetMock = this.resetMock.bind(this);
|
|
429
|
+
this.setVersion = this.setVersion.bind(this);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
FakeAmqplib.prototype.connect = function fakeConnect(amqpUrl, ...args) {
|
|
433
|
+
const connection = this.connectSync(amqpUrl, ...args);
|
|
434
|
+
return resolveOrCallback(args.slice(-1)[0], null, connection);
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
FakeAmqplib.prototype.connectSync = function fakeConnectSync(amqpUrl, ...args) {
|
|
438
|
+
const { _broker } = this.connections.find((conn) => compareConnectionString(conn._url, amqpUrl)) || {};
|
|
439
|
+
const broker = _broker || new smqp.Broker(this);
|
|
440
|
+
const connection = new FakeAmqplibConnection(broker, this.version, amqpUrl, ...args);
|
|
441
|
+
|
|
442
|
+
const connections = this.connections;
|
|
443
|
+
|
|
444
|
+
connections.push(connection);
|
|
445
|
+
|
|
446
|
+
connection._emitter.once('close', () => {
|
|
447
|
+
const idx = connections.indexOf(connection);
|
|
448
|
+
if (idx > -1) connections.splice(idx, 1);
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
return connection;
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
FakeAmqplib.prototype.resetMock = function fakeResetMock() {
|
|
455
|
+
for (const connection of this.connections.splice(0)) {
|
|
456
|
+
connection._broker.reset();
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
FakeAmqplib.prototype.setVersion = function fakeSetVersion(minorVersion) {
|
|
461
|
+
const n = Number(minorVersion);
|
|
462
|
+
if (!isNaN(n)) this.version = n;
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
function resolveOrCallback(optionalCb, err, ...args) {
|
|
466
|
+
if (typeof optionalCb === 'function') optionalCb(err, ...args);
|
|
467
|
+
if (err) return Promise.reject(err);
|
|
468
|
+
return Promise.resolve(...args);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
function generateId() {
|
|
472
|
+
return Math.random().toString(16).substring(2, 12);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
function compareConnectionString(url1, url2) {
|
|
476
|
+
const parsedUrl1 = normalizeAmqpUrl(url1);
|
|
477
|
+
const parsedUrl2 = normalizeAmqpUrl(url2);
|
|
478
|
+
|
|
479
|
+
return parsedUrl1.host === parsedUrl2.host && parsedUrl1.pathname === parsedUrl2.pathname;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
function Message(smqpMessage) {
|
|
483
|
+
this[kSmqp] = smqpMessage;
|
|
484
|
+
this.content = smqpMessage.content;
|
|
485
|
+
this.fields = smqpMessage.fields;
|
|
486
|
+
this.properties = smqpMessage.properties;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
function normalizeAmqpUrl(url$1) {
|
|
490
|
+
if (!url$1) return new URL('amqp://localhost:5672/');
|
|
491
|
+
if (typeof url$1 === 'string') url$1 = new URL(url$1);
|
|
492
|
+
|
|
493
|
+
if (!(url$1 instanceof URL)) {
|
|
494
|
+
const {
|
|
495
|
+
protocol = 'amqp',
|
|
496
|
+
hostname = 'localhost',
|
|
497
|
+
port = 5672,
|
|
498
|
+
vhost = '/',
|
|
499
|
+
username,
|
|
500
|
+
password,
|
|
501
|
+
...rest
|
|
502
|
+
} = url$1;
|
|
503
|
+
let auth = username;
|
|
504
|
+
if (auth && password) {
|
|
505
|
+
auth += `:${password}`;
|
|
506
|
+
}
|
|
507
|
+
url$1 = new URL(url.format({
|
|
508
|
+
protocol,
|
|
509
|
+
hostname,
|
|
510
|
+
port,
|
|
511
|
+
pathname: vhost,
|
|
512
|
+
slashes: true,
|
|
513
|
+
auth,
|
|
514
|
+
}));
|
|
515
|
+
|
|
516
|
+
for (const k in rest) {
|
|
517
|
+
switch (k) {
|
|
518
|
+
case 'locale':
|
|
519
|
+
case 'frameMax':
|
|
520
|
+
case 'heartbeat':
|
|
521
|
+
url$1.searchParams.set(k, rest[k]);
|
|
522
|
+
break;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
if (!url$1.port) url$1.port = 5672;
|
|
528
|
+
if (!url$1.pathname) url$1.pathname = '/';
|
|
529
|
+
return url$1;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
function addConfirmCallback(broker, options, callback) {
|
|
533
|
+
const confirm = `msg.${generateId()}`;
|
|
534
|
+
const consumerTag = `ct-${confirm}`;
|
|
535
|
+
options = { ...options, confirm };
|
|
536
|
+
|
|
537
|
+
broker.on('message.*', onConsumeMessage, { consumerTag });
|
|
538
|
+
|
|
539
|
+
let undelivered;
|
|
540
|
+
function onConsumeMessage(event) {
|
|
541
|
+
switch (event.name) {
|
|
542
|
+
case 'message.nack':
|
|
543
|
+
case 'message.undelivered':
|
|
544
|
+
undelivered = event.name;
|
|
545
|
+
break;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
function confirmCallback() {
|
|
550
|
+
broker.off('message.*', consumerTag);
|
|
551
|
+
switch (undelivered) {
|
|
552
|
+
case 'message.nack':
|
|
553
|
+
return callback(new Error('message nacked'));
|
|
554
|
+
case 'message.undelivered':
|
|
555
|
+
throw callback(new Error('message undelivered'));
|
|
556
|
+
default:
|
|
557
|
+
return callback(null, true);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
return [ options, confirmCallback ];
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
const defaultFake = new FakeAmqplib('3.5');
|
|
565
|
+
const connections = defaultFake.connections;
|
|
566
|
+
|
|
567
|
+
function connect(amqpUrl, ...args) {
|
|
568
|
+
return defaultFake.connect(amqpUrl, ...args);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
function connectSync(amqpUrl, ...args) {
|
|
572
|
+
return defaultFake.connectSync(amqpUrl, ...args);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
function resetMock() {
|
|
576
|
+
return defaultFake.resetMock();
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
function setVersion(minorVersion) {
|
|
580
|
+
return defaultFake.setVersion(minorVersion);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
exports.FakeAmqplib = FakeAmqplib;
|
|
584
|
+
exports.FakeAmqplibChannel = FakeAmqplibChannel;
|
|
585
|
+
exports.FakeAmqplibConfirmChannel = FakeAmqplibConfirmChannel;
|
|
586
|
+
exports.FakeAmqplibConnection = FakeAmqplibConnection;
|
|
587
|
+
exports.connect = connect;
|
|
588
|
+
exports.connectSync = connectSync;
|
|
589
|
+
exports.connections = connections;
|
|
590
|
+
exports.resetMock = resetMock;
|
|
591
|
+
exports.setVersion = setVersion;
|
package/package.json
CHANGED
|
@@ -1,19 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onify/fake-amqplib",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Fake amqplib",
|
|
5
|
-
"
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
"require": "./main.cjs",
|
|
8
|
+
"import": "./index.js"
|
|
9
|
+
},
|
|
10
|
+
"types": "index.d.ts",
|
|
11
|
+
"module": "./index.js",
|
|
12
|
+
"main": "./main.cjs",
|
|
6
13
|
"scripts": {
|
|
7
14
|
"test": "mocha",
|
|
8
|
-
"posttest": "
|
|
9
|
-
"
|
|
15
|
+
"posttest": "npm run lint && npm run dist",
|
|
16
|
+
"lint": "eslint . --cache",
|
|
17
|
+
"dist": "rollup -c",
|
|
18
|
+
"prepack": "npm run dist",
|
|
19
|
+
"cov:html": "c8 -r html -r text mocha",
|
|
20
|
+
"test:lcov": "c8 -r lcov mocha && npm run lint"
|
|
10
21
|
},
|
|
11
22
|
"author": {
|
|
12
23
|
"name": "Onify",
|
|
13
24
|
"url": "https://github.com/onify"
|
|
14
25
|
},
|
|
15
26
|
"engines": {
|
|
16
|
-
"node": ">=
|
|
27
|
+
"node": ">=14"
|
|
17
28
|
},
|
|
18
29
|
"repository": {
|
|
19
30
|
"type": "git",
|
|
@@ -21,7 +32,17 @@
|
|
|
21
32
|
},
|
|
22
33
|
"license": "MIT",
|
|
23
34
|
"dependencies": {
|
|
24
|
-
"smqp": "^
|
|
35
|
+
"smqp": "^8.2.0"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@bonniernews/eslint-config": "^1.0.1",
|
|
39
|
+
"@rollup/plugin-commonjs": "^25.0.5",
|
|
40
|
+
"@types/amqplib": "^0.10.2",
|
|
41
|
+
"c8": "^8.0.1",
|
|
42
|
+
"chai": "^4.3.10",
|
|
43
|
+
"eslint": "^8.51.0",
|
|
44
|
+
"mocha": "^10.2.0",
|
|
45
|
+
"rollup": "^4.0.2"
|
|
25
46
|
},
|
|
26
47
|
"keywords": [
|
|
27
48
|
"fake",
|
|
@@ -30,13 +51,9 @@
|
|
|
30
51
|
"amqplib",
|
|
31
52
|
"rabbitmq"
|
|
32
53
|
],
|
|
33
|
-
"devDependencies": {
|
|
34
|
-
"chai": "^4.3.6",
|
|
35
|
-
"eslint": "^7.32.0",
|
|
36
|
-
"mocha": "^9.2.0",
|
|
37
|
-
"nyc": "^15.1.0"
|
|
38
|
-
},
|
|
39
54
|
"files": [
|
|
40
|
-
"index.js"
|
|
55
|
+
"index.js",
|
|
56
|
+
"index.d.ts",
|
|
57
|
+
"main.cjs"
|
|
41
58
|
]
|
|
42
59
|
}
|