@amqp-contract/client 0.23.1 → 0.24.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 +16 -14
- package/dist/index.cjs +63 -77
- package/dist/index.d.cts +12 -28
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +12 -28
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +63 -77
- package/dist/index.mjs.map +1 -1
- package/docs/index.md +60 -60
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://github.com/btravers/amqp-contract/actions/workflows/ci.yml)
|
|
6
6
|
[](https://www.npmjs.com/package/@amqp-contract/client)
|
|
7
7
|
[](https://www.npmjs.com/package/@amqp-contract/client)
|
|
8
|
-
[](https://www.typescriptlang.org/)
|
|
9
9
|
[](https://opensource.org/licenses/MIT)
|
|
10
10
|
|
|
11
11
|
📖 **[Full documentation →](https://btravers.github.io/amqp-contract/api/client)**
|
|
@@ -23,20 +23,22 @@ import { TypedAmqpClient } from "@amqp-contract/client";
|
|
|
23
23
|
import { contract } from "./contract";
|
|
24
24
|
|
|
25
25
|
// Create client from contract (automatically connects and waits for connection)
|
|
26
|
-
const client =
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
// Publish message with explicit error handling
|
|
32
|
-
const result = await client
|
|
33
|
-
.publish("orderCreated", {
|
|
34
|
-
orderId: "ORD-123",
|
|
35
|
-
amount: 99.99,
|
|
26
|
+
const client = (
|
|
27
|
+
await TypedAmqpClient.create({
|
|
28
|
+
contract,
|
|
29
|
+
urls: ["amqp://localhost"],
|
|
36
30
|
})
|
|
37
|
-
|
|
31
|
+
)._unsafeUnwrap();
|
|
38
32
|
|
|
39
|
-
|
|
33
|
+
// Publish message with explicit error handling
|
|
34
|
+
const result = await client.publish("orderCreated", {
|
|
35
|
+
orderId: "ORD-123",
|
|
36
|
+
amount: 99.99,
|
|
37
|
+
});
|
|
38
|
+
result.match(
|
|
39
|
+
() => console.log("Published successfully"),
|
|
40
|
+
(error) => console.error("Publish failed:", error),
|
|
41
|
+
);
|
|
40
42
|
|
|
41
43
|
// Clean up
|
|
42
44
|
await client.close();
|
|
@@ -44,7 +46,7 @@ await client.close();
|
|
|
44
46
|
|
|
45
47
|
## Error Handling
|
|
46
48
|
|
|
47
|
-
The client uses `Result` types from [
|
|
49
|
+
The client uses `Result` types from [neverthrow](https://github.com/supermacro/neverthrow) for explicit error handling. Runtime errors are part of the type signature:
|
|
48
50
|
|
|
49
51
|
```typescript
|
|
50
52
|
publish(): Result<boolean, TechnicalError | MessageValidationError>
|
package/dist/index.cjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
let _amqp_contract_contract = require("@amqp-contract/contract");
|
|
3
3
|
let _amqp_contract_core = require("@amqp-contract/core");
|
|
4
|
-
let
|
|
4
|
+
let neverthrow = require("neverthrow");
|
|
5
5
|
let node_crypto = require("node:crypto");
|
|
6
6
|
let node_zlib = require("node:zlib");
|
|
7
|
-
let ts_pattern = require("ts-pattern");
|
|
8
7
|
let node_util = require("node:util");
|
|
8
|
+
let ts_pattern = require("ts-pattern");
|
|
9
9
|
//#region src/compression.ts
|
|
10
10
|
const gzipAsync = (0, node_util.promisify)(node_zlib.gzip);
|
|
11
11
|
const deflateAsync = (0, node_util.promisify)(node_zlib.deflate);
|
|
@@ -14,12 +14,12 @@ const deflateAsync = (0, node_util.promisify)(node_zlib.deflate);
|
|
|
14
14
|
*
|
|
15
15
|
* @param buffer - The buffer to compress
|
|
16
16
|
* @param algorithm - The compression algorithm to use
|
|
17
|
-
* @returns A
|
|
17
|
+
* @returns A ResultAsync resolving to the compressed buffer or a TechnicalError
|
|
18
18
|
*
|
|
19
19
|
* @internal
|
|
20
20
|
*/
|
|
21
21
|
function compressBuffer(buffer, algorithm) {
|
|
22
|
-
return (0, ts_pattern.match)(algorithm).with("gzip", () =>
|
|
22
|
+
return (0, ts_pattern.match)(algorithm).with("gzip", () => neverthrow.ResultAsync.fromPromise(gzipAsync(buffer), (error) => new _amqp_contract_core.TechnicalError("Failed to compress with gzip", error))).with("deflate", () => neverthrow.ResultAsync.fromPromise(deflateAsync(buffer), (error) => new _amqp_contract_core.TechnicalError("Failed to compress with deflate", error))).exhaustive();
|
|
23
23
|
}
|
|
24
24
|
//#endregion
|
|
25
25
|
//#region src/errors.ts
|
|
@@ -50,7 +50,7 @@ var RpcTimeoutError = class extends Error {
|
|
|
50
50
|
/**
|
|
51
51
|
* Returned from any in-flight RPC call when the client is closed before the
|
|
52
52
|
* reply is received. The correlation map is cleared on close and every pending
|
|
53
|
-
* caller's promise resolves with `
|
|
53
|
+
* caller's promise resolves with `err(RpcCancelledError)`.
|
|
54
54
|
*/
|
|
55
55
|
var RpcCancelledError = class extends Error {
|
|
56
56
|
constructor(rpcName) {
|
|
@@ -111,12 +111,14 @@ var TypedAmqpClient = class TypedAmqpClient {
|
|
|
111
111
|
persistent: true,
|
|
112
112
|
...defaultPublishOptions
|
|
113
113
|
}, logger, telemetry ?? _amqp_contract_core.defaultTelemetryProvider);
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
114
|
+
const setup = client.waitForConnectionReady().andThen(() => client.setupReplyConsumerIfNeeded());
|
|
115
|
+
return new neverthrow.ResultAsync((async () => {
|
|
116
|
+
const setupResult = await setup;
|
|
117
|
+
if (setupResult.isOk()) return (0, neverthrow.ok)(client);
|
|
118
|
+
const closeResult = await client.close();
|
|
119
|
+
if (closeResult.isErr()) logger?.warn("Failed to close client after connection failure", { error: closeResult.error });
|
|
120
|
+
return (0, neverthrow.err)(setupResult.error);
|
|
121
|
+
})());
|
|
120
122
|
}
|
|
121
123
|
/**
|
|
122
124
|
* If the contract has any RPC entry, subscribe to `amq.rabbitmq.reply-to`
|
|
@@ -125,10 +127,10 @@ var TypedAmqpClient = class TypedAmqpClient {
|
|
|
125
127
|
*/
|
|
126
128
|
setupReplyConsumerIfNeeded() {
|
|
127
129
|
const rpcs = this.contract.rpcs ?? {};
|
|
128
|
-
if (Object.keys(rpcs).length === 0) return
|
|
129
|
-
return this.amqpClient.consume(DIRECT_REPLY_TO, (msg) => this.handleRpcReply(msg), { noAck: true }).
|
|
130
|
+
if (Object.keys(rpcs).length === 0) return (0, neverthrow.okAsync)(void 0);
|
|
131
|
+
return this.amqpClient.consume(DIRECT_REPLY_TO, (msg) => this.handleRpcReply(msg), { noAck: true }).andTee((tag) => {
|
|
130
132
|
this.replyConsumerTag = tag;
|
|
131
|
-
}).
|
|
133
|
+
}).map(() => void 0);
|
|
132
134
|
}
|
|
133
135
|
/**
|
|
134
136
|
* Demultiplex an RPC reply by `correlationId`, validate the body against the
|
|
@@ -159,28 +161,28 @@ var TypedAmqpClient = class TypedAmqpClient {
|
|
|
159
161
|
try {
|
|
160
162
|
parsed = JSON.parse(msg.content.toString());
|
|
161
163
|
} catch (error) {
|
|
162
|
-
pending.resolve(
|
|
164
|
+
pending.resolve((0, neverthrow.err)(new _amqp_contract_core.TechnicalError(`Failed to parse RPC reply JSON for "${pending.rpcName}"`, error)));
|
|
163
165
|
return;
|
|
164
166
|
}
|
|
165
167
|
let rawValidation;
|
|
166
168
|
try {
|
|
167
169
|
rawValidation = pending.responseSchema["~standard"].validate(parsed);
|
|
168
170
|
} catch (error) {
|
|
169
|
-
pending.resolve(
|
|
171
|
+
pending.resolve((0, neverthrow.err)(new _amqp_contract_core.TechnicalError(`RPC reply validation threw for "${pending.rpcName}"`, error)));
|
|
170
172
|
return;
|
|
171
173
|
}
|
|
172
174
|
(rawValidation instanceof Promise ? rawValidation : Promise.resolve(rawValidation)).then((validation) => {
|
|
173
175
|
if (validation.issues) {
|
|
174
|
-
pending.resolve(
|
|
176
|
+
pending.resolve((0, neverthrow.err)(new _amqp_contract_core.MessageValidationError(pending.rpcName, validation.issues)));
|
|
175
177
|
return;
|
|
176
178
|
}
|
|
177
|
-
pending.resolve(
|
|
179
|
+
pending.resolve((0, neverthrow.ok)(validation.value));
|
|
178
180
|
}, (error) => {
|
|
179
|
-
pending.resolve(
|
|
181
|
+
pending.resolve((0, neverthrow.err)(new _amqp_contract_core.TechnicalError(`RPC reply validation threw for "${pending.rpcName}"`, error)));
|
|
180
182
|
});
|
|
181
183
|
}
|
|
182
184
|
/**
|
|
183
|
-
* Publish a message using a defined publisher
|
|
185
|
+
* Publish a message using a defined publisher.
|
|
184
186
|
*
|
|
185
187
|
* @param publisherName - The name of the publisher to use
|
|
186
188
|
* @param message - The message to publish
|
|
@@ -190,12 +192,6 @@ var TypedAmqpClient = class TypedAmqpClient {
|
|
|
190
192
|
* If `options.compression` is specified, the message will be compressed before publishing
|
|
191
193
|
* and the `contentEncoding` property will be set automatically. Any `contentEncoding`
|
|
192
194
|
* value already in options will be overwritten by the compression algorithm.
|
|
193
|
-
*
|
|
194
|
-
* @returns Result.Ok(void) on success, or Result.Error with specific error on failure
|
|
195
|
-
*/
|
|
196
|
-
/**
|
|
197
|
-
* Publish a message using a defined publisher.
|
|
198
|
-
* TypeScript guarantees publisher exists for valid publisher names.
|
|
199
195
|
*/
|
|
200
196
|
publish(publisherName, message, options) {
|
|
201
197
|
const startTime = Date.now();
|
|
@@ -204,9 +200,10 @@ var TypedAmqpClient = class TypedAmqpClient {
|
|
|
204
200
|
const span = (0, _amqp_contract_core.startPublishSpan)(this.telemetry, exchange.name, routingKey, { [_amqp_contract_core.MessagingSemanticConventions.AMQP_PUBLISHER_NAME]: String(publisherName) });
|
|
205
201
|
const validateMessage = () => {
|
|
206
202
|
const validationResult = publisher.message.payload["~standard"].validate(message);
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
return
|
|
203
|
+
const promise = validationResult instanceof Promise ? validationResult : Promise.resolve(validationResult);
|
|
204
|
+
return neverthrow.ResultAsync.fromPromise(promise, (error) => new _amqp_contract_core.TechnicalError("Validation failed", error)).andThen((validation) => {
|
|
205
|
+
if (validation.issues) return (0, neverthrow.err)(new _amqp_contract_core.MessageValidationError(String(publisherName), validation.issues));
|
|
206
|
+
return (0, neverthrow.ok)(validation.value);
|
|
210
207
|
});
|
|
211
208
|
};
|
|
212
209
|
const publishMessage = (validatedMessage) => {
|
|
@@ -221,24 +218,24 @@ var TypedAmqpClient = class TypedAmqpClient {
|
|
|
221
218
|
publishOptions.contentEncoding = compression;
|
|
222
219
|
return compressBuffer(messageBuffer, compression);
|
|
223
220
|
}
|
|
224
|
-
return
|
|
221
|
+
return (0, neverthrow.okAsync)(validatedMessage);
|
|
225
222
|
};
|
|
226
|
-
return preparePayload().
|
|
227
|
-
if (!published) return
|
|
223
|
+
return preparePayload().andThen((payload) => this.amqpClient.publish(publisher.exchange.name, publisher.routingKey ?? "", payload, publishOptions).andThen((published) => {
|
|
224
|
+
if (!published) return (0, neverthrow.err)(new _amqp_contract_core.TechnicalError(`Failed to publish message for publisher "${String(publisherName)}": Channel rejected the message (buffer full or other channel issue)`));
|
|
228
225
|
this.logger?.info("Message published successfully", {
|
|
229
226
|
publisherName: String(publisherName),
|
|
230
227
|
exchange: publisher.exchange.name,
|
|
231
228
|
routingKey: publisher.routingKey,
|
|
232
229
|
compressed: !!compression
|
|
233
230
|
});
|
|
234
|
-
return
|
|
231
|
+
return (0, neverthrow.ok)(void 0);
|
|
235
232
|
}));
|
|
236
233
|
};
|
|
237
|
-
return validateMessage().
|
|
234
|
+
return validateMessage().andThen((validatedMessage) => publishMessage(validatedMessage)).andTee(() => {
|
|
238
235
|
const durationMs = Date.now() - startTime;
|
|
239
236
|
(0, _amqp_contract_core.endSpanSuccess)(span);
|
|
240
237
|
(0, _amqp_contract_core.recordPublishMetric)(this.telemetry, exchange.name, routingKey, true, durationMs);
|
|
241
|
-
}).
|
|
238
|
+
}).orTee((error) => {
|
|
242
239
|
const durationMs = Date.now() - startTime;
|
|
243
240
|
(0, _amqp_contract_core.endSpanError)(span, error);
|
|
244
241
|
(0, _amqp_contract_core.recordPublishMetric)(this.telemetry, exchange.name, routingKey, false, durationMs);
|
|
@@ -250,29 +247,19 @@ var TypedAmqpClient = class TypedAmqpClient {
|
|
|
250
247
|
* The request payload is validated against the RPC's request schema, then
|
|
251
248
|
* published to the AMQP default exchange with the server's queue name as
|
|
252
249
|
* routing key, `replyTo` set to `amq.rabbitmq.reply-to`, and a fresh UUID
|
|
253
|
-
* `correlationId`. The returned
|
|
250
|
+
* `correlationId`. The returned ResultAsync resolves once a matching reply
|
|
254
251
|
* arrives and validates against the response schema, or once `timeoutMs`
|
|
255
252
|
* elapses (whichever comes first).
|
|
256
253
|
*
|
|
257
|
-
* @typeParam TName - An RPC name from `contract.rpcs`.
|
|
258
|
-
* @param rpcName - The RPC name from the contract.
|
|
259
|
-
* @param request - The request payload, validated against the request schema.
|
|
260
|
-
* @param options - Per-call options. `timeoutMs` is required.
|
|
261
|
-
*
|
|
262
|
-
* @returns `Result.Ok(response)` on a successful round-trip; `Result.Error`
|
|
263
|
-
* on validation, transport, timeout, or cancel.
|
|
264
|
-
*
|
|
265
254
|
* @example
|
|
266
255
|
* ```typescript
|
|
267
|
-
* const result = await client
|
|
268
|
-
* .call('calculate', { a: 1, b: 2 }, { timeoutMs: 5_000 })
|
|
269
|
-
* .toPromise();
|
|
256
|
+
* const result = await client.call('calculate', { a: 1, b: 2 }, { timeoutMs: 5_000 });
|
|
270
257
|
* if (result.isOk()) console.log(result.value.sum); // 3
|
|
271
258
|
* ```
|
|
272
259
|
*/
|
|
273
260
|
call(rpcName, request, options) {
|
|
274
261
|
const TIMEOUT_MAX_MS = 2147483647;
|
|
275
|
-
if (typeof options.timeoutMs !== "number" || !Number.isFinite(options.timeoutMs) || options.timeoutMs <= 0 || options.timeoutMs > TIMEOUT_MAX_MS) return
|
|
262
|
+
if (typeof options.timeoutMs !== "number" || !Number.isFinite(options.timeoutMs) || options.timeoutMs <= 0 || options.timeoutMs > TIMEOUT_MAX_MS) return (0, neverthrow.errAsync)(new _amqp_contract_core.TechnicalError(`Invalid timeoutMs for RPC call to "${String(rpcName)}": expected a finite positive number ≤ ${TIMEOUT_MAX_MS}, got ${String(options.timeoutMs)}`));
|
|
276
263
|
const startTime = Date.now();
|
|
277
264
|
const rpc = this.contract.rpcs[rpcName];
|
|
278
265
|
const requestSchema = rpc.request.payload;
|
|
@@ -280,28 +267,30 @@ var TypedAmqpClient = class TypedAmqpClient {
|
|
|
280
267
|
const queueName = (0, _amqp_contract_contract.extractQueue)(rpc.queue).name;
|
|
281
268
|
const span = (0, _amqp_contract_core.startPublishSpan)(this.telemetry, "", queueName, { [_amqp_contract_core.MessagingSemanticConventions.AMQP_PUBLISHER_NAME]: String(rpcName) });
|
|
282
269
|
const correlationId = (0, node_crypto.randomUUID)();
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
this.pendingCalls.
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
270
|
+
let resolveCall;
|
|
271
|
+
const callResultAsync = new neverthrow.ResultAsync(new Promise((res) => {
|
|
272
|
+
resolveCall = res;
|
|
273
|
+
}));
|
|
274
|
+
const timer = setTimeout(() => {
|
|
275
|
+
if (!this.pendingCalls.has(correlationId)) return;
|
|
276
|
+
this.pendingCalls.delete(correlationId);
|
|
277
|
+
resolveCall((0, neverthrow.err)(new RpcTimeoutError(String(rpcName), options.timeoutMs)));
|
|
278
|
+
}, options.timeoutMs);
|
|
279
|
+
this.pendingCalls.set(correlationId, {
|
|
280
|
+
rpcName: String(rpcName),
|
|
281
|
+
responseSchema,
|
|
282
|
+
resolve: resolveCall,
|
|
283
|
+
timer
|
|
295
284
|
});
|
|
296
285
|
const validateRequest = () => {
|
|
297
286
|
let rawValidation;
|
|
298
287
|
try {
|
|
299
288
|
rawValidation = requestSchema["~standard"].validate(request);
|
|
300
289
|
} catch (error) {
|
|
301
|
-
return
|
|
290
|
+
return (0, neverthrow.errAsync)(new _amqp_contract_core.TechnicalError("RPC request validation threw", error));
|
|
302
291
|
}
|
|
303
292
|
const validationPromise = rawValidation instanceof Promise ? rawValidation : Promise.resolve(rawValidation);
|
|
304
|
-
return
|
|
293
|
+
return neverthrow.ResultAsync.fromPromise(validationPromise, (error) => new _amqp_contract_core.TechnicalError("RPC request validation threw", error)).andThen((validation) => validation.issues ? (0, neverthrow.err)(new _amqp_contract_core.MessageValidationError(String(rpcName), validation.issues)) : (0, neverthrow.ok)(validation.value));
|
|
305
294
|
};
|
|
306
295
|
const publishRequest = (validatedRequest) => {
|
|
307
296
|
const { compression: _ignoredCompression, ...defaultsWithoutCompression } = this.defaultPublishOptions;
|
|
@@ -312,23 +301,19 @@ var TypedAmqpClient = class TypedAmqpClient {
|
|
|
312
301
|
correlationId,
|
|
313
302
|
contentType: "application/json"
|
|
314
303
|
};
|
|
315
|
-
return this.amqpClient.publish("", queueName, validatedRequest, publishOptions).
|
|
304
|
+
return this.amqpClient.publish("", queueName, validatedRequest, publishOptions).andThen((published) => published ? (0, neverthrow.ok)(void 0) : (0, neverthrow.err)(new _amqp_contract_core.TechnicalError(`Failed to publish RPC request for "${String(rpcName)}": channel buffer full`)));
|
|
316
305
|
};
|
|
317
|
-
return validateRequest().
|
|
318
|
-
if (
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
clearTimeout(pending.timer);
|
|
322
|
-
this.pendingCalls.delete(correlationId);
|
|
323
|
-
}
|
|
324
|
-
return _swan_io_boxed.Future.value(_swan_io_boxed.Result.Error(preflight.error));
|
|
306
|
+
return validateRequest().andThen((validated) => publishRequest(validated)).andThen(() => callResultAsync).orElse((error) => {
|
|
307
|
+
if (this.pendingCalls.has(correlationId)) {
|
|
308
|
+
clearTimeout(timer);
|
|
309
|
+
this.pendingCalls.delete(correlationId);
|
|
325
310
|
}
|
|
326
|
-
return
|
|
327
|
-
}).
|
|
311
|
+
return (0, neverthrow.errAsync)(error);
|
|
312
|
+
}).andTee(() => {
|
|
328
313
|
const durationMs = Date.now() - startTime;
|
|
329
314
|
(0, _amqp_contract_core.endSpanSuccess)(span);
|
|
330
315
|
(0, _amqp_contract_core.recordPublishMetric)(this.telemetry, "", queueName, true, durationMs);
|
|
331
|
-
}).
|
|
316
|
+
}).orTee((error) => {
|
|
332
317
|
const durationMs = Date.now() - startTime;
|
|
333
318
|
(0, _amqp_contract_core.endSpanError)(span, error);
|
|
334
319
|
(0, _amqp_contract_core.recordPublishMetric)(this.telemetry, "", queueName, false, durationMs);
|
|
@@ -341,12 +326,13 @@ var TypedAmqpClient = class TypedAmqpClient {
|
|
|
341
326
|
close() {
|
|
342
327
|
for (const [, pending] of this.pendingCalls) {
|
|
343
328
|
clearTimeout(pending.timer);
|
|
344
|
-
pending.resolve(
|
|
329
|
+
pending.resolve((0, neverthrow.err)(new RpcCancelledError(pending.rpcName)));
|
|
345
330
|
}
|
|
346
331
|
this.pendingCalls.clear();
|
|
347
|
-
return (this.replyConsumerTag ? this.amqpClient.cancel(this.replyConsumerTag).
|
|
332
|
+
return (this.replyConsumerTag ? this.amqpClient.cancel(this.replyConsumerTag).orElse((error) => {
|
|
348
333
|
this.logger?.warn("Failed to cancel RPC reply consumer during close", { error });
|
|
349
|
-
|
|
334
|
+
return (0, neverthrow.ok)(void 0);
|
|
335
|
+
}) : (0, neverthrow.okAsync)(void 0)).andThen(() => this.amqpClient.close());
|
|
350
336
|
}
|
|
351
337
|
waitForConnectionReady() {
|
|
352
338
|
return this.amqpClient.waitForConnect();
|
package/dist/index.d.cts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { CompressionAlgorithm, ContractDefinition, InferPublisherNames, InferRpcNames, MessageDefinition, PublisherEntry, RpcDefinition } from "@amqp-contract/contract";
|
|
2
2
|
import { Logger, MessageValidationError, PublishOptions as PublishOptions$1, TechnicalError, TelemetryProvider } from "@amqp-contract/core";
|
|
3
|
-
import { Future, Result } from "@swan-io/boxed";
|
|
4
3
|
import * as amqp from "amqplib";
|
|
5
4
|
import { TcpSocketConnectOpts } from "net";
|
|
6
5
|
import { ConnectionOptions } from "tls";
|
|
6
|
+
import { ResultAsync } from "neverthrow";
|
|
7
7
|
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
8
8
|
|
|
9
9
|
//#region ../../node_modules/.pnpm/amqp-connection-manager@5.0.0_amqplib@0.10.9/node_modules/amqp-connection-manager/dist/types/AmqpConnectionManager.d.ts
|
|
@@ -64,7 +64,7 @@ declare class RpcTimeoutError extends Error {
|
|
|
64
64
|
/**
|
|
65
65
|
* Returned from any in-flight RPC call when the client is closed before the
|
|
66
66
|
* reply is received. The correlation map is cleared on close and every pending
|
|
67
|
-
* caller's promise resolves with `
|
|
67
|
+
* caller's promise resolves with `err(RpcCancelledError)`.
|
|
68
68
|
*/
|
|
69
69
|
declare class RpcCancelledError extends Error {
|
|
70
70
|
readonly rpcName: string;
|
|
@@ -141,7 +141,7 @@ type CreateClientOptions<TContract extends ContractDefinition> = {
|
|
|
141
141
|
defaultPublishOptions?: PublishOptions | undefined;
|
|
142
142
|
/**
|
|
143
143
|
* Maximum time in ms to wait for the AMQP connection to become ready before
|
|
144
|
-
* `create()` resolves to `
|
|
144
|
+
* `create()` resolves to an `err(TechnicalError)`. Defaults to 30s
|
|
145
145
|
* (the {@link AmqpClient}'s `DEFAULT_CONNECT_TIMEOUT_MS`). Pass `null` to
|
|
146
146
|
* disable the timeout and let amqp-connection-manager retry indefinitely.
|
|
147
147
|
*/
|
|
@@ -153,8 +153,8 @@ type CreateClientOptions<TContract extends ContractDefinition> = {
|
|
|
153
153
|
type CallOptions = {
|
|
154
154
|
/**
|
|
155
155
|
* Maximum time in ms to wait for an RPC reply. If exceeded, the call resolves
|
|
156
|
-
* to `
|
|
157
|
-
*
|
|
156
|
+
* to `err(RpcTimeoutError)` and the in-memory correlation entry is cleared.
|
|
157
|
+
* A late reply arriving after the timeout is silently dropped.
|
|
158
158
|
*
|
|
159
159
|
* Required: RPC without a timeout is a footgun.
|
|
160
160
|
*/
|
|
@@ -203,7 +203,7 @@ declare class TypedAmqpClient<TContract extends ContractDefinition> {
|
|
|
203
203
|
logger,
|
|
204
204
|
telemetry,
|
|
205
205
|
connectTimeoutMs
|
|
206
|
-
}: CreateClientOptions<TContract>):
|
|
206
|
+
}: CreateClientOptions<TContract>): ResultAsync<TypedAmqpClient<TContract>, TechnicalError>;
|
|
207
207
|
/**
|
|
208
208
|
* If the contract has any RPC entry, subscribe to `amq.rabbitmq.reply-to`
|
|
209
209
|
* once. Replies for every in-flight call arrive on this single consumer and
|
|
@@ -221,7 +221,7 @@ declare class TypedAmqpClient<TContract extends ContractDefinition> {
|
|
|
221
221
|
*/
|
|
222
222
|
private handleRpcReply;
|
|
223
223
|
/**
|
|
224
|
-
* Publish a message using a defined publisher
|
|
224
|
+
* Publish a message using a defined publisher.
|
|
225
225
|
*
|
|
226
226
|
* @param publisherName - The name of the publisher to use
|
|
227
227
|
* @param message - The message to publish
|
|
@@ -231,46 +231,30 @@ declare class TypedAmqpClient<TContract extends ContractDefinition> {
|
|
|
231
231
|
* If `options.compression` is specified, the message will be compressed before publishing
|
|
232
232
|
* and the `contentEncoding` property will be set automatically. Any `contentEncoding`
|
|
233
233
|
* value already in options will be overwritten by the compression algorithm.
|
|
234
|
-
*
|
|
235
|
-
* @returns Result.Ok(void) on success, or Result.Error with specific error on failure
|
|
236
234
|
*/
|
|
237
|
-
|
|
238
|
-
* Publish a message using a defined publisher.
|
|
239
|
-
* TypeScript guarantees publisher exists for valid publisher names.
|
|
240
|
-
*/
|
|
241
|
-
publish<TName extends InferPublisherNames<TContract>>(publisherName: TName, message: ClientInferPublisherInput<TContract, TName>, options?: PublishOptions): Future<Result<void, TechnicalError | MessageValidationError>>;
|
|
235
|
+
publish<TName extends InferPublisherNames<TContract>>(publisherName: TName, message: ClientInferPublisherInput<TContract, TName>, options?: PublishOptions): ResultAsync<void, TechnicalError | MessageValidationError>;
|
|
242
236
|
/**
|
|
243
237
|
* Invoke an RPC defined via `defineRpc` and await the typed response.
|
|
244
238
|
*
|
|
245
239
|
* The request payload is validated against the RPC's request schema, then
|
|
246
240
|
* published to the AMQP default exchange with the server's queue name as
|
|
247
241
|
* routing key, `replyTo` set to `amq.rabbitmq.reply-to`, and a fresh UUID
|
|
248
|
-
* `correlationId`. The returned
|
|
242
|
+
* `correlationId`. The returned ResultAsync resolves once a matching reply
|
|
249
243
|
* arrives and validates against the response schema, or once `timeoutMs`
|
|
250
244
|
* elapses (whichever comes first).
|
|
251
245
|
*
|
|
252
|
-
* @typeParam TName - An RPC name from `contract.rpcs`.
|
|
253
|
-
* @param rpcName - The RPC name from the contract.
|
|
254
|
-
* @param request - The request payload, validated against the request schema.
|
|
255
|
-
* @param options - Per-call options. `timeoutMs` is required.
|
|
256
|
-
*
|
|
257
|
-
* @returns `Result.Ok(response)` on a successful round-trip; `Result.Error`
|
|
258
|
-
* on validation, transport, timeout, or cancel.
|
|
259
|
-
*
|
|
260
246
|
* @example
|
|
261
247
|
* ```typescript
|
|
262
|
-
* const result = await client
|
|
263
|
-
* .call('calculate', { a: 1, b: 2 }, { timeoutMs: 5_000 })
|
|
264
|
-
* .toPromise();
|
|
248
|
+
* const result = await client.call('calculate', { a: 1, b: 2 }, { timeoutMs: 5_000 });
|
|
265
249
|
* if (result.isOk()) console.log(result.value.sum); // 3
|
|
266
250
|
* ```
|
|
267
251
|
*/
|
|
268
|
-
call<TName extends InferRpcNames<TContract>>(rpcName: TName, request: ClientInferRpcRequestInput<TContract, TName>, options: CallOptions):
|
|
252
|
+
call<TName extends InferRpcNames<TContract>>(rpcName: TName, request: ClientInferRpcRequestInput<TContract, TName>, options: CallOptions): ResultAsync<ClientInferRpcResponseOutput<TContract, TName>, TechnicalError | MessageValidationError | RpcTimeoutError | RpcCancelledError>;
|
|
269
253
|
/**
|
|
270
254
|
* Close the channel and connection. Cancels the reply consumer (if any) and
|
|
271
255
|
* rejects every in-flight RPC call with `RpcCancelledError`.
|
|
272
256
|
*/
|
|
273
|
-
close():
|
|
257
|
+
close(): ResultAsync<void, TechnicalError>;
|
|
274
258
|
private waitForConnectionReady;
|
|
275
259
|
}
|
|
276
260
|
//#endregion
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":["amqp","EventEmitter","TcpSocketConnectOpts","ConnectionOptions","ChannelWrapper","CreateChannelOpts","ConnectionUrl","Options","Connect","AmqpConnectionOptions","url","connectionOptions","ConnectListener","Connection","connection","arg","ConnectFailedListener","Error","err","Buffer","noDelay","timeout","keepAlive","keepAliveDelay","clientProperties","credentials","mechanism","username","password","response","AmqpConnectionManagerOptions","Promise","heartbeatIntervalInSeconds","reconnectTimeInSeconds","findServers","urls","callback","IAmqpConnectionManager","Function","ChannelModel","addListener","event","args","listener","reason","listeners","eventName","on","once","prependListener","prependOnceListener","removeListener","connect","options","reconnect","createChannel","close","isConnected","channelCount","AmqpConnectionManager","_channels","_currentUrl","_closed","_cancelRetriesHandler","_connectPromise","_currentConnection","_findServers","_urls","constructor","_connect","default"],"sources":["../../../node_modules/.pnpm/amqp-connection-manager@5.0.0_amqplib@0.10.9/node_modules/amqp-connection-manager/dist/types/AmqpConnectionManager.d.ts","../src/errors.ts","../src/types.ts","../src/client.ts"],"x_google_ignoreList":[0],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":["amqp","EventEmitter","TcpSocketConnectOpts","ConnectionOptions","ChannelWrapper","CreateChannelOpts","ConnectionUrl","Options","Connect","AmqpConnectionOptions","url","connectionOptions","ConnectListener","Connection","connection","arg","ConnectFailedListener","Error","err","Buffer","noDelay","timeout","keepAlive","keepAliveDelay","clientProperties","credentials","mechanism","username","password","response","AmqpConnectionManagerOptions","Promise","heartbeatIntervalInSeconds","reconnectTimeInSeconds","findServers","urls","callback","IAmqpConnectionManager","Function","ChannelModel","addListener","event","args","listener","reason","listeners","eventName","on","once","prependListener","prependOnceListener","removeListener","connect","options","reconnect","createChannel","close","isConnected","channelCount","AmqpConnectionManager","_channels","_currentUrl","_closed","_cancelRetriesHandler","_connectPromise","_currentConnection","_findServers","_urls","constructor","_connect","default"],"sources":["../../../node_modules/.pnpm/amqp-connection-manager@5.0.0_amqplib@0.10.9/node_modules/amqp-connection-manager/dist/types/AmqpConnectionManager.d.ts","../src/errors.ts","../src/types.ts","../src/client.ts"],"x_google_ignoreList":[0],"mappings":";;;;;;;;;KAKYM,aAAAA,YAAyBN,IAAAA,CAAKO,OAAAA,CAAQC,OAAAA;EAC9CE,GAAAA;EACAC,iBAAAA,GAAoBF,qBAAAA;AAAAA;AAAAA,KAcZA,qBAAAA,IAAyBN,iBAAAA,GAAoBD,oBAAAA;EACrDkB,OAAAA;EACAC,OAAAA;EACAC,SAAAA;EACAC,cAAAA;EACAC,gBAAAA;EACAC,WAAAA;IACIC,SAAAA;IACAC,QAAAA;IACAC,QAAAA;IACAC,QAAAA,QAAgBV,MAAAA;EAAAA;IAEhBO,SAAAA;IACAG,QAAAA,QAAgBV,MAAAA;EAAAA;AAAAA;AAAAA,UAGPW,4BAAAA;EATTJ;EAWJM,0BAAAA;EATIJ;;;;EAcJK,sBAAAA;EAVoBd;;;AAGxB;;;;EAeIe,WAAAA,KAAgBE,QAAAA,GAAWD,IAAAA,EAAM7B,aAAAA,GAAgBA,aAAAA,+BAA4CyB,OAAAA,CAAQzB,aAAAA,GAAgBA,aAAAA;EAAhBA;EAErGK,iBAAAA,GAAoBF,qBAAAA;AAAAA;;;;;;;;;;;cChCX,eAAA,SAAwB,KAAA;EAAA,SAEjB,OAAA;EAAA,SACA,SAAA;cADA,OAAA,UACA,SAAA;AAAA;;;;;;cAaP,iBAAA,SAA0B,KAAA;EAAA,SACT,OAAA;cAAA,OAAA;AAAA;;;;;;KC1BzB,gBAAA,iBAAiC,gBAAA,IACpC,OAAA,SAAgB,gBAAA,iBAAiC,MAAA;;;;KAK9C,iBAAA,iBAAkC,gBAAA,IACrC,OAAA,SAAgB,gBAAA,iCAAiD,OAAA;;;;;;KAO9D,mBAAA,oBAAuC,cAAA,IAAkB,UAAA;EAC5D,OAAA;IAAW,OAAA,EAAS,gBAAA;EAAA;AAAA,IAElB,gBAAA,CAAiB,UAAA;AAAA,KAGhB,eAAA,mBAAkC,kBAAA,IAAsB,WAAA,CAAY,SAAA;AAAA,KACpE,cAAA,mBACe,kBAAA,gBACJ,mBAAA,CAAoB,SAAA,KAChC,eAAA,CAAgB,SAAA,EAAW,KAAA;;;;KAKnB,yBAAA,mBACQ,kBAAA,gBACJ,mBAAA,CAAoB,SAAA,KAChC,mBAAA,CAAoB,cAAA,CAAe,SAAA,EAAW,KAAA;AAAA,KAM7C,SAAA,mBAA4B,kBAAA,IAAsB,WAAA,CAAY,SAAA;AAAA,KAC9D,QAAA,mBACe,kBAAA,gBACJ,aAAA,CAAc,SAAA,KAC1B,SAAA,CAAU,SAAA,EAAW,KAAA;;;;KAKb,0BAAA,mBACQ,kBAAA,gBACJ,aAAA,CAAc,SAAA,KAE5B,QAAA,CAAS,SAAA,EAAW,KAAA,UAAe,aAAA,iBAA8B,iBAAA,IAC7D,QAAA,SAAiB,iBAAA,GACf,gBAAA,CAAiB,QAAA;;;;KAOb,4BAAA,mBACQ,kBAAA,gBACJ,aAAA,CAAc,SAAA,KAE5B,QAAA,CAAS,SAAA,EAAW,KAAA,UAAe,aAAA,CAAc,iBAAA,qBAC7C,SAAA,SAAkB,iBAAA,GAChB,iBAAA,CAAkB,SAAA;;;;;;KCjBd,cAAA,GAAiB,gBAAA;EHzDJ;;;;;EG+DvB,WAAA,GAAc,oBAAA;AAAA;;;;KAMJ,mBAAA,mBAAsC,kBAAA;EAChD,QAAA,EAAU,SAAA;EACV,IAAA,EAAM,aAAA;EACN,iBAAA,GAAoB,4BAAA;EACpB,MAAA,GAAS,MAAA;EHzD8CP;;;;;EG+DvD,SAAA,GAAY,iBAAA;EH/D2CA;;;;;EGqEvD,qBAAA,GAAwB,cAAA;EH/DtBuB;;;;;;EGsEF,gBAAA;AAAA;;;;KAMU,WAAA;EHlEiC;;;;;;;EG0E3C,SAAA;EHzD2C;;;;EG+D3C,cAAA,GAAiB,IAAA,CAAK,gBAAA;AAAA;;;;cAMX,eAAA,mBAAkC,kBAAA;EAAA,iBAc1B,QAAA;EAAA,iBACA,UAAA;EAAA,iBACA,qBAAA;EAAA,iBACA,MAAA;EAAA,iBACA,SAAA;EHvFwB;;;;EAAA,iBG0E1B,YAAA;EF1GU;;;;EAAA,QEgHnB,gBAAA;EAAA,QAED,WAAA,CAAA;;;;;;AFlGT;;;;;SEoHS,MAAA,mBAAyB,kBAAA,CAAA,CAAA;IAC9B,QAAA;IACA,IAAA;IACA,iBAAA;IACA,qBAAA;IACA,MAAA;IACA,SAAA;IACA;EAAA,GACC,mBAAA,CAAoB,SAAA,IAAa,WAAA,CAAY,eAAA,CAAgB,SAAA,GAAY,cAAA;;;;;;UAmCpE,0BAAA;;AD7LoD;;;;;;;;UCoNpD,cAAA;ED/M4B;;;;;;;AACmB;;;;;ECyRvD,OAAA,eAAsB,mBAAA,CAAoB,SAAA,EAAA,CACxC,aAAA,EAAe,KAAA,EACf,OAAA,EAAS,yBAAA,CAA0B,SAAA,EAAW,KAAA,GAC9C,OAAA,GAAU,cAAA,GACT,WAAA,OAAkB,cAAA,GAAiB,sBAAA;EDvRN;;;;;;;;;;;AAAwC;;;;;EC+XxE,IAAA,eAAmB,aAAA,CAAc,SAAA,EAAA,CAC/B,OAAA,EAAS,KAAA,EACT,OAAA,EAAS,0BAAA,CAA2B,SAAA,EAAW,KAAA,GAC/C,OAAA,EAAS,WAAA,GACR,WAAA,CACD,4BAAA,CAA6B,SAAA,EAAW,KAAA,GACxC,cAAA,GAAiB,sBAAA,GAAyB,eAAA,GAAkB,iBAAA;ED3X3C;;;;EC2gBnB,KAAA,CAAA,GAAS,WAAA,OAAkB,cAAA;EAAA,QAkBnB,sBAAA;AAAA"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CompressionAlgorithm, ContractDefinition, InferPublisherNames, InferRpcNames, MessageDefinition, PublisherEntry, RpcDefinition } from "@amqp-contract/contract";
|
|
2
2
|
import { Logger, MessageValidationError, PublishOptions as PublishOptions$1, TechnicalError, TelemetryProvider } from "@amqp-contract/core";
|
|
3
|
-
import {
|
|
3
|
+
import { ResultAsync } from "neverthrow";
|
|
4
4
|
import * as amqp from "amqplib";
|
|
5
5
|
import { TcpSocketConnectOpts } from "net";
|
|
6
6
|
import { ConnectionOptions } from "tls";
|
|
@@ -64,7 +64,7 @@ declare class RpcTimeoutError extends Error {
|
|
|
64
64
|
/**
|
|
65
65
|
* Returned from any in-flight RPC call when the client is closed before the
|
|
66
66
|
* reply is received. The correlation map is cleared on close and every pending
|
|
67
|
-
* caller's promise resolves with `
|
|
67
|
+
* caller's promise resolves with `err(RpcCancelledError)`.
|
|
68
68
|
*/
|
|
69
69
|
declare class RpcCancelledError extends Error {
|
|
70
70
|
readonly rpcName: string;
|
|
@@ -141,7 +141,7 @@ type CreateClientOptions<TContract extends ContractDefinition> = {
|
|
|
141
141
|
defaultPublishOptions?: PublishOptions | undefined;
|
|
142
142
|
/**
|
|
143
143
|
* Maximum time in ms to wait for the AMQP connection to become ready before
|
|
144
|
-
* `create()` resolves to `
|
|
144
|
+
* `create()` resolves to an `err(TechnicalError)`. Defaults to 30s
|
|
145
145
|
* (the {@link AmqpClient}'s `DEFAULT_CONNECT_TIMEOUT_MS`). Pass `null` to
|
|
146
146
|
* disable the timeout and let amqp-connection-manager retry indefinitely.
|
|
147
147
|
*/
|
|
@@ -153,8 +153,8 @@ type CreateClientOptions<TContract extends ContractDefinition> = {
|
|
|
153
153
|
type CallOptions = {
|
|
154
154
|
/**
|
|
155
155
|
* Maximum time in ms to wait for an RPC reply. If exceeded, the call resolves
|
|
156
|
-
* to `
|
|
157
|
-
*
|
|
156
|
+
* to `err(RpcTimeoutError)` and the in-memory correlation entry is cleared.
|
|
157
|
+
* A late reply arriving after the timeout is silently dropped.
|
|
158
158
|
*
|
|
159
159
|
* Required: RPC without a timeout is a footgun.
|
|
160
160
|
*/
|
|
@@ -203,7 +203,7 @@ declare class TypedAmqpClient<TContract extends ContractDefinition> {
|
|
|
203
203
|
logger,
|
|
204
204
|
telemetry,
|
|
205
205
|
connectTimeoutMs
|
|
206
|
-
}: CreateClientOptions<TContract>):
|
|
206
|
+
}: CreateClientOptions<TContract>): ResultAsync<TypedAmqpClient<TContract>, TechnicalError>;
|
|
207
207
|
/**
|
|
208
208
|
* If the contract has any RPC entry, subscribe to `amq.rabbitmq.reply-to`
|
|
209
209
|
* once. Replies for every in-flight call arrive on this single consumer and
|
|
@@ -221,7 +221,7 @@ declare class TypedAmqpClient<TContract extends ContractDefinition> {
|
|
|
221
221
|
*/
|
|
222
222
|
private handleRpcReply;
|
|
223
223
|
/**
|
|
224
|
-
* Publish a message using a defined publisher
|
|
224
|
+
* Publish a message using a defined publisher.
|
|
225
225
|
*
|
|
226
226
|
* @param publisherName - The name of the publisher to use
|
|
227
227
|
* @param message - The message to publish
|
|
@@ -231,46 +231,30 @@ declare class TypedAmqpClient<TContract extends ContractDefinition> {
|
|
|
231
231
|
* If `options.compression` is specified, the message will be compressed before publishing
|
|
232
232
|
* and the `contentEncoding` property will be set automatically. Any `contentEncoding`
|
|
233
233
|
* value already in options will be overwritten by the compression algorithm.
|
|
234
|
-
*
|
|
235
|
-
* @returns Result.Ok(void) on success, or Result.Error with specific error on failure
|
|
236
234
|
*/
|
|
237
|
-
|
|
238
|
-
* Publish a message using a defined publisher.
|
|
239
|
-
* TypeScript guarantees publisher exists for valid publisher names.
|
|
240
|
-
*/
|
|
241
|
-
publish<TName extends InferPublisherNames<TContract>>(publisherName: TName, message: ClientInferPublisherInput<TContract, TName>, options?: PublishOptions): Future<Result<void, TechnicalError | MessageValidationError>>;
|
|
235
|
+
publish<TName extends InferPublisherNames<TContract>>(publisherName: TName, message: ClientInferPublisherInput<TContract, TName>, options?: PublishOptions): ResultAsync<void, TechnicalError | MessageValidationError>;
|
|
242
236
|
/**
|
|
243
237
|
* Invoke an RPC defined via `defineRpc` and await the typed response.
|
|
244
238
|
*
|
|
245
239
|
* The request payload is validated against the RPC's request schema, then
|
|
246
240
|
* published to the AMQP default exchange with the server's queue name as
|
|
247
241
|
* routing key, `replyTo` set to `amq.rabbitmq.reply-to`, and a fresh UUID
|
|
248
|
-
* `correlationId`. The returned
|
|
242
|
+
* `correlationId`. The returned ResultAsync resolves once a matching reply
|
|
249
243
|
* arrives and validates against the response schema, or once `timeoutMs`
|
|
250
244
|
* elapses (whichever comes first).
|
|
251
245
|
*
|
|
252
|
-
* @typeParam TName - An RPC name from `contract.rpcs`.
|
|
253
|
-
* @param rpcName - The RPC name from the contract.
|
|
254
|
-
* @param request - The request payload, validated against the request schema.
|
|
255
|
-
* @param options - Per-call options. `timeoutMs` is required.
|
|
256
|
-
*
|
|
257
|
-
* @returns `Result.Ok(response)` on a successful round-trip; `Result.Error`
|
|
258
|
-
* on validation, transport, timeout, or cancel.
|
|
259
|
-
*
|
|
260
246
|
* @example
|
|
261
247
|
* ```typescript
|
|
262
|
-
* const result = await client
|
|
263
|
-
* .call('calculate', { a: 1, b: 2 }, { timeoutMs: 5_000 })
|
|
264
|
-
* .toPromise();
|
|
248
|
+
* const result = await client.call('calculate', { a: 1, b: 2 }, { timeoutMs: 5_000 });
|
|
265
249
|
* if (result.isOk()) console.log(result.value.sum); // 3
|
|
266
250
|
* ```
|
|
267
251
|
*/
|
|
268
|
-
call<TName extends InferRpcNames<TContract>>(rpcName: TName, request: ClientInferRpcRequestInput<TContract, TName>, options: CallOptions):
|
|
252
|
+
call<TName extends InferRpcNames<TContract>>(rpcName: TName, request: ClientInferRpcRequestInput<TContract, TName>, options: CallOptions): ResultAsync<ClientInferRpcResponseOutput<TContract, TName>, TechnicalError | MessageValidationError | RpcTimeoutError | RpcCancelledError>;
|
|
269
253
|
/**
|
|
270
254
|
* Close the channel and connection. Cancels the reply consumer (if any) and
|
|
271
255
|
* rejects every in-flight RPC call with `RpcCancelledError`.
|
|
272
256
|
*/
|
|
273
|
-
close():
|
|
257
|
+
close(): ResultAsync<void, TechnicalError>;
|
|
274
258
|
private waitForConnectionReady;
|
|
275
259
|
}
|
|
276
260
|
//#endregion
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":["amqp","EventEmitter","TcpSocketConnectOpts","ConnectionOptions","ChannelWrapper","CreateChannelOpts","ConnectionUrl","Options","Connect","AmqpConnectionOptions","url","connectionOptions","ConnectListener","Connection","connection","arg","ConnectFailedListener","Error","err","Buffer","noDelay","timeout","keepAlive","keepAliveDelay","clientProperties","credentials","mechanism","username","password","response","AmqpConnectionManagerOptions","Promise","heartbeatIntervalInSeconds","reconnectTimeInSeconds","findServers","urls","callback","IAmqpConnectionManager","Function","ChannelModel","addListener","event","args","listener","reason","listeners","eventName","on","once","prependListener","prependOnceListener","removeListener","connect","options","reconnect","createChannel","close","isConnected","channelCount","AmqpConnectionManager","_channels","_currentUrl","_closed","_cancelRetriesHandler","_connectPromise","_currentConnection","_findServers","_urls","constructor","_connect","default"],"sources":["../../../node_modules/.pnpm/amqp-connection-manager@5.0.0_amqplib@0.10.9/node_modules/amqp-connection-manager/dist/types/AmqpConnectionManager.d.ts","../src/errors.ts","../src/types.ts","../src/client.ts"],"x_google_ignoreList":[0],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":["amqp","EventEmitter","TcpSocketConnectOpts","ConnectionOptions","ChannelWrapper","CreateChannelOpts","ConnectionUrl","Options","Connect","AmqpConnectionOptions","url","connectionOptions","ConnectListener","Connection","connection","arg","ConnectFailedListener","Error","err","Buffer","noDelay","timeout","keepAlive","keepAliveDelay","clientProperties","credentials","mechanism","username","password","response","AmqpConnectionManagerOptions","Promise","heartbeatIntervalInSeconds","reconnectTimeInSeconds","findServers","urls","callback","IAmqpConnectionManager","Function","ChannelModel","addListener","event","args","listener","reason","listeners","eventName","on","once","prependListener","prependOnceListener","removeListener","connect","options","reconnect","createChannel","close","isConnected","channelCount","AmqpConnectionManager","_channels","_currentUrl","_closed","_cancelRetriesHandler","_connectPromise","_currentConnection","_findServers","_urls","constructor","_connect","default"],"sources":["../../../node_modules/.pnpm/amqp-connection-manager@5.0.0_amqplib@0.10.9/node_modules/amqp-connection-manager/dist/types/AmqpConnectionManager.d.ts","../src/errors.ts","../src/types.ts","../src/client.ts"],"x_google_ignoreList":[0],"mappings":"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"}
|