comq 0.24.1 → 0.25.1

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.
@@ -0,0 +1,47 @@
1
+ 'use strict'
2
+
3
+ /**
4
+ * A promise settled by whoever holds it, rather than only from within its executor.
5
+ * `callback` settles it the way node-style callbacks report: an error, or a value.
6
+ *
7
+ * @template T
8
+ * @extends {Promise<T>}
9
+ */
10
+ class Promex extends Promise {
11
+ /** @type {(value?: T | PromiseLike<T>) => void} */
12
+ resolve
13
+
14
+ /** @type {(reason?: any) => void} */
15
+ reject
16
+
17
+ /**
18
+ * @param {(resolve: (value?: any) => void, reject: (reason?: any) => void) => void} [executor]
19
+ */
20
+ constructor (executor = noop) {
21
+ let ok
22
+ let oh
23
+
24
+ super((resolve, reject) => {
25
+ ok = resolve
26
+ oh = reject
27
+
28
+ return executor(resolve, reject)
29
+ })
30
+
31
+ this.resolve = ok
32
+ this.reject = oh
33
+ }
34
+
35
+ /**
36
+ * @param {any} error
37
+ * @param {T} [value]
38
+ */
39
+ callback = (error, value) => {
40
+ if (error !== null && error !== undefined) this.reject(error)
41
+ else this.resolve(value)
42
+ }
43
+ }
44
+
45
+ function noop () {}
46
+
47
+ exports.Promex = Promex
@@ -0,0 +1,79 @@
1
+ 'use strict'
2
+
3
+ const { Promex } = require('./promex')
4
+
5
+ it('should resolve', async () => {
6
+ const promise = new Promex()
7
+
8
+ setImmediate(() => promise.resolve('ok'))
9
+
10
+ await expect(promise).resolves.toStrictEqual('ok')
11
+ })
12
+
13
+ it('should reject', async () => {
14
+ const promise = new Promex()
15
+
16
+ setImmediate(() => promise.reject(new Error('oh')))
17
+
18
+ await expect(promise).rejects.toThrow('oh')
19
+ })
20
+
21
+ it('should resolve using the callback', async () => {
22
+ const promise = new Promex()
23
+
24
+ setImmediate(() => promise.callback(null, 'ok'))
25
+
26
+ await expect(promise).resolves.toStrictEqual('ok')
27
+ })
28
+
29
+ it('should reject using the callback', async () => {
30
+ const promise = new Promex()
31
+
32
+ setImmediate(() => promise.callback('oh'))
33
+
34
+ await expect(promise).rejects.toStrictEqual('oh')
35
+ })
36
+
37
+ it('should resolve using the callback given no error', async () => {
38
+ const promise = new Promex()
39
+
40
+ setImmediate(() => promise.callback(undefined, 'ok'))
41
+
42
+ await expect(promise).resolves.toStrictEqual('ok')
43
+ })
44
+
45
+ it('should run the executor it is given', async () => {
46
+ const promise = new Promex((resolve) => resolve('ok'))
47
+
48
+ await expect(promise).resolves.toStrictEqual('ok')
49
+ })
50
+
51
+ it('should stay settled by whoever holds it', async () => {
52
+ const promise = new Promex()
53
+
54
+ promise.resolve('first')
55
+ promise.resolve('second')
56
+
57
+ await expect(promise).resolves.toStrictEqual('first')
58
+ })
59
+
60
+ it('should be a promise', async () => {
61
+ const promise = new Promex()
62
+
63
+ expect(promise).toBeInstanceOf(Promise)
64
+
65
+ promise.resolve('ok')
66
+
67
+ await expect(Promise.all([promise])).resolves.toStrictEqual(['ok'])
68
+ })
69
+
70
+ it('should derive promises of its own kind', async () => {
71
+ const promise = new Promex()
72
+ const derived = promise.then((value) => value + '!')
73
+
74
+ expect(derived).toBeInstanceOf(Promex)
75
+
76
+ promise.resolve('ok')
77
+
78
+ await expect(derived).resolves.toStrictEqual('ok!')
79
+ })
@@ -0,0 +1,42 @@
1
+ 'use strict'
2
+
3
+ /**
4
+ * Runs an operation until it stops asking for another attempt, waiting longer before
5
+ * each one. The operation is handed the token it returns to ask for a retry; anything
6
+ * else it returns is the result, and whatever it throws is thrown on.
7
+ *
8
+ * @template T
9
+ * @param {(again: symbol) => Promise<T | symbol>} operation
10
+ * @param {Partial<typeof DEFAULTS>} [options]
11
+ * @returns {Promise<T>}
12
+ */
13
+ async function retry (operation, options) {
14
+ const { attempts, base, max, factor, dispersion } = { ...DEFAULTS, ...options }
15
+
16
+ for (let attempt = 0; attempt < attempts; attempt++) {
17
+ const result = await operation(again)
18
+
19
+ if (result !== again) return /** @type {T} */ (result)
20
+
21
+ const interval = Math.min(base * factor ** attempt, max)
22
+
23
+ // attempts that started together are spread out rather than kept in step
24
+ const spread = interval * dispersion * (Math.random() - 0.5)
25
+
26
+ await new Promise((resolve) => setTimeout(resolve, interval + spread))
27
+ }
28
+
29
+ throw new Error('Maximum attempts exceeded')
30
+ }
31
+
32
+ const again = Symbol('again')
33
+
34
+ const DEFAULTS = {
35
+ attempts: Infinity,
36
+ base: 1000,
37
+ max: 30000,
38
+ factor: 1.5,
39
+ dispersion: 0.1
40
+ }
41
+
42
+ exports.retry = retry
@@ -0,0 +1,120 @@
1
+ 'use strict'
2
+
3
+ const { retry } = require('./retry')
4
+
5
+ const immediate = { base: 0, max: 0, dispersion: 0 }
6
+
7
+ it('should return the result', async () => {
8
+ const result = await retry(async () => 'ok', immediate)
9
+
10
+ expect(result).toStrictEqual('ok')
11
+ })
12
+
13
+ it('should retry while the operation asks for it', async () => {
14
+ let attempts = 0
15
+
16
+ const result = await retry(async (again) => {
17
+ attempts++
18
+
19
+ return attempts < 3 ? again : 'ok'
20
+ }, immediate)
21
+
22
+ expect(attempts).toStrictEqual(3)
23
+ expect(result).toStrictEqual('ok')
24
+ })
25
+
26
+ it('should pass the same token on every attempt', async () => {
27
+ const tokens = []
28
+
29
+ await retry(async (again) => {
30
+ tokens.push(again)
31
+
32
+ return tokens.length < 3 ? again : 'ok'
33
+ }, immediate)
34
+
35
+ expect(tokens).toHaveLength(3)
36
+ expect(new Set(tokens).size).toStrictEqual(1)
37
+ })
38
+
39
+ it('should throw what the operation throws', async () => {
40
+ const exception = new Error('nope')
41
+
42
+ await expect(retry(async () => { throw exception }, immediate)).rejects.toThrow(exception)
43
+ })
44
+
45
+ it('should give up after the last attempt', async () => {
46
+ let attempts = 0
47
+
48
+ const attempt = retry(async (again) => {
49
+ attempts++
50
+
51
+ return again
52
+ }, { ...immediate, attempts: 3 })
53
+
54
+ await expect(attempt).rejects.toThrow('Maximum attempts exceeded')
55
+ expect(attempts).toStrictEqual(3)
56
+ })
57
+
58
+ it('should not run the operation without an attempt to spare', async () => {
59
+ const operation = jest.fn(async (again) => again)
60
+
61
+ await expect(retry(operation, { ...immediate, attempts: 0 }))
62
+ .rejects.toThrow('Maximum attempts exceeded')
63
+
64
+ expect(operation).not.toHaveBeenCalled()
65
+ })
66
+
67
+ it('should back off, up to the maximum, before each attempt', async () => {
68
+ jest.useFakeTimers()
69
+
70
+ try {
71
+ const waits = []
72
+
73
+ let last = Date.now()
74
+ let attempts = 0
75
+
76
+ const attempt = retry(async (again) => {
77
+ waits.push(Date.now() - last)
78
+ last = Date.now()
79
+ attempts++
80
+
81
+ return attempts < 5 ? again : 'ok'
82
+ }, { base: 100, factor: 2, max: 300, dispersion: 0 })
83
+
84
+ await jest.advanceTimersByTimeAsync(10_000)
85
+
86
+ expect(await attempt).toStrictEqual('ok')
87
+
88
+ // the first attempt waits for nothing; then 100, 200, and 400 capped at 300
89
+ expect(waits).toStrictEqual([0, 100, 200, 300, 300])
90
+ } finally {
91
+ jest.useRealTimers()
92
+ }
93
+ })
94
+
95
+ it('should spread the wait around the interval', async () => {
96
+ const waits = []
97
+
98
+ const timer = global.setTimeout
99
+
100
+ global.setTimeout = (callback, ms) => {
101
+ waits.push(ms)
102
+
103
+ return timer(callback, 0)
104
+ }
105
+
106
+ try {
107
+ let attempts = 0
108
+
109
+ await retry(async (again) => {
110
+ attempts++
111
+
112
+ return attempts < 20 ? again : 'ok'
113
+ }, { base: 1000, factor: 1, max: 1000, dispersion: 0.1 })
114
+ } finally {
115
+ global.setTimeout = timer
116
+ }
117
+
118
+ expect(waits.every((ms) => ms >= 950 && ms <= 1050)).toStrictEqual(true)
119
+ expect(new Set(waits).size).toBeGreaterThan(1)
120
+ })
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const { Promex } = require('promex')
3
+ const { Promex } = require('../promex')
4
4
  const { RETRY_PREFIX } = require('../channel')
5
5
  const events = require('../events')
6
6
  const emitter = require('../emitter')
@@ -0,0 +1,22 @@
1
+ import * as mock from 'jest-mock'
2
+
3
+ // The test files are written against Jest's mock types, and keep being: the mocks are still
4
+ // Jest's, taken as the standalone `jest-mock` package. This is what @types/jest declared of it.
5
+
6
+ declare global {
7
+
8
+ namespace jest {
9
+
10
+ type Mock<T extends mock.FunctionLike = mock.UnknownFunction> = mock.Mock<T>
11
+
12
+ type Mocked<T extends object> = mock.Mocked<T>
13
+
14
+ type MockedClass<T extends mock.ClassLike> = mock.MockedClass<T>
15
+
16
+ type MockedFunction<T extends mock.FunctionLike = mock.UnknownFunction> = mock.MockedFunction<T>
17
+
18
+ type MockedFn<T extends mock.FunctionLike = mock.UnknownFunction> = mock.MockedFunction<T>
19
+
20
+ type MockedObject<T extends object> = mock.MockedObject<T>
21
+ }
22
+ }
@@ -1,7 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const { Readable } = require('node:stream')
4
- const { Promex } = require('promex')
4
+ const { Promex } = require('../source/promex')
5
5
  const { ReplyPipe } = require('../source/.io/ReplyPipe')
6
6
  const { createReplyEmitter } = require('../source/.io/createReplyEmitter')
7
7
  const { control, FLOW_HEADER } = require('../source/.io/const')
@@ -96,10 +96,14 @@ it('should pull the source no faster than the channel takes', async () => {
96
96
  })
97
97
 
98
98
  it('should hold the source while the consumer has asked for a pause', async () => {
99
- const pipe = await ReplyPipe.create(request, Readable.from([1, 2, 3]), channel, feedback, reply)
99
+ // the pause is asked for while the confirmation is still being published: the pipe does not
100
+ // read its source until that has been published, so nothing can be in flight yet
101
+ const opening = ReplyPipe.create(request, Readable.from([1, 2, 3]), channel, feedback, reply)
100
102
 
101
103
  feedback.emit(request.properties.correlationId, control.pause, {})
102
104
 
105
+ const pipe = await opening
106
+
103
107
  await timeout(10)
104
108
 
105
109
  expect(messages()).toStrictEqual([control.ok])
@@ -208,3 +212,68 @@ it('should destroy the source if the confirmation cannot be sent', async () => {
208
212
 
209
213
  expect(source.destroyed).toStrictEqual(true)
210
214
  })
215
+
216
+ describe('batches', () => {
217
+ beforeEach(() => {
218
+ request.properties.contentType = 'application/json'
219
+ })
220
+
221
+ it('should send the values its source holds as one message', async () => {
222
+ const pipe = await ReplyPipe.create(request, Readable.from([1, 2, 3]), channel, feedback, reply)
223
+
224
+ await closing(pipe)
225
+
226
+ expect(messages()).toStrictEqual([control.ok, [1, 2, 3], control.end])
227
+ expect(sent[1][1].type).toStrictEqual('batch')
228
+ })
229
+
230
+ it('should send each value that arrives on its own as it arrives', async () => {
231
+ async function * source () {
232
+ yield 1
233
+ await timeout(10)
234
+ yield 2
235
+ }
236
+
237
+ const pipe = await ReplyPipe.create(request, Readable.from(source()), channel, feedback, reply)
238
+
239
+ await closing(pipe)
240
+
241
+ expect(messages()).toStrictEqual([control.ok, 1, 2, control.end])
242
+ expect(sent[1][1].type).toBeUndefined()
243
+ })
244
+
245
+ it('should send buffers as one message, each prefixed with its length', async () => {
246
+ const source = Readable.from([Buffer.from('ab'), Buffer.from('cde')])
247
+ const pipe = await ReplyPipe.create(request, source, channel, feedback, reply)
248
+
249
+ await closing(pipe)
250
+
251
+ const expected = Buffer.from([0, 0, 0, 2, 0x61, 0x62, 0, 0, 0, 3, 0x63, 0x64, 0x65])
252
+
253
+ expect(messages()[1]).toStrictEqual(expected)
254
+ expect(sent[1][1].type).toStrictEqual('buffers')
255
+ })
256
+
257
+ it('should send values one at a time in an encoding that holds no list', async () => {
258
+ request.properties.contentType = 'text/plain'
259
+
260
+ const pipe = await ReplyPipe.create(request, Readable.from(['a', 'b']), channel, feedback, reply)
261
+
262
+ await closing(pipe)
263
+
264
+ expect(messages()).toStrictEqual([control.ok, 'a', 'b', control.end])
265
+ })
266
+
267
+ it('should keep a batch within its limit', async () => {
268
+ const values = Array.from({ length: 300 }, (_, i) => i)
269
+ const source = Readable.from(values, { highWaterMark: 1000 })
270
+ const pipe = await ReplyPipe.create(request, source, channel, feedback, reply)
271
+
272
+ await closing(pipe)
273
+
274
+ const batches = messages().slice(1, -1)
275
+
276
+ expect(batches.flat()).toStrictEqual(values)
277
+ expect(Math.max(...batches.map((batch) => [batch].flat().length))).toBeLessThanOrEqual(128)
278
+ })
279
+ })
@@ -204,3 +204,36 @@ describe('flow', () => {
204
204
  }
205
205
  })
206
206
  })
207
+
208
+ describe('batches', () => {
209
+ const ok = { headers: { index: 0, [FLOW_HEADER]: true }, type: 'control' }
210
+ const end = (index) => [control.end, { headers: { index }, type: 'control' }]
211
+
212
+ it('should yield each value of a batch, in order', async () => {
213
+ stream.arrange(control.ok, ok)
214
+ stream.arrange([1, 2, 3], { headers: { index: 1 }, type: 'batch' })
215
+ stream.arrange(4, { headers: { index: 2 } })
216
+ stream.arrange(...end(3))
217
+
218
+ expect(await stream.toArray()).toStrictEqual([1, 2, 3, 4])
219
+ })
220
+
221
+ it('should yield each buffer of a batch of buffers', async () => {
222
+ const buffers = Buffer.from([0, 0, 0, 2, 0x61, 0x62, 0, 0, 0, 0, 0, 0, 0, 1, 0x63])
223
+
224
+ stream.arrange(control.ok, ok)
225
+ stream.arrange(buffers, { headers: { index: 1 }, type: 'buffers' })
226
+ stream.arrange(...end(2))
227
+
228
+ expect(await stream.toArray()).toStrictEqual([Buffer.from('ab'), Buffer.alloc(0), Buffer.from('c')])
229
+ })
230
+
231
+ it('should hold a batch that arrives out of order until the gap is filled', async () => {
232
+ stream.arrange(control.ok, ok)
233
+ stream.arrange([3, 4], { headers: { index: 2 }, type: 'batch' })
234
+ stream.arrange([1, 2], { headers: { index: 1 }, type: 'batch' })
235
+ stream.arrange(...end(3))
236
+
237
+ expect(await stream.toArray()).toStrictEqual([1, 2, 3, 4])
238
+ })
239
+ })
@@ -1251,6 +1251,31 @@ describe('failed messages', () => {
1251
1251
  expect(chan.ack).toHaveBeenCalled()
1252
1252
  })
1253
1253
 
1254
+ it('should release the original before the channel is given back', async () => {
1255
+ await channel.consume(queue, consumer)
1256
+
1257
+ let confirm
1258
+
1259
+ chan.publish.mockImplementationOnce((_0, _1, _2, _3, callback) => (confirm = callback))
1260
+
1261
+ const delivering = deliver(delivery())
1262
+
1263
+ // closed while the copy is on its way: an original still unacknowledged then is
1264
+ // requeued by the broker, and the message is held twice
1265
+ const closing = channel.close()
1266
+
1267
+ await new Promise((resolve) => setImmediate(resolve))
1268
+
1269
+ confirm(null)
1270
+
1271
+ await closing
1272
+ await delivering
1273
+
1274
+ expect(chan.ack).toHaveBeenCalledTimes(1)
1275
+ expect(chan.ack.mock.invocationCallOrder[0])
1276
+ .toBeLessThan(chan.close.mock.invocationCallOrder[0])
1277
+ })
1278
+
1254
1279
  it('should increment the attempt', async () => {
1255
1280
  await channel.consume(queue, consumer)
1256
1281
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  const { generate } = require('randomstring')
6
6
 
7
- const { Promex } = require('promex')
7
+ const { Promex } = require('../source/promex')
8
8
  const { timeout, random } = require('./helpers')
9
9
  const { amqplib, connect } = require('./amqplib.mock')
10
10
  const { channel: create } = require('./connection.mock')
@@ -0,0 +1,143 @@
1
+ 'use strict'
2
+
3
+ // Jest's globals, on top of node:test.
4
+ //
5
+ // The runner is Node's own; the assertions, the mocks and the fake timers are still Jest's,
6
+ // taken as the standalone packages they are published as. Loaded with `--import`, so that
7
+ // the test files themselves keep seeing `it`, `expect` and `jest` as globals.
8
+
9
+ const { createRequire } = require('node:module')
10
+ const { format } = require('node:util')
11
+ const nodeTest = require('node:test')
12
+ const { expect } = require('expect')
13
+ const { ModuleMocker } = require('jest-mock')
14
+ const { ModernFakeTimers } = require('@jest/fake-timers')
15
+
16
+ // node:test drives its own queue with process.nextTick: faking it, as Jest does inside its
17
+ // sandbox, stops the runner mid-file and the tests left behind are never reported as missing
18
+ const DO_NOT_FAKE = ['nextTick']
19
+
20
+ const mocker = new ModuleMocker(globalThis)
21
+ const timers = new ModernFakeTimers({ global: globalThis, config: { rootDir: process.cwd() } })
22
+
23
+ /**
24
+ * Where `jest.mock` was called from, so that its specifier resolves
25
+ * relative to the test file rather than to this one.
26
+ *
27
+ * @returns {string}
28
+ */
29
+ function origin () {
30
+ const prepare = Error.prepareStackTrace
31
+
32
+ Error.prepareStackTrace = (_, frames) => frames
33
+
34
+ const { stack } = new Error('origin')
35
+
36
+ Error.prepareStackTrace = prepare
37
+
38
+ for (const frame of stack) {
39
+ const file = frame.getFileName()
40
+
41
+ if (file !== null && file !== undefined && file !== __filename && !file.startsWith('node:')) {
42
+ return file
43
+ }
44
+ }
45
+
46
+ throw new Error('cannot tell which file has called jest.mock')
47
+ }
48
+
49
+ /**
50
+ * Replaces a module, as `jest.mock` does. Without a factory the module is automocked:
51
+ * every function it exports becomes a mock function.
52
+ *
53
+ * @param {string} specifier
54
+ * @param {() => object} [factory]
55
+ */
56
+ function mockModule (specifier, factory) {
57
+ if (nodeTest.mock.module === undefined) {
58
+ throw new Error('jest.mock requires node --experimental-test-module-mocks')
59
+ }
60
+
61
+ const path = createRequire(origin()).resolve(specifier)
62
+
63
+ const namedExports = factory === undefined
64
+ ? mocker.generateFromMetadata(mocker.getMetadata(require(path)))
65
+ : factory()
66
+
67
+ nodeTest.mock.module(path, { namedExports, cache: false })
68
+ }
69
+
70
+ const jest = {
71
+ fn: (implementation) => mocker.fn(implementation),
72
+ spyOn: (object, property, accessType) => mocker.spyOn(object, property, accessType),
73
+ clearAllMocks: () => mocker.clearAllMocks(),
74
+ resetAllMocks: () => mocker.resetAllMocks(),
75
+ restoreAllMocks: () => mocker.restoreAllMocks(),
76
+ mock: mockModule,
77
+ useFakeTimers: (config) => timers.useFakeTimers({ doNotFake: DO_NOT_FAKE, ...config }),
78
+ useRealTimers: () => timers.useRealTimers(),
79
+ advanceTimersByTime: (ms) => timers.advanceTimersByTime(ms),
80
+ advanceTimersByTimeAsync: (ms) => timers.advanceTimersByTimeAsync(ms),
81
+ runAllTimers: () => timers.runAllTimers(),
82
+ runAllTimersAsync: () => timers.runAllTimersAsync(),
83
+ runOnlyPendingTimers: () => timers.runOnlyPendingTimers(),
84
+ getTimerCount: () => timers.getTimerCount(),
85
+ setSystemTime: (now) => timers.setSystemTime(now)
86
+ }
87
+
88
+ /**
89
+ * `it.each` / `describe.each`: one test per row, the row spread into the callback,
90
+ * the title formatted with the row's values.
91
+ *
92
+ * @param {Function} declare
93
+ * @returns {(table: any[]) => (title: string, fn: Function, options?: object) => void}
94
+ */
95
+ const each = (declare) => (table) => (title, fn, options) => {
96
+ const placeholders = (title.replace(/%%/g, '').match(/%[sdifjoOc]/g) ?? []).length
97
+
98
+ for (const row of table) {
99
+ const values = Array.isArray(row) ? row : [row]
100
+
101
+ declare(format(title, ...values.slice(0, placeholders)), options, () => fn(...values))
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Jest's `it` and `describe` carry `.each`; node:test's do not.
107
+ *
108
+ * @param {Function} declare
109
+ * @returns {Function}
110
+ */
111
+ function extend (declare) {
112
+ // Jest takes a timeout where node:test takes options
113
+ const call = (...args) => declare(...(typeof args[2] === 'number'
114
+ ? [args[0], { timeout: args[2] }, args[1]]
115
+ : args))
116
+
117
+ const extended = Object.assign(call, declare, { each: each(call) })
118
+
119
+ extended.only = Object.assign((...args) => declare.only(...args), { each: each(declare.only) })
120
+ extended.skip = Object.assign((...args) => declare.skip(...args), { each: each(declare.skip) })
121
+ extended.todo = (...args) => declare.todo(...args)
122
+
123
+ return extended
124
+ }
125
+
126
+ Object.assign(globalThis, {
127
+ jest,
128
+ expect,
129
+ it: extend(nodeTest.it),
130
+ test: extend(nodeTest.test),
131
+ describe: extend(nodeTest.describe),
132
+ beforeEach: nodeTest.beforeEach,
133
+ afterEach: nodeTest.afterEach,
134
+ beforeAll: nodeTest.before,
135
+ afterAll: nodeTest.after
136
+ })
137
+
138
+ // `expect.assertions` is only enforced by whoever runs the test
139
+ nodeTest.afterEach(() => {
140
+ const errors = expect.extractExpectedAssertionsErrors()
141
+
142
+ if (errors.length > 0) throw errors[0].error
143
+ })
@@ -2,7 +2,7 @@
2
2
 
3
3
  const { randomBytes } = require('node:crypto')
4
4
  const { generate } = require('randomstring')
5
- const { Promex } = require('promex')
5
+ const { Promex } = require('../source/promex')
6
6
  const { immediate } = require('./helpers')
7
7
 
8
8
  const mock = require('./connection.mock')
@@ -5,7 +5,7 @@
5
5
  const stream = require('node:stream')
6
6
  const { randomBytes } = require('node:crypto')
7
7
  const { generate } = require('randomstring')
8
- const { Promex } = require('promex')
8
+ const { Promex } = require('../source/promex')
9
9
  const { immediate } = require('./helpers')
10
10
  const { encode } = require('../source/encode')
11
11
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  const { randomBytes } = require('node:crypto')
4
4
  const { generate } = require('randomstring')
5
- const { Promex } = require('promex')
5
+ const { Promex } = require('../../source/promex')
6
6
  const { sample, immediate, random } = require('../helpers')
7
7
 
8
8
  const mock = require('../connection.mock')
@@ -1,15 +1,14 @@
1
1
  'use strict'
2
2
 
3
3
  const { generate } = require('randomstring')
4
- const { Promex } = require('promex')
4
+ const { Promex } = require('../../source/promex')
5
5
  const { random, immediate } = require('../helpers')
6
6
 
7
- const { Connection } = require('../../source/shards')
8
-
9
7
  const mock = require('../connection.mock')
10
8
 
11
9
  jest.mock('../../source/shards/channel')
12
10
 
11
+ const { Connection } = require('../../source/shards')
13
12
  const { create } = require('../../source/shards/channel')
14
13
 
15
14
  it('should be', async () => {